crate 0.35.1__py2.py3-none-any.whl → 1.0.0.dev0__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/testing/test_datetime_old.py +90 -0
- crate-1.0.0.dev0-py3.11-nspkg.pth +1 -0
- {crate-0.35.1.dist-info → crate-1.0.0.dev0.dist-info}/METADATA +15 -19
- crate-1.0.0.dev0.dist-info/RECORD +26 -0
- {crate-0.35.1.dist-info → crate-1.0.0.dev0.dist-info}/WHEEL +1 -1
- crate/client/sqlalchemy/__init__.py +0 -50
- crate/client/sqlalchemy/compat/__init__.py +0 -0
- crate/client/sqlalchemy/compat/api13.py +0 -156
- crate/client/sqlalchemy/compat/core10.py +0 -264
- crate/client/sqlalchemy/compat/core14.py +0 -359
- crate/client/sqlalchemy/compat/core20.py +0 -447
- crate/client/sqlalchemy/compiler.py +0 -318
- crate/client/sqlalchemy/dialect.py +0 -369
- crate/client/sqlalchemy/predicates/__init__.py +0 -99
- crate/client/sqlalchemy/sa_version.py +0 -28
- crate/client/sqlalchemy/support.py +0 -62
- crate/client/sqlalchemy/tests/__init__.py +0 -59
- crate/client/sqlalchemy/tests/array_test.py +0 -111
- crate/client/sqlalchemy/tests/bulk_test.py +0 -256
- crate/client/sqlalchemy/tests/compiler_test.py +0 -434
- crate/client/sqlalchemy/tests/connection_test.py +0 -129
- crate/client/sqlalchemy/tests/create_table_test.py +0 -313
- crate/client/sqlalchemy/tests/datetime_test.py +0 -90
- crate/client/sqlalchemy/tests/dialect_test.py +0 -156
- crate/client/sqlalchemy/tests/dict_test.py +0 -460
- crate/client/sqlalchemy/tests/function_test.py +0 -47
- crate/client/sqlalchemy/tests/insert_from_select_test.py +0 -85
- crate/client/sqlalchemy/tests/match_test.py +0 -137
- crate/client/sqlalchemy/tests/query_caching.py +0 -143
- crate/client/sqlalchemy/tests/update_test.py +0 -115
- crate/client/sqlalchemy/tests/warnings_test.py +0 -64
- crate/client/sqlalchemy/types.py +0 -277
- crate/client/tests.py +0 -416
- crate/testing/tests.py +0 -34
- crate-0.35.1-py3.11-nspkg.pth +0 -1
- crate-0.35.1.dist-info/RECORD +0 -55
- crate-0.35.1.dist-info/entry_points.txt +0 -2
- {crate-0.35.1.dist-info → crate-1.0.0.dev0.dist-info}/LICENSE +0 -0
- {crate-0.35.1.dist-info → crate-1.0.0.dev0.dist-info}/NOTICE +0 -0
- {crate-0.35.1.dist-info → crate-1.0.0.dev0.dist-info}/namespace_packages.txt +0 -0
- {crate-0.35.1.dist-info → crate-1.0.0.dev0.dist-info}/top_level.txt +0 -0
@@ -1,313 +0,0 @@
|
|
1
|
-
# -*- coding: utf-8; -*-
|
2
|
-
#
|
3
|
-
# Licensed to CRATE Technology GmbH ("Crate") under one or more contributor
|
4
|
-
# license agreements. See the NOTICE file distributed with this work for
|
5
|
-
# additional information regarding copyright ownership. Crate licenses
|
6
|
-
# this file to you under the Apache License, Version 2.0 (the "License");
|
7
|
-
# you may not use this file except in compliance with the License. You may
|
8
|
-
# obtain a copy of the License at
|
9
|
-
#
|
10
|
-
# http://www.apache.org/licenses/LICENSE-2.0
|
11
|
-
#
|
12
|
-
# Unless required by applicable law or agreed to in writing, software
|
13
|
-
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
14
|
-
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
15
|
-
# License for the specific language governing permissions and limitations
|
16
|
-
# under the License.
|
17
|
-
#
|
18
|
-
# However, if you have executed another commercial license agreement
|
19
|
-
# with Crate these terms will supersede the license and you may use the
|
20
|
-
# software solely pursuant to the terms of the relevant commercial agreement.
|
21
|
-
|
22
|
-
import sqlalchemy as sa
|
23
|
-
try:
|
24
|
-
from sqlalchemy.orm import declarative_base
|
25
|
-
except ImportError:
|
26
|
-
from sqlalchemy.ext.declarative import declarative_base
|
27
|
-
|
28
|
-
from crate.client.sqlalchemy.types import ObjectType, ObjectArray, Geopoint
|
29
|
-
from crate.client.cursor import Cursor
|
30
|
-
|
31
|
-
from unittest import TestCase
|
32
|
-
from unittest.mock import patch, MagicMock
|
33
|
-
|
34
|
-
|
35
|
-
fake_cursor = MagicMock(name='fake_cursor')
|
36
|
-
FakeCursor = MagicMock(name='FakeCursor', spec=Cursor)
|
37
|
-
FakeCursor.return_value = fake_cursor
|
38
|
-
|
39
|
-
|
40
|
-
@patch('crate.client.connection.Cursor', FakeCursor)
|
41
|
-
class SqlAlchemyCreateTableTest(TestCase):
|
42
|
-
|
43
|
-
def setUp(self):
|
44
|
-
self.engine = sa.create_engine('crate://')
|
45
|
-
self.Base = declarative_base()
|
46
|
-
|
47
|
-
def test_table_basic_types(self):
|
48
|
-
class User(self.Base):
|
49
|
-
__tablename__ = 'users'
|
50
|
-
string_col = sa.Column(sa.String, primary_key=True)
|
51
|
-
unicode_col = sa.Column(sa.Unicode)
|
52
|
-
text_col = sa.Column(sa.Text)
|
53
|
-
int_col = sa.Column(sa.Integer)
|
54
|
-
long_col1 = sa.Column(sa.BigInteger)
|
55
|
-
long_col2 = sa.Column(sa.NUMERIC)
|
56
|
-
bool_col = sa.Column(sa.Boolean)
|
57
|
-
short_col = sa.Column(sa.SmallInteger)
|
58
|
-
datetime_col = sa.Column(sa.DateTime)
|
59
|
-
date_col = sa.Column(sa.Date)
|
60
|
-
float_col = sa.Column(sa.Float)
|
61
|
-
double_col = sa.Column(sa.DECIMAL)
|
62
|
-
|
63
|
-
self.Base.metadata.create_all(bind=self.engine)
|
64
|
-
fake_cursor.execute.assert_called_with(
|
65
|
-
('\nCREATE TABLE users (\n\tstring_col STRING NOT NULL, '
|
66
|
-
'\n\tunicode_col STRING, \n\ttext_col STRING, \n\tint_col INT, '
|
67
|
-
'\n\tlong_col1 LONG, \n\tlong_col2 LONG, '
|
68
|
-
'\n\tbool_col BOOLEAN, '
|
69
|
-
'\n\tshort_col SHORT, '
|
70
|
-
'\n\tdatetime_col TIMESTAMP, \n\tdate_col TIMESTAMP, '
|
71
|
-
'\n\tfloat_col FLOAT, \n\tdouble_col DOUBLE, '
|
72
|
-
'\n\tPRIMARY KEY (string_col)\n)\n\n'),
|
73
|
-
())
|
74
|
-
|
75
|
-
def test_column_obj(self):
|
76
|
-
class DummyTable(self.Base):
|
77
|
-
__tablename__ = 'dummy'
|
78
|
-
pk = sa.Column(sa.String, primary_key=True)
|
79
|
-
obj_col = sa.Column(ObjectType)
|
80
|
-
self.Base.metadata.create_all(bind=self.engine)
|
81
|
-
fake_cursor.execute.assert_called_with(
|
82
|
-
('\nCREATE TABLE dummy (\n\tpk STRING NOT NULL, \n\tobj_col OBJECT, '
|
83
|
-
'\n\tPRIMARY KEY (pk)\n)\n\n'),
|
84
|
-
())
|
85
|
-
|
86
|
-
def test_table_clustered_by(self):
|
87
|
-
class DummyTable(self.Base):
|
88
|
-
__tablename__ = 't'
|
89
|
-
__table_args__ = {
|
90
|
-
'crate_clustered_by': 'p'
|
91
|
-
}
|
92
|
-
pk = sa.Column(sa.String, primary_key=True)
|
93
|
-
p = sa.Column(sa.String)
|
94
|
-
self.Base.metadata.create_all(bind=self.engine)
|
95
|
-
fake_cursor.execute.assert_called_with(
|
96
|
-
('\nCREATE TABLE t (\n\t'
|
97
|
-
'pk STRING NOT NULL, \n\t'
|
98
|
-
'p STRING, \n\t'
|
99
|
-
'PRIMARY KEY (pk)\n'
|
100
|
-
') CLUSTERED BY (p)\n\n'),
|
101
|
-
())
|
102
|
-
|
103
|
-
def test_column_computed(self):
|
104
|
-
class DummyTable(self.Base):
|
105
|
-
__tablename__ = 't'
|
106
|
-
ts = sa.Column(sa.BigInteger, primary_key=True)
|
107
|
-
p = sa.Column(sa.BigInteger, sa.Computed("date_trunc('day', ts)"))
|
108
|
-
self.Base.metadata.create_all(bind=self.engine)
|
109
|
-
fake_cursor.execute.assert_called_with(
|
110
|
-
('\nCREATE TABLE t (\n\t'
|
111
|
-
'ts LONG NOT NULL, \n\t'
|
112
|
-
'p LONG GENERATED ALWAYS AS (date_trunc(\'day\', ts)), \n\t'
|
113
|
-
'PRIMARY KEY (ts)\n'
|
114
|
-
')\n\n'),
|
115
|
-
())
|
116
|
-
|
117
|
-
def test_column_computed_virtual(self):
|
118
|
-
class DummyTable(self.Base):
|
119
|
-
__tablename__ = 't'
|
120
|
-
ts = sa.Column(sa.BigInteger, primary_key=True)
|
121
|
-
p = sa.Column(sa.BigInteger, sa.Computed("date_trunc('day', ts)", persisted=False))
|
122
|
-
with self.assertRaises(sa.exc.CompileError):
|
123
|
-
self.Base.metadata.create_all(bind=self.engine)
|
124
|
-
|
125
|
-
def test_table_partitioned_by(self):
|
126
|
-
class DummyTable(self.Base):
|
127
|
-
__tablename__ = 't'
|
128
|
-
__table_args__ = {
|
129
|
-
'crate_partitioned_by': 'p',
|
130
|
-
'invalid_option': 1
|
131
|
-
}
|
132
|
-
pk = sa.Column(sa.String, primary_key=True)
|
133
|
-
p = sa.Column(sa.String)
|
134
|
-
self.Base.metadata.create_all(bind=self.engine)
|
135
|
-
fake_cursor.execute.assert_called_with(
|
136
|
-
('\nCREATE TABLE t (\n\t'
|
137
|
-
'pk STRING NOT NULL, \n\t'
|
138
|
-
'p STRING, \n\t'
|
139
|
-
'PRIMARY KEY (pk)\n'
|
140
|
-
') PARTITIONED BY (p)\n\n'),
|
141
|
-
())
|
142
|
-
|
143
|
-
def test_table_number_of_shards_and_replicas(self):
|
144
|
-
class DummyTable(self.Base):
|
145
|
-
__tablename__ = 't'
|
146
|
-
__table_args__ = {
|
147
|
-
'crate_number_of_replicas': '2',
|
148
|
-
'crate_number_of_shards': 3
|
149
|
-
}
|
150
|
-
pk = sa.Column(sa.String, primary_key=True)
|
151
|
-
|
152
|
-
self.Base.metadata.create_all(bind=self.engine)
|
153
|
-
fake_cursor.execute.assert_called_with(
|
154
|
-
('\nCREATE TABLE t (\n\t'
|
155
|
-
'pk STRING NOT NULL, \n\t'
|
156
|
-
'PRIMARY KEY (pk)\n'
|
157
|
-
') CLUSTERED INTO 3 SHARDS WITH (NUMBER_OF_REPLICAS = 2)\n\n'),
|
158
|
-
())
|
159
|
-
|
160
|
-
def test_table_clustered_by_and_number_of_shards(self):
|
161
|
-
class DummyTable(self.Base):
|
162
|
-
__tablename__ = 't'
|
163
|
-
__table_args__ = {
|
164
|
-
'crate_clustered_by': 'p',
|
165
|
-
'crate_number_of_shards': 3
|
166
|
-
}
|
167
|
-
pk = sa.Column(sa.String, primary_key=True)
|
168
|
-
p = sa.Column(sa.String, primary_key=True)
|
169
|
-
self.Base.metadata.create_all(bind=self.engine)
|
170
|
-
fake_cursor.execute.assert_called_with(
|
171
|
-
('\nCREATE TABLE t (\n\t'
|
172
|
-
'pk STRING NOT NULL, \n\t'
|
173
|
-
'p STRING NOT NULL, \n\t'
|
174
|
-
'PRIMARY KEY (pk, p)\n'
|
175
|
-
') CLUSTERED BY (p) INTO 3 SHARDS\n\n'),
|
176
|
-
())
|
177
|
-
|
178
|
-
def test_column_object_array(self):
|
179
|
-
class DummyTable(self.Base):
|
180
|
-
__tablename__ = 't'
|
181
|
-
pk = sa.Column(sa.String, primary_key=True)
|
182
|
-
tags = sa.Column(ObjectArray)
|
183
|
-
|
184
|
-
self.Base.metadata.create_all(bind=self.engine)
|
185
|
-
fake_cursor.execute.assert_called_with(
|
186
|
-
('\nCREATE TABLE t (\n\t'
|
187
|
-
'pk STRING NOT NULL, \n\t'
|
188
|
-
'tags ARRAY(OBJECT), \n\t'
|
189
|
-
'PRIMARY KEY (pk)\n)\n\n'), ())
|
190
|
-
|
191
|
-
def test_column_nullable(self):
|
192
|
-
class DummyTable(self.Base):
|
193
|
-
__tablename__ = 't'
|
194
|
-
pk = sa.Column(sa.String, primary_key=True)
|
195
|
-
a = sa.Column(sa.Integer, nullable=True)
|
196
|
-
b = sa.Column(sa.Integer, nullable=False)
|
197
|
-
|
198
|
-
self.Base.metadata.create_all(bind=self.engine)
|
199
|
-
fake_cursor.execute.assert_called_with(
|
200
|
-
('\nCREATE TABLE t (\n\t'
|
201
|
-
'pk STRING NOT NULL, \n\t'
|
202
|
-
'a INT, \n\t'
|
203
|
-
'b INT NOT NULL, \n\t'
|
204
|
-
'PRIMARY KEY (pk)\n)\n\n'), ())
|
205
|
-
|
206
|
-
def test_column_pk_nullable(self):
|
207
|
-
class DummyTable(self.Base):
|
208
|
-
__tablename__ = 't'
|
209
|
-
pk = sa.Column(sa.String, primary_key=True, nullable=True)
|
210
|
-
with self.assertRaises(sa.exc.CompileError):
|
211
|
-
self.Base.metadata.create_all(bind=self.engine)
|
212
|
-
|
213
|
-
def test_column_crate_index(self):
|
214
|
-
class DummyTable(self.Base):
|
215
|
-
__tablename__ = 't'
|
216
|
-
pk = sa.Column(sa.String, primary_key=True)
|
217
|
-
a = sa.Column(sa.Integer, crate_index=False)
|
218
|
-
b = sa.Column(sa.Integer, crate_index=True)
|
219
|
-
|
220
|
-
self.Base.metadata.create_all(bind=self.engine)
|
221
|
-
fake_cursor.execute.assert_called_with(
|
222
|
-
('\nCREATE TABLE t (\n\t'
|
223
|
-
'pk STRING NOT NULL, \n\t'
|
224
|
-
'a INT INDEX OFF, \n\t'
|
225
|
-
'b INT, \n\t'
|
226
|
-
'PRIMARY KEY (pk)\n)\n\n'), ())
|
227
|
-
|
228
|
-
def test_column_geopoint_without_index(self):
|
229
|
-
class DummyTable(self.Base):
|
230
|
-
__tablename__ = 't'
|
231
|
-
pk = sa.Column(sa.String, primary_key=True)
|
232
|
-
a = sa.Column(Geopoint, crate_index=False)
|
233
|
-
with self.assertRaises(sa.exc.CompileError):
|
234
|
-
self.Base.metadata.create_all(bind=self.engine)
|
235
|
-
|
236
|
-
def test_text_column_without_columnstore(self):
|
237
|
-
class DummyTable(self.Base):
|
238
|
-
__tablename__ = 't'
|
239
|
-
pk = sa.Column(sa.String, primary_key=True)
|
240
|
-
a = sa.Column(sa.String, crate_columnstore=False)
|
241
|
-
b = sa.Column(sa.String, crate_columnstore=True)
|
242
|
-
c = sa.Column(sa.String)
|
243
|
-
|
244
|
-
self.Base.metadata.create_all(bind=self.engine)
|
245
|
-
|
246
|
-
fake_cursor.execute.assert_called_with(
|
247
|
-
('\nCREATE TABLE t (\n\t'
|
248
|
-
'pk STRING NOT NULL, \n\t'
|
249
|
-
'a STRING STORAGE WITH (columnstore = false), \n\t'
|
250
|
-
'b STRING, \n\t'
|
251
|
-
'c STRING, \n\t'
|
252
|
-
'PRIMARY KEY (pk)\n)\n\n'), ())
|
253
|
-
|
254
|
-
def test_non_text_column_without_columnstore(self):
|
255
|
-
class DummyTable(self.Base):
|
256
|
-
__tablename__ = 't'
|
257
|
-
pk = sa.Column(sa.String, primary_key=True)
|
258
|
-
a = sa.Column(sa.Integer, crate_columnstore=False)
|
259
|
-
|
260
|
-
with self.assertRaises(sa.exc.CompileError):
|
261
|
-
self.Base.metadata.create_all(bind=self.engine)
|
262
|
-
|
263
|
-
def test_column_server_default_text_func(self):
|
264
|
-
class DummyTable(self.Base):
|
265
|
-
__tablename__ = 't'
|
266
|
-
pk = sa.Column(sa.String, primary_key=True)
|
267
|
-
a = sa.Column(sa.DateTime, server_default=sa.text("now()"))
|
268
|
-
|
269
|
-
self.Base.metadata.create_all(bind=self.engine)
|
270
|
-
fake_cursor.execute.assert_called_with(
|
271
|
-
('\nCREATE TABLE t (\n\t'
|
272
|
-
'pk STRING NOT NULL, \n\t'
|
273
|
-
'a TIMESTAMP DEFAULT now(), \n\t'
|
274
|
-
'PRIMARY KEY (pk)\n)\n\n'), ())
|
275
|
-
|
276
|
-
def test_column_server_default_string(self):
|
277
|
-
class DummyTable(self.Base):
|
278
|
-
__tablename__ = 't'
|
279
|
-
pk = sa.Column(sa.String, primary_key=True)
|
280
|
-
a = sa.Column(sa.String, server_default="Zaphod")
|
281
|
-
|
282
|
-
self.Base.metadata.create_all(bind=self.engine)
|
283
|
-
fake_cursor.execute.assert_called_with(
|
284
|
-
('\nCREATE TABLE t (\n\t'
|
285
|
-
'pk STRING NOT NULL, \n\t'
|
286
|
-
'a STRING DEFAULT \'Zaphod\', \n\t'
|
287
|
-
'PRIMARY KEY (pk)\n)\n\n'), ())
|
288
|
-
|
289
|
-
def test_column_server_default_func(self):
|
290
|
-
class DummyTable(self.Base):
|
291
|
-
__tablename__ = 't'
|
292
|
-
pk = sa.Column(sa.String, primary_key=True)
|
293
|
-
a = sa.Column(sa.DateTime, server_default=sa.func.now())
|
294
|
-
|
295
|
-
self.Base.metadata.create_all(bind=self.engine)
|
296
|
-
fake_cursor.execute.assert_called_with(
|
297
|
-
('\nCREATE TABLE t (\n\t'
|
298
|
-
'pk STRING NOT NULL, \n\t'
|
299
|
-
'a TIMESTAMP DEFAULT now(), \n\t'
|
300
|
-
'PRIMARY KEY (pk)\n)\n\n'), ())
|
301
|
-
|
302
|
-
def test_column_server_default_text_constant(self):
|
303
|
-
class DummyTable(self.Base):
|
304
|
-
__tablename__ = 't'
|
305
|
-
pk = sa.Column(sa.String, primary_key=True)
|
306
|
-
answer = sa.Column(sa.Integer, server_default=sa.text("42"))
|
307
|
-
|
308
|
-
self.Base.metadata.create_all(bind=self.engine)
|
309
|
-
fake_cursor.execute.assert_called_with(
|
310
|
-
('\nCREATE TABLE t (\n\t'
|
311
|
-
'pk STRING NOT NULL, \n\t'
|
312
|
-
'answer INT DEFAULT 42, \n\t'
|
313
|
-
'PRIMARY KEY (pk)\n)\n\n'), ())
|
@@ -1,90 +0,0 @@
|
|
1
|
-
# -*- coding: utf-8; -*-
|
2
|
-
#
|
3
|
-
# Licensed to CRATE Technology GmbH ("Crate") under one or more contributor
|
4
|
-
# license agreements. See the NOTICE file distributed with this work for
|
5
|
-
# additional information regarding copyright ownership. Crate licenses
|
6
|
-
# this file to you under the Apache License, Version 2.0 (the "License");
|
7
|
-
# you may not use this file except in compliance with the License. You may
|
8
|
-
# obtain a copy of the License at
|
9
|
-
#
|
10
|
-
# http://www.apache.org/licenses/LICENSE-2.0
|
11
|
-
#
|
12
|
-
# Unless required by applicable law or agreed to in writing, software
|
13
|
-
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
14
|
-
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
15
|
-
# License for the specific language governing permissions and limitations
|
16
|
-
# under the License.
|
17
|
-
#
|
18
|
-
# However, if you have executed another commercial license agreement
|
19
|
-
# with Crate these terms will supersede the license and you may use the
|
20
|
-
# software solely pursuant to the terms of the relevant commercial agreement.
|
21
|
-
|
22
|
-
from __future__ import absolute_import
|
23
|
-
from datetime import datetime, tzinfo, timedelta
|
24
|
-
from unittest import TestCase
|
25
|
-
from unittest.mock import patch, MagicMock
|
26
|
-
|
27
|
-
import sqlalchemy as sa
|
28
|
-
from sqlalchemy.exc import DBAPIError
|
29
|
-
from sqlalchemy.orm import Session
|
30
|
-
try:
|
31
|
-
from sqlalchemy.orm import declarative_base
|
32
|
-
except ImportError:
|
33
|
-
from sqlalchemy.ext.declarative import declarative_base
|
34
|
-
|
35
|
-
from crate.client.cursor import Cursor
|
36
|
-
|
37
|
-
|
38
|
-
fake_cursor = MagicMock(name='fake_cursor')
|
39
|
-
FakeCursor = MagicMock(name='FakeCursor', spec=Cursor)
|
40
|
-
FakeCursor.return_value = fake_cursor
|
41
|
-
|
42
|
-
|
43
|
-
class CST(tzinfo):
|
44
|
-
"""
|
45
|
-
Timezone object for CST
|
46
|
-
"""
|
47
|
-
|
48
|
-
def utcoffset(self, date_time):
|
49
|
-
return timedelta(seconds=-3600)
|
50
|
-
|
51
|
-
def dst(self, date_time):
|
52
|
-
return timedelta(seconds=-7200)
|
53
|
-
|
54
|
-
|
55
|
-
@patch('crate.client.connection.Cursor', FakeCursor)
|
56
|
-
class SqlAlchemyDateAndDateTimeTest(TestCase):
|
57
|
-
|
58
|
-
def setUp(self):
|
59
|
-
self.engine = sa.create_engine('crate://')
|
60
|
-
Base = declarative_base()
|
61
|
-
|
62
|
-
class Character(Base):
|
63
|
-
__tablename__ = 'characters'
|
64
|
-
name = sa.Column(sa.String, primary_key=True)
|
65
|
-
date = sa.Column(sa.Date)
|
66
|
-
timestamp = sa.Column(sa.DateTime)
|
67
|
-
|
68
|
-
fake_cursor.description = (
|
69
|
-
('characters_name', None, None, None, None, None, None),
|
70
|
-
('characters_date', None, None, None, None, None, None)
|
71
|
-
)
|
72
|
-
self.session = Session(bind=self.engine)
|
73
|
-
self.Character = Character
|
74
|
-
|
75
|
-
def test_date_can_handle_datetime(self):
|
76
|
-
""" date type should also be able to handle iso datetime strings.
|
77
|
-
|
78
|
-
this verifies that the fallback in the Date result_processor works.
|
79
|
-
"""
|
80
|
-
fake_cursor.fetchall.return_value = [
|
81
|
-
('Trillian', '2013-07-16T00:00:00.000Z')
|
82
|
-
]
|
83
|
-
self.session.query(self.Character).first()
|
84
|
-
|
85
|
-
def test_date_cannot_handle_tz_aware_datetime(self):
|
86
|
-
character = self.Character()
|
87
|
-
character.name = "Athur"
|
88
|
-
character.timestamp = datetime(2009, 5, 13, 19, 19, 30, tzinfo=CST())
|
89
|
-
self.session.add(character)
|
90
|
-
self.assertRaises(DBAPIError, self.session.commit)
|
@@ -1,156 +0,0 @@
|
|
1
|
-
# -*- coding: utf-8; -*-
|
2
|
-
#
|
3
|
-
# Licensed to CRATE Technology GmbH ("Crate") under one or more contributor
|
4
|
-
# license agreements. See the NOTICE file distributed with this work for
|
5
|
-
# additional information regarding copyright ownership. Crate licenses
|
6
|
-
# this file to you under the Apache License, Version 2.0 (the "License");
|
7
|
-
# you may not use this file except in compliance with the License. You may
|
8
|
-
# obtain a copy of the License at
|
9
|
-
#
|
10
|
-
# http://www.apache.org/licenses/LICENSE-2.0
|
11
|
-
#
|
12
|
-
# Unless required by applicable law or agreed to in writing, software
|
13
|
-
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
14
|
-
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
15
|
-
# License for the specific language governing permissions and limitations
|
16
|
-
# under the License.
|
17
|
-
#
|
18
|
-
# However, if you have executed another commercial license agreement
|
19
|
-
# with Crate these terms will supersede the license and you may use the
|
20
|
-
# software solely pursuant to the terms of the relevant commercial agreement.
|
21
|
-
|
22
|
-
from datetime import datetime
|
23
|
-
from unittest import TestCase, skipIf
|
24
|
-
from unittest.mock import MagicMock, patch
|
25
|
-
|
26
|
-
import sqlalchemy as sa
|
27
|
-
|
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
|
31
|
-
from crate.client.sqlalchemy.types import ObjectType
|
32
|
-
from sqlalchemy import inspect
|
33
|
-
from sqlalchemy.orm import Session
|
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
|
39
|
-
|
40
|
-
FakeCursor = MagicMock(name='FakeCursor', spec=Cursor)
|
41
|
-
|
42
|
-
|
43
|
-
@patch('crate.client.connection.Cursor', FakeCursor)
|
44
|
-
class SqlAlchemyDialectTest(TestCase):
|
45
|
-
|
46
|
-
def execute_wrapper(self, query, *args, **kwargs):
|
47
|
-
self.executed_statement = query
|
48
|
-
return self.fake_cursor
|
49
|
-
|
50
|
-
def setUp(self):
|
51
|
-
|
52
|
-
self.fake_cursor = MagicMock(name='fake_cursor')
|
53
|
-
FakeCursor.return_value = self.fake_cursor
|
54
|
-
|
55
|
-
self.engine = sa.create_engine('crate://')
|
56
|
-
|
57
|
-
self.executed_statement = None
|
58
|
-
|
59
|
-
self.connection = self.engine.connect()
|
60
|
-
|
61
|
-
self.fake_cursor.execute = self.execute_wrapper
|
62
|
-
|
63
|
-
self.base = declarative_base()
|
64
|
-
|
65
|
-
class Character(self.base):
|
66
|
-
__tablename__ = 'characters'
|
67
|
-
|
68
|
-
name = sa.Column(sa.String, primary_key=True)
|
69
|
-
age = sa.Column(sa.Integer, primary_key=True)
|
70
|
-
obj = sa.Column(ObjectType)
|
71
|
-
ts = sa.Column(sa.DateTime, onupdate=datetime.utcnow)
|
72
|
-
|
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)
|
81
|
-
|
82
|
-
def test_primary_keys_2_3_0(self):
|
83
|
-
insp = inspect(self.session.bind)
|
84
|
-
self.engine.dialect.server_version_info = (2, 3, 0)
|
85
|
-
|
86
|
-
self.fake_cursor.rowcount = 3
|
87
|
-
self.fake_cursor.description = (
|
88
|
-
('foo', None, None, None, None, None, None),
|
89
|
-
)
|
90
|
-
self.fake_cursor.fetchall = MagicMock(return_value=[["id"], ["id2"], ["id3"]])
|
91
|
-
|
92
|
-
eq_(insp.get_pk_constraint("characters")['constrained_columns'], {"id", "id2", "id3"})
|
93
|
-
self.fake_cursor.fetchall.assert_called_once_with()
|
94
|
-
in_("information_schema.key_column_usage", self.executed_statement)
|
95
|
-
in_("table_catalog = ?", self.executed_statement)
|
96
|
-
|
97
|
-
def test_primary_keys_3_0_0(self):
|
98
|
-
insp = inspect(self.session.bind)
|
99
|
-
self.engine.dialect.server_version_info = (3, 0, 0)
|
100
|
-
|
101
|
-
self.fake_cursor.rowcount = 3
|
102
|
-
self.fake_cursor.description = (
|
103
|
-
('foo', None, None, None, None, None, None),
|
104
|
-
)
|
105
|
-
self.fake_cursor.fetchall = MagicMock(return_value=[["id"], ["id2"], ["id3"]])
|
106
|
-
|
107
|
-
eq_(insp.get_pk_constraint("characters")['constrained_columns'], {"id", "id2", "id3"})
|
108
|
-
self.fake_cursor.fetchall.assert_called_once_with()
|
109
|
-
in_("information_schema.key_column_usage", self.executed_statement)
|
110
|
-
in_("table_schema = ?", self.executed_statement)
|
111
|
-
|
112
|
-
def test_get_table_names(self):
|
113
|
-
self.fake_cursor.rowcount = 1
|
114
|
-
self.fake_cursor.description = (
|
115
|
-
('foo', None, None, None, None, None, None),
|
116
|
-
)
|
117
|
-
self.fake_cursor.fetchall = MagicMock(return_value=[["t1"], ["t2"]])
|
118
|
-
|
119
|
-
insp = inspect(self.session.bind)
|
120
|
-
self.engine.dialect.server_version_info = (2, 0, 0)
|
121
|
-
eq_(insp.get_table_names(schema="doc"),
|
122
|
-
['t1', 't2'])
|
123
|
-
in_("WHERE table_schema = ? AND table_type = 'BASE TABLE' ORDER BY", self.executed_statement)
|
124
|
-
|
125
|
-
def test_get_view_names(self):
|
126
|
-
self.fake_cursor.rowcount = 1
|
127
|
-
self.fake_cursor.description = (
|
128
|
-
('foo', None, None, None, None, None, None),
|
129
|
-
)
|
130
|
-
self.fake_cursor.fetchall = MagicMock(return_value=[["v1"], ["v2"]])
|
131
|
-
|
132
|
-
insp = inspect(self.session.bind)
|
133
|
-
self.engine.dialect.server_version_info = (2, 0, 0)
|
134
|
-
eq_(insp.get_view_names(schema="doc"),
|
135
|
-
['v1', 'v2'])
|
136
|
-
eq_(self.executed_statement, "SELECT table_name FROM information_schema.views "
|
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")
|