diff --git a/CHANGES.txt b/CHANGES.txt index 141b0667..0a7196f9 100644 --- a/CHANGES.txt +++ b/CHANGES.txt @@ -5,6 +5,9 @@ Changes for crate Unreleased ========== +- SQLAlchemy DDL: Allow turning off column store using ``crate_columnstore=False``. + Thanks, @fetzerms. + 2023/04/18 0.31.1 ================= diff --git a/docs/sqlalchemy.rst b/docs/sqlalchemy.rst index 00bf5d00..b16f2abf 100644 --- a/docs/sqlalchemy.rst +++ b/docs/sqlalchemy.rst @@ -205,6 +205,7 @@ system `: ... more_details = sa.Column(types.ObjectArray) ... name_ft = sa.Column(sa.String) ... quote_ft = sa.Column(sa.String) + ... even_more_details = sa.Column(sa.String, crate_columnstore=False) ... ... __mapper_args__ = { ... 'exclude_properties': ['name_ft', 'quote_ft'] @@ -220,6 +221,7 @@ In this example, we: - Use standard SQLAlchemy types for the ``id``, ``name``, and ``quote`` columns - Use ``nullable=False`` to define a ``NOT NULL`` constraint - Disable indexing of the ``name`` column using ``crate_index=False`` +- Disable the columnstore of the ``even_more_details`` column using ``crate_columnstore=False`` - Define a computed column ``name_normalized`` (based on ``name``) that translates into a generated column - Use the `Object`_ extension type for the ``details`` column diff --git a/src/crate/client/sqlalchemy/compiler.py b/src/crate/client/sqlalchemy/compiler.py index 7e6dad7d..efa88d17 100644 --- a/src/crate/client/sqlalchemy/compiler.py +++ b/src/crate/client/sqlalchemy/compiler.py @@ -25,6 +25,7 @@ import sqlalchemy as sa from sqlalchemy.dialects.postgresql.base import PGCompiler from sqlalchemy.sql import compiler +from sqlalchemy.types import String from .types import MutableDict, _Craty, Geopoint, Geoshape from .sa_version import SA_VERSION, SA_1_4 @@ -128,6 +129,14 @@ def get_column_specification(self, column, **kwargs): colspec += " INDEX OFF" + if column.dialect_options['crate'].get('columnstore') is False: + if not isinstance(column.type, (String, )): + raise sa.exc.CompileError( + "Controlling the columnstore is only allowed for STRING columns" + ) + + colspec += " STORAGE WITH (columnstore = false)" + return colspec def visit_computed_column(self, generated): diff --git a/src/crate/client/sqlalchemy/tests/create_table_test.py b/src/crate/client/sqlalchemy/tests/create_table_test.py index 7eca2628..f876655d 100644 --- a/src/crate/client/sqlalchemy/tests/create_table_test.py +++ b/src/crate/client/sqlalchemy/tests/create_table_test.py @@ -232,3 +232,30 @@ class DummyTable(self.Base): a = sa.Column(Geopoint, crate_index=False) with self.assertRaises(sa.exc.CompileError): self.Base.metadata.create_all(bind=self.engine) + + def test_text_column_without_columnstore(self): + class DummyTable(self.Base): + __tablename__ = 't' + pk = sa.Column(sa.String, primary_key=True) + a = sa.Column(sa.String, crate_columnstore=False) + b = sa.Column(sa.String, crate_columnstore=True) + c = sa.Column(sa.String) + + self.Base.metadata.create_all(bind=self.engine) + + fake_cursor.execute.assert_called_with( + ('\nCREATE TABLE t (\n\t' + 'pk STRING NOT NULL, \n\t' + 'a STRING STORAGE WITH (columnstore = false), \n\t' + 'b STRING, \n\t' + 'c STRING, \n\t' + 'PRIMARY KEY (pk)\n)\n\n'), ()) + + def test_non_text_column_without_columnstore(self): + class DummyTable(self.Base): + __tablename__ = 't' + pk = sa.Column(sa.String, primary_key=True) + a = sa.Column(sa.Integer, crate_columnstore=False) + + with self.assertRaises(sa.exc.CompileError): + self.Base.metadata.create_all(bind=self.engine) pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy