diff --git a/.github/workflows/docs.yml b/.github/workflows/docs.yml index 33c2e311..3a7f2b2a 100644 --- a/.github/workflows/docs.yml +++ b/.github/workflows/docs.yml @@ -17,12 +17,12 @@ jobs: steps: - name: Acquire sources - uses: actions/checkout@v2 + uses: actions/checkout@v3 - name: Set up Python - uses: actions/setup-python@v2 + uses: actions/setup-python@v3 with: - python-version: 3.7 + python-version: '3.9' - name: Build docs run: | diff --git a/.github/workflows/nightly.yml b/.github/workflows/nightly.yml index e81cfaa1..fcda7737 100644 --- a/.github/workflows/nightly.yml +++ b/.github/workflows/nightly.yml @@ -16,15 +16,15 @@ jobs: strategy: matrix: os: [ubuntu-latest] - python-version: [3.5, 3.6, 3.7, 3.8, 3.9] + python-version: ['3.7', '3.8', '3.9', '3.10'] cratedb-version: ['nightly'] - sqla-version: ['1.1.18', '1.2.19', '1.3.23'] + sqla-version: ['1.3.24'] fail-fast: false steps: - - uses: actions/checkout@master + - uses: actions/checkout@v3 - name: Set up Python ${{ matrix.python-version }} - uses: actions/setup-python@v2 + uses: actions/setup-python@v3 with: python-version: ${{ matrix.python-version }} diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 3426b643..99984d86 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -9,12 +9,12 @@ jobs: runs-on: ubuntu-latest if: startsWith(github.event.ref, 'refs/tags') steps: - - uses: actions/checkout@master + - uses: actions/checkout@v3 - - name: Set up python 3.8 - uses: actions/setup-python@v1 + - name: Set up Python + uses: actions/setup-python@v3 with: - python-version: 3.8 + python-version: '3.9' - name: Build package run: | diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml index 731102ab..621d6850 100644 --- a/.github/workflows/tests.yml +++ b/.github/workflows/tests.yml @@ -17,15 +17,15 @@ jobs: strategy: matrix: os: [ubuntu-latest, macos-latest] - python-version: ['3.5', '3.6', '3.7', '3.8', '3.9', '3.10'] + python-version: ['3.7', '3.8', '3.9', '3.10'] cratedb-version: ['4.8.0'] - sqla-version: ['1.1.18', '1.2.19', '1.3.24'] + sqla-version: ['1.3.24'] fail-fast: true steps: - - uses: actions/checkout@master + - uses: actions/checkout@v3 - name: Set up Python ${{ matrix.python-version }} - uses: actions/setup-python@v2 + uses: actions/setup-python@v3 with: python-version: ${{ matrix.python-version }} @@ -36,14 +36,10 @@ jobs: echo "/usr/local/opt/gnu-getopt/bin" >> $GITHUB_PATH - name: Install dependencies - if: | - !(matrix.sqla-version == '1.1.18' && matrix.python-version == '3.10') run: | ./devtools/setup_ci.sh --cratedb-version=${{ matrix.cratedb-version }} --sqlalchemy-version=${{ matrix.sqla-version }} - name: Invoke tests - if: | - !(matrix.sqla-version == '1.1.18' && matrix.python-version == '3.10') run: | bin/flake8 bin/coverage run bin/test -vv1 @@ -51,8 +47,6 @@ jobs: # https://github.com/codecov/codecov-action - name: Upload coverage results to Codecov - if: | - !(matrix.sqla-version == '1.1.18' && matrix.python-version == '3.10') - uses: codecov/codecov-action@v2 + uses: codecov/codecov-action@v3 with: fail_ci_if_error: true diff --git a/CHANGES.txt b/CHANGES.txt index 638626cc..7d754247 100644 --- a/CHANGES.txt +++ b/CHANGES.txt @@ -5,7 +5,13 @@ Changes for crate Unreleased ========== -- Added official support for Python 3.9 and 3.10. +- Added support for Python 3.9 and 3.10. + +- Dropped support for Python 3.4, 3.5 and 3.6. + +- Dropped support for SQLAlchemy 1.1 and 1.2. + +- Dropped support for CrateDB < 2.0.0. - BREAKING CHANGE: The driver now verifies SSL certificates when connecting via HTTP by default. Previously, this setting defaulted to false. This setting diff --git a/NOTICE b/NOTICE index 43f79206..cd2e19fd 100644 --- a/NOTICE +++ b/NOTICE @@ -1,5 +1,5 @@ CrateDB Python Adapter -Copyright 2013-2018 Crate.IO GmbH ("Crate") +Copyright 2013-2022 Crate.IO GmbH ("Crate") Licensed to Crate.IO GmbH (referred to in this notice as "Crate") under one or diff --git a/README.rst b/README.rst index 77650a51..8931a6c3 100644 --- a/README.rst +++ b/README.rst @@ -46,15 +46,14 @@ A Python client library for CrateDB_. This library: - Implements the Python `DB API 2.0`_ specification -- Includes support for SQLAlchemy_ (>= 1.0.0) +- Includes support for SQLAlchemy_ (>= 1.3.0) Prerequisites ============= -Recent versions of this library require **Python 3** (>= 3.4) to run. +Recent versions of this library are validated on Python 3 (>= 3.7). +It might also work on earlier versions of Python. -Use version ``0.21.x`` if you are running Python 2.7/3.3 or version ``0.14.x`` -if you are running Python 2.6. Installation ============ @@ -67,11 +66,8 @@ To install, run:: To update, run:: - $ pip install -U crate + $ pip install --upgrade crate -If you use Python 2.7 or 3.3 with a recent version of pip_, it will install -only version ``0.21.x`` by default, because newer versions of this package are -not compatible with Python 2.7/3.3 any more. Contributing ============ @@ -90,12 +86,12 @@ Looking for more help? - Check out our `support channels`_ .. _contribution docs: CONTRIBUTING.rst -.. _Crate.io: http://crate.io/ +.. _Crate.io: https://crate.io/ .. _CrateDB: https://github.com/crate/crate .. _DB API 2.0: http://www.python.org/dev/peps/pep-0249/ .. _developer docs: DEVELOP.rst .. _pip: https://pypi.python.org/pypi/pip -.. _SQLAlchemy: http://www.sqlalchemy.org -.. _StackOverflow: https://stackoverflow.com/tags/crate +.. _SQLAlchemy: https://www.sqlalchemy.org +.. _StackOverflow: https://stackoverflow.com/tags/cratedb .. _support channels: https://crate.io/support/ -.. _project docs: https://crate.io/docs/reference/python/ +.. _project docs: https://crate.io/docs/python/ diff --git a/devtools/setup_ci.sh b/devtools/setup_ci.sh index ec70f22d..6da60665 100755 --- a/devtools/setup_ci.sh +++ b/devtools/setup_ci.sh @@ -48,9 +48,6 @@ function main() { python -m pip install --upgrade pip - # Workaround needed for Python 3.5 - python -m pip install --upgrade "setuptools>=31,<51" - pip install zc.buildout==2.13.4 # Replace SQLAlchemy version. diff --git a/docs/appendices/compatibility.rst b/docs/appendices/compatibility.rst deleted file mode 100644 index 38052c61..00000000 --- a/docs/appendices/compatibility.rst +++ /dev/null @@ -1,204 +0,0 @@ -.. _compatibility: - -============= -Compatibility -============= - -.. rubric:: Table of contents - -.. contents:: - :local: - -.. _versions: - -Version notes -============= - -.. _python-versions: - -Python ------- - -Python >= 3.7 and the latest client library version is recommended. - -However, if you are running an older version of Python, older versions of the -CrateDB Python client library can be used. - -.. _sqlalchemy-versions: - -SQLAlchemy ----------- - -Consult the following table for SQLAlchemy version compatibility notes: - -+----------------+---------------------------+----------------+ -| Client Version | SQLAlchemy |nbsp| Version | Notes | -+================+===========================+================+ -| Any | 1.0 | Supported. | -+----------------+---------------------------+----------------+ -| >= 0.24.0 | 1.3 | Supported. | -+----------------+---------------------------+----------------+ -| >= 0.22.0 | 1.2 | Supported. | -+----------------+---------------------------+----------------+ -| >= 0.16.5 | 1.1 | Supported. | -+----------------+---------------------------+----------------+ -| >= 0.17 | < 1.0 | Not supported. | -+----------------+---------------------------+----------------+ - -.. _cratedb-versions: - -CrateDB -------- - -Consult the following table for CrateDB version compatibility notes: - -+----------------+-----------------+-------------------------------------------+ -| Client Version | CrateDB Version | Notes | -+================+=================+===========================================+ -| >= 0.15 | Any | Client SSL certificates are supported. | -+----------------+-----------------+-------------------------------------------+ -| >= 0.20 | Any | Username authentication is supported. | -+----------------+-----------------+-------------------------------------------+ -| >= 0.21 | Any | Password authentication is supported. | -+----------------+-----------------+-------------------------------------------+ -| >= 0.22 | Any | Default schema selection is supported. | -+----------------+-----------------+-------------------------------------------+ -| Any | < 0.55 | Default schema selection is not | -| | | supported. | -+----------------+-----------------+-------------------------------------------+ -| Any | >= 2.1.x | Client needs to connect with a valid | -| | | database user to access CrateDB. | -| | | | -| | | The default CrateDB user is ``crate`` and | -| | | has no password is set. | -| | | | -| | | The `enterprise edition`_ of CrateDB | -| | | allows you to `create your own users`_. | -| | | | -| | | Prior versions of CrateDB do not support | -| | | this feature. | -+----------------+-----------------+-------------------------------------------+ - -.. _implementations: - -Implementation notes -==================== - -.. _sqlalchemy-implementation: - -SQLAlchemy ----------- - -.. _sqlalchemy-features: - -Supported features -.................. - -Currently, CrateDB only implements a subset of the SQL standard. Additionally, -because CrateDB is distributed database that uses `eventual consistency`_, some -features typical of a more strongly consistent database are not available. - -Because of this, some SQLAlchemy operations are not supported. - -Consult the following table for specifics: - -+------------+-----------------------------+-----------------------------------+ -| Category | Methods | Notes | -+============+=============================+===================================+ -| `DQL`_ | - `filter()`_ | Supported. | -| | - `filter_by()`_ | | -| | - `limit()`_ | | -| | - `offset()`_ | | -| | - `group_by()`_ | | -| | - `order_by()`_ | | -| +-----------------------------+-----------------------------------+ -| | - `count()`_ | Partially supported. | -| | | | -| | | Consult the section on | -| | | :ref:`aggregate functions | -| | | `. | -| +-----------------------------+-----------------------------------+ -| | - `join()`_, etc. | Joins and subqueries are should | -| | - `subquery()`_ | be work, but tests have not been | -| | | written, so consider this an | -| | | an experimental feature for now. | -+------------+-----------------------------+-----------------------------------+ -| `DML`_ | - `insert()`_ | Supported. | -| | - `from_select()`_ | | -| | - `update()`_ (including | | -| | `correlated updates`_) | | -| | - `delete()`_ | | -+------------+-----------------------------+-----------------------------------+ -| `Session`_ | - `rollback()`_, etc. | CrateDB does not support | -| | | transactions, so this method and | -| | | other methods that work with | -| | | transactions will not do | -| | | anything. | -+ +-----------------------------+-----------------------------------+ -| | - `commit()`_ | Per the previous note, this | -| | | method will only `flush()`_. | -+------------+-----------------------------+-----------------------------------+ - -.. _sqlalchemy-version-notes: - -Version notes -............. - -+----------------+-----------------+-------------------------------------------+ -| Client Version | CrateDB Version | Notes | -+================+=================+===========================================+ -| >= 0.17 | Any | Supported: | -| | | | -| | | - `types.ARRAY`_ | -+----------------+-----------------+-------------------------------------------+ -| >= 0.18 | Any | Supported: | -| | | | -| | | - `from_select()`_ | -| | | - `get_columns()`_ | -| | | - `get_pk_constraint()`_ | -+----------------+-----------------+-------------------------------------------+ -| >= 0.22 | >= 3.0 | Supported: | -| | | | -| | | - `get_table_names()`_ | -+----------------+-----------------+-------------------------------------------+ - -.. _earlier-versions: - -Older versions -============== - -For information about older versions of the client, consult `the 0.14.2 -changelog`_. - -.. _commit(): http://docs.sqlalchemy.org/en/latest/orm/session_api.html#sqlalchemy.orm.Session.commit -.. _correlated updates: http://docs.sqlalchemy.org/en/latest/core/tutorial.html#correlated-updates -.. _count(): http://docs.sqlalchemy.org/en/latest/orm/query.html#sqlalchemy.orm.Query.count -.. _create your own users: https://crate.io/docs/crate/reference/en/latest/admin/user-management.html -.. _date: https://docs.python.org/3/library/datetime.html#date-objects -.. _datetime: https://docs.python.org/3/library/datetime.html#datetime-objects -.. _Decimal: https://docs.python.org/2/library/decimal.html#module-decimal -.. _delete(): http://docs.sqlalchemy.org/en/latest/core/tutorial.html#inserts-and-updates -.. _DML: http://docs.sqlalchemy.org/en/latest/core/dml.html -.. _DQL: http://docs.sqlalchemy.org/en/latest/orm/query.html -.. _enterprise edition: https://crate.io/products/cratedb-enterprise/ -.. _eventual consistency: https://crate.io/docs/crate/guide/en/latest/architecture/storage-consistency.html -.. _filter_by(): http://docs.sqlalchemy.org/en/latest/orm/query.html#sqlalchemy.orm.Query.filter_by -.. _filter(): http://docs.sqlalchemy.org/en/latest/orm/query.html#sqlalchemy.orm.Query.filter -.. _flush(): http://docs.sqlalchemy.org/en/latest/orm/session_basics.html#flushing -.. _from_select(): http://docs.sqlalchemy.org/en/latest/core/dml.html#sqlalchemy.sql.expression.Insert.from_select -.. _get_columns(): http://docs.sqlalchemy.org/en/latest/core/reflection.html#sqlalchemy.engine.reflection.Inspector.get_columns -.. _get_pk_constraint(): http://docs.sqlalchemy.org/en/latest/core/reflection.html#sqlalchemy.engine.reflection.Inspector.get_pk_constraint -.. _get_table_names(): http://docs.sqlalchemy.org/en/latest/core/reflection.html#sqlalchemy.engine.reflection.Inspector.get_table_names -.. _group_by(): http://docs.sqlalchemy.org/en/latest/orm/query.html#sqlalchemy.orm.Query.group_by -.. _insert(): http://docs.sqlalchemy.org/en/latest/core/tutorial.html#inserts-and-updates -.. _join(): http://docs.sqlalchemy.org/en/latest/orm/query.html?sqlalchemy.orm.Query.join -.. _limit(): http://docs.sqlalchemy.org/en/latest/orm/query.html#sqlalchemy.orm.Query.limit -.. _offset(): http://docs.sqlalchemy.org/en/latest/orm/query.html#sqlalchemy.orm.Query.offset -.. _order_by(): http://docs.sqlalchemy.org/en/latest/orm/query.html#sqlalchemy.orm.Query.order_by -.. _PyPI: https://pypi.org/ -.. _rollback(): http://docs.sqlalchemy.org/en/latest/orm/session_api.html#sqlalchemy.orm.Session.rollback -.. _Session: http://docs.sqlalchemy.org/en/latest/orm/session_api.html -.. _subquery(): http://docs.sqlalchemy.org/en/latest/orm/query.html?sqlalchemy.orm.Query.subquery -.. _the 0.14.2 changelog: https://github.com/crate/crate-python/blob/415ee6d1eb3de2fe55a342e57f46841b769f1d44/CHANGES.txt -.. _types.ARRAY: http://docs.sqlalchemy.org/en/latest/core/type_basics.html#sqlalchemy.types.ARRAY -.. _update(): http://docs.sqlalchemy.org/en/latest/core/tutorial.html#inserts-and-updates diff --git a/docs/appendices/index.rst b/docs/appendices/index.rst index bbe6d95b..ae83ef5f 100644 --- a/docs/appendices/index.rst +++ b/docs/appendices/index.rst @@ -12,4 +12,3 @@ Supplementary information for the CrateDB Python client library. :maxdepth: 2 data-types - compatibility diff --git a/docs/connect.rst b/docs/connect.rst index 7649a027..a60c7b37 100644 --- a/docs/connect.rst +++ b/docs/connect.rst @@ -14,8 +14,7 @@ Connect to CrateDB .. SEEALSO:: Supplementary information about the CrateDB Database API client can be found - in the :ref:`data types appendix ` and the - :ref:`compatibility notes `. + in the :ref:`data types appendix `. For general help using the Database API, consult `PEP 0249`_. @@ -218,8 +217,6 @@ Authentication If you are using CrateDB 2.1.x or later, you must supply a username. If you are using earlier versions of CrateDB, this argument is not supported. - See the :ref:`compatibility notes ` for more information. - You can authenticate with CrateDB like so:: >>> connection = client.connect(..., username="", password="") diff --git a/docs/query.rst b/docs/query.rst index c43b90e6..4f0b22ac 100644 --- a/docs/query.rst +++ b/docs/query.rst @@ -14,8 +14,7 @@ Query CrateDB .. SEEALSO:: Supplementary information about the CrateDB Database API client can be found - in the :ref:`data types appendix ` and the - :ref:`compatibility notes `. + in the :ref:`data types appendix `. For general help using the Database API, consult `PEP 0249`_. diff --git a/docs/sqlalchemy.rst b/docs/sqlalchemy.rst index ad67ff76..ee0be079 100644 --- a/docs/sqlalchemy.rst +++ b/docs/sqlalchemy.rst @@ -10,8 +10,8 @@ The CrateDB Python client library provides support for SQLAlchemy. A CrateDB `dialect`_ is registered at installation time and can be used without further configuration. -The CrateDB Python client library works with SQLAlchemy versions ``1.0``, -``1.1``, ``1.2`` and ``1.3``. +The CrateDB Python client library is validated to work with SQLAlchemy versions +``1.3``. .. NOTE:: @@ -23,8 +23,7 @@ The CrateDB Python client library works with SQLAlchemy versions ``1.0``, .. SEEALSO:: Supplementary information about the CrateDB SQLAlchemy dialect can be found - in the :ref:`data types appendix ` and the - :ref:`compatibility notes `. + in the :ref:`data types appendix `. For general help using SQLAlchemy, consult the `SQLAlchemy tutorial`_ or the `SQLAlchemy library`_ . diff --git a/setup.py b/setup.py index fdabaae6..6bb237de 100644 --- a/setup.py +++ b/setup.py @@ -79,9 +79,6 @@ def read(path): 'Operating System :: OS Independent', 'Programming Language :: Python', 'Programming Language :: Python :: 3', - 'Programming Language :: Python :: 3.4', - 'Programming Language :: Python :: 3.5', - 'Programming Language :: Python :: 3.6', 'Programming Language :: Python :: 3.7', 'Programming Language :: Python :: 3.8', 'Programming Language :: Python :: 3.9', diff --git a/src/crate/client/cursor.py b/src/crate/client/cursor.py index 329cb9ff..59e936d7 100644 --- a/src/crate/client/cursor.py +++ b/src/crate/client/cursor.py @@ -20,11 +20,8 @@ # software solely pursuant to the terms of the relevant commercial agreement. from .exceptions import ProgrammingError -from distutils.version import StrictVersion import warnings -BULK_INSERT_MIN_VERSION = StrictVersion("0.42.0") - class Cursor(object): """ @@ -63,20 +60,14 @@ def executemany(self, sql, seq_of_parameters): """ row_counts = [] durations = [] - if self.connection.lowest_server_version >= BULK_INSERT_MIN_VERSION: - self.execute(sql, bulk_parameters=seq_of_parameters) - for result in self._result.get('results', []): - if result.get('rowcount') > -1: - row_counts.append(result.get('rowcount')) - if self.duration > -1: - durations.append(self.duration) - else: - for params in seq_of_parameters: - self.execute(sql, parameters=params) - if self.rowcount > -1: - row_counts.append(self.rowcount) - if self.duration > -1: - durations.append(self.duration) + self.execute(sql, bulk_parameters=seq_of_parameters) + + for result in self._result.get('results', []): + if result.get('rowcount') > -1: + row_counts.append(result.get('rowcount')) + if self.duration > -1: + durations.append(self.duration) + self._result = { "rowcount": sum(row_counts) if row_counts else -1, "duration": sum(durations) if durations else -1, diff --git a/src/crate/client/doctests/connection.txt b/src/crate/client/doctests/connection.txt index 5c38aaae..44abb2cf 100644 --- a/src/crate/client/doctests/connection.txt +++ b/src/crate/client/doctests/connection.txt @@ -10,7 +10,7 @@ We create a new connection object:: >>> connection = connect(client=connection_client_mocked) >>> connection.lowest_server_version.version - (0, 42, 0) + (2, 0, 0) Calling the ``cursor()`` function on the connection will return a cursor object:: diff --git a/src/crate/client/doctests/cursor.txt b/src/crate/client/doctests/cursor.txt index 41ad720a..970465da 100644 --- a/src/crate/client/doctests/cursor.txt +++ b/src/crate/client/doctests/cursor.txt @@ -246,7 +246,7 @@ of parameters:: 123 ``executemany()`` is not intended to be used with statements returning result -sets. The result will alway be empty:: +sets. The result will always be empty:: >>> cursor.fetchall() [] @@ -263,26 +263,6 @@ For completeness' sake the cursor description is updated nonetheless:: ... "duration":123 ... }) -.. Hidden: close connection - - >>> connection.close() - -Usually ``executemany`` sends the ``bulk_args`` parameter to the crate sql -endpoint which was introduced with Crate 0.42.0. -If the client is connected to at least one crate server with an older version -the client executes the statement once for every parameter within the sequence. - -The resulting ``rowcount`` and ``duration`` are the sum of all calls made to -the server during this method execution.:: - - >>> connection_client_mocked.set_next_server_infos("local:4200", "my crate", "0.41.9") - >>> connection = connect(client=connection_client_mocked) - >>> cursor = connection.cursor() - >>> cursor.executemany('', (1,2,3)) - >>> cursor.rowcount - 9 - >>> cursor.duration - 369 close() ======= diff --git a/src/crate/client/sqlalchemy/compiler.py b/src/crate/client/sqlalchemy/compiler.py index 84945944..03347a27 100644 --- a/src/crate/client/sqlalchemy/compiler.py +++ b/src/crate/client/sqlalchemy/compiler.py @@ -26,7 +26,6 @@ from sqlalchemy.sql import crud from sqlalchemy.sql import compiler from .types import MutableDict -from .sa_version import SA_1_1, SA_VERSION def rewrite_update(clauseelement, multiparams, params): @@ -184,104 +183,6 @@ def returning_clause(self, stmt, returning_cols): ] return "RETURNING " + ", ".join(columns) - def visit_insert(self, insert_stmt, asfrom=False, **kw): - """ - used to compile expressions. - - this function wraps insert_from_select statements inside - parentheses to be conform with earlier versions of CreateDB. - """ - - self.stack.append( - {'correlate_froms': set(), - "asfrom_froms": set(), - "selectable": insert_stmt}) - - self.isinsert = True - crud_params = crud._get_crud_params(self, insert_stmt, **kw) - - if not crud_params and \ - not self.dialect.supports_default_values and \ - not self.dialect.supports_empty_insert: - raise NotImplementedError( - "The '%s' dialect with current database version settings does " - "not support empty inserts." % self.dialect.name) - - if insert_stmt._has_multi_parameters: - if not self.dialect.supports_multivalues_insert: - raise NotImplementedError( - "The '%s' dialect with current database " - "version settings does not support " - "in-place multirow inserts." % self.dialect.name) - crud_params_single = crud_params[0] - else: - crud_params_single = crud_params - - preparer = self.preparer - supports_default_values = self.dialect.supports_default_values - - text = "INSERT " - - if insert_stmt._prefixes: - text += self._generate_prefixes(insert_stmt, - insert_stmt._prefixes, **kw) - - text += "INTO " - table_text = preparer.format_table(insert_stmt.table) - - if insert_stmt._hints: - dialect_hints = dict([ - (table, hint_text) - for (table, dialect), hint_text in - insert_stmt._hints.items() - if dialect in ('*', self.dialect.name) - ]) - if insert_stmt.table in dialect_hints: - table_text = self.format_from_hint_text( - table_text, - insert_stmt.table, - dialect_hints[insert_stmt.table], - True - ) - - text += table_text - - if crud_params_single or not supports_default_values: - text += " (%s)" % ', '.join([preparer.format_column(c[0]) - for c in crud_params_single]) - - if self.returning or insert_stmt._returning: - self.returning = self.returning or insert_stmt._returning - returning_clause = self.returning_clause( - insert_stmt, self.returning) - - if self.returning_precedes_values: - text += " " + returning_clause - - if insert_stmt.select is not None: - text += " (%s)" % self.process(self._insert_from_select, **kw) - elif not crud_params and supports_default_values: - text += " DEFAULT VALUES" - elif insert_stmt._has_multi_parameters: - text += " VALUES %s" % ( - ", ".join( - "(%s)" % ( - ', '.join(c[1] for c in crud_param_set) - ) - for crud_param_set in crud_params - ) - ) - else: - text += " VALUES (%s)" % \ - ', '.join([c[1] for c in crud_params]) - - if self.returning and not self.returning_precedes_values: - text += " " + returning_clause - - self.stack.pop(-1) - - return text - def visit_update(self, update_stmt, **kw): """ used to compile expressions @@ -392,12 +293,8 @@ def _get_crud_params(compiler, stmt, **kw): # getters - these are normally just column.key, # but in the case of mysql multi-table update, the rules for # .key must conditionally take tablename into account - if SA_VERSION >= SA_1_1: - _column_as_key, _getattr_col_key, _col_bind_name = \ - crud._key_getters_for_crud_column(compiler, stmt) - else: - _column_as_key, _getattr_col_key, _col_bind_name = \ - crud._key_getters_for_crud_column(compiler) + _column_as_key, _getattr_col_key, _col_bind_name = \ + crud._key_getters_for_crud_column(compiler, stmt) # if we have statement parameters - set defaults in the # compiled params diff --git a/src/crate/client/sqlalchemy/dialect.py b/src/crate/client/sqlalchemy/dialect.py index 4cb16e62..42eb4961 100644 --- a/src/crate/client/sqlalchemy/dialect.py +++ b/src/crate/client/sqlalchemy/dialect.py @@ -35,9 +35,6 @@ from crate.client.exceptions import TimezoneUnawareException from .types import Object, ObjectArray -SCHEMA_MIN_VERSION = (0, 57, 0) -TABLE_TYPE_MIN_VERSION = (2, 0, 0) - TYPES_MAP = { "boolean": sqltypes.Boolean, "short": sqltypes.SmallInteger, @@ -231,13 +228,11 @@ def get_schema_names(self, connection, **kw): @reflection.cache def get_table_names(self, connection, schema=None, **kw): - table_filter = "AND table_type = 'BASE TABLE' " \ - if self.server_version_info >= TABLE_TYPE_MIN_VERSION else "" cursor = connection.execute( "SELECT table_name FROM information_schema.tables " - "WHERE {0} = ? {1}" - "ORDER BY table_name ASC, {0} ASC".format(self.schema_column, - table_filter), + "WHERE {0} = ? " + "AND table_type = 'BASE TABLE' " + "ORDER BY table_name ASC, {0} ASC".format(self.schema_column), [schema or self.default_schema_name] ) return [row[0] for row in cursor.fetchall()] @@ -298,9 +293,7 @@ def get_indexes(self, connection, table_name, schema, **kw): @property def schema_column(self): - return "table_schema" \ - if self.server_version_info >= SCHEMA_MIN_VERSION \ - else "schema_name" + return "table_schema" def _create_column_info(self, row): return { diff --git a/src/crate/client/sqlalchemy/doctests/dialect.txt b/src/crate/client/sqlalchemy/doctests/dialect.txt index 97870789..078de090 100644 --- a/src/crate/client/sqlalchemy/doctests/dialect.txt +++ b/src/crate/client/sqlalchemy/doctests/dialect.txt @@ -9,7 +9,7 @@ The initialize method sets the default schema name and version info:: >>> dialect.initialize(connection) - >>> dialect.server_version_info >= (0, 54, 6) + >>> dialect.server_version_info >= (1, 0, 0) True Check if table exists:: diff --git a/src/crate/client/sqlalchemy/sa_version.py b/src/crate/client/sqlalchemy/sa_version.py index f5144136..0973a14a 100644 --- a/src/crate/client/sqlalchemy/sa_version.py +++ b/src/crate/client/sqlalchemy/sa_version.py @@ -23,5 +23,3 @@ from distutils.version import StrictVersion as V SA_VERSION = V(sa.__version__) - -SA_1_1 = V('1.1a0') diff --git a/src/crate/client/sqlalchemy/tests/__init__.py b/src/crate/client/sqlalchemy/tests/__init__.py index 689bd4f6..cee71db8 100644 --- a/src/crate/client/sqlalchemy/tests/__init__.py +++ b/src/crate/client/sqlalchemy/tests/__init__.py @@ -13,7 +13,6 @@ from .array_test import SqlAlchemyArrayTypeTest from .dialect_test import DialectTest from .function_test import FunctionTest -from ..sa_version import SA_1_1, SA_VERSION def test_suite(): @@ -30,6 +29,5 @@ def test_suite(): tests.addTest(makeSuite(SqlAlchemyInsertFromSelectTest)) tests.addTest(makeSuite(DialectTest)) tests.addTest(makeSuite(FunctionTest)) - if SA_VERSION >= SA_1_1: - tests.addTest(makeSuite(SqlAlchemyArrayTypeTest)) + tests.addTest(makeSuite(SqlAlchemyArrayTypeTest)) return tests diff --git a/src/crate/client/sqlalchemy/tests/dialect_test.py b/src/crate/client/sqlalchemy/tests/dialect_test.py index 8198003f..d3811861 100644 --- a/src/crate/client/sqlalchemy/tests/dialect_test.py +++ b/src/crate/client/sqlalchemy/tests/dialect_test.py @@ -67,22 +67,7 @@ class Character(self.base): self.character = Character self.session = Session() - def test_pks_are_retrieved_depending_on_version_set_old(self): - meta = self.character.metadata - insp = inspect(meta.bind) - self.engine.dialect.server_version_info = (0, 54, 0) - - self.fake_cursor.rowcount = 1 - self.fake_cursor.description = ( - ('foo', None, None, None, None, None, None), - ) - self.fake_cursor.fetchone = MagicMock(return_value=[["id", "id2", "id3"]]) - - eq_(insp.get_pk_constraint("characters")['constrained_columns'], {"id", "id2", "id3"}) - self.fake_cursor.fetchone.assert_called_once_with() - in_("information_schema.table_constraints", self.executed_statement) - - def test_pks_are_retrieved_depending_on_version_set_new(self): + def test_primary_keys(self): meta = self.character.metadata insp = inspect(meta.bind) self.engine.dialect.server_version_info = (2, 3, 0) @@ -109,16 +94,4 @@ def test_get_table_names(self): self.engine.dialect.server_version_info = (2, 0, 0) eq_(insp.get_table_names(self.connection, "doc"), ['t1', 't2']) - in_("AND table_type = 'BASE TABLE' ORDER BY", self.executed_statement) - - insp = inspect(self.character.metadata.bind) - self.engine.dialect.server_version_info = (1, 0, 0) - eq_(insp.get_table_names(self.connection, "doc"), - ['t1', 't2']) - in_("WHERE table_schema = ? ORDER BY", self.executed_statement) - - insp = inspect(self.character.metadata.bind) - self.engine.dialect.server_version_info = (0, 56, 0) - eq_(insp.get_table_names(self.connection, "doc"), - ['t1', 't2']) - in_("WHERE schema_name = ? ORDER BY", self.executed_statement) + in_("WHERE table_schema = ? AND table_type = 'BASE TABLE' ORDER BY", self.executed_statement) diff --git a/src/crate/client/sqlalchemy/tests/insert_from_select_test.py b/src/crate/client/sqlalchemy/tests/insert_from_select_test.py index 9a6d7b54..0c5ba73f 100644 --- a/src/crate/client/sqlalchemy/tests/insert_from_select_test.py +++ b/src/crate/client/sqlalchemy/tests/insert_from_select_test.py @@ -77,6 +77,6 @@ def test_insert_from_select_triggered(self): self.session.execute(ins) self.session.commit() self.assertSQL( - "INSERT INTO characters_archive (name, age) (SELECT characters.name, characters.age FROM characters WHERE characters.status = ?)", + "INSERT INTO characters_archive (name, age) SELECT characters.name, characters.age FROM characters WHERE characters.status = ?", ins ) diff --git a/src/crate/client/tests.py b/src/crate/client/tests.py index b2c56750..7b19a7fb 100644 --- a/src/crate/client/tests.py +++ b/src/crate/client/tests.py @@ -75,7 +75,7 @@ class ClientMocked(object): def __init__(self): self.response = {} - self._server_infos = ("http://localhost:4200", "my server", "0.42.0") + self._server_infos = ("http://localhost:4200", "my server", "2.0.0") def sql(self, stmt=None, parameters=None, bulk_parameters=None): return self.response