Skip to content

Commit 9b8b11f

Browse files
committed
computed columns support
1 parent b04a6c3 commit 9b8b11f

File tree

3 files changed

+86
-1
lines changed

3 files changed

+86
-1
lines changed

sqlalchemy_iris/base.py

Lines changed: 46 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
import re
12
import intersystems_iris.dbapi._DBAPI as dbapi
23
from . import information_schema as ischema
34
from . import types
@@ -461,6 +462,19 @@ def visit_drop_schema(self, drop, **kw):
461462
def visit_check_constraint(self, constraint, **kw):
462463
raise exc.CompileError("Check CONSTRAINT not supported")
463464

465+
def visit_computed_column(self, generated, **kwargs):
466+
text = self.sql_compiler.process(
467+
generated.sqltext, include_table=True, literal_binds=True
468+
)
469+
text = re.sub(r"(?<!')(\b[^\d]\w+\b)", r'{\g<1>}', text)
470+
# text = text.replace("'", '"')
471+
text = 'COMPUTECODE {Set {*} = %s}' % (text,)
472+
if generated.persisted is False:
473+
text += ' CALCULATED'
474+
else:
475+
text += ' COMPUTEONCHANGE ("%%UPDATE")'
476+
return text
477+
464478
def get_column_specification(self, column, **kwargs):
465479

466480
colspec = [
@@ -487,6 +501,9 @@ def get_column_specification(self, column, **kwargs):
487501
if default is not None:
488502
colspec.append("DEFAULT " + default)
489503

504+
if column.computed is not None:
505+
colspec.append(self.process(column.computed))
506+
490507
if not column.nullable:
491508
colspec.append("NOT NULL")
492509

@@ -583,7 +600,6 @@ class IRISDialect(default.DefaultDialect):
583600

584601
def __init__(self, **kwargs):
585602
default.DefaultDialect.__init__(self, **kwargs)
586-
self._auto_parallel = 1
587603

588604
_isolation_lookup = set(
589605
[
@@ -920,7 +936,9 @@ def fkey_rec():
920936

921937
def get_columns(self, connection, table_name, schema=None, **kw):
922938
schema_name = self.get_schema(schema)
939+
tables = ischema.tables
923940
columns = ischema.columns
941+
property = ischema.property
924942

925943
whereclause = sql.and_(
926944
columns.c.table_name == str(table_name),
@@ -938,9 +956,24 @@ def get_columns(self, connection, table_name, schema=None, **kw):
938956
columns.c.column_default,
939957
columns.c.collation_name,
940958
columns.c.auto_increment,
959+
property.c.SqlComputeCode,
960+
property.c.Calculated,
961+
property.c.Transient,
941962
# columns.c.description,
942963
)
943964
.select_from(columns)
965+
.outerjoin(
966+
property,
967+
sql.and_(
968+
property.c.SqlFieldName == columns.c.column_name,
969+
property.c.parent ==
970+
sql.select(tables.c.classname)
971+
.where(
972+
columns.c.table_name == tables.c.table_name,
973+
columns.c.table_schema == tables.c.table_schema,
974+
).scalar_subquery()
975+
),
976+
)
944977
.where(whereclause)
945978
.order_by(columns.c.ordinal_position)
946979
)
@@ -958,6 +991,9 @@ def get_columns(self, connection, table_name, schema=None, **kw):
958991
default = row[columns.c.column_default]
959992
collation = row[columns.c.collation_name]
960993
autoincrement = row[columns.c.auto_increment]
994+
sqlComputeCode = row[property.c.SqlComputeCode]
995+
calculated = row[property.c.Calculated]
996+
transient = row[property.c.Transient]
961997
# description = row[columns.c.description]
962998

963999
coltype = self.ischema_names.get(type_, None)
@@ -997,6 +1033,15 @@ def get_columns(self, connection, table_name, schema=None, **kw):
9971033
"autoincrement": autoincrement,
9981034
# "comment": description,
9991035
}
1036+
if sqlComputeCode and 'set {*} = ' in sqlComputeCode.lower():
1037+
sqltext = sqlComputeCode
1038+
sqltext = sqltext.split(' = ')[1]
1039+
sqltext = re.sub(r"{(\b\w+\b)}", r"\g<1>", sqltext)
1040+
persisted = not calculated and not transient
1041+
cdict['computed'] = {
1042+
"sqltext": sqltext,
1043+
"persisted": persisted,
1044+
}
10001045
cols.append(cdict)
10011046

10021047
if cols:

sqlalchemy_iris/information_schema.py

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,7 @@ def process_result_value(self, value, dialect):
4343
Column("TABLE_SCHEMA", String, key="table_schema"),
4444
Column("TABLE_NAME", String, key="table_name"),
4545
Column("TABLE_TYPE", String, key="table_type"),
46+
Column("CLASSNAME", String, key="classname"),
4647
schema="INFORMATION_SCHEMA",
4748
)
4849

@@ -56,6 +57,8 @@ def process_result_value(self, value, dialect):
5657
Column("ORDINAL_POSITION", Integer, key="ordinal_position"),
5758
Column("COLUMN_DEFAULT", Integer, key="column_default"),
5859
Column("IS_NULLABLE", YESNO, key="is_nullable"),
60+
Column("IS_IDENTITY", YESNO, key="is_identity"),
61+
Column("IS_GENERATED", YESNO, key="is_generated"),
5962
Column("DATA_TYPE", String, key="data_type"),
6063
Column(
6164
"CHARACTER_MAXIMUM_LENGTH", Integer, key="character_maximum_length"
@@ -69,6 +72,17 @@ def process_result_value(self, value, dialect):
6972
Column("DESCIPTION", String, key="desciption"),
7073
schema="INFORMATION_SCHEMA",
7174
)
75+
property = Table(
76+
"PropertyDefinition",
77+
ischema,
78+
Column("parent", String),
79+
Column("SqlFieldName", String),
80+
Column("SqlComputeCode", String),
81+
Column("SqlComputed", Boolean),
82+
Column("Calculated", Boolean),
83+
Column("Transient", Boolean),
84+
schema="%Dictionary",
85+
)
7286

7387
indexes = Table(
7488
"INDEXES",

sqlalchemy_iris/requirements.py

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,3 +39,29 @@ def datetime_historic(self):
3939

4040
return exclusions.open()
4141

42+
@property
43+
def computed_columns(self):
44+
"Supports computed columns"
45+
return exclusions.open()
46+
47+
@property
48+
def computed_columns_stored(self):
49+
"Supports computed columns with `persisted=True`"
50+
return exclusions.open()
51+
52+
@property
53+
def computed_columns_virtual(self):
54+
"Supports computed columns with `persisted=False`"
55+
return exclusions.open()
56+
57+
@property
58+
def computed_columns_default_persisted(self):
59+
"""If the default persistence is virtual or stored when `persisted`
60+
is omitted"""
61+
return exclusions.open()
62+
63+
@property
64+
def computed_columns_reflect_persisted(self):
65+
"""If persistence information is returned by the reflection of
66+
computed columns"""
67+
return exclusions.open()

0 commit comments

Comments
 (0)