zlmdb 25.10.1__cp311-cp311-macosx_10_9_universal2.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.
Potentially problematic release.
This version of zlmdb might be problematic. Click here for more details.
- flatbuffers/__init__.py +19 -0
- flatbuffers/_version.py +17 -0
- flatbuffers/builder.py +776 -0
- flatbuffers/compat.py +86 -0
- flatbuffers/encode.py +42 -0
- flatbuffers/flexbuffers.py +1527 -0
- flatbuffers/number_types.py +181 -0
- flatbuffers/packer.py +42 -0
- flatbuffers/reflection/AdvancedFeatures.py +10 -0
- flatbuffers/reflection/BaseType.py +24 -0
- flatbuffers/reflection/Enum.py +169 -0
- flatbuffers/reflection/EnumVal.py +96 -0
- flatbuffers/reflection/Field.py +208 -0
- flatbuffers/reflection/KeyValue.py +56 -0
- flatbuffers/reflection/Object.py +175 -0
- flatbuffers/reflection/RPCCall.py +131 -0
- flatbuffers/reflection/Schema.py +206 -0
- flatbuffers/reflection/SchemaFile.py +77 -0
- flatbuffers/reflection/Service.py +145 -0
- flatbuffers/reflection/Type.py +98 -0
- flatbuffers/reflection/__init__.py +0 -0
- flatbuffers/table.py +129 -0
- flatbuffers/util.py +43 -0
- zlmdb/__init__.py +312 -0
- zlmdb/_database.py +990 -0
- zlmdb/_errors.py +31 -0
- zlmdb/_meta.py +27 -0
- zlmdb/_pmap.py +1667 -0
- zlmdb/_schema.py +137 -0
- zlmdb/_transaction.py +181 -0
- zlmdb/_types.py +1596 -0
- zlmdb/_version.py +27 -0
- zlmdb/cli.py +41 -0
- zlmdb/flatbuffers/__init__.py +5 -0
- zlmdb/flatbuffers/reflection/AdvancedFeatures.py +10 -0
- zlmdb/flatbuffers/reflection/BaseType.py +25 -0
- zlmdb/flatbuffers/reflection/Enum.py +252 -0
- zlmdb/flatbuffers/reflection/EnumVal.py +144 -0
- zlmdb/flatbuffers/reflection/Field.py +325 -0
- zlmdb/flatbuffers/reflection/KeyValue.py +84 -0
- zlmdb/flatbuffers/reflection/Object.py +260 -0
- zlmdb/flatbuffers/reflection/RPCCall.py +195 -0
- zlmdb/flatbuffers/reflection/Schema.py +301 -0
- zlmdb/flatbuffers/reflection/SchemaFile.py +112 -0
- zlmdb/flatbuffers/reflection/Service.py +213 -0
- zlmdb/flatbuffers/reflection/Type.py +148 -0
- zlmdb/flatbuffers/reflection/__init__.py +0 -0
- zlmdb/flatbuffers/reflection.fbs +152 -0
- zlmdb/lmdb/__init__.py +37 -0
- zlmdb/lmdb/__main__.py +25 -0
- zlmdb/lmdb/_config.py +10 -0
- zlmdb/lmdb/_lmdb_cffi.cpython-311-darwin.so +0 -0
- zlmdb/lmdb/cffi.py +2606 -0
- zlmdb/lmdb/tool.py +670 -0
- zlmdb/tests/lmdb/__init__.py +0 -0
- zlmdb/tests/lmdb/address_book.py +287 -0
- zlmdb/tests/lmdb/crash_test.py +339 -0
- zlmdb/tests/lmdb/cursor_test.py +333 -0
- zlmdb/tests/lmdb/env_test.py +919 -0
- zlmdb/tests/lmdb/getmulti_test.py +92 -0
- zlmdb/tests/lmdb/iteration_test.py +258 -0
- zlmdb/tests/lmdb/package_test.py +70 -0
- zlmdb/tests/lmdb/test_lmdb.py +188 -0
- zlmdb/tests/lmdb/testlib.py +185 -0
- zlmdb/tests/lmdb/tool_test.py +60 -0
- zlmdb/tests/lmdb/txn_test.py +575 -0
- zlmdb/tests/orm/MNodeLog.py +853 -0
- zlmdb/tests/orm/__init__.py +0 -0
- zlmdb/tests/orm/_schema_fbs.py +215 -0
- zlmdb/tests/orm/_schema_mnode_log.py +1201 -0
- zlmdb/tests/orm/_schema_py2.py +250 -0
- zlmdb/tests/orm/_schema_py3.py +307 -0
- zlmdb/tests/orm/_test_flatbuffers.py +144 -0
- zlmdb/tests/orm/_test_serialization.py +144 -0
- zlmdb/tests/orm/test_basic.py +217 -0
- zlmdb/tests/orm/test_etcd.py +275 -0
- zlmdb/tests/orm/test_pmap_indexes.py +466 -0
- zlmdb/tests/orm/test_pmap_types.py +90 -0
- zlmdb/tests/orm/test_pmaps.py +295 -0
- zlmdb/tests/orm/test_select.py +619 -0
- zlmdb-25.10.1.dist-info/METADATA +264 -0
- zlmdb-25.10.1.dist-info/RECORD +87 -0
- zlmdb-25.10.1.dist-info/WHEEL +5 -0
- zlmdb-25.10.1.dist-info/entry_points.txt +2 -0
- zlmdb-25.10.1.dist-info/licenses/LICENSE +137 -0
- zlmdb-25.10.1.dist-info/licenses/NOTICE +41 -0
- zlmdb-25.10.1.dist-info/top_level.txt +2 -0
|
@@ -0,0 +1,466 @@
|
|
|
1
|
+
###############################################################################
|
|
2
|
+
#
|
|
3
|
+
# The MIT License (MIT)
|
|
4
|
+
#
|
|
5
|
+
# Copyright (c) typedef int GmbH
|
|
6
|
+
#
|
|
7
|
+
# Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
8
|
+
# of this software and associated documentation files (the "Software"), to deal
|
|
9
|
+
# in the Software without restriction, including without limitation the rights
|
|
10
|
+
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
11
|
+
# copies of the Software, and to permit persons to whom the Software is
|
|
12
|
+
# furnished to do so, subject to the following conditions:
|
|
13
|
+
#
|
|
14
|
+
# The above copyright notice and this permission notice shall be included in
|
|
15
|
+
# all copies or substantial portions of the Software.
|
|
16
|
+
#
|
|
17
|
+
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
18
|
+
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
19
|
+
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
20
|
+
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
21
|
+
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
22
|
+
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
|
23
|
+
# THE SOFTWARE.
|
|
24
|
+
#
|
|
25
|
+
###############################################################################
|
|
26
|
+
|
|
27
|
+
import os
|
|
28
|
+
import sys
|
|
29
|
+
import pytest
|
|
30
|
+
import logging
|
|
31
|
+
from copy import deepcopy
|
|
32
|
+
|
|
33
|
+
import txaio
|
|
34
|
+
|
|
35
|
+
txaio.use_twisted()
|
|
36
|
+
|
|
37
|
+
import zlmdb # noqa
|
|
38
|
+
|
|
39
|
+
try:
|
|
40
|
+
from tempfile import TemporaryDirectory
|
|
41
|
+
except ImportError:
|
|
42
|
+
from backports.tempfile import TemporaryDirectory # type:ignore
|
|
43
|
+
|
|
44
|
+
sys.path.append(os.path.dirname(os.path.abspath(__file__)))
|
|
45
|
+
|
|
46
|
+
if sys.version_info >= (3, 6):
|
|
47
|
+
logging.info("Using _schema_py3 !")
|
|
48
|
+
from _schema_py3 import User, Schema4
|
|
49
|
+
else:
|
|
50
|
+
logging.info("Using _schema_py2 !")
|
|
51
|
+
from _schema_py2 import User, Schema4
|
|
52
|
+
|
|
53
|
+
|
|
54
|
+
@pytest.fixture(scope="function")
|
|
55
|
+
def testset1(N=10, M=100):
|
|
56
|
+
users = []
|
|
57
|
+
for j in range(N):
|
|
58
|
+
for i in range(M):
|
|
59
|
+
user = User.create_test_user(oid=j * M + i, realm_oid=j)
|
|
60
|
+
users.append(user)
|
|
61
|
+
return users
|
|
62
|
+
|
|
63
|
+
|
|
64
|
+
def test_fill_indexes(testset1):
|
|
65
|
+
"""
|
|
66
|
+
Fill a table with multiple indexes with data records that have all columns filled
|
|
67
|
+
with NON-NULL values.
|
|
68
|
+
"""
|
|
69
|
+
with TemporaryDirectory() as dbpath:
|
|
70
|
+
schema = Schema4()
|
|
71
|
+
|
|
72
|
+
with zlmdb.Database(dbpath) as db:
|
|
73
|
+
stats = zlmdb.TransactionStats()
|
|
74
|
+
|
|
75
|
+
# fill table, which also triggers inserts into the index pmaps
|
|
76
|
+
with db.begin(write=True, stats=stats) as txn:
|
|
77
|
+
for user in testset1:
|
|
78
|
+
schema.users[txn, user.oid] = user
|
|
79
|
+
|
|
80
|
+
# check indexes has been written to (in addition to the table itself)
|
|
81
|
+
num_indexes = len(schema.users.indexes())
|
|
82
|
+
assert stats.puts == len(testset1) * (1 + num_indexes)
|
|
83
|
+
|
|
84
|
+
# check saved objects
|
|
85
|
+
with db.begin() as txn:
|
|
86
|
+
for user in testset1:
|
|
87
|
+
obj = schema.users[txn, user.oid]
|
|
88
|
+
|
|
89
|
+
assert user == obj
|
|
90
|
+
|
|
91
|
+
# check unique indexes
|
|
92
|
+
with db.begin() as txn:
|
|
93
|
+
for user in testset1:
|
|
94
|
+
user_oid = schema.idx_users_by_authid[txn, user.authid]
|
|
95
|
+
assert user.oid == user_oid
|
|
96
|
+
|
|
97
|
+
user_oid = schema.idx_users_by_email[txn, user.email]
|
|
98
|
+
assert user.oid == user_oid
|
|
99
|
+
|
|
100
|
+
user_oid = schema.idx_users_by_icecream[
|
|
101
|
+
txn, (user.icecream, user.oid)
|
|
102
|
+
]
|
|
103
|
+
assert user.oid == user_oid
|
|
104
|
+
|
|
105
|
+
user_oid = schema.idx_users_by_mrealm_authid[
|
|
106
|
+
txn, (user.mrealm, user.authid)
|
|
107
|
+
]
|
|
108
|
+
assert user.oid == user_oid
|
|
109
|
+
|
|
110
|
+
user_oid = schema.idx_users_by_mrealm_notnull_authid[
|
|
111
|
+
txn, (user.mrealm_notnull, user.authid)
|
|
112
|
+
]
|
|
113
|
+
assert user.oid == user_oid
|
|
114
|
+
|
|
115
|
+
# check non-unique index
|
|
116
|
+
users_by_icecream = {}
|
|
117
|
+
for user in testset1:
|
|
118
|
+
if user.icecream not in users_by_icecream:
|
|
119
|
+
users_by_icecream[user.icecream] = set()
|
|
120
|
+
users_by_icecream[user.icecream].add(user.oid)
|
|
121
|
+
|
|
122
|
+
MAX_OID = 9007199254740992
|
|
123
|
+
with db.begin() as txn:
|
|
124
|
+
for icecream in users_by_icecream:
|
|
125
|
+
for _, user_oid in schema.idx_users_by_icecream.select(
|
|
126
|
+
txn,
|
|
127
|
+
from_key=(icecream, 0),
|
|
128
|
+
to_key=(icecream, MAX_OID + 1),
|
|
129
|
+
return_values=False,
|
|
130
|
+
):
|
|
131
|
+
assert user_oid in users_by_icecream[icecream]
|
|
132
|
+
|
|
133
|
+
|
|
134
|
+
def test_fill_indexes_nullable(testset1):
|
|
135
|
+
"""
|
|
136
|
+
Test filling a table with multiple indexes, some of which are on NULLable columns, and fill
|
|
137
|
+
with records that have those column values actually NULL.
|
|
138
|
+
"""
|
|
139
|
+
with TemporaryDirectory() as dbpath:
|
|
140
|
+
schema = Schema4()
|
|
141
|
+
|
|
142
|
+
with zlmdb.Database(dbpath) as db:
|
|
143
|
+
stats = zlmdb.TransactionStats()
|
|
144
|
+
|
|
145
|
+
with db.begin(write=True, stats=stats) as txn:
|
|
146
|
+
for user in testset1:
|
|
147
|
+
_user = deepcopy(user)
|
|
148
|
+
|
|
149
|
+
# "user.email" is an indexed column that is nullable
|
|
150
|
+
_user.email = None
|
|
151
|
+
|
|
152
|
+
# "user.mrealm" is an indexed (composite) column that is nullable
|
|
153
|
+
_user.mrealm = None
|
|
154
|
+
schema.users[txn, _user.oid] = _user
|
|
155
|
+
|
|
156
|
+
# check indexes has been written to (in addition to the table itself)
|
|
157
|
+
num_indexes = len(schema.users.indexes())
|
|
158
|
+
|
|
159
|
+
# because we have set 2 indexed columns to NULL, we need to subtract those 2
|
|
160
|
+
# from the total number of indexes
|
|
161
|
+
assert stats.puts == len(testset1) * (1 + num_indexes - 2)
|
|
162
|
+
|
|
163
|
+
# check saved objects
|
|
164
|
+
with db.begin() as txn:
|
|
165
|
+
for user in testset1:
|
|
166
|
+
_user = deepcopy(user)
|
|
167
|
+
_user.email = None
|
|
168
|
+
_user.mrealm = None
|
|
169
|
+
|
|
170
|
+
obj = schema.users[txn, _user.oid]
|
|
171
|
+
|
|
172
|
+
assert _user == obj
|
|
173
|
+
|
|
174
|
+
# check unique indexes
|
|
175
|
+
with db.begin() as txn:
|
|
176
|
+
for user in testset1:
|
|
177
|
+
# check one of the indexes that was indeed filled
|
|
178
|
+
user_oid = schema.idx_users_by_authid[txn, user.authid]
|
|
179
|
+
assert user.oid == user_oid
|
|
180
|
+
|
|
181
|
+
# check indexes that have NOT been filled
|
|
182
|
+
user_oid = schema.idx_users_by_email[txn, user.email]
|
|
183
|
+
assert user_oid is None
|
|
184
|
+
|
|
185
|
+
user_oid = schema.idx_users_by_mrealm_authid[
|
|
186
|
+
txn, (user.mrealm, user.authid)
|
|
187
|
+
]
|
|
188
|
+
assert user_oid is None
|
|
189
|
+
|
|
190
|
+
|
|
191
|
+
def test_fill_index_non_nullable_raises(testset1):
|
|
192
|
+
"""
|
|
193
|
+
Insert records into a table with a unique-non-nullable index with the
|
|
194
|
+
record having a NULL value in the indexed column raises an exception.
|
|
195
|
+
"""
|
|
196
|
+
with TemporaryDirectory() as dbpath:
|
|
197
|
+
schema = Schema4()
|
|
198
|
+
|
|
199
|
+
with zlmdb.Database(dbpath) as db:
|
|
200
|
+
with db.begin(write=True) as txn:
|
|
201
|
+
for user in testset1:
|
|
202
|
+
# "user.authid" is an indexed column that is non-nullable
|
|
203
|
+
_user = deepcopy(user)
|
|
204
|
+
_user.authid = None
|
|
205
|
+
with pytest.raises(zlmdb.NullValueConstraint):
|
|
206
|
+
schema.users[txn, _user.oid] = _user
|
|
207
|
+
|
|
208
|
+
# "user.mrealm_notnull" is an indexed (composite) column that is non-nullable
|
|
209
|
+
_user = deepcopy(user)
|
|
210
|
+
_user.mrealm_notnull = None
|
|
211
|
+
with pytest.raises(zlmdb.NullValueConstraint):
|
|
212
|
+
schema.users[txn, _user.oid] = _user
|
|
213
|
+
|
|
214
|
+
|
|
215
|
+
def test_fill_non_unique_indexes(testset1):
|
|
216
|
+
"""
|
|
217
|
+
Insert records into a table with a non-unique, non-nullable indexed column.
|
|
218
|
+
"""
|
|
219
|
+
with TemporaryDirectory() as dbpath:
|
|
220
|
+
schema = Schema4()
|
|
221
|
+
|
|
222
|
+
with zlmdb.Database(dbpath) as db:
|
|
223
|
+
stats = zlmdb.TransactionStats()
|
|
224
|
+
|
|
225
|
+
with db.begin(write=True, stats=stats) as txn:
|
|
226
|
+
for user in testset1:
|
|
227
|
+
schema.users[txn, user.oid] = user
|
|
228
|
+
|
|
229
|
+
# check non-unique indexes
|
|
230
|
+
with db.begin() as txn:
|
|
231
|
+
for j in range(10):
|
|
232
|
+
user_oids = list(
|
|
233
|
+
schema.idx_users_by_realm.select(
|
|
234
|
+
txn, return_keys=False, from_key=(j, 0), to_key=(j + 1, 0)
|
|
235
|
+
)
|
|
236
|
+
)
|
|
237
|
+
|
|
238
|
+
assert list(range(j * 100, (j + 1) * 100)) == user_oids
|
|
239
|
+
|
|
240
|
+
|
|
241
|
+
def test_delete_indexes(testset1):
|
|
242
|
+
"""
|
|
243
|
+
Insert records into a table with indexes, delete data records and check that index
|
|
244
|
+
records have been deleted as a consequence too.
|
|
245
|
+
"""
|
|
246
|
+
with TemporaryDirectory() as dbpath:
|
|
247
|
+
schema = Schema4()
|
|
248
|
+
|
|
249
|
+
with zlmdb.Database(dbpath) as db:
|
|
250
|
+
stats = zlmdb.TransactionStats()
|
|
251
|
+
|
|
252
|
+
# insert data records
|
|
253
|
+
with db.begin(write=True, stats=stats) as txn:
|
|
254
|
+
for user in testset1:
|
|
255
|
+
schema.users[txn, user.oid] = user
|
|
256
|
+
|
|
257
|
+
# check that all index records have been deleted as well
|
|
258
|
+
with db.begin(write=True) as txn:
|
|
259
|
+
for user in testset1:
|
|
260
|
+
del schema.users[txn, user.oid]
|
|
261
|
+
|
|
262
|
+
user_oid = schema.idx_users_by_authid[txn, user.authid]
|
|
263
|
+
assert user_oid is None
|
|
264
|
+
|
|
265
|
+
user_oid = schema.idx_users_by_email[txn, user.email]
|
|
266
|
+
assert user_oid is None
|
|
267
|
+
|
|
268
|
+
user_oid = schema.idx_users_by_realm[
|
|
269
|
+
txn, (user.realm_oid, user.oid)
|
|
270
|
+
]
|
|
271
|
+
assert user_oid is None
|
|
272
|
+
|
|
273
|
+
user_oid = schema.idx_users_by_icecream[
|
|
274
|
+
txn, (user.icecream, user.oid)
|
|
275
|
+
]
|
|
276
|
+
assert user_oid is None
|
|
277
|
+
|
|
278
|
+
user_oid = schema.idx_users_by_mrealm_authid[
|
|
279
|
+
txn, (user.mrealm, user.authid)
|
|
280
|
+
]
|
|
281
|
+
assert user_oid is None
|
|
282
|
+
|
|
283
|
+
user_oid = schema.idx_users_by_mrealm_notnull_authid[
|
|
284
|
+
txn, (user.mrealm_notnull, user.authid)
|
|
285
|
+
]
|
|
286
|
+
assert user_oid is None
|
|
287
|
+
|
|
288
|
+
|
|
289
|
+
def test_delete_nonunique_indexes(testset1):
|
|
290
|
+
"""
|
|
291
|
+
Insert records into a table with a non-unique index, delete data records and check
|
|
292
|
+
that index records have been deleted as a consequence too.
|
|
293
|
+
"""
|
|
294
|
+
with TemporaryDirectory() as dbpath:
|
|
295
|
+
schema = Schema4()
|
|
296
|
+
|
|
297
|
+
with zlmdb.Database(dbpath) as db:
|
|
298
|
+
stats = zlmdb.TransactionStats()
|
|
299
|
+
|
|
300
|
+
with db.begin(write=True, stats=stats) as txn:
|
|
301
|
+
for user in testset1:
|
|
302
|
+
schema.users[txn, user.oid] = user
|
|
303
|
+
|
|
304
|
+
with db.begin(write=True) as txn:
|
|
305
|
+
for user in testset1:
|
|
306
|
+
del schema.users[txn, user.oid]
|
|
307
|
+
|
|
308
|
+
with db.begin() as txn:
|
|
309
|
+
for j in range(10):
|
|
310
|
+
user_oids = list(
|
|
311
|
+
schema.idx_users_by_realm.select(
|
|
312
|
+
txn, return_keys=False, from_key=(j, 0), to_key=(j + 1, 0)
|
|
313
|
+
)
|
|
314
|
+
)
|
|
315
|
+
|
|
316
|
+
assert [] == user_oids
|
|
317
|
+
|
|
318
|
+
|
|
319
|
+
def test_delete_nonindexes2(testset1):
|
|
320
|
+
"""
|
|
321
|
+
|
|
322
|
+
WARNING: quadratic run-time (in testset size)
|
|
323
|
+
"""
|
|
324
|
+
with TemporaryDirectory() as dbpath:
|
|
325
|
+
schema = Schema4()
|
|
326
|
+
|
|
327
|
+
with zlmdb.Database(dbpath) as db:
|
|
328
|
+
stats = zlmdb.TransactionStats()
|
|
329
|
+
|
|
330
|
+
with db.begin(write=True, stats=stats) as txn:
|
|
331
|
+
for user in testset1:
|
|
332
|
+
schema.users[txn, user.oid] = user
|
|
333
|
+
|
|
334
|
+
with db.begin(write=True) as txn:
|
|
335
|
+
for j in range(10):
|
|
336
|
+
fullset = set(range(j * 100, (j + 1) * 100))
|
|
337
|
+
for i in range(100):
|
|
338
|
+
user_oid = j * 100 + i
|
|
339
|
+
del schema.users[txn, user_oid]
|
|
340
|
+
fullset.discard(user_oid)
|
|
341
|
+
|
|
342
|
+
user_oids = set(
|
|
343
|
+
schema.idx_users_by_realm.select(
|
|
344
|
+
txn,
|
|
345
|
+
return_keys=False,
|
|
346
|
+
from_key=(j, 0),
|
|
347
|
+
to_key=(j + 1, 0),
|
|
348
|
+
)
|
|
349
|
+
)
|
|
350
|
+
|
|
351
|
+
assert fullset == user_oids
|
|
352
|
+
|
|
353
|
+
|
|
354
|
+
def test_set_null_indexes_nullable(testset1):
|
|
355
|
+
"""
|
|
356
|
+
Fill table with indexed column (unique-nullable) with indexed column
|
|
357
|
+
values NULL, then (in a 2nd transaction) set the indexed column
|
|
358
|
+
to NON-NULL value and check that index records are deleted.
|
|
359
|
+
"""
|
|
360
|
+
with TemporaryDirectory() as dbpath:
|
|
361
|
+
schema = Schema4()
|
|
362
|
+
|
|
363
|
+
with zlmdb.Database(dbpath) as db:
|
|
364
|
+
stats = zlmdb.TransactionStats()
|
|
365
|
+
|
|
366
|
+
# fill table with NON-NULLs in indexed column
|
|
367
|
+
with db.begin(write=True) as txn:
|
|
368
|
+
for user in testset1:
|
|
369
|
+
schema.users[txn, user.oid] = user
|
|
370
|
+
|
|
371
|
+
# now update table with NULLs in indexed column
|
|
372
|
+
with db.begin(write=True, stats=stats) as txn:
|
|
373
|
+
for user in testset1:
|
|
374
|
+
_user = schema.users[txn, user.oid]
|
|
375
|
+
_user.email = None
|
|
376
|
+
schema.users[txn, _user.oid] = _user
|
|
377
|
+
|
|
378
|
+
# check that the table records have their indexed
|
|
379
|
+
# column values updated to NULLs
|
|
380
|
+
with db.begin() as txn:
|
|
381
|
+
for user in testset1:
|
|
382
|
+
_user = deepcopy(user)
|
|
383
|
+
_user.email = None
|
|
384
|
+
obj = schema.users[txn, user.oid]
|
|
385
|
+
assert _user == obj
|
|
386
|
+
|
|
387
|
+
# check that the index records that previously existed
|
|
388
|
+
# have been deleted (as the indexed column values have been
|
|
389
|
+
# set to NULLs)
|
|
390
|
+
with db.begin() as txn:
|
|
391
|
+
for user in testset1:
|
|
392
|
+
user_oid = schema.idx_users_by_authid[txn, user.authid]
|
|
393
|
+
assert user.oid == user_oid
|
|
394
|
+
|
|
395
|
+
user_oid = schema.idx_users_by_email[txn, user.email]
|
|
396
|
+
assert user_oid is None
|
|
397
|
+
|
|
398
|
+
|
|
399
|
+
def test_set_notnull_indexes_nullable(testset1):
|
|
400
|
+
"""
|
|
401
|
+
Fill table with indexed column (unique-nullable) with indexed column
|
|
402
|
+
values NON-NULL, then (in a 2nd transaction) set the indexed column
|
|
403
|
+
to NULL value and check that index records are created.
|
|
404
|
+
"""
|
|
405
|
+
with TemporaryDirectory() as dbpath:
|
|
406
|
+
schema = Schema4()
|
|
407
|
+
|
|
408
|
+
with zlmdb.Database(dbpath) as db:
|
|
409
|
+
stats = zlmdb.TransactionStats()
|
|
410
|
+
|
|
411
|
+
# fill table with NULLs in indexed column
|
|
412
|
+
with db.begin(write=True) as txn:
|
|
413
|
+
for user in testset1:
|
|
414
|
+
_user = deepcopy(user)
|
|
415
|
+
_user.email = None
|
|
416
|
+
schema.users[txn, _user.oid] = _user
|
|
417
|
+
|
|
418
|
+
# now update table with NON-NULLs in indexed column
|
|
419
|
+
with db.begin(write=True, stats=stats) as txn:
|
|
420
|
+
for user in testset1:
|
|
421
|
+
_user = schema.users[txn, user.oid]
|
|
422
|
+
_user.email = user.email
|
|
423
|
+
schema.users[txn, _user.oid] = _user
|
|
424
|
+
|
|
425
|
+
# check that the table records have their indexed
|
|
426
|
+
# column values updated to NON-NULLs
|
|
427
|
+
with db.begin() as txn:
|
|
428
|
+
for user in testset1:
|
|
429
|
+
obj = schema.users[txn, user.oid]
|
|
430
|
+
assert user == obj
|
|
431
|
+
|
|
432
|
+
# check that the index records that previously not existed
|
|
433
|
+
# have been created (as the indexed column values have been
|
|
434
|
+
# set to NON-NULLs)
|
|
435
|
+
with db.begin() as txn:
|
|
436
|
+
for user in testset1:
|
|
437
|
+
user_oid = schema.idx_users_by_authid[txn, user.authid]
|
|
438
|
+
assert user.oid == user_oid
|
|
439
|
+
|
|
440
|
+
user_oid = schema.idx_users_by_email[txn, user.email]
|
|
441
|
+
assert user.oid == user_oid
|
|
442
|
+
|
|
443
|
+
|
|
444
|
+
def test_truncate_table_with_index(testset1):
|
|
445
|
+
"""
|
|
446
|
+
Fill a table with records that has indexes, truncate the table and check that
|
|
447
|
+
all index records have been deleted as well.
|
|
448
|
+
"""
|
|
449
|
+
with TemporaryDirectory() as dbpath:
|
|
450
|
+
schema = Schema4()
|
|
451
|
+
|
|
452
|
+
with zlmdb.Database(dbpath) as db:
|
|
453
|
+
with db.begin(write=True) as txn:
|
|
454
|
+
for user in testset1:
|
|
455
|
+
schema.users[txn, user.oid] = user
|
|
456
|
+
|
|
457
|
+
stats = zlmdb.TransactionStats()
|
|
458
|
+
|
|
459
|
+
with zlmdb.Database(dbpath) as db:
|
|
460
|
+
with db.begin(write=True, stats=stats) as txn:
|
|
461
|
+
records = schema.users.truncate(txn)
|
|
462
|
+
|
|
463
|
+
assert records == len(testset1) * (len(schema.users.indexes()) + 1)
|
|
464
|
+
|
|
465
|
+
assert stats.dels == records
|
|
466
|
+
assert stats.puts == 0
|
|
@@ -0,0 +1,90 @@
|
|
|
1
|
+
###############################################################################
|
|
2
|
+
#
|
|
3
|
+
# The MIT License (MIT)
|
|
4
|
+
#
|
|
5
|
+
# Copyright (c) typedef int GmbH
|
|
6
|
+
#
|
|
7
|
+
# Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
8
|
+
# of this software and associated documentation files (the "Software"), to deal
|
|
9
|
+
# in the Software without restriction, including without limitation the rights
|
|
10
|
+
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
11
|
+
# copies of the Software, and to permit persons to whom the Software is
|
|
12
|
+
# furnished to do so, subject to the following conditions:
|
|
13
|
+
#
|
|
14
|
+
# The above copyright notice and this permission notice shall be included in
|
|
15
|
+
# all copies or substantial portions of the Software.
|
|
16
|
+
#
|
|
17
|
+
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
18
|
+
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
19
|
+
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
20
|
+
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
21
|
+
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
22
|
+
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
|
23
|
+
# THE SOFTWARE.
|
|
24
|
+
#
|
|
25
|
+
###############################################################################
|
|
26
|
+
|
|
27
|
+
import os
|
|
28
|
+
import sys
|
|
29
|
+
import logging
|
|
30
|
+
|
|
31
|
+
try:
|
|
32
|
+
from tempfile import TemporaryDirectory
|
|
33
|
+
except ImportError:
|
|
34
|
+
from backports.tempfile import TemporaryDirectory # type:ignore
|
|
35
|
+
|
|
36
|
+
import txaio
|
|
37
|
+
|
|
38
|
+
txaio.use_twisted()
|
|
39
|
+
|
|
40
|
+
import zlmdb # noqa
|
|
41
|
+
|
|
42
|
+
sys.path.append(os.path.dirname(os.path.abspath(__file__)))
|
|
43
|
+
|
|
44
|
+
if sys.version_info >= (3, 6):
|
|
45
|
+
from _schema_py3 import User, Schema1
|
|
46
|
+
else:
|
|
47
|
+
from _schema_py2 import User, Schema1
|
|
48
|
+
|
|
49
|
+
|
|
50
|
+
def test_pmap_value_types():
|
|
51
|
+
with TemporaryDirectory() as dbpath:
|
|
52
|
+
logging.info("Using temporary directory {} for database".format(dbpath))
|
|
53
|
+
|
|
54
|
+
schema = Schema1()
|
|
55
|
+
|
|
56
|
+
n = 100
|
|
57
|
+
stats = zlmdb.TransactionStats()
|
|
58
|
+
|
|
59
|
+
tabs = [
|
|
60
|
+
(schema.tab_oid_json, schema.tab_str_json, schema.tab_uuid_json),
|
|
61
|
+
(schema.tab_oid_cbor, schema.tab_str_cbor, schema.tab_uuid_cbor),
|
|
62
|
+
(schema.tab_oid_pickle, schema.tab_str_pickle, schema.tab_uuid_pickle),
|
|
63
|
+
]
|
|
64
|
+
|
|
65
|
+
with zlmdb.Database(dbpath) as db:
|
|
66
|
+
for tab_oid, tab_str, tab_uuid in tabs:
|
|
67
|
+
with db.begin(write=True, stats=stats) as txn:
|
|
68
|
+
for i in range(n):
|
|
69
|
+
user = User.create_test_user(i)
|
|
70
|
+
tab_oid[txn, user.oid] = user
|
|
71
|
+
tab_str[txn, user.authid] = user
|
|
72
|
+
tab_uuid[txn, user.uuid] = user
|
|
73
|
+
|
|
74
|
+
logging.info("transaction committed")
|
|
75
|
+
assert stats.puts == n * 3
|
|
76
|
+
assert stats.dels == 0
|
|
77
|
+
|
|
78
|
+
stats.reset()
|
|
79
|
+
|
|
80
|
+
with db.begin() as txn:
|
|
81
|
+
cnt = tab_oid.count(txn)
|
|
82
|
+
assert cnt == n
|
|
83
|
+
|
|
84
|
+
cnt = tab_str.count(txn)
|
|
85
|
+
assert cnt == n
|
|
86
|
+
|
|
87
|
+
cnt = tab_uuid.count(txn)
|
|
88
|
+
assert cnt == n
|
|
89
|
+
|
|
90
|
+
logging.info("database closed")
|