Skip to content

Commit e336735

Browse files
author
Ilya Gurov
authored
fix: NOT NULL computed column creation failure (#173)
1 parent 33c86e8 commit e336735

File tree

2 files changed

+50
-0
lines changed

2 files changed

+50
-0
lines changed

google/cloud/sqlalchemy_spanner/sqlalchemy_spanner.py

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -324,6 +324,29 @@ def limit_clause(self, select, **kw):
324324
class SpannerDDLCompiler(DDLCompiler):
325325
"""Spanner DDL statements compiler."""
326326

327+
def get_column_specification(self, column, **kwargs):
328+
"""Build new column specifications.
329+
330+
Overridden to move the NOT NULL statement to front
331+
of a computed column expression definitions.
332+
"""
333+
colspec = (
334+
self.preparer.format_column(column)
335+
+ " "
336+
+ self.dialect.type_compiler.process(column.type, type_expression=column)
337+
)
338+
default = self.get_column_default_string(column)
339+
if default is not None:
340+
colspec += " DEFAULT " + default
341+
342+
if not column.nullable:
343+
colspec += " NOT NULL"
344+
345+
if column.computed is not None:
346+
colspec += " " + self.process(column.computed)
347+
348+
return colspec
349+
327350
def visit_computed_column(self, generated, **kw):
328351
"""Computed column operator."""
329352
text = "AS (%s) STORED" % self.sql_compiler.process(

test/test_suite.py

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1753,6 +1753,33 @@ def test_get_column_returns_computed(self):
17531753
is_true("sqltext" in compData["computed"])
17541754
eq_(self.normalize(compData["computed"]["sqltext"]), "normal+42")
17551755

1756+
def test_create_not_null_computed_column(self):
1757+
"""
1758+
SPANNER TEST:
1759+
1760+
Check that on creating a computed column with a NOT NULL
1761+
clause the clause is set in front of the computed column
1762+
statement definition and doesn't cause failures.
1763+
"""
1764+
engine = create_engine(get_db_url())
1765+
metadata = MetaData(bind=engine)
1766+
1767+
Table(
1768+
"Singers",
1769+
metadata,
1770+
Column("SingerId", String(36), primary_key=True, nullable=False),
1771+
Column("FirstName", String(200)),
1772+
Column("LastName", String(200), nullable=False),
1773+
Column(
1774+
"FullName",
1775+
String(400),
1776+
Computed("COALESCE(FirstName || ' ', '') || LastName"),
1777+
nullable=False,
1778+
),
1779+
)
1780+
1781+
metadata.create_all(engine)
1782+
17561783

17571784
@pytest.mark.skipif(
17581785
bool(os.environ.get("SPANNER_EMULATOR_HOST")), reason="Skipped on emulator"

0 commit comments

Comments
 (0)