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.
- 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
|
)
|