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
@@ -26,7 +26,10 @@ from unittest.mock import patch, MagicMock
|
|
26
26
|
import sqlalchemy as sa
|
27
27
|
from sqlalchemy.sql import operators
|
28
28
|
from sqlalchemy.orm import Session
|
29
|
-
|
29
|
+
try:
|
30
|
+
from sqlalchemy.orm import declarative_base
|
31
|
+
except ImportError:
|
32
|
+
from sqlalchemy.ext.declarative import declarative_base
|
30
33
|
|
31
34
|
from crate.client.cursor import Cursor
|
32
35
|
|
@@ -40,7 +43,7 @@ class SqlAlchemyArrayTypeTest(TestCase):
|
|
40
43
|
|
41
44
|
def setUp(self):
|
42
45
|
self.engine = sa.create_engine('crate://')
|
43
|
-
Base = declarative_base(
|
46
|
+
Base = declarative_base()
|
44
47
|
self.metadata = sa.MetaData()
|
45
48
|
|
46
49
|
class User(Base):
|
@@ -51,7 +54,7 @@ class SqlAlchemyArrayTypeTest(TestCase):
|
|
51
54
|
scores = sa.Column(sa.ARRAY(sa.Integer))
|
52
55
|
|
53
56
|
self.User = User
|
54
|
-
self.session = Session()
|
57
|
+
self.session = Session(bind=self.engine)
|
55
58
|
|
56
59
|
def assertSQL(self, expected_str, actual_expr):
|
57
60
|
self.assertEqual(expected_str, str(actual_expr).replace('\n', ''))
|
@@ -24,7 +24,10 @@ from unittest.mock import patch, MagicMock
|
|
24
24
|
|
25
25
|
import sqlalchemy as sa
|
26
26
|
from sqlalchemy.orm import Session
|
27
|
-
|
27
|
+
try:
|
28
|
+
from sqlalchemy.orm import declarative_base
|
29
|
+
except ImportError:
|
30
|
+
from sqlalchemy.ext.declarative import declarative_base
|
28
31
|
|
29
32
|
from crate.client.cursor import Cursor
|
30
33
|
|
@@ -38,7 +41,7 @@ class SqlAlchemyBulkTest(TestCase):
|
|
38
41
|
|
39
42
|
def setUp(self):
|
40
43
|
self.engine = sa.create_engine('crate://')
|
41
|
-
Base = declarative_base(
|
44
|
+
Base = declarative_base()
|
42
45
|
|
43
46
|
class Character(Base):
|
44
47
|
__tablename__ = 'characters'
|
@@ -47,7 +50,7 @@ class SqlAlchemyBulkTest(TestCase):
|
|
47
50
|
age = sa.Column(sa.Integer)
|
48
51
|
|
49
52
|
self.character = Character
|
50
|
-
self.session = Session()
|
53
|
+
self.session = Session(bind=self.engine)
|
51
54
|
|
52
55
|
@patch('crate.client.connection.Cursor', FakeCursor)
|
53
56
|
def test_bulk_save(self):
|
@@ -75,4 +78,4 @@ class SqlAlchemyBulkTest(TestCase):
|
|
75
78
|
('Banshee', 26),
|
76
79
|
('Callisto', 37)
|
77
80
|
)
|
78
|
-
self.
|
81
|
+
self.assertSequenceEqual(expected_bulk_args, bulk_args)
|
@@ -24,8 +24,9 @@ from unittest import TestCase
|
|
24
24
|
from crate.client.sqlalchemy.compiler import crate_before_execute
|
25
25
|
|
26
26
|
import sqlalchemy as sa
|
27
|
-
from sqlalchemy.sql import
|
27
|
+
from sqlalchemy.sql import text, Update
|
28
28
|
|
29
|
+
from crate.client.sqlalchemy.sa_version import SA_VERSION, SA_1_4
|
29
30
|
from crate.client.sqlalchemy.types import Craty
|
30
31
|
|
31
32
|
|
@@ -39,7 +40,7 @@ class SqlAlchemyCompilerTest(TestCase):
|
|
39
40
|
sa.Column('name', sa.String),
|
40
41
|
sa.Column('data', Craty))
|
41
42
|
|
42
|
-
self.update =
|
43
|
+
self.update = Update(self.mytable).where(text('name=:name'))
|
43
44
|
self.values = [{'name': 'crate'}]
|
44
45
|
self.values = (self.values, )
|
45
46
|
|
@@ -74,25 +75,25 @@ class SqlAlchemyCompilerTest(TestCase):
|
|
74
75
|
"""
|
75
76
|
Verify the `CrateCompiler.limit_clause` method, with offset.
|
76
77
|
"""
|
77
|
-
self.metadata.bind = self.crate_engine
|
78
78
|
selectable = self.mytable.select().offset(5)
|
79
|
-
statement = str(selectable.compile())
|
80
|
-
|
79
|
+
statement = str(selectable.compile(bind=self.crate_engine))
|
80
|
+
if SA_VERSION >= SA_1_4:
|
81
|
+
self.assertEqual(statement, "SELECT mytable.name, mytable.data \nFROM mytable\n LIMIT ALL OFFSET ?")
|
82
|
+
else:
|
83
|
+
self.assertEqual(statement, "SELECT mytable.name, mytable.data \nFROM mytable \n LIMIT ALL OFFSET ?")
|
81
84
|
|
82
85
|
def test_select_with_limit(self):
|
83
86
|
"""
|
84
87
|
Verify the `CrateCompiler.limit_clause` method, with limit.
|
85
88
|
"""
|
86
|
-
self.metadata.bind = self.crate_engine
|
87
89
|
selectable = self.mytable.select().limit(42)
|
88
|
-
statement = str(selectable.compile())
|
90
|
+
statement = str(selectable.compile(bind=self.crate_engine))
|
89
91
|
self.assertEqual(statement, "SELECT mytable.name, mytable.data \nFROM mytable \n LIMIT ?")
|
90
92
|
|
91
93
|
def test_select_with_offset_and_limit(self):
|
92
94
|
"""
|
93
95
|
Verify the `CrateCompiler.limit_clause` method, with offset and limit.
|
94
96
|
"""
|
95
|
-
self.metadata.bind = self.crate_engine
|
96
97
|
selectable = self.mytable.select().offset(5).limit(42)
|
97
|
-
statement = str(selectable.compile())
|
98
|
+
statement = str(selectable.compile(bind=self.crate_engine))
|
98
99
|
self.assertEqual(statement, "SELECT mytable.name, mytable.data \nFROM mytable \n LIMIT ? OFFSET ?")
|
@@ -34,21 +34,27 @@ class SqlAlchemyConnectionTest(TestCase):
|
|
34
34
|
engine = sa.create_engine('crate://')
|
35
35
|
conn = engine.raw_connection()
|
36
36
|
self.assertEqual("<Connection <Client ['http://127.0.0.1:4200']>>",
|
37
|
-
repr(conn.
|
37
|
+
repr(conn.driver_connection))
|
38
|
+
conn.close()
|
39
|
+
engine.dispose()
|
38
40
|
|
39
41
|
def test_connection_server_uri_http(self):
|
40
42
|
engine = sa.create_engine(
|
41
43
|
"crate://otherhost:19201")
|
42
44
|
conn = engine.raw_connection()
|
43
45
|
self.assertEqual("<Connection <Client ['http://otherhost:19201']>>",
|
44
|
-
repr(conn.
|
46
|
+
repr(conn.driver_connection))
|
47
|
+
conn.close()
|
48
|
+
engine.dispose()
|
45
49
|
|
46
50
|
def test_connection_server_uri_https(self):
|
47
51
|
engine = sa.create_engine(
|
48
52
|
"crate://otherhost:19201/?ssl=true")
|
49
53
|
conn = engine.raw_connection()
|
50
54
|
self.assertEqual("<Connection <Client ['https://otherhost:19201']>>",
|
51
|
-
repr(conn.
|
55
|
+
repr(conn.driver_connection))
|
56
|
+
conn.close()
|
57
|
+
engine.dispose()
|
52
58
|
|
53
59
|
def test_connection_server_uri_invalid_port(self):
|
54
60
|
with self.assertRaises(ValueError) as context:
|
@@ -60,18 +66,22 @@ class SqlAlchemyConnectionTest(TestCase):
|
|
60
66
|
"crate://foo@otherhost:19201/?ssl=true")
|
61
67
|
conn = engine.raw_connection()
|
62
68
|
self.assertEqual("<Connection <Client ['https://otherhost:19201']>>",
|
63
|
-
repr(conn.
|
64
|
-
self.assertEqual(conn.
|
65
|
-
self.assertEqual(conn.
|
69
|
+
repr(conn.driver_connection))
|
70
|
+
self.assertEqual(conn.driver_connection.client.username, "foo")
|
71
|
+
self.assertEqual(conn.driver_connection.client.password, None)
|
72
|
+
conn.close()
|
73
|
+
engine.dispose()
|
66
74
|
|
67
75
|
def test_connection_server_uri_https_with_credentials(self):
|
68
76
|
engine = sa.create_engine(
|
69
77
|
"crate://foo:bar@otherhost:19201/?ssl=true")
|
70
78
|
conn = engine.raw_connection()
|
71
79
|
self.assertEqual("<Connection <Client ['https://otherhost:19201']>>",
|
72
|
-
repr(conn.
|
73
|
-
self.assertEqual(conn.
|
74
|
-
self.assertEqual(conn.
|
80
|
+
repr(conn.driver_connection))
|
81
|
+
self.assertEqual(conn.driver_connection.client.username, "foo")
|
82
|
+
self.assertEqual(conn.driver_connection.client.password, "bar")
|
83
|
+
conn.close()
|
84
|
+
engine.dispose()
|
75
85
|
|
76
86
|
def test_connection_multiple_server_http(self):
|
77
87
|
engine = sa.create_engine(
|
@@ -83,7 +93,9 @@ class SqlAlchemyConnectionTest(TestCase):
|
|
83
93
|
self.assertEqual(
|
84
94
|
"<Connection <Client ['http://localhost:4201', " +
|
85
95
|
"'http://localhost:4202']>>",
|
86
|
-
repr(conn.
|
96
|
+
repr(conn.driver_connection))
|
97
|
+
conn.close()
|
98
|
+
engine.dispose()
|
87
99
|
|
88
100
|
def test_connection_multiple_server_https(self):
|
89
101
|
engine = sa.create_engine(
|
@@ -96,4 +108,6 @@ class SqlAlchemyConnectionTest(TestCase):
|
|
96
108
|
self.assertEqual(
|
97
109
|
"<Connection <Client ['https://localhost:4201', " +
|
98
110
|
"'https://localhost:4202']>>",
|
99
|
-
repr(conn.
|
111
|
+
repr(conn.driver_connection))
|
112
|
+
conn.close()
|
113
|
+
engine.dispose()
|
@@ -20,7 +20,10 @@
|
|
20
20
|
# software solely pursuant to the terms of the relevant commercial agreement.
|
21
21
|
|
22
22
|
import sqlalchemy as sa
|
23
|
-
|
23
|
+
try:
|
24
|
+
from sqlalchemy.orm import declarative_base
|
25
|
+
except ImportError:
|
26
|
+
from sqlalchemy.ext.declarative import declarative_base
|
24
27
|
|
25
28
|
from crate.client.sqlalchemy.types import Object, ObjectArray, Geopoint
|
26
29
|
from crate.client.cursor import Cursor
|
@@ -35,11 +38,11 @@ FakeCursor.return_value = fake_cursor
|
|
35
38
|
|
36
39
|
|
37
40
|
@patch('crate.client.connection.Cursor', FakeCursor)
|
38
|
-
class
|
41
|
+
class SqlAlchemyCreateTableTest(TestCase):
|
39
42
|
|
40
43
|
def setUp(self):
|
41
44
|
self.engine = sa.create_engine('crate://')
|
42
|
-
self.Base = declarative_base(
|
45
|
+
self.Base = declarative_base()
|
43
46
|
|
44
47
|
def test_table_basic_types(self):
|
45
48
|
class User(self.Base):
|
@@ -57,7 +60,7 @@ class CreateTableTest(TestCase):
|
|
57
60
|
float_col = sa.Column(sa.Float)
|
58
61
|
double_col = sa.Column(sa.DECIMAL)
|
59
62
|
|
60
|
-
self.Base.metadata.create_all()
|
63
|
+
self.Base.metadata.create_all(bind=self.engine)
|
61
64
|
fake_cursor.execute.assert_called_with(
|
62
65
|
('\nCREATE TABLE users (\n\tstring_col STRING NOT NULL, '
|
63
66
|
'\n\tunicode_col STRING, \n\ttext_col STRING, \n\tint_col INT, '
|
@@ -74,7 +77,7 @@ class CreateTableTest(TestCase):
|
|
74
77
|
__tablename__ = 'dummy'
|
75
78
|
pk = sa.Column(sa.String, primary_key=True)
|
76
79
|
obj_col = sa.Column(Object)
|
77
|
-
self.Base.metadata.create_all()
|
80
|
+
self.Base.metadata.create_all(bind=self.engine)
|
78
81
|
fake_cursor.execute.assert_called_with(
|
79
82
|
('\nCREATE TABLE dummy (\n\tpk STRING NOT NULL, \n\tobj_col OBJECT, '
|
80
83
|
'\n\tPRIMARY KEY (pk)\n)\n\n'),
|
@@ -88,7 +91,7 @@ class CreateTableTest(TestCase):
|
|
88
91
|
}
|
89
92
|
pk = sa.Column(sa.String, primary_key=True)
|
90
93
|
p = sa.Column(sa.String)
|
91
|
-
self.Base.metadata.create_all()
|
94
|
+
self.Base.metadata.create_all(bind=self.engine)
|
92
95
|
fake_cursor.execute.assert_called_with(
|
93
96
|
('\nCREATE TABLE t (\n\t'
|
94
97
|
'pk STRING NOT NULL, \n\t'
|
@@ -102,7 +105,7 @@ class CreateTableTest(TestCase):
|
|
102
105
|
__tablename__ = 't'
|
103
106
|
ts = sa.Column(sa.BigInteger, primary_key=True)
|
104
107
|
p = sa.Column(sa.BigInteger, sa.Computed("date_trunc('day', ts)"))
|
105
|
-
self.Base.metadata.create_all()
|
108
|
+
self.Base.metadata.create_all(bind=self.engine)
|
106
109
|
fake_cursor.execute.assert_called_with(
|
107
110
|
('\nCREATE TABLE t (\n\t'
|
108
111
|
'ts LONG NOT NULL, \n\t'
|
@@ -117,7 +120,7 @@ class CreateTableTest(TestCase):
|
|
117
120
|
ts = sa.Column(sa.BigInteger, primary_key=True)
|
118
121
|
p = sa.Column(sa.BigInteger, sa.Computed("date_trunc('day', ts)", persisted=False))
|
119
122
|
with self.assertRaises(sa.exc.CompileError):
|
120
|
-
self.Base.metadata.create_all()
|
123
|
+
self.Base.metadata.create_all(bind=self.engine)
|
121
124
|
|
122
125
|
def test_table_partitioned_by(self):
|
123
126
|
class DummyTable(self.Base):
|
@@ -128,7 +131,7 @@ class CreateTableTest(TestCase):
|
|
128
131
|
}
|
129
132
|
pk = sa.Column(sa.String, primary_key=True)
|
130
133
|
p = sa.Column(sa.String)
|
131
|
-
self.Base.metadata.create_all()
|
134
|
+
self.Base.metadata.create_all(bind=self.engine)
|
132
135
|
fake_cursor.execute.assert_called_with(
|
133
136
|
('\nCREATE TABLE t (\n\t'
|
134
137
|
'pk STRING NOT NULL, \n\t'
|
@@ -146,7 +149,7 @@ class CreateTableTest(TestCase):
|
|
146
149
|
}
|
147
150
|
pk = sa.Column(sa.String, primary_key=True)
|
148
151
|
|
149
|
-
self.Base.metadata.create_all()
|
152
|
+
self.Base.metadata.create_all(bind=self.engine)
|
150
153
|
fake_cursor.execute.assert_called_with(
|
151
154
|
('\nCREATE TABLE t (\n\t'
|
152
155
|
'pk STRING NOT NULL, \n\t'
|
@@ -163,7 +166,7 @@ class CreateTableTest(TestCase):
|
|
163
166
|
}
|
164
167
|
pk = sa.Column(sa.String, primary_key=True)
|
165
168
|
p = sa.Column(sa.String, primary_key=True)
|
166
|
-
self.Base.metadata.create_all()
|
169
|
+
self.Base.metadata.create_all(bind=self.engine)
|
167
170
|
fake_cursor.execute.assert_called_with(
|
168
171
|
('\nCREATE TABLE t (\n\t'
|
169
172
|
'pk STRING NOT NULL, \n\t'
|
@@ -178,7 +181,7 @@ class CreateTableTest(TestCase):
|
|
178
181
|
pk = sa.Column(sa.String, primary_key=True)
|
179
182
|
tags = sa.Column(ObjectArray)
|
180
183
|
|
181
|
-
self.Base.metadata.create_all()
|
184
|
+
self.Base.metadata.create_all(bind=self.engine)
|
182
185
|
fake_cursor.execute.assert_called_with(
|
183
186
|
('\nCREATE TABLE t (\n\t'
|
184
187
|
'pk STRING NOT NULL, \n\t'
|
@@ -192,7 +195,7 @@ class CreateTableTest(TestCase):
|
|
192
195
|
a = sa.Column(sa.Integer, nullable=True)
|
193
196
|
b = sa.Column(sa.Integer, nullable=False)
|
194
197
|
|
195
|
-
self.Base.metadata.create_all()
|
198
|
+
self.Base.metadata.create_all(bind=self.engine)
|
196
199
|
fake_cursor.execute.assert_called_with(
|
197
200
|
('\nCREATE TABLE t (\n\t'
|
198
201
|
'pk STRING NOT NULL, \n\t'
|
@@ -205,7 +208,7 @@ class CreateTableTest(TestCase):
|
|
205
208
|
__tablename__ = 't'
|
206
209
|
pk = sa.Column(sa.String, primary_key=True, nullable=True)
|
207
210
|
with self.assertRaises(sa.exc.CompileError):
|
208
|
-
self.Base.metadata.create_all()
|
211
|
+
self.Base.metadata.create_all(bind=self.engine)
|
209
212
|
|
210
213
|
def test_column_crate_index(self):
|
211
214
|
class DummyTable(self.Base):
|
@@ -214,7 +217,7 @@ class CreateTableTest(TestCase):
|
|
214
217
|
a = sa.Column(sa.Integer, crate_index=False)
|
215
218
|
b = sa.Column(sa.Integer, crate_index=True)
|
216
219
|
|
217
|
-
self.Base.metadata.create_all()
|
220
|
+
self.Base.metadata.create_all(bind=self.engine)
|
218
221
|
fake_cursor.execute.assert_called_with(
|
219
222
|
('\nCREATE TABLE t (\n\t'
|
220
223
|
'pk STRING NOT NULL, \n\t'
|
@@ -228,4 +231,4 @@ class CreateTableTest(TestCase):
|
|
228
231
|
pk = sa.Column(sa.String, primary_key=True)
|
229
232
|
a = sa.Column(Geopoint, crate_index=False)
|
230
233
|
with self.assertRaises(sa.exc.CompileError):
|
231
|
-
self.Base.metadata.create_all()
|
234
|
+
self.Base.metadata.create_all(bind=self.engine)
|
@@ -27,7 +27,10 @@ from unittest.mock import patch, MagicMock
|
|
27
27
|
import sqlalchemy as sa
|
28
28
|
from sqlalchemy.exc import DBAPIError
|
29
29
|
from sqlalchemy.orm import Session
|
30
|
-
|
30
|
+
try:
|
31
|
+
from sqlalchemy.orm import declarative_base
|
32
|
+
except ImportError:
|
33
|
+
from sqlalchemy.ext.declarative import declarative_base
|
31
34
|
|
32
35
|
from crate.client.cursor import Cursor
|
33
36
|
|
@@ -54,7 +57,7 @@ class SqlAlchemyDateAndDateTimeTest(TestCase):
|
|
54
57
|
|
55
58
|
def setUp(self):
|
56
59
|
self.engine = sa.create_engine('crate://')
|
57
|
-
Base = declarative_base(
|
60
|
+
Base = declarative_base()
|
58
61
|
|
59
62
|
class Character(Base):
|
60
63
|
__tablename__ = 'characters'
|
@@ -66,7 +69,7 @@ class SqlAlchemyDateAndDateTimeTest(TestCase):
|
|
66
69
|
('characters_name', None, None, None, None, None, None),
|
67
70
|
('characters_date', None, None, None, None, None, None)
|
68
71
|
)
|
69
|
-
self.session = Session()
|
72
|
+
self.session = Session(bind=self.engine)
|
70
73
|
self.Character = Character
|
71
74
|
|
72
75
|
def test_date_can_handle_datetime(self):
|
@@ -20,23 +20,28 @@
|
|
20
20
|
# software solely pursuant to the terms of the relevant commercial agreement.
|
21
21
|
|
22
22
|
from datetime import datetime
|
23
|
-
from unittest import TestCase
|
23
|
+
from unittest import TestCase, skipIf
|
24
24
|
from unittest.mock import MagicMock, patch
|
25
25
|
|
26
26
|
import sqlalchemy as sa
|
27
27
|
|
28
28
|
from crate.client.cursor import Cursor
|
29
|
+
from crate.client.sqlalchemy import SA_VERSION
|
30
|
+
from crate.client.sqlalchemy.sa_version import SA_1_4, SA_2_0
|
29
31
|
from crate.client.sqlalchemy.types import Object
|
30
32
|
from sqlalchemy import inspect
|
31
|
-
from sqlalchemy.ext.declarative import declarative_base
|
32
33
|
from sqlalchemy.orm import Session
|
33
|
-
|
34
|
+
try:
|
35
|
+
from sqlalchemy.orm import declarative_base
|
36
|
+
except ImportError:
|
37
|
+
from sqlalchemy.ext.declarative import declarative_base
|
38
|
+
from sqlalchemy.testing import eq_, in_, is_true
|
34
39
|
|
35
40
|
FakeCursor = MagicMock(name='FakeCursor', spec=Cursor)
|
36
41
|
|
37
42
|
|
38
43
|
@patch('crate.client.connection.Cursor', FakeCursor)
|
39
|
-
class
|
44
|
+
class SqlAlchemyDialectTest(TestCase):
|
40
45
|
|
41
46
|
def execute_wrapper(self, query, *args, **kwargs):
|
42
47
|
self.executed_statement = query
|
@@ -48,13 +53,14 @@ class DialectTest(TestCase):
|
|
48
53
|
FakeCursor.return_value = self.fake_cursor
|
49
54
|
|
50
55
|
self.engine = sa.create_engine('crate://')
|
56
|
+
|
51
57
|
self.executed_statement = None
|
52
58
|
|
53
59
|
self.connection = self.engine.connect()
|
54
60
|
|
55
61
|
self.fake_cursor.execute = self.execute_wrapper
|
56
62
|
|
57
|
-
self.base = declarative_base(
|
63
|
+
self.base = declarative_base()
|
58
64
|
|
59
65
|
class Character(self.base):
|
60
66
|
__tablename__ = 'characters'
|
@@ -64,12 +70,17 @@ class DialectTest(TestCase):
|
|
64
70
|
obj = sa.Column(Object)
|
65
71
|
ts = sa.Column(sa.DateTime, onupdate=datetime.utcnow)
|
66
72
|
|
67
|
-
self.
|
68
|
-
|
73
|
+
self.session = Session(bind=self.engine)
|
74
|
+
|
75
|
+
def init_mock(self, return_value=None):
|
76
|
+
self.fake_cursor.rowcount = 1
|
77
|
+
self.fake_cursor.description = (
|
78
|
+
('foo', None, None, None, None, None, None),
|
79
|
+
)
|
80
|
+
self.fake_cursor.fetchall = MagicMock(return_value=return_value)
|
69
81
|
|
70
82
|
def test_primary_keys_2_3_0(self):
|
71
|
-
|
72
|
-
insp = inspect(meta.bind)
|
83
|
+
insp = inspect(self.session.bind)
|
73
84
|
self.engine.dialect.server_version_info = (2, 3, 0)
|
74
85
|
|
75
86
|
self.fake_cursor.rowcount = 3
|
@@ -84,8 +95,7 @@ class DialectTest(TestCase):
|
|
84
95
|
in_("table_catalog = ?", self.executed_statement)
|
85
96
|
|
86
97
|
def test_primary_keys_3_0_0(self):
|
87
|
-
|
88
|
-
insp = inspect(meta.bind)
|
98
|
+
insp = inspect(self.session.bind)
|
89
99
|
self.engine.dialect.server_version_info = (3, 0, 0)
|
90
100
|
|
91
101
|
self.fake_cursor.rowcount = 3
|
@@ -106,7 +116,7 @@ class DialectTest(TestCase):
|
|
106
116
|
)
|
107
117
|
self.fake_cursor.fetchall = MagicMock(return_value=[["t1"], ["t2"]])
|
108
118
|
|
109
|
-
insp = inspect(self.
|
119
|
+
insp = inspect(self.session.bind)
|
110
120
|
self.engine.dialect.server_version_info = (2, 0, 0)
|
111
121
|
eq_(insp.get_table_names(schema="doc"),
|
112
122
|
['t1', 't2'])
|
@@ -119,9 +129,28 @@ class DialectTest(TestCase):
|
|
119
129
|
)
|
120
130
|
self.fake_cursor.fetchall = MagicMock(return_value=[["v1"], ["v2"]])
|
121
131
|
|
122
|
-
insp = inspect(self.
|
132
|
+
insp = inspect(self.session.bind)
|
123
133
|
self.engine.dialect.server_version_info = (2, 0, 0)
|
124
134
|
eq_(insp.get_view_names(schema="doc"),
|
125
135
|
['v1', 'v2'])
|
126
136
|
eq_(self.executed_statement, "SELECT table_name FROM information_schema.views "
|
127
137
|
"ORDER BY table_name ASC, table_schema ASC")
|
138
|
+
|
139
|
+
@skipIf(SA_VERSION < SA_1_4, "Inspector.has_table only available on SQLAlchemy>=1.4")
|
140
|
+
def test_has_table(self):
|
141
|
+
self.init_mock(return_value=[["foo"], ["bar"]])
|
142
|
+
insp = inspect(self.session.bind)
|
143
|
+
is_true(insp.has_table("bar"))
|
144
|
+
eq_(self.executed_statement,
|
145
|
+
"SELECT table_name FROM information_schema.tables "
|
146
|
+
"WHERE table_schema = ? AND table_type = 'BASE TABLE' "
|
147
|
+
"ORDER BY table_name ASC, table_schema ASC")
|
148
|
+
|
149
|
+
@skipIf(SA_VERSION < SA_2_0, "Inspector.has_schema only available on SQLAlchemy>=2.0")
|
150
|
+
def test_has_schema(self):
|
151
|
+
self.init_mock(
|
152
|
+
return_value=[["blob"], ["doc"], ["information_schema"], ["pg_catalog"], ["sys"]])
|
153
|
+
insp = inspect(self.session.bind)
|
154
|
+
is_true(insp.has_schema("doc"))
|
155
|
+
eq_(self.executed_statement,
|
156
|
+
"select schema_name from information_schema.schemata order by schema_name asc")
|
@@ -26,7 +26,10 @@ from unittest.mock import patch, MagicMock
|
|
26
26
|
import sqlalchemy as sa
|
27
27
|
from sqlalchemy.sql import select
|
28
28
|
from sqlalchemy.orm import Session
|
29
|
-
|
29
|
+
try:
|
30
|
+
from sqlalchemy.orm import declarative_base
|
31
|
+
except ImportError:
|
32
|
+
from sqlalchemy.ext.declarative import declarative_base
|
30
33
|
|
31
34
|
from crate.client.sqlalchemy.types import Craty, ObjectArray
|
32
35
|
from crate.client.cursor import Cursor
|
@@ -46,19 +49,20 @@ class SqlAlchemyDictTypeTest(TestCase):
|
|
46
49
|
sa.Column('name', sa.String),
|
47
50
|
sa.Column('data', Craty))
|
48
51
|
|
49
|
-
def assertSQL(self, expected_str,
|
52
|
+
def assertSQL(self, expected_str, selectable):
|
53
|
+
actual_expr = selectable.compile(bind=self.engine)
|
50
54
|
self.assertEqual(expected_str, str(actual_expr).replace('\n', ''))
|
51
55
|
|
52
56
|
def test_select_with_dict_column(self):
|
53
57
|
mytable = self.mytable
|
54
58
|
self.assertSQL(
|
55
59
|
"SELECT mytable.data['x'] AS anon_1 FROM mytable",
|
56
|
-
select(
|
60
|
+
select(mytable.c.data['x'])
|
57
61
|
)
|
58
62
|
|
59
63
|
def test_select_with_dict_column_where_clause(self):
|
60
64
|
mytable = self.mytable
|
61
|
-
s = select(
|
65
|
+
s = select(mytable.c.data).\
|
62
66
|
where(mytable.c.data['x'] == 1)
|
63
67
|
self.assertSQL(
|
64
68
|
"SELECT mytable.data FROM mytable WHERE mytable.data['x'] = ?",
|
@@ -67,7 +71,7 @@ class SqlAlchemyDictTypeTest(TestCase):
|
|
67
71
|
|
68
72
|
def test_select_with_dict_column_nested_where(self):
|
69
73
|
mytable = self.mytable
|
70
|
-
s = select(
|
74
|
+
s = select(mytable.c.name)
|
71
75
|
s = s.where(mytable.c.data['x']['y'] == 1)
|
72
76
|
self.assertSQL(
|
73
77
|
"SELECT mytable.name FROM mytable " +
|
@@ -77,7 +81,7 @@ class SqlAlchemyDictTypeTest(TestCase):
|
|
77
81
|
|
78
82
|
def test_select_with_dict_column_where_clause_gt(self):
|
79
83
|
mytable = self.mytable
|
80
|
-
s = select(
|
84
|
+
s = select(mytable.c.data).\
|
81
85
|
where(mytable.c.data['x'] > 1)
|
82
86
|
self.assertSQL(
|
83
87
|
"SELECT mytable.data FROM mytable WHERE mytable.data['x'] > ?",
|
@@ -86,7 +90,7 @@ class SqlAlchemyDictTypeTest(TestCase):
|
|
86
90
|
|
87
91
|
def test_select_with_dict_column_where_clause_other_col(self):
|
88
92
|
mytable = self.mytable
|
89
|
-
s = select(
|
93
|
+
s = select(mytable.c.name)
|
90
94
|
s = s.where(mytable.c.data['x'] == mytable.c.name)
|
91
95
|
self.assertSQL(
|
92
96
|
"SELECT mytable.name FROM mytable " +
|
@@ -96,7 +100,7 @@ class SqlAlchemyDictTypeTest(TestCase):
|
|
96
100
|
|
97
101
|
def test_update_with_dict_column(self):
|
98
102
|
mytable = self.mytable
|
99
|
-
stmt = mytable.update(
|
103
|
+
stmt = mytable.update().\
|
100
104
|
where(mytable.c.name == 'Arthur Dent').\
|
101
105
|
values({
|
102
106
|
"data['x']": "Trillian"
|
@@ -114,7 +118,7 @@ class SqlAlchemyDictTypeTest(TestCase):
|
|
114
118
|
('characters_data', None, None, None, None, None, None)
|
115
119
|
)
|
116
120
|
fake_cursor.rowcount = 1
|
117
|
-
Base = declarative_base(
|
121
|
+
Base = declarative_base()
|
118
122
|
|
119
123
|
class Character(Base):
|
120
124
|
__tablename__ = 'characters'
|
@@ -123,7 +127,7 @@ class SqlAlchemyDictTypeTest(TestCase):
|
|
123
127
|
data = sa.Column(Craty)
|
124
128
|
data_list = sa.Column(ObjectArray)
|
125
129
|
|
126
|
-
session = Session()
|
130
|
+
session = Session(bind=self.engine)
|
127
131
|
return session, Character
|
128
132
|
|
129
133
|
def test_assign_null_to_object_array(self):
|
@@ -266,7 +270,7 @@ class SqlAlchemyDictTypeTest(TestCase):
|
|
266
270
|
return_value=[('Trillian', {'x': 1})]
|
267
271
|
)
|
268
272
|
|
269
|
-
session = Session()
|
273
|
+
session = Session(bind=self.engine)
|
270
274
|
char = Character(name='Trillian')
|
271
275
|
char.data = {'x': 1}
|
272
276
|
session.add(char)
|
@@ -339,14 +343,14 @@ class SqlAlchemyDictTypeTest(TestCase):
|
|
339
343
|
|
340
344
|
)
|
341
345
|
fake_cursor.rowcount = 1
|
342
|
-
Base = declarative_base(
|
346
|
+
Base = declarative_base()
|
343
347
|
|
344
348
|
class Character(Base):
|
345
349
|
__tablename__ = 'characters'
|
346
350
|
name = sa.Column(sa.String, primary_key=True)
|
347
351
|
data_list = sa.Column(ObjectArray)
|
348
352
|
|
349
|
-
session = Session()
|
353
|
+
session = Session(bind=self.engine)
|
350
354
|
return session, Character
|
351
355
|
|
352
356
|
def _setup_object_array_char(self):
|
@@ -23,12 +23,15 @@ from unittest import TestCase
|
|
23
23
|
|
24
24
|
import sqlalchemy as sa
|
25
25
|
from sqlalchemy.sql.sqltypes import TIMESTAMP
|
26
|
-
|
26
|
+
try:
|
27
|
+
from sqlalchemy.orm import declarative_base
|
28
|
+
except ImportError:
|
29
|
+
from sqlalchemy.ext.declarative import declarative_base
|
27
30
|
|
28
31
|
|
29
|
-
class
|
32
|
+
class SqlAlchemyFunctionTest(TestCase):
|
30
33
|
def setUp(self):
|
31
|
-
Base = declarative_base(
|
34
|
+
Base = declarative_base()
|
32
35
|
|
33
36
|
class Character(Base):
|
34
37
|
__tablename__ = "characters"
|
@@ -24,9 +24,12 @@ from unittest import TestCase
|
|
24
24
|
from unittest.mock import patch, MagicMock
|
25
25
|
|
26
26
|
import sqlalchemy as sa
|
27
|
-
from sqlalchemy.orm import Session
|
28
|
-
from sqlalchemy.ext.declarative import declarative_base
|
29
27
|
from sqlalchemy import select, insert
|
28
|
+
from sqlalchemy.orm import Session
|
29
|
+
try:
|
30
|
+
from sqlalchemy.orm import declarative_base
|
31
|
+
except ImportError:
|
32
|
+
from sqlalchemy.ext.declarative import declarative_base
|
30
33
|
|
31
34
|
from crate.client.cursor import Cursor
|
32
35
|
|
@@ -44,7 +47,7 @@ class SqlAlchemyInsertFromSelectTest(TestCase):
|
|
44
47
|
|
45
48
|
def setUp(self):
|
46
49
|
self.engine = sa.create_engine('crate://')
|
47
|
-
Base = declarative_base(
|
50
|
+
Base = declarative_base()
|
48
51
|
|
49
52
|
class Character(Base):
|
50
53
|
__tablename__ = 'characters'
|
@@ -64,7 +67,7 @@ class SqlAlchemyInsertFromSelectTest(TestCase):
|
|
64
67
|
|
65
68
|
self.character = Character
|
66
69
|
self.character_archived = CharacterArchive
|
67
|
-
self.session = Session()
|
70
|
+
self.session = Session(bind=self.engine)
|
68
71
|
|
69
72
|
@patch('crate.client.connection.Cursor', FakeCursor)
|
70
73
|
def test_insert_from_select_triggered(self):
|
@@ -72,11 +75,11 @@ class SqlAlchemyInsertFromSelectTest(TestCase):
|
|
72
75
|
self.session.add(char)
|
73
76
|
self.session.commit()
|
74
77
|
|
75
|
-
sel = select(
|
78
|
+
sel = select(self.character.name, self.character.age).where(self.character.status == "Archived")
|
76
79
|
ins = insert(self.character_archived).from_select(['name', 'age'], sel)
|
77
80
|
self.session.execute(ins)
|
78
81
|
self.session.commit()
|
79
82
|
self.assertSQL(
|
80
83
|
"INSERT INTO characters_archive (name, age) SELECT characters.name, characters.age FROM characters WHERE characters.status = ?",
|
81
|
-
ins
|
84
|
+
ins.compile(bind=self.engine)
|
82
85
|
)
|