Skip to content

Commit 04f475d

Browse files
committed
Types: Improve type mappings
- Consequently use upper-case type definitions from `sqlalchemy.types` - Add `timestamp without time zone` types (scalar and array) - On SQLAlchemy 2, map `real` and `double{_precision}` types to the newly introduced `sqltypes.{DOUBLE,DOUBLE_PRECISION}` types All of this is intended to improve reverse type lookups / reflections.
1 parent 0d45175 commit 04f475d

File tree

3 files changed

+51
-32
lines changed

3 files changed

+51
-32
lines changed

docs/inspection-reflection.rst

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -87,10 +87,10 @@ Create a SQLAlchemy table object:
8787
Reflect column data types from the table metadata:
8888

8989
>>> table.columns.get('name')
90-
Column('name', String(), table=<characters>)
90+
Column('name', VARCHAR(), table=<characters>)
9191

9292
>>> table.primary_key
93-
PrimaryKeyConstraint(Column('id', String(), table=<characters>, primary_key=True...
93+
PrimaryKeyConstraint(Column('id', VARCHAR(), table=<characters>, primary_key=True...
9494

9595

9696
CrateDialect

src/sqlalchemy_cratedb/dialect.py

Lines changed: 39 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -36,45 +36,58 @@
3636
from .type import FloatVector, ObjectArray, ObjectType
3737
from .type.binary import LargeBinary
3838

39+
# For SQLAlchemy >= 1.1.
3940
TYPES_MAP = {
40-
"boolean": sqltypes.Boolean,
41-
"short": sqltypes.SmallInteger,
42-
"smallint": sqltypes.SmallInteger,
43-
"timestamp": sqltypes.TIMESTAMP(timezone=False),
41+
"boolean": sqltypes.BOOLEAN,
42+
"short": sqltypes.SMALLINT,
43+
"smallint": sqltypes.SMALLINT,
44+
"timestamp": sqltypes.TIMESTAMP,
4445
"timestamp with time zone": sqltypes.TIMESTAMP(timezone=True),
46+
"timestamp without time zone": sqltypes.TIMESTAMP(timezone=False),
4547
"object": ObjectType,
46-
"integer": sqltypes.Integer,
47-
"long": sqltypes.NUMERIC,
48-
"bigint": sqltypes.NUMERIC,
48+
"object_array": ObjectArray, # TODO: Can this also be improved to use `sqltypes.ARRAY`?
49+
"integer": sqltypes.INTEGER,
50+
"long": sqltypes.BIGINT,
51+
"bigint": sqltypes.BIGINT,
52+
"float": sqltypes.FLOAT,
4953
"double": sqltypes.DECIMAL,
5054
"double precision": sqltypes.DECIMAL,
51-
"object_array": ObjectArray,
52-
"float": sqltypes.Float,
53-
"real": sqltypes.Float,
54-
"string": sqltypes.String,
55-
"text": sqltypes.String,
55+
"real": sqltypes.REAL,
56+
"string": sqltypes.VARCHAR,
57+
"text": sqltypes.VARCHAR,
5658
"float_vector": FloatVector,
5759
}
5860

59-
# Needed for SQLAlchemy >= 1.1.
60-
# TODO: Dissolve.
61+
# For SQLAlchemy >= 1.4.
6162
try:
6263
from sqlalchemy.types import ARRAY
6364

64-
TYPES_MAP["integer_array"] = ARRAY(sqltypes.Integer)
65-
TYPES_MAP["boolean_array"] = ARRAY(sqltypes.Boolean)
66-
TYPES_MAP["short_array"] = ARRAY(sqltypes.SmallInteger)
67-
TYPES_MAP["smallint_array"] = ARRAY(sqltypes.SmallInteger)
65+
TYPES_MAP["integer_array"] = ARRAY(sqltypes.INTEGER)
66+
TYPES_MAP["boolean_array"] = ARRAY(sqltypes.BOOLEAN)
67+
TYPES_MAP["short_array"] = ARRAY(sqltypes.SMALLINT)
68+
TYPES_MAP["smallint_array"] = ARRAY(sqltypes.SMALLINT)
69+
TYPES_MAP["timestamp_array"] = ARRAY(sqltypes.TIMESTAMP)
6870
TYPES_MAP["timestamp_array"] = ARRAY(sqltypes.TIMESTAMP(timezone=False))
6971
TYPES_MAP["timestamp with time zone_array"] = ARRAY(sqltypes.TIMESTAMP(timezone=True))
70-
TYPES_MAP["long_array"] = ARRAY(sqltypes.NUMERIC)
71-
TYPES_MAP["bigint_array"] = ARRAY(sqltypes.NUMERIC)
72-
TYPES_MAP["double_array"] = ARRAY(sqltypes.DECIMAL)
73-
TYPES_MAP["double precision_array"] = ARRAY(sqltypes.DECIMAL)
74-
TYPES_MAP["float_array"] = ARRAY(sqltypes.Float)
75-
TYPES_MAP["real_array"] = ARRAY(sqltypes.Float)
76-
TYPES_MAP["string_array"] = ARRAY(sqltypes.String)
77-
TYPES_MAP["text_array"] = ARRAY(sqltypes.String)
72+
TYPES_MAP["long_array"] = ARRAY(sqltypes.BIGINT)
73+
TYPES_MAP["bigint_array"] = ARRAY(sqltypes.BIGINT)
74+
TYPES_MAP["float_array"] = ARRAY(sqltypes.FLOAT)
75+
TYPES_MAP["real_array"] = ARRAY(sqltypes.REAL)
76+
TYPES_MAP["string_array"] = ARRAY(sqltypes.VARCHAR)
77+
TYPES_MAP["text_array"] = ARRAY(sqltypes.VARCHAR)
78+
except Exception: # noqa: S110
79+
pass
80+
81+
# For SQLAlchemy >= 2.0.
82+
try:
83+
from sqlalchemy.types import DOUBLE, DOUBLE_PRECISION
84+
85+
TYPES_MAP["real"] = DOUBLE
86+
TYPES_MAP["real_array"] = ARRAY(DOUBLE)
87+
TYPES_MAP["double"] = DOUBLE
88+
TYPES_MAP["double_array"] = ARRAY(DOUBLE)
89+
TYPES_MAP["double precision"] = DOUBLE_PRECISION
90+
TYPES_MAP["double precision_array"] = ARRAY(DOUBLE_PRECISION)
7891
except Exception: # noqa: S110
7992
pass
8093

tests/integration.py

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@
3030

3131
from crate.client import connect
3232

33-
from sqlalchemy_cratedb.sa_version import SA_2_0, SA_VERSION
33+
from sqlalchemy_cratedb.sa_version import SA_1_4, SA_2_0, SA_VERSION
3434
from tests.settings import crate_host
3535

3636
log = logging.getLogger()
@@ -179,16 +179,22 @@ def create_test_suite():
179179
"docs/crud.rst",
180180
"docs/working-with-types.rst",
181181
"docs/advanced-querying.rst",
182-
"docs/inspection-reflection.rst",
183182
]
184183

185-
# Don't run DataFrame integration tests on SQLAlchemy 1.3 and Python 3.7.
186-
skip_dataframe = SA_VERSION < SA_2_0 or sys.version_info < (3, 8) or sys.version_info >= (3, 13)
184+
# Don't run DataFrame integration tests on SQLAlchemy 1.4 and earlier, or Python 3.7.
185+
skip_dataframe = SA_VERSION < SA_2_0 or sys.version_info < (3, 8)
187186
if not skip_dataframe:
188187
sqlalchemy_integration_tests += [
189188
"docs/dataframe.rst",
190189
]
191190

191+
# Don't run reflection integration tests on SQLAlchemy 1.3 and earlier and Python 3.10 and 3.11.
192+
skip_reflection = SA_VERSION < SA_1_4 and (3, 10) <= sys.version_info < (3, 12)
193+
if not skip_reflection:
194+
sqlalchemy_integration_tests += [
195+
"docs/inspection-reflection.rst",
196+
]
197+
192198
s = doctest.DocFileSuite(
193199
*sqlalchemy_integration_tests,
194200
module_relative=False,

0 commit comments

Comments
 (0)