forked from geldata/gel
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathtest_transactions.py
215 lines (167 loc) · 6.56 KB
/
test_transactions.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
##
# Copyright (c) 2016-present MagicStack Inc.
# All rights reserved.
#
# See LICENSE for details.
##
from edgedb.server import _testbase as tb
from edgedb.client import exceptions
class TestTransactions(tb.QueryTestCase):
SETUP = """
CREATE LINK test::name {
SET mapping := '11';
SET readonly := False;
};
CREATE CONCEPT test::TransactionTest EXTENDING std::Object {
CREATE LINK test::name TO std::str {
SET mapping := '11';
SET readonly := False;
};
};
"""
async def test_transaction_regular_01(self):
self.assertIsNone(self.con._top_xact)
tr = self.con.transaction()
self.assertIsNone(self.con._top_xact)
with self.assertRaises(ZeroDivisionError):
async with tr as with_tr:
self.assertIs(self.con._top_xact, tr)
# We don't return the transaction object from __aenter__,
# to make it harder for people to use '.rollback()' and
# '.commit()' from within an 'async with' block.
self.assertIsNone(with_tr)
await self.con.execute('''
INSERT test::TransactionTest {
name := 'Test Transaction'
};
''')
1 / 0
self.assertIsNone(self.con._top_xact)
result = await self.con.execute('''
SELECT
test::TransactionTest
FILTER
test::TransactionTest.name = 'Test Transaction';
''')
self.assertEqual(result[0], [])
async def test_transaction_nested_01(self):
self.assertIsNone(self.con._top_xact)
tr = self.con.transaction()
self.assertIsNone(self.con._top_xact)
with self.assertRaises(ZeroDivisionError):
async with tr:
self.assertIs(self.con._top_xact, tr)
async with self.con.transaction():
self.assertIs(self.con._top_xact, tr)
await self.con.execute('''
INSERT test::TransactionTest {
name := 'TXTEST 1'
};
''')
self.assertIs(self.con._top_xact, tr)
with self.assertRaises(ZeroDivisionError):
in_tr = self.con.transaction()
async with in_tr:
self.assertIs(self.con._top_xact, tr)
await self.con.execute('''
INSERT test::TransactionTest {
name := 'TXTEST 2'
};
''')
1 / 0
result = await self.con.execute('''
SELECT
test::TransactionTest {
name
}
FILTER
test::TransactionTest.name LIKE 'TXTEST%';
''')
recs = result[0]
self.assertEqual(len(recs), 1)
self.assertEqual(recs[0]['name'], 'TXTEST 1')
self.assertIs(self.con._top_xact, tr)
1 / 0
self.assertIs(self.con._top_xact, None)
result = await self.con.execute('''
SELECT
test::TransactionTest {
name
}
FILTER
test::TransactionTest.name LIKE 'TXTEST%';
''')
recs = result[0]
self.assertEqual(len(recs), 0)
async def test_transaction_nested_02(self):
await self.assert_query_result(r"""
# test some explicit nested transactions without errors
SELECT test::TransactionTest{name};
START TRANSACTION;
INSERT test::TransactionTest{name:='q1'};
INSERT test::TransactionTest{name:='q2'};
SELECT test::TransactionTest.name;
START TRANSACTION;
INSERT test::TransactionTest{name:='w1'};
SELECT test::TransactionTest.name;
ROLLBACK;
SELECT test::TransactionTest.name;
START TRANSACTION;
INSERT test::TransactionTest{name:='e1'};
SELECT test::TransactionTest.name;
COMMIT;
SELECT test::TransactionTest.name;
ROLLBACK;
SELECT test::TransactionTest.name;
""", [
[],
None, # transaction start
[1], # insert
[1], # insert
{'q1', 'q2'},
None, # transaction start
[1], # insert
{'q1', 'q2', 'w1'},
None, # transaction rollback
{'q1', 'q2'},
None, # transaction start
[1], # insert
{'q1', 'q2', 'e1'},
None, # transaction commit
{'q1', 'q2', 'e1'},
None, # transaction rollback
[],
])
async def test_transaction_interface_errors(self):
self.assertIsNone(self.con._top_xact)
tr = self.con.transaction()
with self.assertRaisesRegex(exceptions.InterfaceError,
'cannot start; .* already started'):
async with tr:
await tr.start()
self.assertTrue(repr(tr).startswith(
'<edgedb.Transaction state:rolledback'))
self.assertIsNone(self.con._top_xact)
with self.assertRaisesRegex(exceptions.InterfaceError,
'cannot start; .* already rolled back'):
async with tr:
pass
self.assertIsNone(self.con._top_xact)
tr = self.con.transaction()
with self.assertRaisesRegex(exceptions.InterfaceError,
'cannot manually commit.*async with'):
async with tr:
await tr.commit()
self.assertIsNone(self.con._top_xact)
tr = self.con.transaction()
with self.assertRaisesRegex(exceptions.InterfaceError,
'cannot manually rollback.*async with'):
async with tr:
await tr.rollback()
self.assertIsNone(self.con._top_xact)
tr = self.con.transaction()
with self.assertRaisesRegex(exceptions.InterfaceError,
'cannot enter context:.*async with'):
async with tr:
async with tr:
pass