Skip to content

Commit 2707929

Browse files
committed
Types: Add support for BINARY columns and improve support for FLOATs
1 parent f547ebb commit 2707929

File tree

4 files changed

+74
-0
lines changed

4 files changed

+74
-0
lines changed

src/sqlalchemy_cratedb/compiler.py

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -200,6 +200,9 @@ def visit_unique_constraint(self, constraint, **kw):
200200
)
201201
return
202202

203+
def visit_create_index(self, create, **kw):
204+
return "SELECT 1;"
205+
203206

204207
class CrateTypeCompiler(compiler.GenericTypeCompiler):
205208
def visit_string(self, type_, **kw):
@@ -254,6 +257,30 @@ def visit_TIMESTAMP(self, type_, **kw):
254257
"""
255258
return "TIMESTAMP %s" % ((type_.timezone and "WITH" or "WITHOUT") + " TIME ZONE",)
256259

260+
def visit_BLOB(self, type_, **kw):
261+
return "STRING"
262+
263+
def visit_FLOAT(self, type_, **kw):
264+
"""
265+
From `sqlalchemy.sql.sqltypes.Float`.
266+
267+
When a :paramref:`.Float.precision` is not provided in a
268+
:class:`_types.Float` type some backend may compile this type as
269+
an 8 bytes / 64 bit float datatype. To use a 4 bytes / 32 bit float
270+
datatype a precision <= 24 can usually be provided or the
271+
:class:`_types.REAL` type can be used.
272+
This is known to be the case in the PostgreSQL and MSSQL dialects
273+
that render the type as ``FLOAT`` that's in both an alias of
274+
``DOUBLE PRECISION``. Other third party dialects may have similar
275+
behavior.
276+
"""
277+
if not type_.precision:
278+
return "FLOAT"
279+
elif type_.precision <= 24:
280+
return "FLOAT"
281+
else:
282+
return "DOUBLE"
283+
257284

258285
class CrateCompiler(compiler.SQLCompiler):
259286
def visit_getitem_binary(self, binary, operator, **kw):

src/sqlalchemy_cratedb/dialect.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@
3434
)
3535
from .sa_version import SA_1_4, SA_2_0, SA_VERSION
3636
from .type import FloatVector, ObjectArray, ObjectType
37+
from .type.binary import LargeBinary
3738

3839
TYPES_MAP = {
3940
"boolean": sqltypes.Boolean,
@@ -158,6 +159,7 @@ def process(value):
158159
sqltypes.Date: Date,
159160
sqltypes.DateTime: DateTime,
160161
sqltypes.TIMESTAMP: DateTime,
162+
sqltypes.LargeBinary: LargeBinary,
161163
}
162164

163165

src/sqlalchemy_cratedb/type/__init__.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
from .array import ObjectArray
2+
from .binary import LargeBinary
23
from .geo import Geopoint, Geoshape
34
from .object import ObjectType
45
from .vector import FloatVector, knn_match

src/sqlalchemy_cratedb/type/binary.py

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
import base64
2+
3+
import sqlalchemy as sa
4+
5+
6+
class LargeBinary(sa.String):
7+
"""A type for large binary byte data.
8+
9+
The :class:`.LargeBinary` type corresponds to a large and/or unlengthed
10+
binary type for the target platform, such as BLOB on MySQL and BYTEA for
11+
PostgreSQL. It also handles the necessary conversions for the DBAPI.
12+
13+
"""
14+
15+
__visit_name__ = "large_binary"
16+
17+
def bind_processor(self, dialect):
18+
if dialect.dbapi is None:
19+
return None
20+
21+
# TODO: DBAPIBinary = dialect.dbapi.Binary
22+
23+
def process(value):
24+
if value is not None:
25+
# TODO: return DBAPIBinary(value)
26+
return base64.b64encode(value).decode()
27+
else:
28+
return None
29+
30+
return process
31+
32+
# Python 3 has native bytes() type
33+
# both sqlite3 and pg8000 seem to return it,
34+
# psycopg2 as of 2.5 returns 'memoryview'
35+
def result_processor(self, dialect, coltype):
36+
if dialect.returns_native_bytes:
37+
return None
38+
39+
def process(value):
40+
if value is not None:
41+
return base64.b64decode(value)
42+
return value
43+
44+
return process

0 commit comments

Comments
 (0)