Skip to content

Commit

Permalink
Support computed columns in SQLAlchemy ORM
Browse files Browse the repository at this point in the history
  • Loading branch information
hammerhead committed Dec 2, 2022
1 parent ab6f03a commit e79f46f
Show file tree
Hide file tree
Showing 3 changed files with 38 additions and 0 deletions.
1 change: 1 addition & 0 deletions CHANGES.txt
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ Unreleased
that SQL statement clauses like ``LIMIT -1`` could have been generated. Both
PostgreSQL and CrateDB only accept ``LIMIT ALL`` instead.

- Added support for computed columns in the SQLAlchemy ORM

2022/10/10 0.27.2
=================
Expand Down
15 changes: 15 additions & 0 deletions src/crate/client/sqlalchemy/compiler.py
Original file line number Diff line number Diff line change
Expand Up @@ -108,8 +108,23 @@ def get_column_specification(self, column, **kwargs):
colspec = self.preparer.format_column(column) + " " + \
self.dialect.type_compiler.process(column.type)
# TODO: once supported add default / NOT NULL here

if column.computed is not None:
colspec += " " + self.process(column.computed)

return colspec

def visit_computed_column(self, generated):
if generated.persisted is False:
raise sa.exc.CompileError(
"Virtual computed columns are not supported, set "
"'persisted' to None or True"
)

return "GENERATED ALWAYS AS (%s)" % self.sql_compiler.process(
generated.sqltext, include_table=False, literal_binds=True
)

def post_create_table(self, table):
special_options = ''
clustered_options = defaultdict(str)
Expand Down
22 changes: 22 additions & 0 deletions src/crate/client/sqlalchemy/tests/create_table_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -97,6 +97,28 @@ class DummyTable(self.Base):
') CLUSTERED BY (p)\n\n'),
())

def test_with_computed_column(self):
class DummyTable(self.Base):
__tablename__ = 't'
ts = sa.Column(sa.BigInteger, primary_key=True)
p = sa.Column(sa.BigInteger, sa.Computed("date_trunc('day', ts)"))
self.Base.metadata.create_all()
fake_cursor.execute.assert_called_with(
('\nCREATE TABLE t (\n\t'
'ts LONG, \n\t'
'p LONG GENERATED ALWAYS AS (date_trunc(\'day\', ts)), \n\t'
'PRIMARY KEY (ts)\n'
')\n\n'),
())

def test_with_virtual_computed_column(self):
class DummyTable(self.Base):
__tablename__ = 't'
ts = sa.Column(sa.BigInteger, primary_key=True)
p = sa.Column(sa.BigInteger, sa.Computed("date_trunc('day', ts)", persisted=False))
with self.assertRaises(sa.exc.CompileError):
self.Base.metadata.create_all()

def test_with_partitioned_by(self):
class DummyTable(self.Base):
__tablename__ = 't'
Expand Down

0 comments on commit e79f46f

Please sign in to comment.