Skip to content

Commit 2a34862

Browse files
committed
Types: Add support for BINARY columns and improve support for FLOATs
1 parent 2f08b2a commit 2a34862

File tree

4 files changed

+75
-1
lines changed

4 files changed

+75
-1
lines changed

src/sqlalchemy_cratedb/compiler.py

+27
Original file line numberDiff line numberDiff line change
@@ -196,6 +196,9 @@ def visit_unique_constraint(self, constraint, **kw):
196196
"they will be omitted when generating DDL statements.")
197197
return None
198198

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

200203
class CrateTypeCompiler(compiler.GenericTypeCompiler):
201204

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

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

248275
class CrateCompiler(compiler.SQLCompiler):
249276

src/sqlalchemy_cratedb/dialect.py

+3-1
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@
3434
from crate.client.exceptions import TimezoneUnawareException
3535
from .sa_version import SA_VERSION, SA_1_4, SA_2_0
3636
from .type import FloatVector, ObjectArray, ObjectType
37+
from .type.binary import LargeBinary
3738

3839
TYPES_MAP = {
3940
"boolean": sqltypes.Boolean,
@@ -152,7 +153,8 @@ def process(value):
152153

153154
colspecs = {
154155
sqltypes.DateTime: DateTime,
155-
sqltypes.Date: Date
156+
sqltypes.Date: Date,
157+
sqltypes.LargeBinary: LargeBinary,
156158
}
157159

158160

+1
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

src/sqlalchemy_cratedb/type/binary.py

+44
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)