Skip to content

Commit e0197e5

Browse files
authored
Add mogrify method to cursor to evaluate full query (#28)
* Add mogrify method to cursor to evaluate full query * Use DefaultDialect definition of unicode items * Support JSON type * Allow support multi-value inserts * JSON/VARIANT are same thing * No cascade on Drop Schema
1 parent 020d3de commit e0197e5

File tree

3 files changed

+31
-12
lines changed

3 files changed

+31
-12
lines changed

databend_sqlalchemy/connector.py

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -165,10 +165,15 @@ def description(self):
165165
def close(self):
166166
self._reset_state()
167167

168+
def mogrify(self, query, parameters):
169+
if parameters:
170+
query = query % _escaper.escape_args(parameters)
171+
return query
172+
168173
def execute(self, operation, parameters=None, is_response=True):
169174
"""Prepare and execute a database operation (query or command)."""
170175

171-
#ToDo - Fix this, which is preventing the execution of blank DDL sunch as CREATE INDEX statements which aren't suppoorted
176+
#ToDo - Fix this, which is preventing the execution of blank DDL sunch as CREATE INDEX statements which aren't currently supported
172177
# Seems hard to fix when statements are coming from metadata.create_all()
173178
if operation == "":
174179
return
@@ -179,11 +184,7 @@ def execute(self, operation, parameters=None, is_response=True):
179184
self._uuid = uuid.uuid1()
180185

181186
try:
182-
# operation = operation.replace('%%', '%')
183-
if parameters:
184-
query = operation % _escaper.escape_args(parameters)
185-
else:
186-
query = operation
187+
query = self.mogrify(operation, parameters)
187188
query = query.replace('%%', '%')
188189
if is_response:
189190
rows = self._db.query_iter(query)

databend_sqlalchemy/databend_dialect.py

Lines changed: 17 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -128,6 +128,7 @@ def process(value):
128128
"array": ARRAY,
129129
"map": MAP,
130130
"json": JSON,
131+
"variant": JSON,
131132
"varchar": VARCHAR,
132133
"boolean": BOOLEAN,
133134
"binary": BINARY,
@@ -259,6 +260,9 @@ def visit_NUMERIC(self, type_, **kw):
259260
def visit_NVARCHAR(self, type_, **kw):
260261
return self.visit_VARCHAR(type_, **kw)
261262

263+
def visit_JSON(self, type_, **kw):
264+
return "JSON" # or VARIANT
265+
262266

263267
class DatabendDDLCompiler(compiler.DDLCompiler):
264268

@@ -279,13 +283,16 @@ def visit_create_index(self, create, include_schema=False, include_table_schema=
279283
def visit_drop_index(self, drop, **kw):
280284
return ""
281285

286+
def visit_drop_schema(self, drop, **kw):
287+
# Override - Databend does not support the CASCADE option
288+
schema = self.preparer.format_schema(drop.element)
289+
return "DROP SCHEMA " + schema
290+
282291

283292
class DatabendDialect(default.DefaultDialect):
284293
name = "databend"
285294
driver = "databend"
286295
supports_cast = True
287-
supports_unicode_statements = True
288-
supports_unicode_binds = True
289296
supports_sane_rowcount = False
290297
supports_sane_multi_rowcount = False
291298
supports_native_boolean = True
@@ -294,6 +301,7 @@ class DatabendDialect(default.DefaultDialect):
294301
supports_comments = False
295302
supports_empty_insert = False
296303
supports_is_distinct_from = False
304+
supports_multivalues_insert = True
297305

298306
supports_statement_cache = False
299307
supports_server_side_cursors = True
@@ -302,8 +310,6 @@ class DatabendDialect(default.DefaultDialect):
302310
default_paramstyle = "pyformat"
303311
colspecs = colspecs
304312
ischema_names = ischema_names
305-
convert_unicode = True
306-
returns_unicode_strings = True
307313
returns_native_bytes = True
308314
div_is_floordiv = False
309315
description_encoding = None
@@ -319,10 +325,16 @@ class DatabendDialect(default.DefaultDialect):
319325
_backslash_escapes = True
320326

321327
def __init__(
322-
self, context: Optional[ExecutionContext] = None, *args: Any, **kwargs: Any
328+
self,
329+
context: Optional[ExecutionContext] = None,
330+
json_serializer=None,
331+
json_deserializer=None,
332+
*args: Any, **kwargs: Any
323333
):
324334
super(DatabendDialect, self).__init__(*args, **kwargs)
325335
self.context: Union[ExecutionContext, Dict] = context or {}
336+
self._json_serializer = json_serializer
337+
self._json_deserializer = json_deserializer
326338

327339
@classmethod
328340
def dbapi(cls):

databend_sqlalchemy/requirements.py

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -175,7 +175,7 @@ def precision_generic_float_type(self):
175175
least seven decimal places when using the generic Float type.
176176
177177
"""
178-
return exclusions.closed() # I couldn't get the test for this one working, maybe when the driver returns a python decimal?
178+
return exclusions.closed() #ToDo - I couldn't get the test for this one working, not sure where the issue is - AssertionError: {Decimal('15.7563829')} != {Decimal('15.7563827')}
179179

180180
@property
181181
def array_type(self):
@@ -186,3 +186,9 @@ def float_is_numeric(self):
186186
"""target backend uses Numeric for Float/Dual"""
187187

188188
return exclusions.closed()
189+
190+
@property
191+
def json_type(self):
192+
"""target platform implements a native JSON type."""
193+
194+
return exclusions.closed() #ToDo - This could be enabled if primary keys were supported

0 commit comments

Comments
 (0)