transactd 2.0.1 → 2.1.0
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.
- checksums.yaml +4 -4
- data/BUILD_UNIX-JA +6 -6
- data/README +16 -16
- data/README-JA +16 -16
- data/bin/common/tdclc_32_2_1.dll +0 -0
- data/bin/common/tdclc_64_2_1.dll +0 -0
- data/build/common/transactd_cl_common.cmake +0 -1
- data/build/common/transactd_common.cmake +28 -38
- data/build/swig/ruby/ruby.swg +36 -30
- data/build/swig/ruby/tdclrb_wrap.cpp +35016 -0
- data/build/swig/tdcl.i +217 -62
- data/build/tdclc/CMakeLists.txt +14 -26
- data/build/tdclc/libtdclcm.map +4 -0
- data/build/tdclc/tdclc.cbproj +1 -1
- data/build/tdclc/tdclc.rc +0 -0
- data/build/tdclcpp/CMakeLists.txt +7 -22
- data/build/tdclcpp/tdclcpp.rc +0 -0
- data/build/tdclcpp/tdclcpp_bc.cbproj +1 -1
- data/build/tdclrb/CMakeLists.txt +7 -49
- data/build/tdclrb/tdclrb.rc +62 -0
- data/source/bzs/db/blobBuffer.h +5 -0
- data/source/bzs/db/blobStructs.h +2 -0
- data/source/bzs/db/engine/mysql/IReadRecords.h +9 -0
- data/source/bzs/db/engine/mysql/database.cpp +391 -169
- data/source/bzs/db/engine/mysql/database.h +178 -40
- data/source/bzs/db/engine/mysql/dbManager.cpp +45 -3
- data/source/bzs/db/engine/mysql/dbManager.h +3 -39
- data/source/bzs/db/engine/mysql/errorMessage.cpp +11 -7
- data/source/bzs/db/engine/mysql/errorMessage.h +1 -1
- data/source/bzs/db/engine/mysql/mydebuglog.cpp +1 -2
- data/source/bzs/db/engine/mysql/mysqlInternal.h +8 -8
- data/source/bzs/db/engine/mysql/mysqlThd.cpp +11 -0
- data/source/bzs/db/protocol/hs/hsCommandExecuter.cpp +1 -1
- data/source/bzs/db/protocol/tdap/client/activeTable.cpp +41 -6
- data/source/bzs/db/protocol/tdap/client/activeTable.h +177 -8
- data/source/bzs/db/protocol/tdap/client/activeTableImple.h +141 -62
- data/source/bzs/db/protocol/tdap/client/client.cpp +39 -35
- data/source/bzs/db/protocol/tdap/client/client.h +52 -25
- data/source/bzs/db/protocol/tdap/client/connectionPool.cpp +17 -0
- data/source/bzs/db/protocol/tdap/client/connectionPool.h +1 -0
- data/source/bzs/db/protocol/tdap/client/database.cpp +5 -1
- data/source/bzs/db/protocol/tdap/client/database.h +1 -1
- data/source/bzs/db/protocol/tdap/client/databaseFactory.cpp +49 -12
- data/source/bzs/db/protocol/tdap/client/databaseManager.h +42 -5
- data/source/bzs/db/protocol/tdap/client/dbDef.cpp +4 -2
- data/source/bzs/db/protocol/tdap/client/dllmain.cpp +71 -41
- data/source/bzs/db/protocol/tdap/client/errorMessage_ja.cpp +49 -49
- data/source/bzs/db/protocol/tdap/client/field.cpp +22 -13
- data/source/bzs/db/protocol/tdap/client/field.h +7 -3
- data/source/bzs/db/protocol/tdap/client/fieldDDF.cpp +1 -1
- data/source/bzs/db/protocol/tdap/client/fieldNameAlias.cpp +0 -1
- data/source/bzs/db/protocol/tdap/client/fieldNameAlias.h +1 -0
- data/source/bzs/db/protocol/tdap/client/fields.h +111 -24
- data/source/bzs/db/protocol/tdap/client/fileDDF.cpp +1 -1
- data/source/bzs/db/protocol/tdap/client/filter.h +687 -310
- data/source/bzs/db/protocol/tdap/client/groupQuery.cpp +12 -4
- data/source/bzs/db/protocol/tdap/client/indexDDF.cpp +1 -1
- data/source/bzs/db/protocol/tdap/client/memRecord.cpp +190 -32
- data/source/bzs/db/protocol/tdap/client/memRecord.h +64 -22
- data/source/bzs/db/protocol/tdap/client/nsDatabase.cpp +4 -4
- data/source/bzs/db/protocol/tdap/client/nsDatabase.h +4 -2
- data/source/bzs/db/protocol/tdap/client/nsTable.cpp +6 -3
- data/source/bzs/db/protocol/tdap/client/nsTable.h +1 -1
- data/source/bzs/db/protocol/tdap/client/pooledDatabaseManager.h +19 -8
- data/source/bzs/db/protocol/tdap/client/recordsetImple.h +194 -87
- data/source/bzs/db/protocol/tdap/client/request.h +84 -26
- data/source/bzs/db/protocol/tdap/client/stringConverter.h +22 -12
- data/source/bzs/db/protocol/tdap/client/table.cpp +494 -286
- data/source/bzs/db/protocol/tdap/client/table.h +48 -5
- data/source/bzs/db/protocol/tdap/client/trdboostapi.h +133 -87
- data/source/bzs/db/protocol/tdap/client/trdboostapiInternal.h +22 -22
- data/source/bzs/db/protocol/tdap/client/trdormapi.h +43 -18
- data/source/bzs/db/protocol/tdap/client/trnsctcl.def +3 -3
- data/source/bzs/db/protocol/tdap/mysql/databaseSchema.cpp +1 -0
- data/source/bzs/db/protocol/tdap/mysql/recordsetReader.h +268 -74
- data/source/bzs/db/protocol/tdap/mysql/request.h +4 -4
- data/source/bzs/db/protocol/tdap/mysql/tdapCommandExecuter.cpp +179 -43
- data/source/bzs/db/protocol/tdap/mysql/tdapCommandExecuter.h +4 -4
- data/source/bzs/db/protocol/tdap/tdapRequest.h +15 -14
- data/source/bzs/db/protocol/tdap/tdapSchema.h +125 -90
- data/source/bzs/db/protocol/tdap/tdapcapi.h +46 -5
- data/source/bzs/db/transactd/appModule.h +1 -1
- data/source/bzs/db/transactd/connManager.cpp +2 -0
- data/source/bzs/db/transactd/transactd.cpp +1 -0
- data/source/bzs/env/compiler.h +10 -0
- data/source/bzs/env/mbcswchrLinux.cpp +42 -6
- data/source/bzs/env/mbcswchrLinux.h +40 -12
- data/source/bzs/example/queryData.cpp +33 -4
- data/source/bzs/netsvc/client/iconnection.h +107 -0
- data/source/bzs/netsvc/client/tcpClient.cpp +15 -1
- data/source/bzs/netsvc/client/tcpClient.h +96 -87
- data/source/bzs/netsvc/server/serverCpt.cpp +5 -6
- data/source/bzs/rtl/benchmark.cpp +2 -2
- data/source/bzs/rtl/stringBuffers.cpp +3 -3
- data/source/bzs/rtl/stringBuffers.h +2 -2
- data/source/bzs/test/tdclatl/bench_query_atl.js +92 -99
- data/source/bzs/test/tdclatl/test_query_atl.js +224 -115
- data/source/bzs/test/tdclphp/bench.php +126 -101
- data/source/bzs/test/tdclphp/transactd_Test.php +1122 -158
- data/source/bzs/test/tdclrb/bench_tdclcpp.rb +12 -14
- data/source/bzs/test/tdclrb/transactd_spec.rb +1127 -142
- data/source/bzs/test/transactdBench/query_bench.cpp +32 -15
- data/source/bzs/test/transactdBench/scaling_bench.cpp +32 -7
- data/source/bzs/test/transactdBench/transactdBench.cpp +1 -1
- data/source/bzs/test/transactdBench/workerBase.h +46 -0
- data/source/bzs/test/transactdBench/workerMySQLImple.h +15 -7
- data/source/bzs/test/transactdBench/workerTransactdImple.h +10 -18
- data/source/bzs/test/trdclengn/test_trdclengn.cpp +1487 -174
- data/source/global/ormsrcgen/main.cpp +2 -0
- data/source/global/tdclatl/Database.cpp +2 -2
- data/source/global/tdclatl/Database.h +1 -1
- data/source/global/tdclatl/FieldDefs.cpp +0 -3
- data/source/global/tdclatl/PooledDbManager.cpp +2 -2
- data/source/global/tdclatl/PooledDbManager.h +1 -1
- data/source/global/tdclatl/PreparedQuery.cpp +53 -0
- data/source/global/tdclatl/PreparedQuery.h +61 -0
- data/source/global/tdclatl/QueryBase.cpp +2 -1
- data/source/global/tdclatl/QueryBase.h +1 -1
- data/source/global/tdclatl/Record.cpp +3 -15
- data/source/global/tdclatl/Recordset.cpp +15 -10
- data/source/global/tdclatl/Recordset.h +3 -0
- data/source/global/tdclatl/Table.cpp +42 -7
- data/source/global/tdclatl/Table.h +3 -1
- data/source/global/tdclatl/activeTable.cpp +264 -76
- data/source/global/tdclatl/activeTable.h +12 -3
- data/source/global/tdclatl/tdclatl.idl +92 -10
- data/source/linux/charsetConvert.h +7 -7
- data/transactd.gemspec +14 -27
- metadata +18 -27
- data/bin/common/tdclc_32_2_0.dll +0 -0
- data/bin/common/tdclc_64_2_0.dll +0 -0
- data/build/swig/php/generate.cmake.in +0 -56
- data/build/swig/php/generate.cmd.in +0 -47
- data/build/swig/php/php.swg +0 -197
- data/build/swig/php/transactd.no_yield.php +0 -4494
- data/build/swig/php/transactd.no_yield.php.git.patch +0 -685
- data/build/swig/php/transactd.no_yield.php.patch +0 -685
- data/build/swig/php/transactd.yield.php +0 -4461
- data/build/swig/php/transactd.yield.php.git.patch +0 -652
- data/build/swig/php/transactd.yield.php.patch +0 -652
- data/build/swig/ruby/generate.cmake.in +0 -35
- data/build/swig/ruby/generate.cmd.in +0 -19
- data/build/tdclc/BUILDNUMBER.txt +0 -1
- data/build/tdclcpp/BUILDNUMBER.txt +0 -1
- data/build/tdclrb/BUILDNUMBER.txt +0 -1
- data/build/tdclrb/GEM_RELEASE_VERSION +0 -1
|
@@ -21,16 +21,14 @@ mb_internal_encoding('UTF-8');
|
|
|
21
21
|
|
|
22
22
|
require_once("transactd.php");
|
|
23
23
|
use BizStation\Transactd as Bz;
|
|
24
|
-
|
|
25
|
-
define('URL', 'tdap://localhost/test_bench?dbfile=test.bdf');
|
|
26
24
|
define('TABLENAME', 'users');
|
|
27
25
|
define('FDI_ID', 0);
|
|
28
26
|
define('FDI_NAME', 1);
|
|
29
27
|
define('BULKBUFSIZE', 65535 - 1000);
|
|
30
|
-
|
|
31
28
|
define('RECORD_COUNT', 20000);
|
|
32
29
|
define('RECORD_UNIT', 20);
|
|
33
30
|
|
|
31
|
+
|
|
34
32
|
function assertEquals($a, $b, $msg = '') {
|
|
35
33
|
if ($a !== $b) {
|
|
36
34
|
echo("$a !== $b $msg");
|
|
@@ -46,19 +44,19 @@ function assertNotEquals($a, $b, $msg = '') {
|
|
|
46
44
|
return true;
|
|
47
45
|
}
|
|
48
46
|
|
|
49
|
-
function create($
|
|
47
|
+
function create($URI) {
|
|
50
48
|
// create database
|
|
51
49
|
$db = new Bz\database();
|
|
52
|
-
$db->create($
|
|
50
|
+
$db->create($URI);
|
|
53
51
|
if ($db->stat() == Bz\transactd::STATUS_TABLE_EXISTS_ERROR) {
|
|
54
|
-
$db->open($
|
|
52
|
+
$db->open($URI);
|
|
55
53
|
assertEquals($db->stat(), 0);
|
|
56
54
|
$db->drop();
|
|
57
55
|
assertEquals($db->stat(), 0);
|
|
58
|
-
$db->create($
|
|
56
|
+
$db->create($URI);
|
|
59
57
|
}
|
|
60
58
|
assertEquals($db->stat(), 0);
|
|
61
|
-
$db->open($
|
|
59
|
+
$db->open($URI, Bz\transactd::TYPE_SCHEMA_BDF, Bz\transactd::TD_OPEN_NORMAL);
|
|
62
60
|
assertEquals($db->stat(), 0);
|
|
63
61
|
// create table
|
|
64
62
|
$dbdef = $db->dbDef();
|
|
@@ -124,8 +122,8 @@ function deleteAll($db, $tb) {
|
|
|
124
122
|
|
|
125
123
|
function insert($db, $tb) {
|
|
126
124
|
$tb->setKeyNum(0);
|
|
125
|
+
$tb->clearBuffer();
|
|
127
126
|
for ($i = 1; $i <= RECORD_COUNT; $i++) {
|
|
128
|
-
$tb->clearBuffer();
|
|
129
127
|
$tb->setFV(FDI_ID, $i);
|
|
130
128
|
$tb->setFV(FDI_NAME, $i);
|
|
131
129
|
$tb->insert();
|
|
@@ -138,15 +136,15 @@ function insert($db, $tb) {
|
|
|
138
136
|
function insertTransaction($db, $tb) {
|
|
139
137
|
$tb->setKeyNum(0);
|
|
140
138
|
$start = 1;
|
|
139
|
+
$tb->clearBuffer();
|
|
141
140
|
while ($start < RECORD_COUNT) {
|
|
142
141
|
$db->beginTrn();
|
|
143
142
|
for ($i = $start; $i < $start + RECORD_UNIT; $i++) {
|
|
144
|
-
$tb->clearBuffer();
|
|
145
143
|
$tb->setFV(FDI_ID, $i);
|
|
146
144
|
$tb->setFV(FDI_NAME, $i);
|
|
147
145
|
$tb->insert();
|
|
148
146
|
if (!assertEquals($tb->stat(), 0, 'insertTransaction')) {
|
|
149
|
-
$db->
|
|
147
|
+
$db->abortTrn();
|
|
150
148
|
return false;
|
|
151
149
|
}
|
|
152
150
|
}
|
|
@@ -159,10 +157,10 @@ function insertTransaction($db, $tb) {
|
|
|
159
157
|
function insertBulk($db, $tb) {
|
|
160
158
|
$tb->setKeyNum(0);
|
|
161
159
|
$start = 1;
|
|
160
|
+
$tb->clearBuffer();
|
|
162
161
|
while ($start < RECORD_COUNT) {
|
|
163
162
|
$tb->beginBulkInsert(BULKBUFSIZE);
|
|
164
163
|
for ($i = $start; $i < $start + RECORD_UNIT; $i++) {
|
|
165
|
-
$tb->clearBuffer();
|
|
166
164
|
$tb->setFV(FDI_ID, $i);
|
|
167
165
|
$tb->setFV(FDI_NAME, $i);
|
|
168
166
|
$tb->insert();
|
|
@@ -179,12 +177,13 @@ function insertBulk($db, $tb) {
|
|
|
179
177
|
|
|
180
178
|
function read($db, $tb) {
|
|
181
179
|
$tb->setKeyNum(0);
|
|
180
|
+
$tb->clearBuffer();
|
|
182
181
|
for ($i = 1; $i <= RECORD_COUNT; $i++) {
|
|
183
|
-
$tb->clearBuffer();
|
|
184
182
|
$tb->setFV(FDI_ID, $i);
|
|
185
183
|
$tb->seek();
|
|
186
|
-
if (
|
|
187
|
-
|
|
184
|
+
if (($tb->stat() !==0) || ($tb->getFVint(FDI_ID) !== $i))
|
|
185
|
+
{
|
|
186
|
+
echo("seek stat = ".$tb->stat()." value ".$i." = ".$tb->getFVint(FDI_ID));
|
|
188
187
|
return false;
|
|
189
188
|
}
|
|
190
189
|
}
|
|
@@ -192,17 +191,17 @@ function read($db, $tb) {
|
|
|
192
191
|
}
|
|
193
192
|
|
|
194
193
|
function readSnapshot($db, $tb) {
|
|
195
|
-
$ret = true;
|
|
196
194
|
$tb->setKeyNum(0);
|
|
197
195
|
$db->beginSnapshot();
|
|
196
|
+
$tb->clearBuffer();
|
|
198
197
|
for ($i = 1; $i <= RECORD_COUNT; $i++) {
|
|
199
|
-
$tb->clearBuffer();
|
|
200
198
|
$tb->setFV(FDI_ID, $i);
|
|
201
199
|
$tb->seek();
|
|
202
|
-
if (
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
200
|
+
if (($tb->stat() !==0) || ($tb->getFVint(FDI_ID) !== $i))
|
|
201
|
+
{
|
|
202
|
+
echo("seek stat = ".$tb->stat()." value ".$i." = ".$tb->getFVint(FDI_ID));
|
|
203
|
+
$db->endSnapshot();
|
|
204
|
+
return false;
|
|
206
205
|
}
|
|
207
206
|
}
|
|
208
207
|
$db->endSnapshot();
|
|
@@ -210,16 +209,17 @@ function readSnapshot($db, $tb) {
|
|
|
210
209
|
}
|
|
211
210
|
|
|
212
211
|
function readRange($db, $tb) {
|
|
213
|
-
$tb->setKeyNum(0);
|
|
214
212
|
$start = 1;
|
|
213
|
+
$tb->setKeyNum(0);
|
|
214
|
+
$tb->clearBuffer();
|
|
215
|
+
$tb->setFilter('*', 1, RECORD_UNIT);
|
|
216
|
+
$tb->setFV(FDI_ID, $start);
|
|
217
|
+
$tb->find(Bz\table::findForword);
|
|
215
218
|
while ($start < RECORD_COUNT) {
|
|
216
|
-
$tb->clearBuffer();
|
|
217
|
-
$tb->setFilter('*', 1, RECORD_UNIT);
|
|
218
|
-
$tb->setFV(FDI_ID, $start);
|
|
219
|
-
$tb->find(Bz\table::findForword);
|
|
220
219
|
for ($i = $start; $i < $start + RECORD_UNIT; $i++) {
|
|
221
|
-
if (
|
|
222
|
-
|
|
220
|
+
if (/*($tb->stat() !==0) || */($tb->getFVint(FDI_ID) !== $i))
|
|
221
|
+
{
|
|
222
|
+
echo("find stat = ".$tb->stat()." value ".$i." = ".$tb->getFVint(FDI_ID));
|
|
223
223
|
return false;
|
|
224
224
|
}
|
|
225
225
|
$tb->findNext();
|
|
@@ -230,17 +230,19 @@ function readRange($db, $tb) {
|
|
|
230
230
|
}
|
|
231
231
|
|
|
232
232
|
function readRangeSnapshot($db, $tb) {
|
|
233
|
+
$start = 1;
|
|
233
234
|
$tb->setKeyNum(0);
|
|
235
|
+
$tb->clearBuffer();
|
|
236
|
+
$tb->setFilter('*', 1, RECORD_UNIT);
|
|
237
|
+
$tb->setFV(FDI_ID, $start);
|
|
234
238
|
$db->beginSnapshot();
|
|
235
|
-
$
|
|
239
|
+
$tb->find(Bz\table::findForword);
|
|
236
240
|
while ($start < RECORD_COUNT) {
|
|
237
|
-
$tb->clearBuffer();
|
|
238
|
-
$tb->setFilter('*', 1, RECORD_UNIT);
|
|
239
|
-
$tb->setFV(FDI_ID, $start);
|
|
240
|
-
$tb->find(Bz\table::findForword);
|
|
241
241
|
for ($i = $start; $i < $start + RECORD_UNIT; $i++) {
|
|
242
|
-
if (
|
|
243
|
-
|
|
242
|
+
if (/*($tb->stat() !==0) || */($tb->getFVint(FDI_ID) !== $i))
|
|
243
|
+
{
|
|
244
|
+
echo("find stat = ".$tb->stat()." value ".$i." = ".$tb->getFVint(FDI_ID));
|
|
245
|
+
$db->endSnapshot();
|
|
244
246
|
return false;
|
|
245
247
|
}
|
|
246
248
|
$tb->findNext();
|
|
@@ -253,13 +255,16 @@ function readRangeSnapshot($db, $tb) {
|
|
|
253
255
|
|
|
254
256
|
function update($db, $tb) {
|
|
255
257
|
$tb->setKeyNum(0);
|
|
258
|
+
$tb->clearBuffer();
|
|
256
259
|
for ($i = 1; $i <= RECORD_COUNT; $i++) {
|
|
257
|
-
$tb->clearBuffer();
|
|
258
260
|
$tb->setFV(FDI_ID, $i);
|
|
259
261
|
$tb->setFV(FDI_NAME, ($i + 1));
|
|
260
262
|
$tb->update(Bz\table::changeInKey);
|
|
261
|
-
if (
|
|
263
|
+
if ($tb->stat() !==0)
|
|
264
|
+
{
|
|
265
|
+
echo("update stat = ".$tb->stat());
|
|
262
266
|
return false;
|
|
267
|
+
}
|
|
263
268
|
}
|
|
264
269
|
return true;
|
|
265
270
|
}
|
|
@@ -267,15 +272,17 @@ function update($db, $tb) {
|
|
|
267
272
|
function updateTransaction($db, $tb) {
|
|
268
273
|
$tb->setKeyNum(0);
|
|
269
274
|
$start = 1;
|
|
275
|
+
$tb->clearBuffer();
|
|
270
276
|
while ($start < RECORD_COUNT) {
|
|
271
277
|
$db->beginTrn();
|
|
272
278
|
for ($i = $start; $i < $start + RECORD_UNIT; $i++) {
|
|
273
|
-
$tb->clearBuffer();
|
|
274
279
|
$tb->setFV(FDI_ID, $i);
|
|
275
280
|
$tb->setFV(FDI_NAME, ($i + 2));
|
|
276
281
|
$tb->update(Bz\table::changeInKey);
|
|
277
|
-
if (
|
|
278
|
-
|
|
282
|
+
if ($tb->stat() !==0)
|
|
283
|
+
{
|
|
284
|
+
echo("update stat = ".$tb->stat());
|
|
285
|
+
$db->abortTrn();
|
|
279
286
|
return false;
|
|
280
287
|
}
|
|
281
288
|
}
|
|
@@ -285,73 +292,91 @@ function updateTransaction($db, $tb) {
|
|
|
285
292
|
return true;
|
|
286
293
|
}
|
|
287
294
|
|
|
288
|
-
function main($
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
295
|
+
function main($argc, $argv) {
|
|
296
|
+
if ($argc < 4) {
|
|
297
|
+
echo("usage: php bench.php databaseUri processNumber functionNumber\n");
|
|
298
|
+
echo("\t --- functionNumber list ---\n");
|
|
299
|
+
echo("\t-1: all function\n");
|
|
300
|
+
echo("\t 0: Insert\n");
|
|
301
|
+
echo("\t 1: Insert in transaction. 20rec x 1000times\n");
|
|
302
|
+
echo("\t 2: Insert by bulkmode. 20rec x 1000times\n");
|
|
303
|
+
echo("\t 3: read each record\n");
|
|
304
|
+
echo("\t 4: read each record with snapshot\n");
|
|
305
|
+
echo("\t 5: read range. 20rec x 1000times\n");
|
|
306
|
+
echo("\t 6: read range with snapshpot. 20rec x 1000times\n");
|
|
307
|
+
echo("\t 7: update\n");
|
|
308
|
+
echo("\t 8: update in transaction. 20rec x 1000times\n");
|
|
309
|
+
echo("example : php bench.php \"tdap://localhost/test?dbfile=test.bdf\" 0 -1\n");
|
|
310
|
+
return;
|
|
311
|
+
}
|
|
312
|
+
|
|
313
|
+
$URI = $argv[1];
|
|
314
|
+
// Currenty $proc is ignored.
|
|
315
|
+
$proc = (int)$argv[2];
|
|
316
|
+
$funcNum = (int)$argv[3];
|
|
317
|
+
|
|
318
|
+
create($URI);
|
|
319
|
+
echo("CreateDataBase success.\n");
|
|
320
|
+
echo("Start Bench mark Insert Items = ".RECORD_COUNT."\n");
|
|
321
|
+
echo(date(DATE_ATOM)."\n");
|
|
322
|
+
echo($URI."\n");
|
|
323
|
+
echo("----------------------------------------\n");
|
|
292
324
|
|
|
293
325
|
$db = new Bz\database();
|
|
294
|
-
$db->open($
|
|
326
|
+
$db->open($URI, Bz\transactd::TYPE_SCHEMA_BDF, Bz\transactd::TD_OPEN_NORMAL);
|
|
295
327
|
assertEquals($db->stat(), 0);
|
|
296
328
|
$tb = $db->openTable(TABLENAME);
|
|
297
329
|
assertEquals($db->stat(), 0);
|
|
298
330
|
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
echo("--------------------------------\n");
|
|
307
|
-
|
|
308
|
-
deleteAll($db, $tb);
|
|
309
|
-
Bz\benchmark::start();
|
|
310
|
-
$ret = insertTransaction($db, $tb);
|
|
311
|
-
Bz\benchmark::showTimeSec($ret, ': insertTransaction ' . RECORD_COUNT . ' with transaction per ' . RECORD_UNIT);
|
|
312
|
-
|
|
313
|
-
echo("--------------------------------\n");
|
|
314
|
-
|
|
315
|
-
deleteAll($db, $tb);
|
|
316
|
-
Bz\benchmark::start();
|
|
317
|
-
$ret = insertBulk($db, $tb);
|
|
318
|
-
Bz\benchmark::showTimeSec($ret, ': insertBulk ' . RECORD_COUNT . ' with bulkmode per ' . RECORD_UNIT);
|
|
319
|
-
|
|
320
|
-
echo("--------------------------------\n");
|
|
321
|
-
|
|
322
|
-
Bz\benchmark::start();
|
|
323
|
-
$ret = read($db, $tb);
|
|
324
|
-
Bz\benchmark::showTimeSec($ret, ': read ' . RECORD_COUNT);
|
|
325
|
-
|
|
326
|
-
echo("--------------------------------\n");
|
|
327
|
-
|
|
328
|
-
Bz\benchmark::start();
|
|
329
|
-
$ret = readSnapshot($db, $tb);
|
|
330
|
-
Bz\benchmark::showTimeSec($ret, ': read with snapshot ' . RECORD_COUNT);
|
|
331
|
-
|
|
332
|
-
echo("--------------------------------\n");
|
|
333
|
-
|
|
334
|
-
Bz\benchmark::start();
|
|
335
|
-
$ret = readRange($db, $tb);
|
|
336
|
-
Bz\benchmark::showTimeSec($ret, ': read ' . RECORD_COUNT . ' with range per ' . RECORD_UNIT);
|
|
337
|
-
|
|
338
|
-
echo("--------------------------------\n");
|
|
339
|
-
|
|
340
|
-
Bz\benchmark::start();
|
|
341
|
-
$ret = readRangeSnapshot($db, $tb);
|
|
342
|
-
Bz\benchmark::showTimeSec($ret, ': read ' . RECORD_COUNT . ' with snapshot and range per ' . RECORD_UNIT);
|
|
343
|
-
|
|
344
|
-
echo("--------------------------------\n");
|
|
345
|
-
|
|
346
|
-
Bz\benchmark::start();
|
|
347
|
-
$ret = update($db, $tb);
|
|
348
|
-
Bz\benchmark::showTimeSec($ret, ': update ' . RECORD_COUNT);
|
|
331
|
+
if (($funcNum === -1) || ($funcNum === 0)) {
|
|
332
|
+
deleteAll($db, $tb);
|
|
333
|
+
Bz\benchmark::start();
|
|
334
|
+
$ret = insert($db, $tb);
|
|
335
|
+
Bz\benchmark::showTimeSec($ret, ': insert ' . RECORD_COUNT);
|
|
336
|
+
}
|
|
349
337
|
|
|
350
|
-
|
|
338
|
+
if (($funcNum === -1) || ($funcNum === 1)) {
|
|
339
|
+
deleteAll($db, $tb);
|
|
340
|
+
Bz\benchmark::start();
|
|
341
|
+
$ret = insertTransaction($db, $tb);
|
|
342
|
+
Bz\benchmark::showTimeSec($ret, ': insertTransaction ' . RECORD_COUNT . ' with transaction per ' . RECORD_UNIT);
|
|
343
|
+
}
|
|
351
344
|
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
345
|
+
if (($funcNum === -1) || ($funcNum === 2)) {
|
|
346
|
+
deleteAll($db, $tb);
|
|
347
|
+
Bz\benchmark::start();
|
|
348
|
+
$ret = insertBulk($db, $tb);
|
|
349
|
+
Bz\benchmark::showTimeSec($ret, ': insertBulk ' . RECORD_COUNT . ' with bulkmode per ' . RECORD_UNIT);
|
|
350
|
+
}
|
|
351
|
+
if (($funcNum === -1) || ($funcNum === 3)) {
|
|
352
|
+
Bz\benchmark::start();
|
|
353
|
+
$ret = read($db, $tb);
|
|
354
|
+
Bz\benchmark::showTimeSec($ret, ': read ' . RECORD_COUNT);
|
|
355
|
+
}
|
|
356
|
+
if (($funcNum === -1) || ($funcNum === 4)) {
|
|
357
|
+
Bz\benchmark::start();
|
|
358
|
+
$ret = readSnapshot($db, $tb);
|
|
359
|
+
Bz\benchmark::showTimeSec($ret, ': read with snapshot ' . RECORD_COUNT);
|
|
360
|
+
}
|
|
361
|
+
if (($funcNum === -1) || ($funcNum === 5)) {
|
|
362
|
+
Bz\benchmark::start();
|
|
363
|
+
$ret = readRange($db, $tb);
|
|
364
|
+
Bz\benchmark::showTimeSec($ret, ': read ' . RECORD_COUNT . ' with range per ' . RECORD_UNIT);
|
|
365
|
+
}
|
|
366
|
+
if (($funcNum === -1) || ($funcNum === 6)) {
|
|
367
|
+
Bz\benchmark::start();
|
|
368
|
+
$ret = readRangeSnapshot($db, $tb);
|
|
369
|
+
Bz\benchmark::showTimeSec($ret, ': read ' . RECORD_COUNT . ' with snapshot and range per ' . RECORD_UNIT);
|
|
370
|
+
}
|
|
371
|
+
if (($funcNum === -1) || ($funcNum === 7)) {
|
|
372
|
+
Bz\benchmark::start();
|
|
373
|
+
$ret = update($db, $tb);
|
|
374
|
+
Bz\benchmark::showTimeSec($ret, ': update ' . RECORD_COUNT);
|
|
375
|
+
}
|
|
376
|
+
if (($funcNum === -1) || ($funcNum === 8)) {
|
|
377
|
+
Bz\benchmark::start();
|
|
378
|
+
$ret = updateTransaction($db, $tb);
|
|
379
|
+
Bz\benchmark::showTimeSec($ret, ': updateTransaction ' . RECORD_COUNT . ' with transaction per ' . RECORD_UNIT);
|
|
380
|
+
}
|
|
355
381
|
}
|
|
356
|
-
|
|
357
|
-
main(URL);
|
|
382
|
+
main($argc, $argv);
|
|
@@ -44,9 +44,6 @@ define("TEST_COUNT", 20000);
|
|
|
44
44
|
define("FIVE_PERCENT_OF_TEST_COUNT", TEST_COUNT / 20);
|
|
45
45
|
define("ALLOWABLE_ERROR_DISTANCE_IN_ESTIMATE_COUNT", TEST_COUNT / 4);
|
|
46
46
|
|
|
47
|
-
define("ISOLATION_READ_COMMITTED", true);
|
|
48
|
-
define("ISOLATION_REPEATABLE_READ", false);
|
|
49
|
-
|
|
50
47
|
class transactdTest extends PHPUnit_Framework_TestCase
|
|
51
48
|
{
|
|
52
49
|
private function dropDatabase($db)
|
|
@@ -84,8 +81,7 @@ class transactdTest extends PHPUnit_Framework_TestCase
|
|
|
84
81
|
$td->setFileName(TABLENAME . '.dat');
|
|
85
82
|
// Set table default charaset index
|
|
86
83
|
// - default charset for field VALUE
|
|
87
|
-
|
|
88
|
-
//
|
|
84
|
+
$td->charsetIndex = Bz\transactd::charsetIndex(Bz\transactd::CP_UTF8);
|
|
89
85
|
$tableid = 1;
|
|
90
86
|
$td->id = $tableid;
|
|
91
87
|
$td->pageSize = 2048;
|
|
@@ -93,14 +89,14 @@ class transactdTest extends PHPUnit_Framework_TestCase
|
|
|
93
89
|
$this->assertEquals($dbdef->stat(), 0);
|
|
94
90
|
|
|
95
91
|
$fd = $dbdef->insertField($tableid, 0);
|
|
96
|
-
$fd->setName(
|
|
92
|
+
$fd->setName('id');
|
|
97
93
|
$fd->type = Bz\transactd::ft_integer;
|
|
98
94
|
$fd->len = 4;
|
|
99
95
|
$dbdef->updateTableDef($tableid);
|
|
100
96
|
$this->assertEquals($dbdef->stat(), 0);
|
|
101
97
|
|
|
102
98
|
$fd = $dbdef->insertField($tableid, 1);
|
|
103
|
-
$fd->setName(
|
|
99
|
+
$fd->setName('name');
|
|
104
100
|
$fd->type = Bz\transactd::ft_zstring;
|
|
105
101
|
$fd->len = 33;
|
|
106
102
|
$dbdef->updateTableDef($tableid);
|
|
@@ -110,24 +106,58 @@ class transactdTest extends PHPUnit_Framework_TestCase
|
|
|
110
106
|
// $fd->setCharsetIndex(Bz\transactd::charsetIndex(Bz\transactd::CP_UTF8))
|
|
111
107
|
|
|
112
108
|
$fd = $dbdef->insertField($tableid, 2);
|
|
113
|
-
$fd->setName(
|
|
109
|
+
$fd->setName('select');
|
|
114
110
|
$fd->type = Bz\transactd::ft_integer;
|
|
115
111
|
$fd->len = 4;
|
|
116
112
|
$dbdef->updateTableDef($tableid);
|
|
117
113
|
$this->assertEquals($dbdef->stat(), 0);
|
|
118
114
|
|
|
119
115
|
$fd = $dbdef->insertField($tableid, 3);
|
|
120
|
-
$fd->setName(
|
|
116
|
+
$fd->setName('in');
|
|
117
|
+
$fd->type = Bz\transactd::ft_integer;
|
|
118
|
+
$fd->len = 4;
|
|
119
|
+
$dbdef->updateTableDef($tableid);
|
|
120
|
+
$this->assertEquals($dbdef->stat(), 0);
|
|
121
|
+
|
|
122
|
+
$kd = $dbdef->insertKey($tableid, 0);
|
|
123
|
+
$kd->segment(0)->fieldNum = 0;
|
|
124
|
+
$kd->segment(0)->flags->bit8 = 1;
|
|
125
|
+
$kd->segment(0)->flags->bit1 = 1;
|
|
126
|
+
$kd->segmentCount = 1;
|
|
127
|
+
$dbdef->updateTableDef($tableid);
|
|
128
|
+
$this->assertEquals($dbdef->stat(), 0);
|
|
129
|
+
|
|
130
|
+
// group table
|
|
131
|
+
$td = new Bz\tabledef();
|
|
132
|
+
$td->schemaCodePage = Bz\transactd::CP_UTF8;
|
|
133
|
+
$td->setTableName('group');
|
|
134
|
+
$td->setFileName('group.dat');
|
|
135
|
+
$tableid = 2;
|
|
136
|
+
$td->id = $tableid;
|
|
137
|
+
$td->pageSize = 2048;
|
|
138
|
+
$dbdef->insertTable($td);
|
|
139
|
+
$this->assertEquals($dbdef->stat(), 0);
|
|
140
|
+
|
|
141
|
+
$fd = $dbdef->insertField($tableid, 0);
|
|
142
|
+
$fd->setName('id');
|
|
121
143
|
$fd->type = Bz\transactd::ft_integer;
|
|
122
144
|
$fd->len = 4;
|
|
123
145
|
$dbdef->updateTableDef($tableid);
|
|
124
146
|
$this->assertEquals($dbdef->stat(), 0);
|
|
125
147
|
|
|
148
|
+
$fd = $dbdef->insertField($tableid, 1);
|
|
149
|
+
$fd->setName('name');
|
|
150
|
+
$fd->type = Bz\transactd::ft_zstring;
|
|
151
|
+
$fd->len = 33;
|
|
152
|
+
$dbdef->updateTableDef($tableid);
|
|
153
|
+
$this->assertEquals($dbdef->stat(), 0);
|
|
154
|
+
|
|
126
155
|
$kd = $dbdef->insertKey($tableid, 0);
|
|
127
156
|
$kd->segment(0)->fieldNum = 0;
|
|
128
157
|
$kd->segment(0)->flags->bit8 = 1;
|
|
129
158
|
$kd->segment(0)->flags->bit1 = 1;
|
|
130
159
|
$kd->segmentCount = 1;
|
|
160
|
+
|
|
131
161
|
$dbdef->updateTableDef($tableid);
|
|
132
162
|
$this->assertEquals($dbdef->stat(), 0);
|
|
133
163
|
}
|
|
@@ -285,6 +315,8 @@ class transactdTest extends PHPUnit_Framework_TestCase
|
|
|
285
315
|
while ($i < TEST_COUNT)
|
|
286
316
|
{
|
|
287
317
|
$this->assertEquals($tb->stat(), 0);
|
|
318
|
+
if ($tb->stat() != 0)
|
|
319
|
+
break;
|
|
288
320
|
$this->assertEquals($tb->getFVint(FDI_ID), $i);
|
|
289
321
|
$tb->findNext(true); // 11 - 19
|
|
290
322
|
$i = $i + 1;
|
|
@@ -298,6 +330,8 @@ class transactdTest extends PHPUnit_Framework_TestCase
|
|
|
298
330
|
while ($i >= 10)
|
|
299
331
|
{
|
|
300
332
|
$this->assertEquals($tb->stat(), 0);
|
|
333
|
+
if ($tb->stat() != 0)
|
|
334
|
+
break;
|
|
301
335
|
$this->assertEquals($tb->getFVint(FDI_ID), $i);
|
|
302
336
|
$tb->findPrev(true); // 11 - 19
|
|
303
337
|
$i = $i - 1;
|
|
@@ -324,6 +358,8 @@ class transactdTest extends PHPUnit_Framework_TestCase
|
|
|
324
358
|
for ($i = $v + 1; $i <= (TEST_COUNT - 1); $i++)
|
|
325
359
|
{
|
|
326
360
|
$tb->findNext(true); // 11 - 19
|
|
361
|
+
if ($tb->stat() != 0)
|
|
362
|
+
break;
|
|
327
363
|
$this->assertEquals($tb->stat(), 0);
|
|
328
364
|
$this->assertEquals($tb->getFVint(FDI_ID), $i);
|
|
329
365
|
}
|
|
@@ -370,10 +406,9 @@ class transactdTest extends PHPUnit_Framework_TestCase
|
|
|
370
406
|
$this->assertEquals($tb->stat(), Bz\transactd::STATUS_EOF);
|
|
371
407
|
|
|
372
408
|
// Many params
|
|
373
|
-
$
|
|
374
|
-
for($i = 2; $i <= 10000; $i++)
|
|
409
|
+
for($i = 1; $i <= 10000; $i++)
|
|
375
410
|
{
|
|
376
|
-
$q->addSeekKeyValue(strval($i));
|
|
411
|
+
$q->addSeekKeyValue(strval($i), ($i == 1)); // reset
|
|
377
412
|
}
|
|
378
413
|
$tb->setQuery($q);
|
|
379
414
|
$this->assertEquals($tb->stat(), 0);
|
|
@@ -459,6 +494,8 @@ class transactdTest extends PHPUnit_Framework_TestCase
|
|
|
459
494
|
{
|
|
460
495
|
$tb->seekNext();
|
|
461
496
|
$this->assertEquals($tb->getFVint(FDI_ID), $i);
|
|
497
|
+
if ($i != $tb->getFVint(FDI_ID))
|
|
498
|
+
break;
|
|
462
499
|
}
|
|
463
500
|
$db->endSnapshot();
|
|
464
501
|
}
|
|
@@ -477,10 +514,27 @@ class transactdTest extends PHPUnit_Framework_TestCase
|
|
|
477
514
|
{
|
|
478
515
|
$tb->seekPrev();
|
|
479
516
|
$this->assertEquals($tb->getFVint(FDI_ID), $i);
|
|
517
|
+
if ($i != $tb->getFVint(FDI_ID))
|
|
518
|
+
break;
|
|
480
519
|
}
|
|
481
520
|
$tb->seekPrev();
|
|
482
521
|
$this->assertEquals($tb->getFVstr(FDI_NAME), 'kosaka');
|
|
483
522
|
$db->endSnapshot();
|
|
523
|
+
// without snapshot
|
|
524
|
+
$vv = TEST_COUNT + 1;
|
|
525
|
+
$tb->clearBuffer();
|
|
526
|
+
$tb->setFV(FDI_ID, $vv);
|
|
527
|
+
$tb->seek();
|
|
528
|
+
$this->assertEquals($tb->getFVint(FDI_ID), $vv);
|
|
529
|
+
for ($i = TEST_COUNT; $i > 1; $i--)
|
|
530
|
+
{
|
|
531
|
+
$tb->seekPrev();
|
|
532
|
+
$this->assertEquals($tb->getFVint(FDI_ID), $i);
|
|
533
|
+
if ($i != $tb->getFVint(FDI_ID))
|
|
534
|
+
break;
|
|
535
|
+
}
|
|
536
|
+
$tb->seekPrev();
|
|
537
|
+
$this->assertEquals($tb->getFVstr(FDI_NAME), 'kosaka');
|
|
484
538
|
}
|
|
485
539
|
public function testGetGreater()
|
|
486
540
|
{
|
|
@@ -627,53 +681,117 @@ class transactdTest extends PHPUnit_Framework_TestCase
|
|
|
627
681
|
$tb->seek();
|
|
628
682
|
$this->assertEquals($tb->getFVstr(FDI_NAME), 'ABC');
|
|
629
683
|
}
|
|
630
|
-
public function
|
|
684
|
+
public function testSnapshot()
|
|
631
685
|
{
|
|
632
686
|
$db = new Bz\database();
|
|
633
|
-
$db2 = new Bz\database();
|
|
634
|
-
$db2->connect(PROTOCOL . HOSTNAME . DBNAME, true);
|
|
635
|
-
$this->assertEquals($db2->stat(), 0);
|
|
636
687
|
$tb = $this->openTable($db);
|
|
637
688
|
$this->assertNotEquals($tb, NULL);
|
|
689
|
+
$tbg = $db->openTable('group');
|
|
690
|
+
$this->assertEquals($db->stat(), 0);
|
|
691
|
+
$this->assertNotEquals($tbg, NULL);
|
|
692
|
+
$db2 = new Bz\database();
|
|
693
|
+
$this->assertEquals($db2->stat(), 0);
|
|
694
|
+
$db2->connect(PROTOCOL . HOSTNAME . DBNAME, true);
|
|
638
695
|
$tb2 = $this->openTable($db2);
|
|
639
696
|
$this->assertNotEquals($tb2, NULL);
|
|
640
|
-
$
|
|
697
|
+
$tbg2 = $db2->openTable('group');
|
|
698
|
+
$this->assertEquals($db2->stat(), 0);
|
|
699
|
+
$this->assertNotEquals($tbg2, NULL);
|
|
700
|
+
|
|
701
|
+
// No locking repeatable read
|
|
702
|
+
// ----------------------------------------------------
|
|
703
|
+
$db->beginSnapshot(); // CONSISTENT_READ is default
|
|
641
704
|
$this->assertEquals($db->stat(), 0);
|
|
705
|
+
$db->beginTrn();
|
|
706
|
+
$this->assertEquals($db->stat(), Bz\transactd::STATUS_ALREADY_INSNAPSHOT);
|
|
707
|
+
|
|
642
708
|
$tb->setKeyNum(0);
|
|
643
709
|
$tb->seekFirst();
|
|
644
710
|
$this->assertEquals($tb->stat(), 0);
|
|
645
711
|
$firstValue = $tb->getFVstr(FDI_NAME);
|
|
646
712
|
$tb->seekNext();
|
|
647
|
-
|
|
648
|
-
|
|
713
|
+
$this->assertEquals($tb->stat(), 0);
|
|
714
|
+
$this->assertEquals($tb->getFVint(FDI_ID), 2);
|
|
715
|
+
$tbg->seekFirst();
|
|
716
|
+
$this->assertEquals($tbg->stat(), Bz\transactd::STATUS_EOF);
|
|
717
|
+
$this->assertEquals($tbg->recordCount(false), 0);
|
|
718
|
+
|
|
719
|
+
// Change data on 2 tables by another connection
|
|
649
720
|
$tb2->setKeyNum(0);
|
|
650
721
|
$tb2->seekFirst();
|
|
651
722
|
$this->assertEquals($tb2->stat(), 0);
|
|
652
723
|
$tb2->setFV(FDI_NAME, $tb2->getFVint(FDI_ID) + 1);
|
|
653
|
-
$tb2->update();
|
|
654
|
-
|
|
655
|
-
|
|
656
|
-
|
|
657
|
-
|
|
658
|
-
|
|
724
|
+
$tb2->update(); //Change success
|
|
725
|
+
$this->assertEquals($tb2->stat(), 0);
|
|
726
|
+
$tbg2->setFV(FDI_ID, 1);
|
|
727
|
+
$tbg2->setFV(FDI_NAME, 'ABC');
|
|
728
|
+
$tbg2->insert();
|
|
729
|
+
$this->assertEquals($tbg2->stat(), 0);
|
|
730
|
+
|
|
731
|
+
// in-snapshot repeatable read check same value
|
|
659
732
|
$tb->seekFirst();
|
|
660
733
|
$secondValue = $tb->getFVstr(FDI_NAME);
|
|
661
734
|
$this->assertEquals($tb->stat(), 0);
|
|
735
|
+
$this->assertEquals($secondValue, $firstValue, "$firstValue != $secondValue");
|
|
736
|
+
|
|
737
|
+
$tbg->seekFirst();
|
|
738
|
+
$this->assertEquals($tbg->stat(), Bz\transactd::STATUS_EOF);
|
|
739
|
+
$this->assertEquals($tbg->recordCount(false), 0);
|
|
740
|
+
|
|
741
|
+
// in-snapshot update
|
|
742
|
+
$tb->update();
|
|
743
|
+
$this->assertEquals($tb->stat(), Bz\transactd::STATUS_INVALID_LOCKTYPE);
|
|
744
|
+
|
|
745
|
+
// in-snapshot insert
|
|
746
|
+
$tb->setFV(FDI_ID, 0);
|
|
747
|
+
$tb->insert();
|
|
748
|
+
$this->assertEquals($tb->stat(), Bz\transactd::STATUS_INVALID_LOCKTYPE);
|
|
749
|
+
|
|
750
|
+
// phantom read
|
|
751
|
+
$tb2->setFV(FDI_ID, 29999);
|
|
752
|
+
$tb2->insert();
|
|
753
|
+
$this->assertEquals($tb2->stat(), 0);
|
|
754
|
+
$tb->setFV(FDI_ID, 29999);
|
|
755
|
+
$tb->seek();
|
|
756
|
+
$this->assertEquals($tb->stat(), Bz\transactd::STATUS_NOT_FOUND_TI);
|
|
757
|
+
|
|
758
|
+
// clean up
|
|
759
|
+
$tb2->del();
|
|
760
|
+
$this->assertEquals($tb2->stat(), 0);
|
|
761
|
+
|
|
662
762
|
$db->endSnapshot();
|
|
763
|
+
$this->assertEquals($db->stat(), 0);
|
|
764
|
+
|
|
765
|
+
// After snapshot, db can read new versions.
|
|
766
|
+
$tb->seekFirst();
|
|
663
767
|
$this->assertEquals($tb->stat(), 0);
|
|
664
|
-
|
|
665
|
-
|
|
666
|
-
|
|
667
|
-
|
|
668
|
-
|
|
768
|
+
$this->assertEquals($tb->getFVint(FDI_ID), 1);
|
|
769
|
+
$tbg->seekFirst();
|
|
770
|
+
$this->assertEquals($tbg->stat(), 0);
|
|
771
|
+
$this->assertEquals($tbg->recordCount(false), 1);
|
|
772
|
+
|
|
773
|
+
// gap lock
|
|
774
|
+
$db->beginSnapshot(Bz\transactd::MULTILOCK_GAP_SHARE);
|
|
775
|
+
$tb->seekLast(); // id = 30000
|
|
776
|
+
$this->assertEquals($tb->stat(), 0);
|
|
777
|
+
$tb->seekPrev(); // id = 20002
|
|
778
|
+
$this->assertEquals($tb->stat(), 0);
|
|
779
|
+
$tb->seekPrev(); // id = 20001
|
|
780
|
+
$this->assertEquals($tb->stat(), 0);
|
|
781
|
+
|
|
782
|
+
$tb2->setFV(FDI_ID, 29999);
|
|
783
|
+
$tb2->insert();
|
|
784
|
+
$this->assertEquals($tb2->stat(), Bz\transactd::STATUS_LOCK_ERROR);
|
|
785
|
+
|
|
786
|
+
$db->endSnapshot();
|
|
669
787
|
}
|
|
670
788
|
public function testConflict()
|
|
671
789
|
{
|
|
672
790
|
$db = new Bz\database();
|
|
791
|
+
$tb = $this->openTable($db);
|
|
673
792
|
$db2 = new Bz\database();
|
|
674
793
|
$db2->connect(PROTOCOL . HOSTNAME . DBNAME, true);
|
|
675
794
|
$this->assertEquals($db2->stat(), 0);
|
|
676
|
-
$tb = $this->openTable($db);
|
|
677
795
|
$this->assertNotEquals($tb, NULL);
|
|
678
796
|
$tb2 = $this->openTable($db2);
|
|
679
797
|
$this->assertNotEquals($tb2, NULL);
|
|
@@ -717,93 +835,584 @@ class transactdTest extends PHPUnit_Framework_TestCase
|
|
|
717
835
|
unset($db2);
|
|
718
836
|
unset($db);
|
|
719
837
|
}
|
|
720
|
-
|
|
838
|
+
// isoration Level ISO_REPEATABLE_READ
|
|
839
|
+
public function testTransactionLockRepeatable()
|
|
721
840
|
{
|
|
722
841
|
$db = new Bz\database();
|
|
842
|
+
$tb = $this->openTable($db);
|
|
843
|
+
$this->assertNotEquals($tb, NULL);
|
|
723
844
|
$db2 = new Bz\database();
|
|
724
845
|
$db2->connect(PROTOCOL . HOSTNAME . DBNAME, true);
|
|
725
846
|
$this->assertEquals($db2->stat(), 0);
|
|
726
|
-
$tb = $this->openTable($db);
|
|
727
|
-
$this->assertNotEquals($tb, NULL);
|
|
728
847
|
$tb2 = $this->openTable($db2);
|
|
729
848
|
$this->assertNotEquals($tb2, NULL);
|
|
730
|
-
|
|
731
|
-
|
|
732
|
-
|
|
733
|
-
|
|
734
|
-
$
|
|
849
|
+
|
|
850
|
+
$db->beginTrn(Bz\transactd::MULTILOCK_REPEATABLE_READ);
|
|
851
|
+
$this->assertEquals($db->stat(), 0);
|
|
852
|
+
// Test Invalid operation
|
|
853
|
+
$db->beginSnapshot();
|
|
854
|
+
$this->assertEquals($db->stat(), Bz\transactd::STATUS_ALREADY_INTRANSACTION);
|
|
855
|
+
|
|
856
|
+
// ------------------------------------------------------
|
|
857
|
+
// Test Read with lock
|
|
858
|
+
// ------------------------------------------------------
|
|
859
|
+
// lock(X) the first record
|
|
735
860
|
$tb->seekFirst();
|
|
736
861
|
$this->assertEquals($tb->stat(), 0);
|
|
737
|
-
|
|
862
|
+
|
|
863
|
+
// Add lock(X) the second record
|
|
738
864
|
$tb->seekNext();
|
|
865
|
+
|
|
866
|
+
// No transaction user can read allways. Use consistent_read
|
|
739
867
|
$tb2->seekFirst();
|
|
740
868
|
$this->assertEquals($tb2->stat(), 0);
|
|
869
|
+
|
|
870
|
+
$tb2->seekNext();
|
|
871
|
+
$this->assertEquals($tb2->stat(), 0);
|
|
872
|
+
|
|
873
|
+
// The second transaction user can not lock same record.
|
|
741
874
|
$db2->beginTrn();
|
|
742
875
|
$tb2->setKeyNum(0);
|
|
876
|
+
|
|
877
|
+
// Try lock(X)
|
|
878
|
+
$tb2->seekFirst();
|
|
879
|
+
$this->assertEquals($tb2->stat(), Bz\transactd::STATUS_LOCK_ERROR);
|
|
880
|
+
$db2->endTrn();
|
|
881
|
+
$db->endTrn();
|
|
882
|
+
|
|
883
|
+
// ------------------------------------------------------
|
|
884
|
+
// Test single record lock and Transaction lock
|
|
885
|
+
// ------------------------------------------------------
|
|
886
|
+
// lock(X) non-transaction
|
|
887
|
+
$tb2->seekFirst(Bz\transactd::ROW_LOCK_X);
|
|
888
|
+
|
|
889
|
+
$db->beginTrn(Bz\transactd::MULTILOCK_REPEATABLE_READ);
|
|
890
|
+
$this->assertEquals($db->stat(), 0);
|
|
891
|
+
|
|
892
|
+
// Try lock(X)
|
|
893
|
+
$tb->seekFirst();
|
|
894
|
+
$this->assertEquals($tb->stat(), Bz\transactd::STATUS_LOCK_ERROR);
|
|
895
|
+
|
|
896
|
+
// Remove lock(X)
|
|
897
|
+
$tb2->seekFirst();
|
|
898
|
+
|
|
899
|
+
// Retry lock(X)
|
|
900
|
+
$tb->seekFirst();
|
|
901
|
+
$this->assertEquals($tb->stat(), 0);
|
|
902
|
+
|
|
903
|
+
$tb->setFV(FDI_NAME, 'ABC');
|
|
904
|
+
$tb->update();
|
|
905
|
+
$this->assertEquals($tb->stat(), 0);
|
|
906
|
+
|
|
907
|
+
// No transaction user can read allways. Use consistent_read
|
|
743
908
|
$tb2->seekFirst();
|
|
744
909
|
$this->assertEquals($tb2->stat(), 0);
|
|
910
|
+
$this->assertNotEquals($tb2->getFVstr(FDI_NAME), 'ABC');
|
|
911
|
+
|
|
912
|
+
// ------------------------------------------------------
|
|
913
|
+
// Test Transaction lock and Transaction lock
|
|
914
|
+
// ------------------------------------------------------
|
|
915
|
+
$db2->beginTrn();
|
|
916
|
+
$this->assertEquals($db2->stat(), 0);
|
|
917
|
+
|
|
918
|
+
// try lock(X)
|
|
919
|
+
$tb2->seekFirst();
|
|
920
|
+
$this->assertEquals($tb2->stat(), Bz\transactd::STATUS_LOCK_ERROR);
|
|
921
|
+
|
|
922
|
+
// Try unlock updated record. Can not unlock updated record.
|
|
923
|
+
$tb->unlock();
|
|
924
|
+
|
|
925
|
+
// try lock(X)
|
|
926
|
+
$tb2->seekFirst();
|
|
927
|
+
$this->assertEquals($tb2->stat(), Bz\transactd::STATUS_LOCK_ERROR);
|
|
928
|
+
|
|
745
929
|
$db2->endTrn();
|
|
746
930
|
$db->endTrn();
|
|
931
|
+
|
|
747
932
|
// ----------------------------------------------------
|
|
748
|
-
//
|
|
933
|
+
// Test phantom read
|
|
749
934
|
// ----------------------------------------------------
|
|
750
|
-
$db->beginTrn(Bz\transactd::
|
|
751
|
-
$
|
|
935
|
+
$db->beginTrn(Bz\transactd::MULTILOCK_REPEATABLE_READ);
|
|
936
|
+
$this->assertEquals($db->stat(), 0);
|
|
937
|
+
|
|
938
|
+
// read last row
|
|
939
|
+
$tb->seekLast(); // lock(X) last id = 30000
|
|
940
|
+
$this->assertEquals($tb->stat(), 0);
|
|
941
|
+
$tb->seekPrev(); // Add lock(X)
|
|
942
|
+
$this->assertEquals($tb->stat(), 0);
|
|
943
|
+
$last2 = $tb->getFVint(FDI_ID);
|
|
944
|
+
|
|
945
|
+
// insert test row
|
|
946
|
+
$tb2->setFV(FDI_ID, 29999);
|
|
947
|
+
$tb2->insert(); // Can not insert by gap lock
|
|
948
|
+
$this->assertEquals($tb2->stat(), Bz\transactd::STATUS_LOCK_ERROR);
|
|
949
|
+
|
|
950
|
+
$tb->seekLast();
|
|
951
|
+
$this->assertEquals($tb->stat(), 0);
|
|
952
|
+
$tb->seekPrev();
|
|
953
|
+
$this->assertEquals($tb->stat(), 0);
|
|
954
|
+
$this->assertEquals($tb->getFVint(FDI_ID), $last2);
|
|
955
|
+
$db->endTrn();
|
|
956
|
+
|
|
957
|
+
// ----------------------------------------------------
|
|
958
|
+
// Test Abort
|
|
959
|
+
// ----------------------------------------------------
|
|
960
|
+
$db->beginTrn(Bz\transactd::MULTILOCK_REPEATABLE_READ);
|
|
961
|
+
$this->assertEquals($db->stat(), 0);
|
|
962
|
+
|
|
963
|
+
// lock(X)
|
|
752
964
|
$tb->seekFirst();
|
|
753
965
|
$this->assertEquals($tb->stat(), 0);
|
|
966
|
+
$tb->setFV(FDI_NAME, 'EFG');
|
|
967
|
+
$tb->update();
|
|
968
|
+
$this->assertEquals($tb->stat(), 0);
|
|
969
|
+
|
|
754
970
|
// move from first record.
|
|
755
971
|
$tb->seekNext();
|
|
756
|
-
|
|
972
|
+
$db->abortTrn();
|
|
973
|
+
|
|
974
|
+
$tb2->setKeyNum(0);
|
|
975
|
+
$tb2->seekFirst();
|
|
976
|
+
$this->assertEquals($tb2->getFVstr(FDI_NAME), 'ABC');
|
|
977
|
+
|
|
978
|
+
// ----------------------------------------------------
|
|
979
|
+
// Test Query and locks Multi record lock
|
|
980
|
+
// ----------------------------------------------------
|
|
981
|
+
$db->beginTrn(Bz\transactd::MULTILOCK_REPEATABLE_READ);
|
|
982
|
+
$this->assertEquals($db->stat(), 0);
|
|
983
|
+
|
|
984
|
+
// Test find records are lock.
|
|
985
|
+
$q = new Bz\query();
|
|
986
|
+
$q->where('id', '<=', 15)->and_('id', '<>', 13)->reject(0xFFFF);
|
|
987
|
+
$tb->setQuery($q);
|
|
988
|
+
$tb->setFV(FDI_ID, 12);
|
|
989
|
+
$tb->find();
|
|
990
|
+
while ($tb->stat() == 0)
|
|
991
|
+
$tb->findNext();
|
|
992
|
+
$this->assertEquals($tb->getFVint(FDI_ID), 15);
|
|
993
|
+
|
|
994
|
+
// all records locked
|
|
995
|
+
for ($i = 12; $i <= 16; $i++)
|
|
996
|
+
{
|
|
997
|
+
$tb2->setFV(FDI_ID, $i);
|
|
998
|
+
$tb2->seek(Bz\transactd::ROW_LOCK_X);
|
|
999
|
+
$this->assertEquals($tb2->stat(), Bz\transactd::STATUS_LOCK_ERROR);
|
|
1000
|
+
}
|
|
1001
|
+
$db->endTrn();
|
|
1002
|
+
}
|
|
1003
|
+
public function testTransactionLockReadCommited()
|
|
1004
|
+
{
|
|
1005
|
+
$db = new Bz\database();
|
|
1006
|
+
$tb = $this->openTable($db);
|
|
1007
|
+
$this->assertNotEquals($tb, NULL);
|
|
1008
|
+
$db2 = new Bz\database();
|
|
1009
|
+
$db2->connect(PROTOCOL . HOSTNAME . DBNAME, true);
|
|
1010
|
+
$this->assertEquals($db2->stat(), 0);
|
|
1011
|
+
$tb2 = $this->openTable($db2);
|
|
1012
|
+
$this->assertNotEquals($tb2, NULL);
|
|
1013
|
+
|
|
1014
|
+
// ------------------------------------------------------
|
|
1015
|
+
// Test single record lock Transaction and read
|
|
1016
|
+
// ------------------------------------------------------
|
|
1017
|
+
$db->beginTrn(Bz\transactd::SINGLELOCK_READ_COMMITED);
|
|
1018
|
+
$this->assertEquals($db->stat(), 0);
|
|
1019
|
+
// Test Invalid operation
|
|
1020
|
+
$db->beginSnapshot();
|
|
1021
|
+
$this->assertEquals($db->stat(), Bz\transactd::STATUS_ALREADY_INTRANSACTION);
|
|
1022
|
+
|
|
1023
|
+
$tb->setKeyNum(0);
|
|
1024
|
+
$tb->seekFirst(); // lock(X)
|
|
1025
|
+
$this->assertEquals($tb->stat(), 0);
|
|
1026
|
+
|
|
1027
|
+
// Try lock(X)
|
|
1028
|
+
$tb2->seekFirst(Bz\transactd::ROW_LOCK_X);
|
|
1029
|
+
$this->assertEquals($tb2->stat(), Bz\transactd::STATUS_LOCK_ERROR);
|
|
1030
|
+
|
|
1031
|
+
// consistent read
|
|
1032
|
+
$tb2->seekFirst();
|
|
1033
|
+
$this->assertEquals($tb2->stat(), 0);
|
|
1034
|
+
|
|
1035
|
+
// Unlock first record. And lock(X) second record
|
|
1036
|
+
$tb->seekNext();
|
|
1037
|
+
|
|
1038
|
+
// test unlocked first record
|
|
757
1039
|
$tb2->seekFirst();
|
|
1040
|
+
$this->assertEquals($tb2->stat(), 0);
|
|
1041
|
+
$tb2->update();
|
|
1042
|
+
$this->assertEquals($tb2->stat(), 0);
|
|
1043
|
+
|
|
1044
|
+
// The second record, consistent read
|
|
1045
|
+
$tb2->seekNext();
|
|
1046
|
+
$this->assertEquals($tb2->stat(), 0);
|
|
1047
|
+
// Try lock(X) whith lock(IX)
|
|
1048
|
+
$tb2->update();
|
|
758
1049
|
$this->assertEquals($tb2->stat(), Bz\transactd::STATUS_LOCK_ERROR);
|
|
759
|
-
|
|
1050
|
+
|
|
1051
|
+
// ------------------------------------------------------
|
|
1052
|
+
// Test single record lock Transaction and Transaction lock
|
|
1053
|
+
// ------------------------------------------------------
|
|
760
1054
|
$db2->beginTrn();
|
|
761
|
-
|
|
1055
|
+
// Try lock(X)
|
|
762
1056
|
$tb2->seekFirst();
|
|
1057
|
+
$this->assertEquals($tb2->stat(), 0);
|
|
1058
|
+
// Try lock(X)
|
|
1059
|
+
$tb2->seekNext();
|
|
763
1060
|
$this->assertEquals($tb2->stat(), Bz\transactd::STATUS_LOCK_ERROR);
|
|
764
1061
|
$db2->endTrn();
|
|
765
1062
|
$db->endTrn();
|
|
766
|
-
|
|
767
|
-
//
|
|
768
|
-
//
|
|
769
|
-
|
|
770
|
-
$
|
|
1063
|
+
|
|
1064
|
+
// ------------------------------------------------------
|
|
1065
|
+
// Test multi record lock Transaction and non-transaction read
|
|
1066
|
+
// ------------------------------------------------------
|
|
1067
|
+
$db->beginTrn(Bz\transactd::MULTILOCK_READ_COMMITED);
|
|
1068
|
+
$this->assertEquals($db->stat(), 0);
|
|
1069
|
+
|
|
1070
|
+
// lock(X) the first record
|
|
1071
|
+
$tb->seekFirst();
|
|
1072
|
+
$this->assertEquals($tb->stat(), 0);
|
|
1073
|
+
|
|
1074
|
+
// Add lock(X) the second record
|
|
1075
|
+
$tb->seekNext();
|
|
1076
|
+
|
|
1077
|
+
// No transaction user read can read allways. Use consistent_read
|
|
1078
|
+
$tb2->seekFirst();
|
|
1079
|
+
$this->assertEquals($tb2->stat(), 0);
|
|
1080
|
+
|
|
1081
|
+
$tb2->seekNext();
|
|
1082
|
+
$this->assertEquals($tb2->stat(), 0);
|
|
1083
|
+
|
|
1084
|
+
// ------------------------------------------------------
|
|
1085
|
+
// Test unlock
|
|
1086
|
+
// ------------------------------------------------------
|
|
1087
|
+
$tb2->seekFirst();
|
|
1088
|
+
$tb2->seekNext(Bz\transactd::ROW_LOCK_X);
|
|
1089
|
+
$this->assertEquals($tb2->stat(), Bz\transactd::STATUS_LOCK_ERROR);
|
|
1090
|
+
|
|
1091
|
+
$tb->unlock();
|
|
1092
|
+
// retry seekNext. Before operation is failed but do not lost currency.
|
|
1093
|
+
$tb2->seekNext(Bz\transactd::ROW_LOCK_X);
|
|
1094
|
+
$this->assertEquals($tb2->stat(), 0);
|
|
1095
|
+
$tb2->seekNext();
|
|
1096
|
+
// ------------------------------------------------------
|
|
1097
|
+
// Test undate record unlock
|
|
1098
|
+
// ------------------------------------------------------
|
|
1099
|
+
$tb->seekFirst();
|
|
1100
|
+
$this->assertEquals($tb->stat(), 0);
|
|
1101
|
+
$tb->seekNext();
|
|
1102
|
+
$this->assertEquals($tb->stat(), 0);
|
|
1103
|
+
$tb->update();
|
|
1104
|
+
$this->assertEquals($tb->stat(), 0);
|
|
1105
|
+
$tb->unlock(); // Can not unlock updated record
|
|
1106
|
+
$this->assertEquals($tb->stat(), 0);
|
|
1107
|
+
$tb2->seekFirst();
|
|
1108
|
+
$tb2->seekNext(Bz\transactd::ROW_LOCK_X);
|
|
1109
|
+
$this->assertEquals($tb2->stat(), Bz\transactd::STATUS_LOCK_ERROR);
|
|
1110
|
+
|
|
1111
|
+
// ------------------------------------------------------
|
|
1112
|
+
// Test multi record lock Transaction and Transaction
|
|
1113
|
+
// ------------------------------------------------------
|
|
1114
|
+
$db2->beginTrn();
|
|
1115
|
+
$this->assertEquals($db2->stat(), 0);
|
|
1116
|
+
|
|
1117
|
+
// Try lock(X)
|
|
1118
|
+
$tb2->seekFirst();
|
|
1119
|
+
$this->assertEquals($tb2->stat(), Bz\transactd::STATUS_LOCK_ERROR);
|
|
1120
|
+
$db2->endTrn();
|
|
1121
|
+
$db->endTrn();
|
|
1122
|
+
|
|
1123
|
+
// ------------------------------------------------------
|
|
1124
|
+
// Test multi record lock Transaction and non-transaction record lock
|
|
1125
|
+
// ------------------------------------------------------
|
|
1126
|
+
// lock(X) non-transaction
|
|
1127
|
+
$tb2->seekFirst(Bz\transactd::ROW_LOCK_X);
|
|
1128
|
+
|
|
1129
|
+
$db->beginTrn(Bz\transactd::SINGLELOCK_READ_COMMITED);
|
|
1130
|
+
$this->assertEquals($db->stat(), 0);
|
|
1131
|
+
|
|
1132
|
+
// Try lock(X)
|
|
1133
|
+
$tb->seekFirst();
|
|
1134
|
+
$this->assertEquals($tb->stat(), Bz\transactd::STATUS_LOCK_ERROR);
|
|
1135
|
+
|
|
1136
|
+
// Remove lock(X)
|
|
1137
|
+
$tb2->seekFirst();
|
|
1138
|
+
|
|
1139
|
+
// Retry lock(X)
|
|
771
1140
|
$tb->seekFirst();
|
|
772
1141
|
$this->assertEquals($tb->stat(), 0);
|
|
1142
|
+
|
|
1143
|
+
// update in transaction
|
|
773
1144
|
$tb->setFV(FDI_NAME, 'ABC');
|
|
774
1145
|
$tb->update();
|
|
775
1146
|
$this->assertEquals($tb->stat(), 0);
|
|
776
|
-
|
|
777
|
-
|
|
778
|
-
$
|
|
779
|
-
|
|
1147
|
+
|
|
1148
|
+
// move from first record.
|
|
1149
|
+
$tb->seekNext();
|
|
1150
|
+
|
|
1151
|
+
// No transaction read can read allways. Use consistent_read
|
|
1152
|
+
$tb2->seekFirst();
|
|
1153
|
+
$this->assertEquals($tb2->stat(), 0);
|
|
1154
|
+
$tb2->update();
|
|
1155
|
+
$this->assertEquals($tb2->stat(), Bz\transactd::STATUS_LOCK_ERROR);
|
|
1156
|
+
|
|
1157
|
+
$db->endTrn();
|
|
1158
|
+
// ------------------------------------------------------
|
|
1159
|
+
// Test phantom read
|
|
1160
|
+
// ------------------------------------------------------
|
|
1161
|
+
$db->beginTrn(Bz\transactd::MULTILOCK_READ_COMMITED);
|
|
1162
|
+
$this->assertEquals($db->stat(), 0);
|
|
1163
|
+
|
|
1164
|
+
// read last row
|
|
1165
|
+
$tb->seekLast(); // lock(X) last id = 30000
|
|
1166
|
+
$this->assertEquals($tb->stat(), 0);
|
|
1167
|
+
$tb->seekPrev(); // Add lock(X)
|
|
1168
|
+
$this->assertEquals($tb->stat(), 0);
|
|
1169
|
+
$last2 = $tb->getFVint(FDI_ID);
|
|
1170
|
+
|
|
1171
|
+
//insert test row
|
|
1172
|
+
$tb2->setFV(FDI_ID, 29999);
|
|
1173
|
+
$tb2->insert();
|
|
1174
|
+
$this->assertEquals($tb2->stat(), 0);
|
|
1175
|
+
|
|
1176
|
+
$tb->seekLast();
|
|
1177
|
+
$this->assertEquals($tb->stat(), 0);
|
|
1178
|
+
$tb->seekPrev();
|
|
1179
|
+
$this->assertEquals($tb->stat(), 0);
|
|
1180
|
+
$this->assertNotEquals($tb->getFVint(FDI_ID), $last2);
|
|
1181
|
+
$db->endTrn();
|
|
1182
|
+
|
|
1183
|
+
// cleanup
|
|
1184
|
+
$tb2->del(); // last id = 29999
|
|
1185
|
+
$this->assertEquals($tb->stat(), 0);
|
|
1186
|
+
|
|
1187
|
+
// ------------------------------------------------------
|
|
1188
|
+
// Test use shared lock option
|
|
1189
|
+
// ------------------------------------------------------
|
|
1190
|
+
$db->beginTrn(Bz\transactd::MULTILOCK_REPEATABLE_READ);
|
|
1191
|
+
$this->assertEquals($db->stat(), 0);
|
|
1192
|
+
|
|
1193
|
+
$db2->beginTrn(Bz\transactd::MULTILOCK_REPEATABLE_READ);
|
|
1194
|
+
$this->assertEquals($db2->stat(), 0);
|
|
1195
|
+
|
|
1196
|
+
$tb->seekLast(Bz\transactd::ROW_LOCK_S);
|
|
1197
|
+
$this->assertEquals($tb->stat(), 0);
|
|
1198
|
+
$tb2->seekLast(Bz\transactd::ROW_LOCK_S);
|
|
1199
|
+
$this->assertEquals($tb2->stat(), 0);
|
|
1200
|
+
|
|
1201
|
+
$tb->seekPrev(); // Lock(X)
|
|
1202
|
+
$this->assertEquals($tb->stat(), 0);
|
|
1203
|
+
|
|
1204
|
+
$tb2->seekPrev(Bz\transactd::ROW_LOCK_S);
|
|
1205
|
+
$this->assertEquals($tb2->stat(), Bz\transactd::STATUS_LOCK_ERROR);
|
|
1206
|
+
|
|
1207
|
+
$tb->seekPrev(Bz\transactd::ROW_LOCK_S);
|
|
1208
|
+
$this->assertEquals($tb->stat(), 0);
|
|
1209
|
+
$id = $tb->getFVint(FDI_ID);
|
|
1210
|
+
|
|
1211
|
+
$tb2->setFV(FDI_ID, $id);
|
|
1212
|
+
$tb2->seek(Bz\transactd::ROW_LOCK_S);
|
|
1213
|
+
$this->assertEquals($tb2->stat(), 0);
|
|
1214
|
+
|
|
1215
|
+
$db2->endTrn();
|
|
1216
|
+
$db->endTrn();
|
|
1217
|
+
|
|
1218
|
+
// ------------------------------------------------------
|
|
1219
|
+
// Abort test
|
|
1220
|
+
// ------------------------------------------------------
|
|
1221
|
+
$db->beginTrn(Bz\transactd::SINGLELOCK_READ_COMMITED);
|
|
1222
|
+
$this->assertEquals($db->stat(), 0);
|
|
1223
|
+
|
|
1224
|
+
$tb->seekFirst();
|
|
1225
|
+
$this->assertEquals($tb->stat(), 0);
|
|
1226
|
+
$tb->setFV(FDI_NAME, 'EFG');
|
|
1227
|
+
$tb->update();
|
|
1228
|
+
$this->assertEquals($tb->stat(), 0);
|
|
1229
|
+
|
|
1230
|
+
$tb->seekNext();
|
|
1231
|
+
$db->abortTrn();
|
|
1232
|
+
$tb2->setKeyNum(0);
|
|
1233
|
+
$tb2->seekFirst();
|
|
1234
|
+
$this->assertEquals($tb2->getFVstr(FDI_NAME), 'ABC');
|
|
1235
|
+
|
|
1236
|
+
// ------------------------------------------------------
|
|
1237
|
+
// Test Query and locks Single record lock
|
|
1238
|
+
// ------------------------------------------------------
|
|
1239
|
+
$db->beginTrn(Bz\transactd::SINGLELOCK_READ_COMMITED);
|
|
1240
|
+
$this->assertEquals($db->stat(), 0);
|
|
1241
|
+
|
|
1242
|
+
// Test find last record locked
|
|
1243
|
+
$q = new Bz\query();
|
|
1244
|
+
$q->where('id', '<=', '100');
|
|
1245
|
+
$tb->setQuery($q);
|
|
1246
|
+
$tb->setFV(FDI_ID, 1);
|
|
1247
|
+
$tb->find();
|
|
1248
|
+
while ($tb->stat() == 0)
|
|
1249
|
+
$tb->findNext();
|
|
1250
|
+
$this->assertEquals($tb->getFVint(FDI_ID), 100);
|
|
1251
|
+
|
|
1252
|
+
// find read last is record of id = 101.
|
|
1253
|
+
// Would be difficult to identify the last
|
|
1254
|
+
// access to records at SINGLELOCK_READ_COMMITED.
|
|
1255
|
+
// No match records are unlocked.
|
|
1256
|
+
$tb2->setFV(FDI_ID, 100);
|
|
1257
|
+
$tb2->seek(Bz\transactd::ROW_LOCK_X);
|
|
1258
|
+
$this->assertEquals($tb2->stat(), 0);
|
|
1259
|
+
$tb2->unlock();
|
|
1260
|
+
$db->endTrn();
|
|
1261
|
+
|
|
1262
|
+
// ------------------------------------------------------
|
|
1263
|
+
// Test Query and locks Multi record lock
|
|
1264
|
+
// ------------------------------------------------------
|
|
1265
|
+
$db->beginTrn(Bz\transactd::MULTILOCK_READ_COMMITED);
|
|
1266
|
+
$this->assertEquals($db->stat(), 0);
|
|
1267
|
+
|
|
1268
|
+
// Test find records are lock.
|
|
1269
|
+
$q->reset()->where('id', '<=', 15)->and_('id', '<>', 13)->reject(0xFFFF);
|
|
1270
|
+
$tb->setQuery($q);
|
|
1271
|
+
$tb->setFV(FDI_ID, 12);
|
|
1272
|
+
$tb->find();
|
|
1273
|
+
while ($tb->stat() == 0)
|
|
1274
|
+
$tb->findNext();
|
|
1275
|
+
$this->assertEquals($tb->getFVint(FDI_ID), 15);
|
|
1276
|
+
|
|
1277
|
+
for ($i = 12; $i <= 16; $i++)
|
|
1278
|
+
{
|
|
1279
|
+
$tb2->setFV(FDI_ID, $i);
|
|
1280
|
+
$tb2->seek(Bz\transactd::ROW_LOCK_X);
|
|
1281
|
+
if (($i == 16) || ($i == 13))
|
|
1282
|
+
$this->assertEquals($tb2->stat(), 0);
|
|
1283
|
+
else
|
|
1284
|
+
$this->assertEquals($tb2->stat(), Bz\transactd::STATUS_LOCK_ERROR);
|
|
1285
|
+
}
|
|
1286
|
+
$db->endTrn();
|
|
1287
|
+
}
|
|
1288
|
+
public function testRecordLock()
|
|
1289
|
+
{
|
|
1290
|
+
$db = new Bz\database();
|
|
1291
|
+
$tb = $this->openTable($db);
|
|
1292
|
+
$this->assertNotEquals($tb, NULL);
|
|
1293
|
+
$db2 = new Bz\database();
|
|
1294
|
+
$db2->connect(PROTOCOL . HOSTNAME . DBNAME, true);
|
|
1295
|
+
$this->assertEquals($db2->stat(), 0);
|
|
1296
|
+
$tb2 = $this->openTable($db2);
|
|
1297
|
+
$this->assertNotEquals($tb2, NULL);
|
|
1298
|
+
|
|
1299
|
+
$tb->setKeyNum(0);
|
|
1300
|
+
$tb2->setKeyNum(0);
|
|
1301
|
+
|
|
1302
|
+
// Single record lock
|
|
1303
|
+
$tb->seekFirst(Bz\transactd::ROW_LOCK_X); // lock(X)
|
|
1304
|
+
$this->assertEquals($tb->stat(), 0);
|
|
1305
|
+
$tb2->seekFirst(); // Use consistent_read
|
|
1306
|
+
$this->assertEquals($tb2->stat(), 0);
|
|
1307
|
+
|
|
1308
|
+
$tb2->seekFirst(Bz\transactd::ROW_LOCK_X); // Try lock(X) single
|
|
1309
|
+
$this->assertEquals($tb2->stat(), Bz\transactd::STATUS_LOCK_ERROR);
|
|
1310
|
+
|
|
1311
|
+
// try consistent_read. Check ended that before auto transaction
|
|
1312
|
+
$tb2->seekFirst();
|
|
1313
|
+
$this->assertEquals($tb2->stat(), 0);
|
|
1314
|
+
|
|
1315
|
+
$tb2->seekNext(Bz\transactd::ROW_LOCK_X); // lock(X) second
|
|
1316
|
+
$this->assertEquals($tb2->stat(), 0);
|
|
1317
|
+
|
|
1318
|
+
$tb2->seekNext(Bz\transactd::ROW_LOCK_X); // lock(X) third, second lock freed
|
|
1319
|
+
$this->assertEquals($tb2->stat(), 0);
|
|
1320
|
+
|
|
1321
|
+
$tb->seekNext(); // nobody lock second.
|
|
1322
|
+
$this->assertEquals($tb->stat(), 0);
|
|
1323
|
+
$tb->seekNext(Bz\transactd::ROW_LOCK_X); // Try lock(X) third
|
|
1324
|
+
$this->assertEquals($tb->stat(), Bz\transactd::STATUS_LOCK_ERROR);
|
|
1325
|
+
|
|
1326
|
+
// Update test change third with lock(X)
|
|
1327
|
+
$tb2->setFV(FDI_NAME, 'The 3rd');
|
|
1328
|
+
$tb2->update(); // auto trn commit and unlock all locks
|
|
1329
|
+
$this->assertEquals($tb2->stat(), 0);
|
|
1330
|
+
$tb2->seekNext(Bz\transactd::ROW_LOCK_X); // lock(X) 4th
|
|
1331
|
+
$this->assertEquals($tb2->stat(), 0);
|
|
1332
|
+
$tb2->setFV(FDI_NAME, 'The 4th');
|
|
1333
|
+
$tb2->update(); // auto trn commit and unlock all locks
|
|
1334
|
+
|
|
1335
|
+
// Test unlock all locks, after update
|
|
1336
|
+
$tb->seekFirst(Bz\transactd::ROW_LOCK_X); // lock(X) first
|
|
1337
|
+
$this->assertEquals($tb2->stat(), 0);
|
|
1338
|
+
$tb->seekNext(Bz\transactd::ROW_LOCK_X); // lock(X) second
|
|
1339
|
+
$this->assertEquals($tb2->stat(), 0);
|
|
1340
|
+
$tb->seekNext(Bz\transactd::ROW_LOCK_X); // lock(X) third
|
|
1341
|
+
$this->assertEquals($tb2->stat(), 0);
|
|
1342
|
+
$this->assertEquals($tb->getFVstr(FDI_NAME), 'The 3rd');
|
|
1343
|
+
|
|
1344
|
+
// Test Insert, After record lock operation
|
|
1345
|
+
$tb->setFV(FDI_ID, 21000);
|
|
1346
|
+
$tb->insert();
|
|
1347
|
+
$this->assertEquals($tb->stat(), 0);
|
|
1348
|
+
$tb->del();
|
|
1349
|
+
$this->assertEquals($tb->stat(), 0);
|
|
1350
|
+
|
|
1351
|
+
// --------- Unlock test ----------------------------
|
|
1352
|
+
// 1 unlock()
|
|
1353
|
+
$tb->seekFirst(Bz\transactd::ROW_LOCK_X);
|
|
1354
|
+
$this->assertEquals($tb->stat(), 0);
|
|
1355
|
+
|
|
1356
|
+
$tb->unlock();
|
|
1357
|
+
|
|
1358
|
+
$tb2->seekFirst(Bz\transactd::ROW_LOCK_X);
|
|
1359
|
+
$this->assertEquals($tb2->stat(), 0);
|
|
1360
|
+
$tb2->unlock();
|
|
1361
|
+
|
|
1362
|
+
// 2 auto tran ended
|
|
1363
|
+
$tb3 = $this->openTable($db2);
|
|
1364
|
+
$tb2->seekFirst(Bz\transactd::ROW_LOCK_X);
|
|
1365
|
+
$this->assertEquals($tb2->stat(), 0);
|
|
1366
|
+
|
|
1367
|
+
$tb3->seekLast(); //This operation is another table handle, then auto tran ended
|
|
1368
|
+
$this->assertEquals($tb3->stat(), 0);
|
|
1369
|
+
|
|
1370
|
+
$tb->seekFirst(Bz\transactd::ROW_LOCK_X);
|
|
1371
|
+
$this->assertEquals($tb->stat(), 0);
|
|
1372
|
+
$tb->unlock();
|
|
1373
|
+
|
|
1374
|
+
// begin trn
|
|
1375
|
+
$tb3->seekFirst(Bz\transactd::ROW_LOCK_X);
|
|
1376
|
+
$this->assertEquals($tb3->stat(), 0);
|
|
1377
|
+
|
|
1378
|
+
$tb->seekFirst(Bz\transactd::ROW_LOCK_X);
|
|
1379
|
+
$this->assertEquals($tb->stat(), Bz\transactd::STATUS_LOCK_ERROR);
|
|
780
1380
|
$db2->beginTrn();
|
|
781
|
-
|
|
782
|
-
$
|
|
783
|
-
$this->assertEquals($
|
|
1381
|
+
|
|
1382
|
+
$tb->seekFirst(Bz\transactd::ROW_LOCK_X);
|
|
1383
|
+
$this->assertEquals($tb->stat(), 0);
|
|
784
1384
|
$db2->endTrn();
|
|
785
|
-
$
|
|
786
|
-
//
|
|
787
|
-
|
|
788
|
-
|
|
789
|
-
|
|
790
|
-
$tb->
|
|
791
|
-
$tb->
|
|
1385
|
+
$tb->unlock();
|
|
1386
|
+
// begin snapshot
|
|
1387
|
+
$tb3->seekFirst(Bz\transactd::ROW_LOCK_X);
|
|
1388
|
+
$this->assertEquals($tb3->stat(), 0);
|
|
1389
|
+
|
|
1390
|
+
$tb->seekFirst(Bz\transactd::ROW_LOCK_X);
|
|
1391
|
+
$this->assertEquals($tb->stat(), Bz\transactd::STATUS_LOCK_ERROR);
|
|
1392
|
+
$db2->beginSnapshot();
|
|
1393
|
+
$tb->seekFirst(Bz\transactd::ROW_LOCK_X);
|
|
792
1394
|
$this->assertEquals($tb->stat(), 0);
|
|
793
|
-
$
|
|
794
|
-
$tb->
|
|
1395
|
+
$db2->endSnapshot();
|
|
1396
|
+
$tb->unlock();
|
|
1397
|
+
// close Table
|
|
1398
|
+
$tb->seekFirst(Bz\transactd::ROW_LOCK_X);
|
|
795
1399
|
$this->assertEquals($tb->stat(), 0);
|
|
796
|
-
|
|
797
|
-
$
|
|
798
|
-
$
|
|
799
|
-
$
|
|
800
|
-
$tb2->seekFirst();
|
|
801
|
-
$this->assertEquals($tb2->
|
|
1400
|
+
|
|
1401
|
+
$tb2->seekFirst(Bz\transactd::ROW_LOCK_X);
|
|
1402
|
+
$this->assertEquals($tb2->stat(), Bz\transactd::STATUS_LOCK_ERROR);
|
|
1403
|
+
$tb->release();
|
|
1404
|
+
$tb2->seekFirst(Bz\transactd::ROW_LOCK_X);
|
|
1405
|
+
$this->assertEquals($tb2->stat(), 0);
|
|
1406
|
+
$tb2->unlock();
|
|
1407
|
+
// --------- End Unlock test ----------------------------
|
|
802
1408
|
}
|
|
803
1409
|
public function testExclusive()
|
|
804
1410
|
{
|
|
805
1411
|
// db mode exclusive
|
|
806
1412
|
$db = new Bz\database();
|
|
1413
|
+
// ------------------------------------------------------
|
|
1414
|
+
// database WRITE EXCLUSIVE
|
|
1415
|
+
// ------------------------------------------------------
|
|
807
1416
|
$db->open(URL, Bz\transactd::TYPE_SCHEMA_BDF, Bz\transactd::TD_OPEN_EXCLUSIVE);
|
|
808
1417
|
$this->assertEquals($db->stat(), 0);
|
|
809
1418
|
$tb = $db->openTable(TABLENAME);
|
|
@@ -815,71 +1424,167 @@ class transactdTest extends PHPUnit_Framework_TestCase
|
|
|
815
1424
|
$this->assertEquals($db2->stat(), 0);
|
|
816
1425
|
$db2->open(URL, Bz\transactd::TYPE_SCHEMA_BDF);
|
|
817
1426
|
$this->assertEquals($db2->stat(), Bz\transactd::STATUS_CANNOT_LOCK_TABLE);
|
|
818
|
-
|
|
819
|
-
$tb2 = $db->openTable(TABLENAME);
|
|
820
|
-
$this->assertEquals($db->stat(), 0);
|
|
821
|
-
|
|
822
|
-
$tb->setKeyNum(0);
|
|
823
|
-
$tb->seekFirst();
|
|
824
|
-
$this->assertEquals($tb->stat(), 0);
|
|
825
|
-
|
|
826
|
-
$tb->setFV(FDI_NAME, 'ABC123');
|
|
827
|
-
$tb->update();
|
|
828
|
-
$this->assertEquals($tb->stat(), 0);
|
|
829
|
-
|
|
830
|
-
$tb2->setKeyNum(0);
|
|
831
|
-
$tb2->seekFirst();
|
|
832
|
-
$this->assertEquals($tb2->stat(), 0);
|
|
833
|
-
$tb2->setFV(FDI_NAME, 'ABC124');
|
|
834
|
-
$tb2->update();
|
|
835
|
-
$this->assertEquals($tb2->stat(), 0);
|
|
836
|
-
|
|
837
1427
|
$tb->close();
|
|
838
|
-
$tb2->close();
|
|
839
1428
|
$db->close();
|
|
840
1429
|
$db2->close();
|
|
841
1430
|
|
|
1431
|
+
// ------------------------------------------------------
|
|
1432
|
+
// database WRITE EXCLUSIVE
|
|
1433
|
+
// ------------------------------------------------------
|
|
842
1434
|
// table mode exclusive
|
|
843
1435
|
$db = new Bz\database();
|
|
844
|
-
$db->open(URL, Bz\transactd::TYPE_SCHEMA_BDF, Bz\transactd::
|
|
1436
|
+
$db->open(URL, Bz\transactd::TYPE_SCHEMA_BDF, Bz\transactd::TD_OPEN_READONLY_EXCLUSIVE);
|
|
845
1437
|
$this->assertEquals($db->stat(), 0);
|
|
846
|
-
$tb = $db->openTable(TABLENAME, Bz\transactd::
|
|
1438
|
+
$tb = $db->openTable(TABLENAME, Bz\transactd::TD_OPEN_READONLY_EXCLUSIVE);
|
|
847
1439
|
$this->assertEquals($db->stat(), 0);
|
|
848
1440
|
|
|
1441
|
+
// Read only open
|
|
849
1442
|
$db2 = new Bz\database();
|
|
850
|
-
$db2->connect(PROTOCOL . HOSTNAME . DBNAME, true);
|
|
851
|
-
$this->assertEquals($db2->stat(), 0);
|
|
852
1443
|
$db2->open(URL, Bz\transactd::TYPE_SCHEMA_BDF);
|
|
853
1444
|
$this->assertEquals($db2->stat(), 0);
|
|
1445
|
+
$db2->close();
|
|
854
1446
|
|
|
855
|
-
//
|
|
856
|
-
$
|
|
857
|
-
$
|
|
1447
|
+
// Normal open
|
|
1448
|
+
$db2->connect(PROTOCOL . HOSTNAME . DBNAME, true);
|
|
1449
|
+
$db2->open(URL, Bz\transactd::TYPE_SCHEMA_BDF, Bz\transactd::TD_OPEN_NORMAL);
|
|
1450
|
+
$this->assertEquals($db2->stat(), 0);
|
|
1451
|
+
$db2->close();
|
|
858
1452
|
|
|
859
|
-
//
|
|
860
|
-
$
|
|
861
|
-
$this->assertEquals($
|
|
1453
|
+
// Write Exclusive open
|
|
1454
|
+
$db2->open(URL, Bz\transactd::TYPE_SCHEMA_BDF, Bz\transactd::TD_OPEN_EXCLUSIVE);
|
|
1455
|
+
$this->assertEquals($db2->stat(), Bz\transactd::STATUS_CANNOT_LOCK_TABLE);
|
|
1456
|
+
$db2->close();
|
|
862
1457
|
|
|
863
|
-
|
|
864
|
-
|
|
865
|
-
$
|
|
866
|
-
$db->close();
|
|
1458
|
+
// Read Exclusive open
|
|
1459
|
+
$db2->open(URL, Bz\transactd::TYPE_SCHEMA_BDF, Bz\transactd::TD_OPEN_READONLY_EXCLUSIVE);
|
|
1460
|
+
$this->assertEquals($db2->stat(), 0);
|
|
867
1461
|
$db2->close();
|
|
1462
|
+
$db->close();
|
|
868
1463
|
|
|
869
|
-
//
|
|
870
|
-
|
|
871
|
-
|
|
1464
|
+
// ------------------------------------------------------
|
|
1465
|
+
// Normal and Exclusive open tables mix use
|
|
1466
|
+
// ------------------------------------------------------
|
|
1467
|
+
$db->open(URL, Bz\transactd::TYPE_SCHEMA_BDF, Bz\transactd::TD_OPEN_NORMAL);
|
|
872
1468
|
$this->assertEquals($db->stat(), 0);
|
|
873
|
-
$tb = $db->openTable(TABLENAME);
|
|
1469
|
+
$tb = $db->openTable(TABLENAME, Bz\transactd::TD_OPEN_NORMAL);
|
|
874
1470
|
$this->assertEquals($db->stat(), 0);
|
|
1471
|
+
$db2->open(URL, Bz\transactd::TYPE_SCHEMA_BDF);
|
|
1472
|
+
$this->assertEquals($db2->stat(), 0);
|
|
875
1473
|
|
|
876
|
-
$
|
|
1474
|
+
$tb2 = $db->openTable('group', Bz\transactd::TD_OPEN_EXCLUSIVE);
|
|
1475
|
+
$this->assertEquals($db->stat(), 0);
|
|
1476
|
+
// Check tb2 Exclusive
|
|
1477
|
+
$tb3 = $db2->openTable('group', Bz\transactd::TD_OPEN_NORMAL);
|
|
1478
|
+
$this->assertEquals($db2->stat(), Bz\transactd::STATUS_CANNOT_LOCK_TABLE);
|
|
1479
|
+
|
|
1480
|
+
for ($i = 1; $i < 5; $i++)
|
|
1481
|
+
{
|
|
1482
|
+
$tb2->setFV(FDI_ID, $i + 1);
|
|
1483
|
+
$tb2->setFV(FDI_NAME, $i + 1);
|
|
1484
|
+
$tb2->insert();
|
|
1485
|
+
$this->assertEquals($tb2->stat(), 0);
|
|
1486
|
+
}
|
|
1487
|
+
$tb2->seekFirst();
|
|
1488
|
+
$this->assertEquals($tb2->stat(), 0);
|
|
1489
|
+
$tb->seekFirst();
|
|
1490
|
+
$this->assertEquals($tb->stat(), 0);
|
|
1491
|
+
$tb2->seekLast();
|
|
1492
|
+
$this->assertEquals($tb2->stat(), 0);
|
|
1493
|
+
$tb->seekLast();
|
|
1494
|
+
$this->assertEquals($tb->stat(), 0);
|
|
1495
|
+
// Normal close first
|
|
1496
|
+
$tb->close();
|
|
1497
|
+
$tb2->seekLast();
|
|
1498
|
+
$this->assertEquals($tb2->stat(), 0);
|
|
1499
|
+
$tb2->seekFirst();
|
|
1500
|
+
$this->assertEquals($tb2->stat(), 0);
|
|
1501
|
+
|
|
1502
|
+
// Reopen Normal
|
|
1503
|
+
$tb = $db->openTable('user');
|
|
1504
|
+
$tb2->seekFirst();
|
|
1505
|
+
$this->assertEquals($tb2->stat(), 0);
|
|
1506
|
+
$tb->seekFirst();
|
|
1507
|
+
$this->assertEquals($tb->stat(), 0);
|
|
1508
|
+
$tb2->seekLast();
|
|
1509
|
+
$this->assertEquals($tb2->stat(), 0);
|
|
1510
|
+
$tb->seekLast();
|
|
1511
|
+
$this->assertEquals($tb->stat(), 0);
|
|
1512
|
+
// Exclusive close first
|
|
1513
|
+
$tb2->close();
|
|
1514
|
+
$tb->seekFirst();
|
|
1515
|
+
$this->assertEquals($tb->stat(), 0);
|
|
1516
|
+
$tb->seekLast();
|
|
1517
|
+
$this->assertEquals($tb->stat(), 0);
|
|
1518
|
+
|
|
1519
|
+
// ------------------------------------------------------
|
|
1520
|
+
// Normal and Exclusive opend tables mix transaction
|
|
1521
|
+
// ------------------------------------------------------
|
|
1522
|
+
$tb2 = $db->openTable('group', Bz\transactd::TD_OPEN_EXCLUSIVE);
|
|
1523
|
+
$this->assertEquals($tb2->stat(), 0);
|
|
1524
|
+
// Check tb2 Exclusive
|
|
1525
|
+
$tb3 = $db2->openTable('group', Bz\transactd::TD_OPEN_NORMAL);
|
|
1526
|
+
$this->assertEquals($db2->stat(), Bz\transactd::STATUS_CANNOT_LOCK_TABLE);
|
|
1527
|
+
|
|
1528
|
+
$db->beginTrn();
|
|
877
1529
|
$tb->seekFirst();
|
|
878
1530
|
$this->assertEquals($tb->stat(), 0);
|
|
1531
|
+
$tb->setFV(FDI_NAME, 'mix trn');
|
|
1532
|
+
$tb->update();
|
|
1533
|
+
$this->assertEquals($tb->stat(), 0);
|
|
1534
|
+
|
|
1535
|
+
$tb2->seekFirst();
|
|
1536
|
+
$this->assertEquals($tb2->stat(), 0);
|
|
1537
|
+
$tb2->setFV(FDI_NAME, 'first mix trn tb2');
|
|
1538
|
+
$tb2->update();
|
|
1539
|
+
$this->assertEquals($tb2->stat(), 0);
|
|
1540
|
+
|
|
1541
|
+
$tb2->seekNext();
|
|
1542
|
+
$tb2->setFV(FDI_NAME, 'second mix trn tb2');
|
|
1543
|
+
$tb2->update();
|
|
1544
|
+
$this->assertEquals($tb2->stat(), 0);
|
|
1545
|
+
$db->endTrn();
|
|
1546
|
+
$tb2->seekFirst();
|
|
1547
|
+
$v = $tb2->getFVstr(FDI_NAME);
|
|
1548
|
+
$this->assertEquals($v, 'first mix trn tb2');
|
|
1549
|
+
$tb2->seekNext();
|
|
1550
|
+
$v = $tb2->getFVstr(FDI_NAME);
|
|
1551
|
+
$this->assertEquals($v, 'second mix trn tb2');
|
|
1552
|
+
|
|
1553
|
+
$tb2->close();
|
|
1554
|
+
$tb->close();
|
|
1555
|
+
}
|
|
1556
|
+
public function testMultiDatabase()
|
|
1557
|
+
{
|
|
1558
|
+
$db = new Bz\database();
|
|
1559
|
+
$tb = $this->openTable($db);
|
|
1560
|
+
$this->assertNotEquals($tb, NULL);
|
|
1561
|
+
$db2 = new Bz\database();
|
|
1562
|
+
$this->openDatabase($db2);
|
|
1563
|
+
$tb2 = $db2->openTable('group');
|
|
1564
|
+
$this->assertEquals($db2->stat(), 0);
|
|
1565
|
+
$this->assertNotEquals($tb2, NULL);
|
|
1566
|
+
|
|
1567
|
+
$db->beginTrn();
|
|
1568
|
+
$db2->beginTrn();
|
|
879
1569
|
|
|
880
|
-
$tb->
|
|
1570
|
+
$tb->seekFirst();
|
|
1571
|
+
$this->assertEquals($tb->stat(), 0);
|
|
1572
|
+
$v = $tb->getFVstr(FDI_NAME);
|
|
1573
|
+
$tb->setFV(FDI_NAME, 'MultiDatabase');
|
|
881
1574
|
$tb->update();
|
|
1575
|
+
|
|
1576
|
+
$tb2->seekFirst();
|
|
1577
|
+
$this->assertEquals($tb2->stat(), 0);
|
|
1578
|
+
$tb2->setFV(FDI_NAME, 'MultiDatabase');
|
|
1579
|
+
$tb2->update();
|
|
1580
|
+
$this->assertEquals($tb2->stat(), 0);
|
|
1581
|
+
$db2->endTrn();
|
|
1582
|
+
$db->abortTrn();
|
|
1583
|
+
|
|
1584
|
+
$tb->seekFirst();
|
|
882
1585
|
$this->assertEquals($tb->stat(), 0);
|
|
1586
|
+
$v2 = $tb->getFVstr(FDI_NAME);
|
|
1587
|
+
$this->assertEquals($v, $v2);
|
|
883
1588
|
}
|
|
884
1589
|
public function testInsert2()
|
|
885
1590
|
{
|
|
@@ -976,8 +1681,9 @@ class transactdTest extends PHPUnit_Framework_TestCase
|
|
|
976
1681
|
{
|
|
977
1682
|
// second connection
|
|
978
1683
|
$db2 = new Bz\database();
|
|
979
|
-
$db2->connect(PROTOCOL . HOSTNAME
|
|
980
|
-
$this->assertEquals($
|
|
1684
|
+
$db2->connect(PROTOCOL . HOSTNAME, true);
|
|
1685
|
+
$this->assertEquals($db2->stat(), 0);
|
|
1686
|
+
unset($db2);
|
|
981
1687
|
$db->disconnect(PROTOCOL . HOSTNAME);
|
|
982
1688
|
$this->assertEquals($db->stat(), 0);
|
|
983
1689
|
}
|
|
@@ -1188,103 +1894,103 @@ class transactdTest extends PHPUnit_Framework_TestCase
|
|
|
1188
1894
|
//}
|
|
1189
1895
|
// Set Ansi Get Wide
|
|
1190
1896
|
// too long string
|
|
1191
|
-
$tb->
|
|
1897
|
+
$tb->setFV(FDI_NAME, '1234567');
|
|
1192
1898
|
if ($varCharField)
|
|
1193
|
-
$this->assertEquals($tb->
|
|
1899
|
+
$this->assertEquals($tb->getFVstr(FDI_NAME), '123');
|
|
1194
1900
|
else
|
|
1195
|
-
$this->assertEquals($tb->
|
|
1901
|
+
$this->assertEquals($tb->getFVstr(FDI_NAME), '123456');
|
|
1196
1902
|
//if ($this->isWindows())
|
|
1197
1903
|
// $this->assertEquals($tb->getFVWstr(FDI_GROUP), '68');
|
|
1198
1904
|
//else
|
|
1199
|
-
$this->assertEquals($tb->
|
|
1905
|
+
$this->assertEquals($tb->getFVstr(FDI_GROUP), '68');
|
|
1200
1906
|
// short string
|
|
1201
|
-
$tb->
|
|
1202
|
-
$this->assertEquals($tb->
|
|
1907
|
+
$tb->setFV(FDI_NAME, '13 ');
|
|
1908
|
+
$this->assertEquals($tb->getFVstr(FDI_NAME), '13 ');
|
|
1203
1909
|
//if ($this->isWindows())
|
|
1204
1910
|
// $this->assertEquals($tb->getFVWstr(FDI_GROUP), '68');
|
|
1205
1911
|
//else
|
|
1206
|
-
$this->assertEquals($tb->
|
|
1912
|
+
$this->assertEquals($tb->getFVstr(FDI_GROUP), '68');
|
|
1207
1913
|
// too long kanji
|
|
1208
1914
|
if ($unicodeField)
|
|
1209
1915
|
{
|
|
1210
1916
|
if ($this->isWindows())
|
|
1211
1917
|
{
|
|
1212
|
-
$tb->
|
|
1918
|
+
$tb->setFV(FDI_NAME, 'あいうえお𩸽'); // hiragana 'aiueo' kanji 'hokke'
|
|
1213
1919
|
if ($varCharField)
|
|
1214
|
-
$this->assertEquals($tb->
|
|
1920
|
+
$this->assertEquals($tb->getFVstr(FDI_NAME), 'あいう');
|
|
1215
1921
|
else
|
|
1216
|
-
$this->assertEquals($tb->
|
|
1922
|
+
$this->assertEquals($tb->getFVstr(FDI_NAME), 'あいうえお');
|
|
1217
1923
|
}
|
|
1218
1924
|
}
|
|
1219
1925
|
else
|
|
1220
1926
|
{
|
|
1221
|
-
$tb->
|
|
1222
|
-
$is_valid_value = ($tb->
|
|
1927
|
+
$tb->setFV(FDI_NAME, '0松本市'); // numeric '0' kanji 'matumostoshi'
|
|
1928
|
+
$is_valid_value = ($tb->getFVstr(FDI_NAME) == '0松本');
|
|
1223
1929
|
$this->assertTrue($is_valid_value);
|
|
1224
1930
|
if (! $is_valid_value)
|
|
1225
|
-
print_r($tb->
|
|
1931
|
+
print_r($tb->getFVstr(FDI_NAME));
|
|
1226
1932
|
}
|
|
1227
|
-
$this->assertEquals($tb->
|
|
1933
|
+
$this->assertEquals($tb->getFVstr(FDI_GROUP), '68');
|
|
1228
1934
|
//// Set Wide Get Ansi
|
|
1229
1935
|
//if ($this->isWindows())
|
|
1230
1936
|
//{
|
|
1231
1937
|
// // too long string
|
|
1232
1938
|
// $tb->setFVW(FDI_NAME, '1234567');
|
|
1233
1939
|
// if ($varCharField)
|
|
1234
|
-
// $this->assertEquals($tb->
|
|
1940
|
+
// $this->assertEquals($tb->getFVstr(FDI_NAME), '123');
|
|
1235
1941
|
// else
|
|
1236
|
-
// $this->assertEquals($tb->
|
|
1942
|
+
// $this->assertEquals($tb->getFVstr(FDI_NAME), '123456');
|
|
1237
1943
|
// $this->assertEquals($tb->getFVWstr(FDI_GROUP), '68');
|
|
1238
1944
|
// // short string
|
|
1239
1945
|
// $tb->setFVW(1, '23 ');
|
|
1240
|
-
// $this->assertEquals($tb->
|
|
1946
|
+
// $this->assertEquals($tb->getFVstr(FDI_NAME), '23 ');
|
|
1241
1947
|
// $this->assertEquals($tb->getFVWstr(FDI_GROUP), '68');
|
|
1242
1948
|
// // too long kanji
|
|
1243
1949
|
// if ($unicodeField)
|
|
1244
1950
|
// {
|
|
1245
1951
|
// $tb->setFVW(FDI_NAME, 'あいうえお𩸽'); // hiragana 'aiueo' kanji 'hokke'
|
|
1246
1952
|
// if ($varCharField)
|
|
1247
|
-
// $this->assertEquals($tb->
|
|
1953
|
+
// $this->assertEquals($tb->getFVstr(FDI_NAME), 'あいう');
|
|
1248
1954
|
// else
|
|
1249
|
-
// $this->assertEquals($tb->
|
|
1955
|
+
// $this->assertEquals($tb->getFVstr(FDI_NAME), 'あいうえお');
|
|
1250
1956
|
// }
|
|
1251
1957
|
// else
|
|
1252
1958
|
// {
|
|
1253
1959
|
// $tb->setFVW(FDI_NAME, '0松本市'); // numeric '0' kanji 'matumostoshi'
|
|
1254
|
-
// $this->assertEquals($tb->
|
|
1960
|
+
// $this->assertEquals($tb->getFVstr(FDI_NAME), '0松本');
|
|
1255
1961
|
// }
|
|
1256
1962
|
// $this->assertEquals($tb->getFVWstr(FDI_GROUP), '68');
|
|
1257
1963
|
//}
|
|
1258
1964
|
// Set Ansi Get Ansi
|
|
1259
1965
|
// too long string
|
|
1260
|
-
$tb->
|
|
1966
|
+
$tb->setFV(FDI_NAME, '1234567');
|
|
1261
1967
|
if ($varCharField)
|
|
1262
|
-
$this->assertEquals($tb->
|
|
1968
|
+
$this->assertEquals($tb->getFVstr(FDI_NAME), '123');
|
|
1263
1969
|
else
|
|
1264
|
-
$this->assertEquals($tb->
|
|
1265
|
-
$this->assertEquals($tb->
|
|
1970
|
+
$this->assertEquals($tb->getFVstr(FDI_NAME), '123456');
|
|
1971
|
+
$this->assertEquals($tb->getFVstr(FDI_GROUP), '68');
|
|
1266
1972
|
// short string
|
|
1267
|
-
$tb->
|
|
1268
|
-
$this->assertEquals($tb->
|
|
1269
|
-
$this->assertEquals($tb->
|
|
1973
|
+
$tb->setFV(FDI_NAME, '13 ');
|
|
1974
|
+
$this->assertEquals($tb->getFVstr(FDI_NAME), '13 ');
|
|
1975
|
+
$this->assertEquals($tb->getFVstr(FDI_GROUP), '68');
|
|
1270
1976
|
// too long lanji
|
|
1271
1977
|
if ($unicodeField)
|
|
1272
1978
|
{
|
|
1273
1979
|
if ($this->isWindows())
|
|
1274
1980
|
{
|
|
1275
|
-
$tb->
|
|
1981
|
+
$tb->setFV(FDI_NAME, 'あいうえお𩸽'); // hiragana 'aiueo' kanji 'hokke'
|
|
1276
1982
|
if ($varCharField)
|
|
1277
|
-
$this->assertEquals($tb->
|
|
1983
|
+
$this->assertEquals($tb->getFVstr(FDI_NAME), 'あいう');
|
|
1278
1984
|
else
|
|
1279
|
-
$this->assertEquals($tb->
|
|
1985
|
+
$this->assertEquals($tb->getFVstr(FDI_NAME), 'あいうえお');
|
|
1280
1986
|
}
|
|
1281
1987
|
}
|
|
1282
1988
|
else
|
|
1283
1989
|
{
|
|
1284
|
-
$tb->
|
|
1285
|
-
$this->assertEquals($tb->
|
|
1990
|
+
$tb->setFV(FDI_NAME, '0松本市'); // numeric '0' kanji 'matumostoshi'
|
|
1991
|
+
$this->assertEquals($tb->getFVstr(FDI_NAME), '0松本');
|
|
1286
1992
|
}
|
|
1287
|
-
$this->assertEquals($tb->
|
|
1993
|
+
$this->assertEquals($tb->getFVstr(FDI_GROUP), '68');
|
|
1288
1994
|
}
|
|
1289
1995
|
public function testVarField()
|
|
1290
1996
|
{
|
|
@@ -1318,7 +2024,6 @@ class transactdTest extends PHPUnit_Framework_TestCase
|
|
|
1318
2024
|
$this->assertEquals($db->stat(), 0);
|
|
1319
2025
|
// utf8 varchar
|
|
1320
2026
|
$this->setGetVar($tb, true, true);
|
|
1321
|
-
$tb->close();
|
|
1322
2027
|
}
|
|
1323
2028
|
private function doVarInsert($db, $name, $codePage, $str, $startid, $endid, $bulk)
|
|
1324
2029
|
{
|
|
@@ -1934,7 +2639,7 @@ class transactdTest extends PHPUnit_Framework_TestCase
|
|
|
1934
2639
|
$td->id = $id;
|
|
1935
2640
|
$td->pageSize = 2048;
|
|
1936
2641
|
$td->schemaCodePage = Bz\transactd::CP_UTF8;
|
|
1937
|
-
$td->charsetIndex = Bz\transactd::
|
|
2642
|
+
$td->charsetIndex = Bz\transactd::CHARSET_UTF8;
|
|
1938
2643
|
$dbdef->insertTable($td);
|
|
1939
2644
|
$this->assertEquals($dbdef->stat(), 0);
|
|
1940
2645
|
// id field
|
|
@@ -1990,7 +2695,7 @@ class transactdTest extends PHPUnit_Framework_TestCase
|
|
|
1990
2695
|
$td->id = $id;
|
|
1991
2696
|
$td->pageSize = 2048;
|
|
1992
2697
|
$td->schemaCodePage = Bz\transactd::CP_UTF8;
|
|
1993
|
-
$td->charsetIndex = Bz\transactd::
|
|
2698
|
+
$td->charsetIndex = Bz\transactd::CHARSET_UTF8;
|
|
1994
2699
|
$dbdef->insertTable($td);
|
|
1995
2700
|
$this->assertEquals($dbdef->stat(), 0);
|
|
1996
2701
|
// code field
|
|
@@ -2029,7 +2734,7 @@ class transactdTest extends PHPUnit_Framework_TestCase
|
|
|
2029
2734
|
$td->id = $id;
|
|
2030
2735
|
$td->pageSize = 2048;
|
|
2031
2736
|
$td->schemaCodePage = Bz\transactd::CP_UTF8;
|
|
2032
|
-
$td->charsetIndex = Bz\transactd::
|
|
2737
|
+
$td->charsetIndex = Bz\transactd::CHARSET_UTF8;
|
|
2033
2738
|
$dbdef->insertTable($td);
|
|
2034
2739
|
$this->assertEquals($dbdef->stat(), 0);
|
|
2035
2740
|
// id field
|
|
@@ -2042,6 +2747,11 @@ class transactdTest extends PHPUnit_Framework_TestCase
|
|
|
2042
2747
|
$fd->setName('comment');
|
|
2043
2748
|
$fd->type = Bz\transactd::ft_myvarchar;
|
|
2044
2749
|
$fd->setLenByCharnum(60);
|
|
2750
|
+
// blob field
|
|
2751
|
+
$fd = $dbdef->insertField($id, 2);
|
|
2752
|
+
$fd->setName('blob');
|
|
2753
|
+
$fd->type = Bz\transactd::ft_myblob;
|
|
2754
|
+
$fd->len = 10;
|
|
2045
2755
|
// key 0 (primary) id
|
|
2046
2756
|
$kd = $dbdef->insertKey($id, 0);
|
|
2047
2757
|
$kd->segment(0)->fieldNum = 0;
|
|
@@ -2094,10 +2804,10 @@ class transactdTest extends PHPUnit_Framework_TestCase
|
|
|
2094
2804
|
{
|
|
2095
2805
|
$tb->setFV(0, $i);
|
|
2096
2806
|
$tb->setFV(1, "$i comment");
|
|
2807
|
+
$tb->setFV(2, "$i blob");
|
|
2097
2808
|
$tb->insert();
|
|
2098
2809
|
$this->assertEquals($tb->stat(), 0);
|
|
2099
2810
|
}
|
|
2100
|
-
$tb->close();
|
|
2101
2811
|
$db->endTrn();
|
|
2102
2812
|
}
|
|
2103
2813
|
|
|
@@ -2106,10 +2816,21 @@ class transactdTest extends PHPUnit_Framework_TestCase
|
|
|
2106
2816
|
$db = new Bz\database();
|
|
2107
2817
|
// check database existence
|
|
2108
2818
|
$db->open(URL_QT, Bz\transactd::TYPE_SCHEMA_BDF, Bz\transactd::TD_OPEN_NORMAL);
|
|
2109
|
-
if ($db->stat()
|
|
2110
|
-
|
|
2819
|
+
if ($db->stat() !== 0)
|
|
2820
|
+
echo("\nDatabase " . DBNAME_QT . " not found");
|
|
2821
|
+
else
|
|
2822
|
+
{
|
|
2823
|
+
$def = $db->dbDef();
|
|
2824
|
+
$td = $def->tableDefs(3);
|
|
2825
|
+
if ($td != NULL && $td->fieldCount === 3) {
|
|
2826
|
+
$tb = $db->openTable('extention');
|
|
2827
|
+
if ($db->stat() === 0 && $tb->recordCount(false) === TEST_COUNT)
|
|
2828
|
+
return;
|
|
2829
|
+
$tb->close();
|
|
2830
|
+
}
|
|
2831
|
+
$db->drop();
|
|
2111
2832
|
}
|
|
2112
|
-
echo("\
|
|
2833
|
+
echo("\nCreate database " . DBNAME_QT . "\n");
|
|
2113
2834
|
$db->create(URL_QT);
|
|
2114
2835
|
$this->assertEquals($db->stat(), 0);
|
|
2115
2836
|
$db->open(URL_QT, Bz\transactd::TYPE_SCHEMA_BDF, Bz\transactd::TD_OPEN_NORMAL);
|
|
@@ -2276,15 +2997,22 @@ class transactdTest extends PHPUnit_Framework_TestCase
|
|
|
2276
2997
|
$q->select('id', 'name', 'group')->where('id', '<=', 15000);
|
|
2277
2998
|
$rs = $atu->index(0)->keyValue(1)->read($q);
|
|
2278
2999
|
$this->assertEquals($rs->size(), 15000);
|
|
3000
|
+
$this->assertEquals($rs->fieldDefs()->size(), 3);
|
|
2279
3001
|
|
|
2280
3002
|
// Join extention::comment
|
|
2281
3003
|
$q->reset();
|
|
2282
|
-
$
|
|
2283
|
-
|
|
3004
|
+
$this->assertEquals($q->selectCount(), 0);
|
|
3005
|
+
|
|
3006
|
+
$q->select('comment')->optimize(Bz\queryBase::joinHasOneOrHasMany);
|
|
3007
|
+
$this->assertEquals($q->selectCount(), 1);
|
|
3008
|
+
$ate->index(0)->join($rs, $q, 'id');
|
|
3009
|
+
$this->assertEquals($q->selectCount(), 1);
|
|
2284
3010
|
$this->assertEquals($rs->size(), 15000);
|
|
3011
|
+
$this->assertEquals($rs->fieldDefs()->size(), 4);
|
|
2285
3012
|
|
|
2286
3013
|
// reverse and get first (so it means 'get last')
|
|
2287
3014
|
$last = $rs->reverse()->first();
|
|
3015
|
+
$this->assertEquals($rs->size(), 15000);
|
|
2288
3016
|
$this->assertEquals($last['id'], 15000);
|
|
2289
3017
|
$this->assertEquals($last['comment'], '15000 comment');
|
|
2290
3018
|
|
|
@@ -2350,9 +3078,13 @@ class transactdTest extends PHPUnit_Framework_TestCase
|
|
|
2350
3078
|
|
|
2351
3079
|
// clone
|
|
2352
3080
|
$rsv = clone $rs;
|
|
3081
|
+
$this->assertEquals($rsv->size(), 16000);
|
|
2353
3082
|
$gq->reset();
|
|
2354
3083
|
$count3 = new Bz\count('count3');
|
|
2355
3084
|
$gq->addFunction($count3)->keyField('group');
|
|
3085
|
+
$this->assertEquals($gq->functionCount(), 1);
|
|
3086
|
+
$this->assertEquals($gq->getKeyFields()->count(), 1);
|
|
3087
|
+
|
|
2356
3088
|
$rs->groupBy($gq);
|
|
2357
3089
|
$this->assertEquals($rs->size(), 5);
|
|
2358
3090
|
$this->assertEquals($rsv->size(), 16000);
|
|
@@ -2387,6 +3119,238 @@ class transactdTest extends PHPUnit_Framework_TestCase
|
|
|
2387
3119
|
$q3->keyField('group', 'id');
|
|
2388
3120
|
unset($q3);
|
|
2389
3121
|
}
|
|
3122
|
+
public function testPrepareJoin()
|
|
3123
|
+
{
|
|
3124
|
+
$db = new Bz\database();
|
|
3125
|
+
$db->open(URL_QT);
|
|
3126
|
+
$this->assertEquals($db->stat(), 0);
|
|
3127
|
+
|
|
3128
|
+
$atu = new Bz\ActiveTable($db, 'user');
|
|
3129
|
+
$atu->alias('名前', 'name');
|
|
3130
|
+
$atg = new Bz\ActiveTable($db, 'groups');
|
|
3131
|
+
$atg->alias('name', 'group_name');
|
|
3132
|
+
$ate = new Bz\ActiveTable($db, 'extention');
|
|
3133
|
+
$q = new Bz\query();
|
|
3134
|
+
|
|
3135
|
+
$q->select('id', 'name', 'group')->where('id', '<=', '?');
|
|
3136
|
+
$pq = $atu->prepare($q);
|
|
3137
|
+
|
|
3138
|
+
// int value
|
|
3139
|
+
$rs = $atu->index(0)->keyValue(1)->read($pq, 15000);
|
|
3140
|
+
$this->assertEquals($rs->size(), 15000);
|
|
3141
|
+
$this->assertEquals($rs->fieldDefs()->size(), 3);
|
|
3142
|
+
// string value
|
|
3143
|
+
$rs = $atu->index(0)->keyValue(1)->read($pq, '15000');
|
|
3144
|
+
$this->assertEquals($rs->size(), 15000);
|
|
3145
|
+
$this->assertEquals($rs->fieldDefs()->size(), 3);
|
|
3146
|
+
// double value
|
|
3147
|
+
$rs = $atu->index(0)->keyValue(1)->read($pq, 15000.000);
|
|
3148
|
+
$this->assertEquals($rs->size(), 15000);
|
|
3149
|
+
$this->assertEquals($rs->fieldDefs()->size(), 3);
|
|
3150
|
+
// Using supply value
|
|
3151
|
+
$pq->supplyValue(0, 15000);
|
|
3152
|
+
$rs = $atu->index(0)->keyValue(1)->read($pq);
|
|
3153
|
+
$this->assertEquals($rs->size(), 15000);
|
|
3154
|
+
$this->assertEquals($rs->fieldDefs()->size(), 3);
|
|
3155
|
+
|
|
3156
|
+
// Join extention::comment
|
|
3157
|
+
$q->reset();
|
|
3158
|
+
$this->assertEquals($q->selectCount(), 0);
|
|
3159
|
+
$q->select('comment')->optimize(Bz\queryBase::joinHasOneOrHasMany);
|
|
3160
|
+
$this->assertEquals($q->selectCount(), 1);
|
|
3161
|
+
$pq = $ate->prepare($q);
|
|
3162
|
+
|
|
3163
|
+
$ate->index(0)->join($rs, $pq, 'id');
|
|
3164
|
+
$this->assertEquals($q->selectCount(), 1);
|
|
3165
|
+
$this->assertEquals($rs->size(), 15000);
|
|
3166
|
+
$this->assertEquals($rs->fieldDefs()->size(), 4);
|
|
3167
|
+
// reverse and get first (so it means 'get last')
|
|
3168
|
+
$last = $rs->reverse()->first();
|
|
3169
|
+
$this->assertEquals($rs->size(), 15000);
|
|
3170
|
+
$this->assertEquals($last['id'], 15000);
|
|
3171
|
+
$this->assertEquals($last['comment'], '15000 comment');
|
|
3172
|
+
|
|
3173
|
+
// Join group::name
|
|
3174
|
+
$q->reset()->select('group_name');
|
|
3175
|
+
$pq = $atg->prepare($q);
|
|
3176
|
+
$atg->index(0)->join($rs, $pq, 'group');
|
|
3177
|
+
$this->assertEquals($rs->size(), 15000);
|
|
3178
|
+
|
|
3179
|
+
// get last (the rs is reversed, so it means 'get first')
|
|
3180
|
+
$first = $rs->last();
|
|
3181
|
+
$this->assertEquals($first['id'], 1);
|
|
3182
|
+
$this->assertEquals($first['comment'], '1 comment');
|
|
3183
|
+
$this->assertEquals($first['group_name'], '1 group');
|
|
3184
|
+
|
|
3185
|
+
// row in rs[15000 - 9]
|
|
3186
|
+
$rec = $rs[15000 - 9];
|
|
3187
|
+
$this->assertEquals($rec['group_name'], '4 group');
|
|
3188
|
+
}
|
|
3189
|
+
public function testServerPrepareJoin()
|
|
3190
|
+
{
|
|
3191
|
+
define('NO_RECORD_ID', 5);
|
|
3192
|
+
$db = new Bz\database();
|
|
3193
|
+
$db->open(URL_QT);
|
|
3194
|
+
$this->assertEquals($db->stat(), 0);
|
|
3195
|
+
|
|
3196
|
+
$atu = new Bz\ActiveTable($db, 'user');
|
|
3197
|
+
$atu->alias('名前', 'name');
|
|
3198
|
+
$atg = new Bz\ActiveTable($db, 'groups');
|
|
3199
|
+
$atg->alias('name', 'group_name');
|
|
3200
|
+
$ate = new Bz\ActiveTable($db, 'extention');
|
|
3201
|
+
$q = new Bz\query();
|
|
3202
|
+
|
|
3203
|
+
$q->select('id', 'name', 'group')->where('id', '<=', '?');
|
|
3204
|
+
$stmt1 = $atu->prepare($q, true);
|
|
3205
|
+
$this->assertNotEquals($stmt1, NULL);
|
|
3206
|
+
|
|
3207
|
+
$q->reset()->select('comment')->optimize(Bz\queryBase::joinHasOneOrHasMany);
|
|
3208
|
+
$stmt2 = $ate->prepare($q, true);
|
|
3209
|
+
$this->assertNotEquals($stmt2, NULL);
|
|
3210
|
+
|
|
3211
|
+
$q->reset()->select('group_name');
|
|
3212
|
+
$stmt3 = $atg->prepare($q, true);
|
|
3213
|
+
$this->assertNotEquals($stmt3, NULL);
|
|
3214
|
+
|
|
3215
|
+
$rs = $atu->index(0)->keyValue(1)->read($stmt1, 15000);
|
|
3216
|
+
$this->assertEquals($rs->size(), 15000);
|
|
3217
|
+
|
|
3218
|
+
// Join extention::comment
|
|
3219
|
+
$ate->index(0)->join($rs, $stmt2, 'id');
|
|
3220
|
+
$this->assertEquals($rs->size(), 15000);
|
|
3221
|
+
|
|
3222
|
+
// test reverse
|
|
3223
|
+
$last = $rs->reverse()->first();
|
|
3224
|
+
$this->assertEquals($last['id'], 15000);
|
|
3225
|
+
$this->assertEquals($last['comment'], '15000 comment');
|
|
3226
|
+
|
|
3227
|
+
// Join group::name
|
|
3228
|
+
$atg->index(0)->join($rs, $stmt3, 'group');
|
|
3229
|
+
$this->assertEquals($rs->size(), 15000);
|
|
3230
|
+
$first = $rs->last();
|
|
3231
|
+
|
|
3232
|
+
$this->assertEquals($first['id'], 1);
|
|
3233
|
+
$this->assertEquals($first['comment'], '1 comment');
|
|
3234
|
+
$this->assertEquals($first['group_name'], '1 group');
|
|
3235
|
+
|
|
3236
|
+
// $rs[15000 - 9];
|
|
3237
|
+
$rec = $rs[15000 - 9];
|
|
3238
|
+
$this->assertEquals($rec['group_name'], '4 group');
|
|
3239
|
+
|
|
3240
|
+
// Test orderby
|
|
3241
|
+
$rs->orderBy('group_name');
|
|
3242
|
+
// $rs[0];
|
|
3243
|
+
$this->assertEquals($rs[0]['group_name'], '1 group');
|
|
3244
|
+
|
|
3245
|
+
/*
|
|
3246
|
+
sortFields orderRv;
|
|
3247
|
+
orderRv.add('group_name', false);
|
|
3248
|
+
rs.orderBy(orderRv);
|
|
3249
|
+
|
|
3250
|
+
sortFields order;
|
|
3251
|
+
order.add('group_name', true);
|
|
3252
|
+
rs.orderBy(order);
|
|
3253
|
+
BOOST_CHECK_MESSAGE(_tstring(rs[(size_t)0]['group_name'].c_str()) ==
|
|
3254
|
+
_tstring('1 group'),
|
|
3255
|
+
"group_name = 1 group "
|
|
3256
|
+
<< string(rs[(size_t)0]['group_name'].a_str()));
|
|
3257
|
+
*/
|
|
3258
|
+
// All fields
|
|
3259
|
+
$rs->clear();
|
|
3260
|
+
$q->reset()->all();
|
|
3261
|
+
$q->where('id', '<=', '?');
|
|
3262
|
+
$stmt1 = $atu->prepare($q, true);
|
|
3263
|
+
$rs = $atu->keyValue(1)->read($stmt1, 15000);
|
|
3264
|
+
$this->assertEquals($rs->size(), 15000);
|
|
3265
|
+
if ($rs->size() == 15000)
|
|
3266
|
+
{
|
|
3267
|
+
for ($i = 0; $i < 15000; $i++)
|
|
3268
|
+
$this->assertEquals($rs[$i]['id'], $i + 1);
|
|
3269
|
+
}
|
|
3270
|
+
|
|
3271
|
+
$ate->join($rs, $stmt2, 'id');
|
|
3272
|
+
$this->assertEquals($rs->size(), 15000);
|
|
3273
|
+
$atg->join($rs, $stmt3, 'group');
|
|
3274
|
+
$this->assertEquals($rs->size(), 15000);
|
|
3275
|
+
|
|
3276
|
+
// OuterJoin
|
|
3277
|
+
$tb = $ate->table();
|
|
3278
|
+
$tb->setFV('id', NO_RECORD_ID);
|
|
3279
|
+
$tb->seek();
|
|
3280
|
+
$this->assertEquals($tb->stat(), 0);
|
|
3281
|
+
if ($tb->stat() == 0)
|
|
3282
|
+
$tb->del();
|
|
3283
|
+
$this->assertEquals($tb->stat(), 0);
|
|
3284
|
+
$q->reset()->select('comment', 'blob')->optimize(Bz\queryBase::joinHasOneOrHasMany);
|
|
3285
|
+
$stmt2 = $ate->prepare($q, true);
|
|
3286
|
+
|
|
3287
|
+
// Join is remove record(s) no join target record.
|
|
3288
|
+
$rs->clear();
|
|
3289
|
+
$rs = $atu->keyValue(1)->read($stmt1, 15000);
|
|
3290
|
+
$ate->join($rs, $stmt2, 'id');
|
|
3291
|
+
$this->assertEquals($rs->size(), 14999);
|
|
3292
|
+
$this->assertEquals($rs[NO_RECORD_ID - 1]['id'], NO_RECORD_ID + 1);
|
|
3293
|
+
$this->assertEquals($rs[NO_RECORD_ID - 1]['comment'], '' . (NO_RECORD_ID + 1) . ' comment');
|
|
3294
|
+
$this->assertEquals($rs[NO_RECORD_ID - 1]['blob'], '' . (NO_RECORD_ID + 1) . ' blob');
|
|
3295
|
+
|
|
3296
|
+
// OuterJoin is no remove record(s) no join target record.
|
|
3297
|
+
$rs->clear();
|
|
3298
|
+
$rs = $atu->keyValue(1)->read($stmt1, 15000);
|
|
3299
|
+
$ate->outerJoin($rs, $stmt2, 'id');
|
|
3300
|
+
$this->assertEquals($rs->size(), 15000);
|
|
3301
|
+
$atg->outerJoin($rs, $stmt3, 'group');
|
|
3302
|
+
$this->assertEquals($rs->size(), 15000);
|
|
3303
|
+
|
|
3304
|
+
$this->assertEquals($rs[NO_RECORD_ID - 1]->isInvalidRecord(), true);
|
|
3305
|
+
$this->assertEquals($rs[NO_RECORD_ID]['comment'], '' . (NO_RECORD_ID + 1) . ' comment');
|
|
3306
|
+
$this->assertEquals($rs[NO_RECORD_ID]['blob'], '' . (NO_RECORD_ID + 1) . ' blob');
|
|
3307
|
+
|
|
3308
|
+
// OuterJoin All Join fields
|
|
3309
|
+
$q->reset()->optimize(Bz\queryBase::joinHasOneOrHasMany)->all();
|
|
3310
|
+
$stmt2 = $ate->prepare($q, true);
|
|
3311
|
+
$rs->clear();
|
|
3312
|
+
$rs = $atu->keyValue(1)->read($stmt1, 15000);
|
|
3313
|
+
$ate->outerJoin($rs, $stmt2, 'id');
|
|
3314
|
+
$this->assertEquals($rs->size(), 15000);
|
|
3315
|
+
$this->assertEquals($rs[NO_RECORD_ID - 1]->isInvalidRecord(), true);
|
|
3316
|
+
$this->assertEquals($rs[NO_RECORD_ID]['comment'], '' . (NO_RECORD_ID + 1) . ' comment');
|
|
3317
|
+
$this->assertEquals($rs[NO_RECORD_ID]['blob'], '' . (NO_RECORD_ID + 1) . ' blob');
|
|
3318
|
+
|
|
3319
|
+
// Test clone blob field
|
|
3320
|
+
$rs2 = clone($rs);
|
|
3321
|
+
$this->assertEquals($rs2->size(), 15000);
|
|
3322
|
+
$this->assertEquals($rs2[NO_RECORD_ID - 1]->isInvalidRecord(), true);
|
|
3323
|
+
$this->assertEquals($rs2[NO_RECORD_ID]['comment'], '' . (NO_RECORD_ID + 1) . ' comment');
|
|
3324
|
+
$this->assertEquals($rs2[NO_RECORD_ID]['blob'], '' . (NO_RECORD_ID + 1) . ' blob');
|
|
3325
|
+
|
|
3326
|
+
// hasManyJoin inner
|
|
3327
|
+
$rs->clear();
|
|
3328
|
+
$q->reset()->reject(0xFFFF)->limit(0)->all();
|
|
3329
|
+
$rs = $atg->keyValue(1)->read($q);
|
|
3330
|
+
$this->assertEquals($rs->size(), 100);
|
|
3331
|
+
$q->all()->optimize(Bz\queryBase::joinHasOneOrHasMany);
|
|
3332
|
+
$atu->index(1)->join($rs, $q, 'code');
|
|
3333
|
+
$this->assertEquals($rs->size(), 20000);
|
|
3334
|
+
|
|
3335
|
+
// hasManyJoin outer
|
|
3336
|
+
$rs->clear();
|
|
3337
|
+
$q->reset()->reject(0xFFFF)->limit(0)->all();
|
|
3338
|
+
$rs = $atg->keyValue(1)->read($q);
|
|
3339
|
+
$this->assertEquals($rs->size(), 100);
|
|
3340
|
+
$q->all()->optimize(Bz\queryBase::joinHasOneOrHasMany);
|
|
3341
|
+
$atu->index(1)->outerJoin($rs, $q, 'code');
|
|
3342
|
+
$this->assertEquals($rs->size(), 20095);
|
|
3343
|
+
|
|
3344
|
+
// restore record
|
|
3345
|
+
$tb->clearBuffer();
|
|
3346
|
+
$tb->setFV('id', NO_RECORD_ID);
|
|
3347
|
+
$tb->setFV('comment', '5 comment');
|
|
3348
|
+
$tb->setFV('blob', '5 blob');
|
|
3349
|
+
$tb->insert();
|
|
3350
|
+
$this->assertEquals($tb->stat(), 0);
|
|
3351
|
+
if ($tb->stat() != 0)
|
|
3352
|
+
$db->drop();
|
|
3353
|
+
}
|
|
2390
3354
|
public function testWritableRecord()
|
|
2391
3355
|
{
|
|
2392
3356
|
$db = new Bz\database();
|