crate 0.29.0__py2.py3-none-any.whl → 0.30.1__py2.py3-none-any.whl

Sign up to get free protection for your applications and to get access to all the features.
Files changed (43) hide show
  1. crate/client/__init__.py +1 -1
  2. crate/client/_pep440.py +501 -0
  3. crate/client/connection.py +3 -3
  4. crate/client/sqlalchemy/__init__.py +24 -0
  5. crate/client/sqlalchemy/compat/__init__.py +0 -0
  6. crate/client/sqlalchemy/compat/api13.py +156 -0
  7. crate/client/sqlalchemy/compat/core10.py +264 -0
  8. crate/client/sqlalchemy/compat/core14.py +359 -0
  9. crate/client/sqlalchemy/compat/core20.py +447 -0
  10. crate/client/sqlalchemy/compiler.py +1 -481
  11. crate/client/sqlalchemy/dialect.py +32 -17
  12. crate/client/sqlalchemy/sa_version.py +4 -3
  13. crate/client/sqlalchemy/tests/__init__.py +17 -6
  14. crate/client/sqlalchemy/tests/array_test.py +6 -3
  15. crate/client/sqlalchemy/tests/bulk_test.py +7 -4
  16. crate/client/sqlalchemy/tests/compiler_test.py +10 -9
  17. crate/client/sqlalchemy/tests/connection_test.py +25 -11
  18. crate/client/sqlalchemy/tests/create_table_test.py +19 -16
  19. crate/client/sqlalchemy/tests/datetime_test.py +6 -3
  20. crate/client/sqlalchemy/tests/dialect_test.py +42 -13
  21. crate/client/sqlalchemy/tests/dict_test.py +17 -13
  22. crate/client/sqlalchemy/tests/function_test.py +6 -3
  23. crate/client/sqlalchemy/tests/insert_from_select_test.py +9 -6
  24. crate/client/sqlalchemy/tests/match_test.py +6 -3
  25. crate/client/sqlalchemy/tests/update_test.py +6 -3
  26. crate/client/sqlalchemy/tests/warnings_test.py +33 -0
  27. crate/client/test_connection.py +25 -0
  28. crate/client/tests.py +98 -119
  29. crate/testing/layer.py +1 -1
  30. crate/testing/settings.py +51 -0
  31. crate/testing/test_layer.py +188 -2
  32. crate/testing/tests.py +2 -38
  33. crate/testing/util.py +20 -0
  34. {crate-0.29.0.dist-info → crate-0.30.1.dist-info}/METADATA +10 -8
  35. crate-0.30.1.dist-info/RECORD +53 -0
  36. crate-0.29.0.dist-info/RECORD +0 -44
  37. /crate-0.29.0-py3.9-nspkg.pth → /crate-0.30.1-py3.9-nspkg.pth +0 -0
  38. {crate-0.29.0.dist-info → crate-0.30.1.dist-info}/LICENSE +0 -0
  39. {crate-0.29.0.dist-info → crate-0.30.1.dist-info}/NOTICE +0 -0
  40. {crate-0.29.0.dist-info → crate-0.30.1.dist-info}/WHEEL +0 -0
  41. {crate-0.29.0.dist-info → crate-0.30.1.dist-info}/entry_points.txt +0 -0
  42. {crate-0.29.0.dist-info → crate-0.30.1.dist-info}/namespace_packages.txt +0 -0
  43. {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, crud, selectable
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 = CrateCompiler
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 dbapi(cls):
222
+ def import_dbapi(cls):
212
223
  from crate import client
213
224
  return client
214
225
 
215
- def has_schema(self, connection, schema):
216
- return schema in self.get_schema_names(connection)
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.execute(
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.execute(
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
- [schema or self.default_schema_name]
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.execute(
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
- [schema or self.default_schema_name]
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.execute(
272
+ cursor = connection.exec_driver_sql(
258
273
  query,
259
- [table_name,
274
+ (table_name,
260
275
  schema or self.default_schema_name,
261
- r"(.*)\[\'(.*)\'\]"] # regex to filter subscript
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.execute(
311
+ pk_result = engine.exec_driver_sql(
297
312
  query,
298
- [table_name, schema or self.default_schema_name]
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 distutils.version import StrictVersion as V
23
+ from crate.client._pep440 import Version
24
24
 
25
- SA_VERSION = V(sa.__version__)
25
+ SA_VERSION = Version(sa.__version__)
26
26
 
27
- SA_1_4 = V('1.4.0b1')
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 CreateTableTest
21
+ from .create_table_test import SqlAlchemyCreateTableTest
13
22
  from .array_test import SqlAlchemyArrayTypeTest
14
- from .dialect_test import DialectTest
15
- from .function_test import FunctionTest
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(CreateTableTest))
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(DialectTest))
31
- tests.addTest(makeSuite(FunctionTest))
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