crate 0.29.0__py2.py3-none-any.whl → 0.30.1__py2.py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- crate/client/__init__.py +1 -1
- crate/client/_pep440.py +501 -0
- crate/client/connection.py +3 -3
- crate/client/sqlalchemy/__init__.py +24 -0
- crate/client/sqlalchemy/compat/__init__.py +0 -0
- crate/client/sqlalchemy/compat/api13.py +156 -0
- crate/client/sqlalchemy/compat/core10.py +264 -0
- crate/client/sqlalchemy/compat/core14.py +359 -0
- crate/client/sqlalchemy/compat/core20.py +447 -0
- crate/client/sqlalchemy/compiler.py +1 -481
- crate/client/sqlalchemy/dialect.py +32 -17
- crate/client/sqlalchemy/sa_version.py +4 -3
- crate/client/sqlalchemy/tests/__init__.py +17 -6
- crate/client/sqlalchemy/tests/array_test.py +6 -3
- crate/client/sqlalchemy/tests/bulk_test.py +7 -4
- crate/client/sqlalchemy/tests/compiler_test.py +10 -9
- crate/client/sqlalchemy/tests/connection_test.py +25 -11
- crate/client/sqlalchemy/tests/create_table_test.py +19 -16
- crate/client/sqlalchemy/tests/datetime_test.py +6 -3
- crate/client/sqlalchemy/tests/dialect_test.py +42 -13
- crate/client/sqlalchemy/tests/dict_test.py +17 -13
- crate/client/sqlalchemy/tests/function_test.py +6 -3
- crate/client/sqlalchemy/tests/insert_from_select_test.py +9 -6
- crate/client/sqlalchemy/tests/match_test.py +6 -3
- crate/client/sqlalchemy/tests/update_test.py +6 -3
- crate/client/sqlalchemy/tests/warnings_test.py +33 -0
- crate/client/test_connection.py +25 -0
- crate/client/tests.py +98 -119
- crate/testing/layer.py +1 -1
- crate/testing/settings.py +51 -0
- crate/testing/test_layer.py +188 -2
- crate/testing/tests.py +2 -38
- crate/testing/util.py +20 -0
- {crate-0.29.0.dist-info → crate-0.30.1.dist-info}/METADATA +10 -8
- crate-0.30.1.dist-info/RECORD +53 -0
- crate-0.29.0.dist-info/RECORD +0 -44
- /crate-0.29.0-py3.9-nspkg.pth → /crate-0.30.1-py3.9-nspkg.pth +0 -0
- {crate-0.29.0.dist-info → crate-0.30.1.dist-info}/LICENSE +0 -0
- {crate-0.29.0.dist-info → crate-0.30.1.dist-info}/NOTICE +0 -0
- {crate-0.29.0.dist-info → crate-0.30.1.dist-info}/WHEEL +0 -0
- {crate-0.29.0.dist-info → crate-0.30.1.dist-info}/entry_points.txt +0 -0
- {crate-0.29.0.dist-info → crate-0.30.1.dist-info}/namespace_packages.txt +0 -0
- {crate-0.29.0.dist-info → crate-0.30.1.dist-info}/top_level.txt +0 -0
@@ -24,7 +24,7 @@ from collections import defaultdict
|
|
24
24
|
|
25
25
|
import sqlalchemy as sa
|
26
26
|
from sqlalchemy.dialects.postgresql.base import PGCompiler
|
27
|
-
from sqlalchemy.sql import compiler
|
27
|
+
from sqlalchemy.sql import compiler
|
28
28
|
from .types import MutableDict, _Craty, Geopoint, Geoshape
|
29
29
|
from .sa_version import SA_VERSION, SA_1_4
|
30
30
|
|
@@ -208,8 +208,6 @@ class CrateTypeCompiler(compiler.GenericTypeCompiler):
|
|
208
208
|
|
209
209
|
class CrateCompiler(compiler.SQLCompiler):
|
210
210
|
|
211
|
-
prefetch = []
|
212
|
-
|
213
211
|
def visit_getitem_binary(self, binary, operator, **kw):
|
214
212
|
return "{0}['{1}']".format(
|
215
213
|
self.process(binary.left, **kw),
|
@@ -223,486 +221,8 @@ class CrateCompiler(compiler.SQLCompiler):
|
|
223
221
|
self.process(element.right, **kw)
|
224
222
|
)
|
225
223
|
|
226
|
-
def returning_clause(self, stmt, returning_cols):
|
227
|
-
columns = [
|
228
|
-
self._label_select_column(None, c, True, False, {})
|
229
|
-
for c in sa.sql.expression._select_iterables(returning_cols)
|
230
|
-
]
|
231
|
-
return "RETURNING " + ", ".join(columns)
|
232
|
-
|
233
|
-
def visit_update(self, update_stmt, **kw):
|
234
|
-
"""
|
235
|
-
used to compile <sql.expression.Update> expressions
|
236
|
-
Parts are taken from the SQLCompiler base class.
|
237
|
-
"""
|
238
|
-
|
239
|
-
if SA_VERSION >= SA_1_4:
|
240
|
-
return self.visit_update_14(update_stmt, **kw)
|
241
|
-
|
242
|
-
if not update_stmt.parameters and \
|
243
|
-
not hasattr(update_stmt, '_crate_specific'):
|
244
|
-
return super(CrateCompiler, self).visit_update(update_stmt, **kw)
|
245
|
-
|
246
|
-
self.isupdate = True
|
247
|
-
|
248
|
-
extra_froms = update_stmt._extra_froms
|
249
|
-
|
250
|
-
text = 'UPDATE '
|
251
|
-
|
252
|
-
if update_stmt._prefixes:
|
253
|
-
text += self._generate_prefixes(update_stmt,
|
254
|
-
update_stmt._prefixes, **kw)
|
255
|
-
|
256
|
-
table_text = self.update_tables_clause(update_stmt, update_stmt.table,
|
257
|
-
extra_froms, **kw)
|
258
|
-
|
259
|
-
dialect_hints = None
|
260
|
-
if update_stmt._hints:
|
261
|
-
dialect_hints, table_text = self._setup_crud_hints(
|
262
|
-
update_stmt, table_text
|
263
|
-
)
|
264
|
-
|
265
|
-
# CrateDB patch.
|
266
|
-
crud_params = self._get_crud_params(update_stmt, **kw)
|
267
|
-
|
268
|
-
text += table_text
|
269
|
-
|
270
|
-
text += ' SET '
|
271
|
-
|
272
|
-
# CrateDB patch begin.
|
273
|
-
include_table = extra_froms and \
|
274
|
-
self.render_table_with_column_in_update_from
|
275
|
-
|
276
|
-
set_clauses = []
|
277
|
-
|
278
|
-
for k, v in crud_params:
|
279
|
-
clause = k._compiler_dispatch(self,
|
280
|
-
include_table=include_table) + \
|
281
|
-
' = ' + v
|
282
|
-
set_clauses.append(clause)
|
283
|
-
|
284
|
-
for k, v in update_stmt.parameters.items():
|
285
|
-
if isinstance(k, str) and '[' in k:
|
286
|
-
bindparam = sa.sql.bindparam(k, v)
|
287
|
-
set_clauses.append(k + ' = ' + self.process(bindparam))
|
288
|
-
|
289
|
-
text += ', '.join(set_clauses)
|
290
|
-
# CrateDB patch end.
|
291
|
-
|
292
|
-
if self.returning or update_stmt._returning:
|
293
|
-
if not self.returning:
|
294
|
-
self.returning = update_stmt._returning
|
295
|
-
if self.returning_precedes_values:
|
296
|
-
text += " " + self.returning_clause(
|
297
|
-
update_stmt, self.returning)
|
298
|
-
|
299
|
-
if extra_froms:
|
300
|
-
extra_from_text = self.update_from_clause(
|
301
|
-
update_stmt,
|
302
|
-
update_stmt.table,
|
303
|
-
extra_froms,
|
304
|
-
dialect_hints,
|
305
|
-
**kw)
|
306
|
-
if extra_from_text:
|
307
|
-
text += " " + extra_from_text
|
308
|
-
|
309
|
-
if update_stmt._whereclause is not None:
|
310
|
-
t = self.process(update_stmt._whereclause)
|
311
|
-
if t:
|
312
|
-
text += " WHERE " + t
|
313
|
-
|
314
|
-
limit_clause = self.update_limit_clause(update_stmt)
|
315
|
-
if limit_clause:
|
316
|
-
text += " " + limit_clause
|
317
|
-
|
318
|
-
if self.returning and not self.returning_precedes_values:
|
319
|
-
text += " " + self.returning_clause(
|
320
|
-
update_stmt, self.returning)
|
321
|
-
|
322
|
-
return text
|
323
|
-
|
324
224
|
def limit_clause(self, select, **kw):
|
325
225
|
"""
|
326
226
|
Generate OFFSET / LIMIT clause, PostgreSQL-compatible.
|
327
227
|
"""
|
328
228
|
return PGCompiler.limit_clause(self, select, **kw)
|
329
|
-
|
330
|
-
def _get_crud_params(compiler, stmt, **kw):
|
331
|
-
""" extract values from crud parameters
|
332
|
-
taken from SQLAlchemy's crud module (since 1.0.x) and
|
333
|
-
adapted for Crate dialect"""
|
334
|
-
|
335
|
-
compiler.postfetch = []
|
336
|
-
compiler.insert_prefetch = []
|
337
|
-
compiler.update_prefetch = []
|
338
|
-
compiler.returning = []
|
339
|
-
|
340
|
-
# no parameters in the statement, no parameters in the
|
341
|
-
# compiled params - return binds for all columns
|
342
|
-
if compiler.column_keys is None and stmt.parameters is None:
|
343
|
-
return [(c, crud._create_bind_param(compiler, c, None,
|
344
|
-
required=True))
|
345
|
-
for c in stmt.table.columns]
|
346
|
-
|
347
|
-
if stmt._has_multi_parameters:
|
348
|
-
stmt_parameters = stmt.parameters[0]
|
349
|
-
else:
|
350
|
-
stmt_parameters = stmt.parameters
|
351
|
-
|
352
|
-
# getters - these are normally just column.key,
|
353
|
-
# but in the case of mysql multi-table update, the rules for
|
354
|
-
# .key must conditionally take tablename into account
|
355
|
-
_column_as_key, _getattr_col_key, _col_bind_name = \
|
356
|
-
crud._key_getters_for_crud_column(compiler, stmt)
|
357
|
-
|
358
|
-
# if we have statement parameters - set defaults in the
|
359
|
-
# compiled params
|
360
|
-
if compiler.column_keys is None:
|
361
|
-
parameters = {}
|
362
|
-
else:
|
363
|
-
parameters = dict((_column_as_key(key), crud.REQUIRED)
|
364
|
-
for key in compiler.column_keys
|
365
|
-
if not stmt_parameters or
|
366
|
-
key not in stmt_parameters)
|
367
|
-
|
368
|
-
# create a list of column assignment clauses as tuples
|
369
|
-
values = []
|
370
|
-
|
371
|
-
if stmt_parameters is not None:
|
372
|
-
crud._get_stmt_parameters_params(
|
373
|
-
compiler,
|
374
|
-
parameters, stmt_parameters, _column_as_key, values, kw)
|
375
|
-
|
376
|
-
check_columns = {}
|
377
|
-
|
378
|
-
crud._scan_cols(compiler, stmt, parameters,
|
379
|
-
_getattr_col_key, _column_as_key,
|
380
|
-
_col_bind_name, check_columns, values, kw)
|
381
|
-
|
382
|
-
if stmt._has_multi_parameters:
|
383
|
-
values = crud._extend_values_for_multiparams(compiler, stmt,
|
384
|
-
values, kw)
|
385
|
-
|
386
|
-
return values
|
387
|
-
|
388
|
-
def visit_update_14(self, update_stmt, **kw):
|
389
|
-
|
390
|
-
compile_state = update_stmt._compile_state_factory(
|
391
|
-
update_stmt, self, **kw
|
392
|
-
)
|
393
|
-
update_stmt = compile_state.statement
|
394
|
-
|
395
|
-
toplevel = not self.stack
|
396
|
-
if toplevel:
|
397
|
-
self.isupdate = True
|
398
|
-
if not self.compile_state:
|
399
|
-
self.compile_state = compile_state
|
400
|
-
|
401
|
-
extra_froms = compile_state._extra_froms
|
402
|
-
is_multitable = bool(extra_froms)
|
403
|
-
|
404
|
-
if is_multitable:
|
405
|
-
# main table might be a JOIN
|
406
|
-
main_froms = set(selectable._from_objects(update_stmt.table))
|
407
|
-
render_extra_froms = [
|
408
|
-
f for f in extra_froms if f not in main_froms
|
409
|
-
]
|
410
|
-
correlate_froms = main_froms.union(extra_froms)
|
411
|
-
else:
|
412
|
-
render_extra_froms = []
|
413
|
-
correlate_froms = {update_stmt.table}
|
414
|
-
|
415
|
-
self.stack.append(
|
416
|
-
{
|
417
|
-
"correlate_froms": correlate_froms,
|
418
|
-
"asfrom_froms": correlate_froms,
|
419
|
-
"selectable": update_stmt,
|
420
|
-
}
|
421
|
-
)
|
422
|
-
|
423
|
-
text = "UPDATE "
|
424
|
-
|
425
|
-
if update_stmt._prefixes:
|
426
|
-
text += self._generate_prefixes(
|
427
|
-
update_stmt, update_stmt._prefixes, **kw
|
428
|
-
)
|
429
|
-
|
430
|
-
table_text = self.update_tables_clause(
|
431
|
-
update_stmt, update_stmt.table, render_extra_froms, **kw
|
432
|
-
)
|
433
|
-
|
434
|
-
# CrateDB patch.
|
435
|
-
crud_params = _get_crud_params_14(
|
436
|
-
self, update_stmt, compile_state, **kw
|
437
|
-
)
|
438
|
-
|
439
|
-
if update_stmt._hints:
|
440
|
-
dialect_hints, table_text = self._setup_crud_hints(
|
441
|
-
update_stmt, table_text
|
442
|
-
)
|
443
|
-
else:
|
444
|
-
dialect_hints = None
|
445
|
-
|
446
|
-
if update_stmt._independent_ctes:
|
447
|
-
for cte in update_stmt._independent_ctes:
|
448
|
-
cte._compiler_dispatch(self, **kw)
|
449
|
-
|
450
|
-
text += table_text
|
451
|
-
|
452
|
-
text += " SET "
|
453
|
-
|
454
|
-
# CrateDB patch begin.
|
455
|
-
include_table = extra_froms and \
|
456
|
-
self.render_table_with_column_in_update_from
|
457
|
-
|
458
|
-
set_clauses = []
|
459
|
-
|
460
|
-
for c, expr, value in crud_params:
|
461
|
-
key = c._compiler_dispatch(self, include_table=include_table)
|
462
|
-
clause = key + ' = ' + value
|
463
|
-
set_clauses.append(clause)
|
464
|
-
|
465
|
-
for k, v in compile_state._dict_parameters.items():
|
466
|
-
if isinstance(k, str) and '[' in k:
|
467
|
-
bindparam = sa.sql.bindparam(k, v)
|
468
|
-
clause = k + ' = ' + self.process(bindparam)
|
469
|
-
set_clauses.append(clause)
|
470
|
-
|
471
|
-
text += ', '.join(set_clauses)
|
472
|
-
# CrateDB patch end.
|
473
|
-
|
474
|
-
if self.returning or update_stmt._returning:
|
475
|
-
if self.returning_precedes_values:
|
476
|
-
text += " " + self.returning_clause(
|
477
|
-
update_stmt, self.returning or update_stmt._returning
|
478
|
-
)
|
479
|
-
|
480
|
-
if extra_froms:
|
481
|
-
extra_from_text = self.update_from_clause(
|
482
|
-
update_stmt,
|
483
|
-
update_stmt.table,
|
484
|
-
render_extra_froms,
|
485
|
-
dialect_hints,
|
486
|
-
**kw
|
487
|
-
)
|
488
|
-
if extra_from_text:
|
489
|
-
text += " " + extra_from_text
|
490
|
-
|
491
|
-
if update_stmt._where_criteria:
|
492
|
-
t = self._generate_delimited_and_list(
|
493
|
-
update_stmt._where_criteria, **kw
|
494
|
-
)
|
495
|
-
if t:
|
496
|
-
text += " WHERE " + t
|
497
|
-
|
498
|
-
limit_clause = self.update_limit_clause(update_stmt)
|
499
|
-
if limit_clause:
|
500
|
-
text += " " + limit_clause
|
501
|
-
|
502
|
-
if (
|
503
|
-
self.returning or update_stmt._returning
|
504
|
-
) and not self.returning_precedes_values:
|
505
|
-
text += " " + self.returning_clause(
|
506
|
-
update_stmt, self.returning or update_stmt._returning
|
507
|
-
)
|
508
|
-
|
509
|
-
if self.ctes:
|
510
|
-
nesting_level = len(self.stack) if not toplevel else None
|
511
|
-
text = self._render_cte_clause(nesting_level=nesting_level) + text
|
512
|
-
|
513
|
-
self.stack.pop(-1)
|
514
|
-
|
515
|
-
return text
|
516
|
-
|
517
|
-
|
518
|
-
def _get_crud_params_14(compiler, stmt, compile_state, **kw):
|
519
|
-
"""create a set of tuples representing column/string pairs for use
|
520
|
-
in an INSERT or UPDATE statement.
|
521
|
-
|
522
|
-
Also generates the Compiled object's postfetch, prefetch, and
|
523
|
-
returning column collections, used for default handling and ultimately
|
524
|
-
populating the CursorResult's prefetch_cols() and postfetch_cols()
|
525
|
-
collections.
|
526
|
-
|
527
|
-
"""
|
528
|
-
from sqlalchemy.sql.crud import _key_getters_for_crud_column
|
529
|
-
from sqlalchemy.sql.crud import _create_bind_param
|
530
|
-
from sqlalchemy.sql.crud import REQUIRED
|
531
|
-
from sqlalchemy.sql.crud import _get_stmt_parameter_tuples_params
|
532
|
-
from sqlalchemy.sql.crud import _get_update_multitable_params
|
533
|
-
from sqlalchemy.sql.crud import _scan_insert_from_select_cols
|
534
|
-
from sqlalchemy.sql.crud import _scan_cols
|
535
|
-
from sqlalchemy import exc # noqa: F401
|
536
|
-
from sqlalchemy.sql.crud import _extend_values_for_multiparams
|
537
|
-
|
538
|
-
compiler.postfetch = []
|
539
|
-
compiler.insert_prefetch = []
|
540
|
-
compiler.update_prefetch = []
|
541
|
-
compiler.returning = []
|
542
|
-
|
543
|
-
# getters - these are normally just column.key,
|
544
|
-
# but in the case of mysql multi-table update, the rules for
|
545
|
-
# .key must conditionally take tablename into account
|
546
|
-
(
|
547
|
-
_column_as_key,
|
548
|
-
_getattr_col_key,
|
549
|
-
_col_bind_name,
|
550
|
-
) = getters = _key_getters_for_crud_column(compiler, stmt, compile_state)
|
551
|
-
|
552
|
-
compiler._key_getters_for_crud_column = getters
|
553
|
-
|
554
|
-
# no parameters in the statement, no parameters in the
|
555
|
-
# compiled params - return binds for all columns
|
556
|
-
if compiler.column_keys is None and compile_state._no_parameters:
|
557
|
-
return [
|
558
|
-
(
|
559
|
-
c,
|
560
|
-
compiler.preparer.format_column(c),
|
561
|
-
_create_bind_param(compiler, c, None, required=True),
|
562
|
-
)
|
563
|
-
for c in stmt.table.columns
|
564
|
-
]
|
565
|
-
|
566
|
-
if compile_state._has_multi_parameters:
|
567
|
-
spd = compile_state._multi_parameters[0]
|
568
|
-
stmt_parameter_tuples = list(spd.items())
|
569
|
-
elif compile_state._ordered_values:
|
570
|
-
spd = compile_state._dict_parameters
|
571
|
-
stmt_parameter_tuples = compile_state._ordered_values
|
572
|
-
elif compile_state._dict_parameters:
|
573
|
-
spd = compile_state._dict_parameters
|
574
|
-
stmt_parameter_tuples = list(spd.items())
|
575
|
-
else:
|
576
|
-
stmt_parameter_tuples = spd = None
|
577
|
-
|
578
|
-
# if we have statement parameters - set defaults in the
|
579
|
-
# compiled params
|
580
|
-
if compiler.column_keys is None:
|
581
|
-
parameters = {}
|
582
|
-
elif stmt_parameter_tuples:
|
583
|
-
parameters = dict(
|
584
|
-
(_column_as_key(key), REQUIRED)
|
585
|
-
for key in compiler.column_keys
|
586
|
-
if key not in spd
|
587
|
-
)
|
588
|
-
else:
|
589
|
-
parameters = dict(
|
590
|
-
(_column_as_key(key), REQUIRED) for key in compiler.column_keys
|
591
|
-
)
|
592
|
-
|
593
|
-
# create a list of column assignment clauses as tuples
|
594
|
-
values = []
|
595
|
-
|
596
|
-
if stmt_parameter_tuples is not None:
|
597
|
-
_get_stmt_parameter_tuples_params(
|
598
|
-
compiler,
|
599
|
-
compile_state,
|
600
|
-
parameters,
|
601
|
-
stmt_parameter_tuples,
|
602
|
-
_column_as_key,
|
603
|
-
values,
|
604
|
-
kw,
|
605
|
-
)
|
606
|
-
|
607
|
-
check_columns = {}
|
608
|
-
|
609
|
-
# special logic that only occurs for multi-table UPDATE
|
610
|
-
# statements
|
611
|
-
if compile_state.isupdate and compile_state.is_multitable:
|
612
|
-
_get_update_multitable_params(
|
613
|
-
compiler,
|
614
|
-
stmt,
|
615
|
-
compile_state,
|
616
|
-
stmt_parameter_tuples,
|
617
|
-
check_columns,
|
618
|
-
_col_bind_name,
|
619
|
-
_getattr_col_key,
|
620
|
-
values,
|
621
|
-
kw,
|
622
|
-
)
|
623
|
-
|
624
|
-
if compile_state.isinsert and stmt._select_names:
|
625
|
-
_scan_insert_from_select_cols(
|
626
|
-
compiler,
|
627
|
-
stmt,
|
628
|
-
compile_state,
|
629
|
-
parameters,
|
630
|
-
_getattr_col_key,
|
631
|
-
_column_as_key,
|
632
|
-
_col_bind_name,
|
633
|
-
check_columns,
|
634
|
-
values,
|
635
|
-
kw,
|
636
|
-
)
|
637
|
-
else:
|
638
|
-
_scan_cols(
|
639
|
-
compiler,
|
640
|
-
stmt,
|
641
|
-
compile_state,
|
642
|
-
parameters,
|
643
|
-
_getattr_col_key,
|
644
|
-
_column_as_key,
|
645
|
-
_col_bind_name,
|
646
|
-
check_columns,
|
647
|
-
values,
|
648
|
-
kw,
|
649
|
-
)
|
650
|
-
|
651
|
-
# CrateDB patch.
|
652
|
-
#
|
653
|
-
# This sanity check performed by SQLAlchemy currently needs to be
|
654
|
-
# deactivated in order to satisfy the rewriting logic of the CrateDB
|
655
|
-
# dialect in `rewrite_update` and `visit_update`.
|
656
|
-
#
|
657
|
-
# It can be quickly reproduced by activating this section and running the
|
658
|
-
# test cases::
|
659
|
-
#
|
660
|
-
# ./bin/test -vvvv -t dict_test
|
661
|
-
#
|
662
|
-
# That croaks like::
|
663
|
-
#
|
664
|
-
# sqlalchemy.exc.CompileError: Unconsumed column names: characters_name, data['nested']
|
665
|
-
#
|
666
|
-
# TODO: Investigate why this is actually happening and eventually mitigate
|
667
|
-
# the root cause.
|
668
|
-
"""
|
669
|
-
if parameters and stmt_parameter_tuples:
|
670
|
-
check = (
|
671
|
-
set(parameters)
|
672
|
-
.intersection(_column_as_key(k) for k, v in stmt_parameter_tuples)
|
673
|
-
.difference(check_columns)
|
674
|
-
)
|
675
|
-
if check:
|
676
|
-
raise exc.CompileError(
|
677
|
-
"Unconsumed column names: %s"
|
678
|
-
% (", ".join("%s" % (c,) for c in check))
|
679
|
-
)
|
680
|
-
"""
|
681
|
-
|
682
|
-
if compile_state._has_multi_parameters:
|
683
|
-
values = _extend_values_for_multiparams(
|
684
|
-
compiler,
|
685
|
-
stmt,
|
686
|
-
compile_state,
|
687
|
-
values,
|
688
|
-
_column_as_key,
|
689
|
-
kw,
|
690
|
-
)
|
691
|
-
elif (
|
692
|
-
not values
|
693
|
-
and compiler.for_executemany # noqa: W503
|
694
|
-
and compiler.dialect.supports_default_metavalue # noqa: W503
|
695
|
-
):
|
696
|
-
# convert an "INSERT DEFAULT VALUES"
|
697
|
-
# into INSERT (firstcol) VALUES (DEFAULT) which can be turned
|
698
|
-
# into an in-place multi values. This supports
|
699
|
-
# insert_executemany_returning mode :)
|
700
|
-
values = [
|
701
|
-
(
|
702
|
-
stmt.table.columns[0],
|
703
|
-
compiler.preparer.format_column(stmt.table.columns[0]),
|
704
|
-
"DEFAULT",
|
705
|
-
)
|
706
|
-
]
|
707
|
-
|
708
|
-
return values
|
@@ -28,11 +28,11 @@ from sqlalchemy.sql import functions
|
|
28
28
|
from sqlalchemy.util import asbool, to_list
|
29
29
|
|
30
30
|
from .compiler import (
|
31
|
-
CrateCompiler,
|
32
31
|
CrateTypeCompiler,
|
33
32
|
CrateDDLCompiler
|
34
33
|
)
|
35
34
|
from crate.client.exceptions import TimezoneUnawareException
|
35
|
+
from .sa_version import SA_VERSION, SA_1_4, SA_2_0
|
36
36
|
from .types import Object, ObjectArray
|
37
37
|
|
38
38
|
TYPES_MAP = {
|
@@ -155,10 +155,21 @@ colspecs = {
|
|
155
155
|
}
|
156
156
|
|
157
157
|
|
158
|
+
if SA_VERSION >= SA_2_0:
|
159
|
+
from .compat.core20 import CrateCompilerSA20
|
160
|
+
statement_compiler = CrateCompilerSA20
|
161
|
+
elif SA_VERSION >= SA_1_4:
|
162
|
+
from .compat.core14 import CrateCompilerSA14
|
163
|
+
statement_compiler = CrateCompilerSA14
|
164
|
+
else:
|
165
|
+
from .compat.core10 import CrateCompilerSA10
|
166
|
+
statement_compiler = CrateCompilerSA10
|
167
|
+
|
168
|
+
|
158
169
|
class CrateDialect(default.DefaultDialect):
|
159
170
|
name = 'crate'
|
160
171
|
driver = 'crate-python'
|
161
|
-
statement_compiler =
|
172
|
+
statement_compiler = statement_compiler
|
162
173
|
ddl_compiler = CrateDDLCompiler
|
163
174
|
type_compiler = CrateTypeCompiler
|
164
175
|
supports_native_boolean = True
|
@@ -208,19 +219,23 @@ class CrateDialect(default.DefaultDialect):
|
|
208
219
|
return tuple(connection.connection.lowest_server_version.version)
|
209
220
|
|
210
221
|
@classmethod
|
211
|
-
def
|
222
|
+
def import_dbapi(cls):
|
212
223
|
from crate import client
|
213
224
|
return client
|
214
225
|
|
215
|
-
|
216
|
-
|
226
|
+
@classmethod
|
227
|
+
def dbapi(cls):
|
228
|
+
return cls.import_dbapi()
|
229
|
+
|
230
|
+
def has_schema(self, connection, schema, **kw):
|
231
|
+
return schema in self.get_schema_names(connection, **kw)
|
217
232
|
|
218
|
-
def has_table(self, connection, table_name, schema=None):
|
219
|
-
return table_name in self.get_table_names(connection, schema=schema)
|
233
|
+
def has_table(self, connection, table_name, schema=None, **kw):
|
234
|
+
return table_name in self.get_table_names(connection, schema=schema, **kw)
|
220
235
|
|
221
236
|
@reflection.cache
|
222
237
|
def get_schema_names(self, connection, **kw):
|
223
|
-
cursor = connection.
|
238
|
+
cursor = connection.exec_driver_sql(
|
224
239
|
"select schema_name "
|
225
240
|
"from information_schema.schemata "
|
226
241
|
"order by schema_name asc"
|
@@ -229,21 +244,21 @@ class CrateDialect(default.DefaultDialect):
|
|
229
244
|
|
230
245
|
@reflection.cache
|
231
246
|
def get_table_names(self, connection, schema=None, **kw):
|
232
|
-
cursor = connection.
|
247
|
+
cursor = connection.exec_driver_sql(
|
233
248
|
"SELECT table_name FROM information_schema.tables "
|
234
249
|
"WHERE {0} = ? "
|
235
250
|
"AND table_type = 'BASE TABLE' "
|
236
251
|
"ORDER BY table_name ASC, {0} ASC".format(self.schema_column),
|
237
|
-
|
252
|
+
(schema or self.default_schema_name, )
|
238
253
|
)
|
239
254
|
return [row[0] for row in cursor.fetchall()]
|
240
255
|
|
241
256
|
@reflection.cache
|
242
257
|
def get_view_names(self, connection, schema=None, **kw):
|
243
|
-
cursor = connection.
|
258
|
+
cursor = connection.exec_driver_sql(
|
244
259
|
"SELECT table_name FROM information_schema.views "
|
245
260
|
"ORDER BY table_name ASC, {0} ASC".format(self.schema_column),
|
246
|
-
|
261
|
+
(schema or self.default_schema_name, )
|
247
262
|
)
|
248
263
|
return [row[0] for row in cursor.fetchall()]
|
249
264
|
|
@@ -254,11 +269,11 @@ class CrateDialect(default.DefaultDialect):
|
|
254
269
|
"WHERE table_name = ? AND {0} = ? " \
|
255
270
|
"AND column_name !~ ?" \
|
256
271
|
.format(self.schema_column)
|
257
|
-
cursor = connection.
|
272
|
+
cursor = connection.exec_driver_sql(
|
258
273
|
query,
|
259
|
-
|
274
|
+
(table_name,
|
260
275
|
schema or self.default_schema_name,
|
261
|
-
r"(.*)\[\'(.*)\'\]"
|
276
|
+
r"(.*)\[\'(.*)\'\]") # regex to filter subscript
|
262
277
|
)
|
263
278
|
return [self._create_column_info(row) for row in cursor.fetchall()]
|
264
279
|
|
@@ -293,9 +308,9 @@ class CrateDialect(default.DefaultDialect):
|
|
293
308
|
rows = result.fetchone()
|
294
309
|
return set(rows[0] if rows else [])
|
295
310
|
|
296
|
-
pk_result = engine.
|
311
|
+
pk_result = engine.exec_driver_sql(
|
297
312
|
query,
|
298
|
-
|
313
|
+
(table_name, schema or self.default_schema_name)
|
299
314
|
)
|
300
315
|
pks = result_fun(pk_result)
|
301
316
|
return {'constrained_columns': pks,
|
@@ -20,8 +20,9 @@
|
|
20
20
|
# software solely pursuant to the terms of the relevant commercial agreement.
|
21
21
|
|
22
22
|
import sqlalchemy as sa
|
23
|
-
from
|
23
|
+
from crate.client._pep440 import Version
|
24
24
|
|
25
|
-
SA_VERSION =
|
25
|
+
SA_VERSION = Version(sa.__version__)
|
26
26
|
|
27
|
-
SA_1_4 =
|
27
|
+
SA_1_4 = Version('1.4.0b1')
|
28
|
+
SA_2_0 = Version('2.0.0')
|
@@ -1,5 +1,14 @@
|
|
1
1
|
# -*- coding: utf-8 -*-
|
2
2
|
|
3
|
+
from ..compat.api13 import monkeypatch_amend_select_sa14, monkeypatch_add_connectionfairy_driver_connection
|
4
|
+
from ..sa_version import SA_1_4, SA_VERSION
|
5
|
+
|
6
|
+
# `sql.select()` of SQLAlchemy 1.3 uses old calling semantics,
|
7
|
+
# but the test cases already need the modern ones.
|
8
|
+
if SA_VERSION < SA_1_4:
|
9
|
+
monkeypatch_amend_select_sa14()
|
10
|
+
monkeypatch_add_connectionfairy_driver_connection()
|
11
|
+
|
3
12
|
from unittest import TestSuite, makeSuite
|
4
13
|
from .connection_test import SqlAlchemyConnectionTest
|
5
14
|
from .dict_test import SqlAlchemyDictTypeTest
|
@@ -9,10 +18,11 @@ from .update_test import SqlAlchemyUpdateTest
|
|
9
18
|
from .match_test import SqlAlchemyMatchTest
|
10
19
|
from .bulk_test import SqlAlchemyBulkTest
|
11
20
|
from .insert_from_select_test import SqlAlchemyInsertFromSelectTest
|
12
|
-
from .create_table_test import
|
21
|
+
from .create_table_test import SqlAlchemyCreateTableTest
|
13
22
|
from .array_test import SqlAlchemyArrayTypeTest
|
14
|
-
from .dialect_test import
|
15
|
-
from .function_test import
|
23
|
+
from .dialect_test import SqlAlchemyDialectTest
|
24
|
+
from .function_test import SqlAlchemyFunctionTest
|
25
|
+
from .warnings_test import SqlAlchemyWarningsTest
|
16
26
|
|
17
27
|
|
18
28
|
def test_suite():
|
@@ -23,11 +33,12 @@ def test_suite():
|
|
23
33
|
tests.addTest(makeSuite(SqlAlchemyCompilerTest))
|
24
34
|
tests.addTest(makeSuite(SqlAlchemyUpdateTest))
|
25
35
|
tests.addTest(makeSuite(SqlAlchemyMatchTest))
|
26
|
-
tests.addTest(makeSuite(
|
36
|
+
tests.addTest(makeSuite(SqlAlchemyCreateTableTest))
|
27
37
|
tests.addTest(makeSuite(SqlAlchemyBulkTest))
|
28
38
|
tests.addTest(makeSuite(SqlAlchemyInsertFromSelectTest))
|
29
39
|
tests.addTest(makeSuite(SqlAlchemyInsertFromSelectTest))
|
30
|
-
tests.addTest(makeSuite(
|
31
|
-
tests.addTest(makeSuite(
|
40
|
+
tests.addTest(makeSuite(SqlAlchemyDialectTest))
|
41
|
+
tests.addTest(makeSuite(SqlAlchemyFunctionTest))
|
32
42
|
tests.addTest(makeSuite(SqlAlchemyArrayTypeTest))
|
43
|
+
tests.addTest(makeSuite(SqlAlchemyWarningsTest))
|
33
44
|
return tests
|