Skip to content

Commit 8f01308

Browse files
committed
Types: Add support for BINARY columns and improve support for FLOATs
1 parent 67b2e32 commit 8f01308

File tree

4 files changed

+75
-1
lines changed

4 files changed

+75
-1
lines changed

src/sqlalchemy_cratedb/compiler.py

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -197,6 +197,9 @@ def visit_unique_constraint(self, constraint, **kw):
197197
"they will be omitted when generating DDL statements.")
198198
return None
199199

200+
def visit_create_index(self, create, **kw):
201+
return "SELECT 1;"
202+
200203

201204
class CrateTypeCompiler(compiler.GenericTypeCompiler):
202205

@@ -245,6 +248,30 @@ def visit_FLOAT_VECTOR(self, type_, **kw):
245248
raise ValueError("FloatVector must be initialized with dimension size")
246249
return f"FLOAT_VECTOR({dimensions})"
247250

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

249276
class CrateCompiler(compiler.SQLCompiler):
250277

src/sqlalchemy_cratedb/dialect.py

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,7 @@
3535
from crate.client.exceptions import TimezoneUnawareException
3636
from .sa_version import SA_VERSION, SA_1_4, SA_2_0
3737
from .type import FloatVector, ObjectArray, ObjectType
38+
from .type.binary import LargeBinary
3839

3940
TYPES_MAP = {
4041
"boolean": sqltypes.Boolean,
@@ -153,7 +154,8 @@ def process(value):
153154

154155
colspecs = {
155156
sqltypes.DateTime: DateTime,
156-
sqltypes.Date: Date
157+
sqltypes.Date: Date,
158+
sqltypes.LargeBinary: LargeBinary,
157159
}
158160

159161

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+
import sqlalchemy as sa
3+
4+
5+
class LargeBinary(sa.String):
6+
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)