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
|
@@ -16,6 +16,13 @@
|
|
|
16
16
|
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
|
|
17
17
|
02111-1307, USA.
|
|
18
18
|
=================================================================*/
|
|
19
|
+
#ifdef _MSC_VER
|
|
20
|
+
#ifdef _DEBUG
|
|
21
|
+
#define _CRTDBG_MAP_ALLOC
|
|
22
|
+
#include <stdlib.h>
|
|
23
|
+
#include <crtdbg.h>
|
|
24
|
+
#endif // _DEBUG
|
|
25
|
+
#endif // _MSC_VER
|
|
19
26
|
#include <bzs/db/protocol/tdap/client/activeTable.h>
|
|
20
27
|
#include <bzs/rtl/benchmark.h>
|
|
21
28
|
#include <bzs/example/queryData.h>
|
|
@@ -63,33 +70,37 @@ bool btest(recordset* rsp, activeTable* atup, activeTable* atgp,
|
|
|
63
70
|
activeTable& ate = *atep;
|
|
64
71
|
recordset& rs = *rsp;
|
|
65
72
|
query q;
|
|
73
|
+
q.select(_T("id"), _T("name"), _T("group"))
|
|
74
|
+
.where(_T("id"), _T("<="), _T("?"));
|
|
75
|
+
atu.alias(fd_name, _T("name"));
|
|
76
|
+
pq_handle stmt = atu.prepare(q, true);
|
|
77
|
+
if (!stmt) return false;
|
|
78
|
+
|
|
79
|
+
q.reset().select(_T("comment")).optimize(queryBase::joinHasOneOrHasMany);
|
|
80
|
+
pq_handle stmt2 = ate.prepare(q, true);
|
|
81
|
+
if (!stmt2) return false;
|
|
82
|
+
|
|
83
|
+
atg.alias(_T("name"), _T("group_name"));
|
|
84
|
+
q.reset().select(_T("group_name"));
|
|
85
|
+
pq_handle stmt3 = atg.prepare(q, true);
|
|
86
|
+
if (!stmt3) return false;
|
|
66
87
|
|
|
67
88
|
for (int i = 0; i < n; ++i)
|
|
68
89
|
{
|
|
69
90
|
rs.clear();
|
|
70
91
|
if (kind & 1)
|
|
71
92
|
{
|
|
72
|
-
|
|
73
|
-
atu.
|
|
74
|
-
|
|
75
|
-
q.select(_T("id"), _T("name"), _T("group"))
|
|
76
|
-
.where(_T("id"), _T("<="), i + 15000);
|
|
77
|
-
atu.index(0).keyValue(i + 1).read(rs, q);
|
|
78
|
-
|
|
93
|
+
supplyValue(stmt, 0, i + 15000);
|
|
94
|
+
atu.index(0).keyValue(i + 1).read(rs, stmt);
|
|
79
95
|
// Join extention::comment
|
|
80
96
|
if (kind & 2)
|
|
81
97
|
{
|
|
82
|
-
|
|
83
|
-
ate.index(0).join(rs, q.select(_T("comment")).optimize(
|
|
84
|
-
queryBase::joinHasOneOrHasMany),
|
|
85
|
-
_T("id"));
|
|
98
|
+
ate.index(0).join(rs, stmt2, _T("id"));
|
|
86
99
|
}
|
|
87
100
|
if (kind & 4)
|
|
88
101
|
{
|
|
89
102
|
// Join group::name
|
|
90
|
-
|
|
91
|
-
atg.alias(_T("name"), _T("group_name"));
|
|
92
|
-
atg.index(0).join(rs, q.select(_T("group_name")), _T("group"));
|
|
103
|
+
atg.index(0).join(rs, stmt3, _T("group"));
|
|
93
104
|
}
|
|
94
105
|
}
|
|
95
106
|
if (kind & 8)
|
|
@@ -110,6 +121,7 @@ int _tmain(int argc, _TCHAR* argv[])
|
|
|
110
121
|
database_ptr db = createDatabaseObject();
|
|
111
122
|
try
|
|
112
123
|
{
|
|
124
|
+
{
|
|
113
125
|
const _TCHAR* host = _T("localhost");
|
|
114
126
|
int kind = 15;
|
|
115
127
|
int n = 100;
|
|
@@ -134,6 +146,7 @@ int _tmain(int argc, _TCHAR* argv[])
|
|
|
134
146
|
std::tcout << "The query data build error." << std::endl;
|
|
135
147
|
return 1;
|
|
136
148
|
}
|
|
149
|
+
|
|
137
150
|
activeTable atu(db, _T("user"));
|
|
138
151
|
activeTable atg(db, _T("groups"));
|
|
139
152
|
activeTable ate(db, _T("extention"));
|
|
@@ -143,7 +156,11 @@ int _tmain(int argc, _TCHAR* argv[])
|
|
|
143
156
|
bzs::rtl::benchmark bm;
|
|
144
157
|
bm.report(boost::bind(btest, &rs, &atu, &atg, &ate, kind, n),
|
|
145
158
|
"exec time ");
|
|
146
|
-
|
|
159
|
+
}
|
|
160
|
+
db.reset();
|
|
161
|
+
#ifdef _MSC_VER
|
|
162
|
+
_CrtDumpMemoryLeaks();
|
|
163
|
+
#endif
|
|
147
164
|
return 0;
|
|
148
165
|
}
|
|
149
166
|
|
|
@@ -27,9 +27,10 @@ typedef std::vector<boost::shared_ptr<workerBase> > workers;
|
|
|
27
27
|
|
|
28
28
|
struct transactionSec
|
|
29
29
|
{
|
|
30
|
-
transactionSec() : value(0) {}
|
|
30
|
+
transactionSec() : value(0),timeOne(0) {}
|
|
31
31
|
int workes;
|
|
32
32
|
__int64 value;
|
|
33
|
+
double timeOne;
|
|
33
34
|
};
|
|
34
35
|
|
|
35
36
|
struct commandLineParam
|
|
@@ -59,13 +60,21 @@ void showResult(const std::vector<transactionSec>& results, int total,
|
|
|
59
60
|
int totalTransactionTime, int totalTransactions,
|
|
60
61
|
bool stressMode)
|
|
61
62
|
{
|
|
63
|
+
|
|
62
64
|
std::tcout << _T("----------------------------------") << std::endl;
|
|
63
65
|
std::tcout << _T("Clients \tTransactions/sec") << std::endl;
|
|
64
66
|
std::tcout << _T("----------------------------------") << std::endl;
|
|
65
67
|
|
|
66
68
|
for (int i = 0; i < (int)results.size(); ++i)
|
|
67
|
-
|
|
69
|
+
{
|
|
70
|
+
if (!stressMode)
|
|
71
|
+
std::tcout << results[i].workes << _T("\t") << results[i].value
|
|
72
|
+
<< _T("\t") << results[i].timeOne
|
|
68
73
|
<< std::endl;
|
|
74
|
+
else
|
|
75
|
+
std::tcout << results[i].workes << _T("\t") << results[i].value
|
|
76
|
+
<< std::endl;
|
|
77
|
+
}
|
|
69
78
|
if (!stressMode)
|
|
70
79
|
{
|
|
71
80
|
std::tcout << _T("----------------------------------") << std::endl;
|
|
@@ -90,7 +99,10 @@ bool tableFixer(const connectParams& param)
|
|
|
90
99
|
short index = def->tableNumByName(_T("cache"));
|
|
91
100
|
if (index == -1 && !createCacheTable(def))
|
|
92
101
|
return false;
|
|
102
|
+
try{
|
|
93
103
|
dropTable(db, _T("cache"));
|
|
104
|
+
}
|
|
105
|
+
catch(...){}
|
|
94
106
|
openTable(db, _T("cache"));
|
|
95
107
|
return true;
|
|
96
108
|
}
|
|
@@ -139,18 +151,22 @@ double executeWorkers(const commandLineParam& cmd, const connectParams param,
|
|
|
139
151
|
}
|
|
140
152
|
printf("*");
|
|
141
153
|
fflush(stdout);
|
|
142
|
-
Sleep(
|
|
154
|
+
Sleep(500 * MCRTOMM);
|
|
143
155
|
sync.wait(); // start all workers
|
|
144
156
|
if (cmd.stressMode)
|
|
145
157
|
{
|
|
146
158
|
Sleep(200 * MCRTOMM);
|
|
147
159
|
g_bench_signal = BENCH_SIGNAL_GREEN;
|
|
160
|
+
//Measurement interval
|
|
148
161
|
Sleep((unsigned int)(BENCH_TIMER_SECONDS * 1000 * MCRTOMM));
|
|
149
162
|
g_bench_signal = BENCH_SIGNAL_BREAK;
|
|
150
163
|
}
|
|
151
164
|
threads.join_all();
|
|
152
165
|
for (int i = 0; i < wn; ++i)
|
|
166
|
+
{
|
|
153
167
|
t += workers[i]->total();
|
|
168
|
+
//std::tcout << _T("Execute Workers = ") << wn << " " << workers[i]->total() << std::endl;
|
|
169
|
+
}
|
|
154
170
|
}
|
|
155
171
|
return t;
|
|
156
172
|
}
|
|
@@ -172,11 +188,15 @@ int execute(const commandLineParam& cmd, const connectParams param,
|
|
|
172
188
|
}
|
|
173
189
|
else
|
|
174
190
|
{
|
|
191
|
+
int n = wn * cmd.loopCount * cmd.avg_count;
|
|
175
192
|
totalTransactionTime += t;
|
|
176
|
-
totalTransactions +=
|
|
193
|
+
totalTransactions += n;
|
|
177
194
|
if (t)
|
|
195
|
+
{
|
|
196
|
+
ts.timeOne = t / n / 1000000.0f;
|
|
178
197
|
ts.value = (__int64)((double)1000000.0f * wn * wn *
|
|
179
|
-
|
|
198
|
+
cmd.avg_count * cmd.loopCount / t);
|
|
199
|
+
}
|
|
180
200
|
}
|
|
181
201
|
ts.workes = wn;
|
|
182
202
|
results.push_back(ts);
|
|
@@ -251,9 +271,11 @@ int _tmain(int argc, _TCHAR* argv[])
|
|
|
251
271
|
printf("\n");
|
|
252
272
|
showResult(results, bm.end(), (int)totalTransactionTime,
|
|
253
273
|
totalTransactions, cmd.stressMode);
|
|
254
|
-
|
|
274
|
+
pooledDbManager pdb;
|
|
275
|
+
pdb.reset(0);
|
|
276
|
+
//return 0;
|
|
255
277
|
}
|
|
256
|
-
return 1;
|
|
278
|
+
//return 1;
|
|
257
279
|
}
|
|
258
280
|
|
|
259
281
|
catch (bzs::rtl::exception& e)
|
|
@@ -261,5 +283,8 @@ int _tmain(int argc, _TCHAR* argv[])
|
|
|
261
283
|
std::_tstring s = *bzs::rtl::getMsg(e);
|
|
262
284
|
std::tcout << _T("[ERROR] ") << s << std::endl;
|
|
263
285
|
}
|
|
286
|
+
#ifdef _MSC_VER
|
|
287
|
+
_CrtDumpMemoryLeaks();
|
|
288
|
+
#endif
|
|
264
289
|
return 1;
|
|
265
290
|
}
|
|
@@ -262,7 +262,7 @@ bool createTestDataBase(client::database* db, const _TCHAR* uri)
|
|
|
262
262
|
db->create(uri);
|
|
263
263
|
if (db->stat() != 0)
|
|
264
264
|
{
|
|
265
|
-
|
|
265
|
+
_tprintf(_T("createTestDataBase erorr:No.%d %s\r\n"), db->stat(), uri);
|
|
266
266
|
return false;
|
|
267
267
|
}
|
|
268
268
|
if (db->open(uri, TYPE_BDF, TD_OPEN_NORMAL, _T(""), _T("")))
|
|
@@ -22,7 +22,12 @@
|
|
|
22
22
|
#include <boost/thread/mutex.hpp>
|
|
23
23
|
#include <bzs/rtl/benchmark.h>
|
|
24
24
|
#include <iostream>
|
|
25
|
+
#include <bzs/env/tstring.h>
|
|
26
|
+
#include <stdio.h>
|
|
25
27
|
|
|
28
|
+
#ifdef _WIN32
|
|
29
|
+
#include <windows.h>
|
|
30
|
+
#endif
|
|
26
31
|
namespace bzs
|
|
27
32
|
{
|
|
28
33
|
namespace test
|
|
@@ -49,6 +54,21 @@ protected:
|
|
|
49
54
|
virtual void doExecute() = 0;
|
|
50
55
|
virtual void endExecute(){};
|
|
51
56
|
virtual void initExecute(){};
|
|
57
|
+
std::_tstring dummyWork()
|
|
58
|
+
{
|
|
59
|
+
std::_tstring s;
|
|
60
|
+
__int64 v = 0;
|
|
61
|
+
for (int i=1;i<100;++i)
|
|
62
|
+
{
|
|
63
|
+
v+=rand();
|
|
64
|
+
v = v/i;
|
|
65
|
+
_TCHAR tmp[30];
|
|
66
|
+
_stprintf_s(tmp, 30, _T("random number %d ."), v);
|
|
67
|
+
s += tmp;
|
|
68
|
+
}
|
|
69
|
+
return s;
|
|
70
|
+
}
|
|
71
|
+
|
|
52
72
|
|
|
53
73
|
public:
|
|
54
74
|
workerBase(int id, int loopCount, int functionNumber, boost::barrier& sync)
|
|
@@ -72,12 +92,38 @@ public:
|
|
|
72
92
|
else if (g_bench_signal == BENCH_SIGNAL_BLUE)
|
|
73
93
|
{
|
|
74
94
|
m_bresult = bm.end();
|
|
95
|
+
dummyWork();
|
|
96
|
+
break;
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
endExecute();
|
|
101
|
+
}
|
|
102
|
+
#ifdef _WIN32
|
|
103
|
+
void execute2(HANDLE hHandle)
|
|
104
|
+
{
|
|
105
|
+
initExecute();
|
|
106
|
+
bzs::rtl::benchmarkMt bm;
|
|
107
|
+
WaitForSingleObject(hHandle, INFINITE);
|
|
108
|
+
|
|
109
|
+
bm.start();
|
|
110
|
+
m_bresult = 0;
|
|
111
|
+
while (g_bench_signal)
|
|
112
|
+
{
|
|
113
|
+
doExecute();
|
|
114
|
+
if (g_bench_signal == BENCH_SIGNAL_GREEN)
|
|
115
|
+
++m_bresult;
|
|
116
|
+
else if (g_bench_signal == BENCH_SIGNAL_BLUE)
|
|
117
|
+
{
|
|
118
|
+
m_bresult = bm.end();
|
|
119
|
+
dummyWork();
|
|
75
120
|
break;
|
|
76
121
|
}
|
|
77
122
|
}
|
|
78
123
|
|
|
79
124
|
endExecute();
|
|
80
125
|
}
|
|
126
|
+
#endif
|
|
81
127
|
int total() const { return m_bresult; }
|
|
82
128
|
};
|
|
83
129
|
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
#ifndef BZS_TEST_BENCH_WORKERMYSQLIMPLE_H
|
|
1
|
+
#ifndef BZS_TEST_BENCH_WORKERMYSQLIMPLE_H
|
|
2
2
|
#define BZS_TEST_BENCH_WORKERMYSQLIMPLE_H
|
|
3
3
|
/* =================================================================
|
|
4
4
|
Copyright (C) 20014 BizStation Corp All rights reserved.
|
|
@@ -35,7 +35,7 @@ namespace mysql
|
|
|
35
35
|
#define MYSQL_READ_ONE 10
|
|
36
36
|
#define MYSQL_INSERT_ONE 11
|
|
37
37
|
#define MYSQL_QUERY 12
|
|
38
|
-
#define MYSQL_RECORDSET_COUNT
|
|
38
|
+
#define MYSQL_RECORDSET_COUNT 30
|
|
39
39
|
|
|
40
40
|
class connectParam
|
|
41
41
|
{
|
|
@@ -183,10 +183,10 @@ class worker : public workerBase
|
|
|
183
183
|
MYSQL_STMT* init(const char* query)
|
|
184
184
|
{
|
|
185
185
|
#ifdef LINUX
|
|
186
|
-
const char* fd_name = "
|
|
186
|
+
const char* fd_name = "名前";
|
|
187
187
|
#else
|
|
188
188
|
char fd_name[30];
|
|
189
|
-
WideCharToMultiByte(CP_UTF8, 0, L"
|
|
189
|
+
WideCharToMultiByte(CP_UTF8, 0, L"名前", -1, fd_name, 30, NULL, NULL);
|
|
190
190
|
#endif
|
|
191
191
|
char tmp[512];
|
|
192
192
|
if (m_functionNumber == MYSQL_QUERY)
|
|
@@ -202,6 +202,7 @@ class worker : public workerBase
|
|
|
202
202
|
printf("error: %s\n", mysql_error(m_mysql));
|
|
203
203
|
bindParam(stmt);
|
|
204
204
|
bindOutput(stmt);
|
|
205
|
+
|
|
205
206
|
return stmt;
|
|
206
207
|
}
|
|
207
208
|
|
|
@@ -209,7 +210,7 @@ class worker : public workerBase
|
|
|
209
210
|
{
|
|
210
211
|
m_bindParam = m_id % 20000 + 1;
|
|
211
212
|
mysql_stmt_execute(stmt);
|
|
212
|
-
int ret;
|
|
213
|
+
int ret=0;
|
|
213
214
|
ret = mysql_stmt_fetch(stmt);
|
|
214
215
|
if (ret)
|
|
215
216
|
printf("error: %s\n", mysql_error(m_mysql));
|
|
@@ -251,8 +252,8 @@ public:
|
|
|
251
252
|
: workerBase(id, loopCount, functionNumber, sync), m_parmas(param)
|
|
252
253
|
{
|
|
253
254
|
boost::mutex::scoped_lock lck(m_mutex);
|
|
254
|
-
|
|
255
|
-
|
|
255
|
+
|
|
256
|
+
|
|
256
257
|
m_mysql = mysql_init(NULL);
|
|
257
258
|
int v = 1;
|
|
258
259
|
if (NULL == mysql_real_connect(
|
|
@@ -261,14 +262,21 @@ public:
|
|
|
261
262
|
m_parmas.database.c_str(), m_parmas.port, NULL, 0))
|
|
262
263
|
printf("error: %s\n", mysql_error(m_mysql));
|
|
263
264
|
}
|
|
265
|
+
|
|
264
266
|
|
|
265
267
|
void initExecute()
|
|
266
268
|
{
|
|
269
|
+
mysql_thread_init();
|
|
270
|
+
mysql_set_character_set(m_mysql, "utf8");
|
|
271
|
+
|
|
267
272
|
#ifdef USE_SHARED_PREPAREDSTATEMENT
|
|
268
273
|
if (m_functionNumber == MYSQL_READ_ONE)
|
|
269
274
|
m_stmt = init(readOneQuery);
|
|
270
275
|
else if (m_functionNumber == MYSQL_QUERY)
|
|
276
|
+
{
|
|
271
277
|
m_stmt = init(queryOneQuery);
|
|
278
|
+
queryOne(m_stmt);
|
|
279
|
+
}
|
|
272
280
|
#endif
|
|
273
281
|
}
|
|
274
282
|
|
|
@@ -40,7 +40,7 @@ namespace transactd
|
|
|
40
40
|
#define TRD_READ_ONE 0
|
|
41
41
|
#define TRD_INSERT_ONE 1
|
|
42
42
|
#define TRD_QUERY 2
|
|
43
|
-
#define TRD_RECORDSET_COUNT
|
|
43
|
+
#define TRD_RECORDSET_COUNT 30
|
|
44
44
|
|
|
45
45
|
class worker : public workerBase
|
|
46
46
|
{
|
|
@@ -59,7 +59,8 @@ class worker : public workerBase
|
|
|
59
59
|
recordset m_rs;
|
|
60
60
|
void readOne(table_ptr& tb)
|
|
61
61
|
{
|
|
62
|
-
int v = (rand() % 15000) + 1;
|
|
62
|
+
//int v = (rand() % 15000) + 1;
|
|
63
|
+
int v = m_id % 20000 + 1;
|
|
63
64
|
tb->setFV((short)0, v);
|
|
64
65
|
tb->seek();
|
|
65
66
|
if (tb->stat() != 0)
|
|
@@ -68,7 +69,8 @@ class worker : public workerBase
|
|
|
68
69
|
|
|
69
70
|
void insertOne(table_ptr& tb)
|
|
70
71
|
{
|
|
71
|
-
tb->clearBuffer();
|
|
72
|
+
//tb->clearBuffer();
|
|
73
|
+
tb->setFV((short)0, (int)0);
|
|
72
74
|
tb->setFV(1, m_id);
|
|
73
75
|
insertRecord(tb);
|
|
74
76
|
}
|
|
@@ -77,25 +79,14 @@ class worker : public workerBase
|
|
|
77
79
|
{
|
|
78
80
|
m_rs.clear();
|
|
79
81
|
query q;
|
|
80
|
-
int v = (rand() % 15000) + 1;
|
|
82
|
+
//int v = (rand() % 15000) + 1;
|
|
83
|
+
int v = m_id % 20000 + 1;
|
|
81
84
|
q.select(_T("id"), _T("name"), _T("group"))
|
|
82
85
|
.where(_T("id"), _T("<"), v + TRD_RECORDSET_COUNT);
|
|
83
86
|
m_atu->index(0).keyValue(v).read(m_rs, q);
|
|
84
|
-
q.reset();
|
|
85
|
-
|
|
86
|
-
// m_ate->index(0).join(m_rs,
|
|
87
|
-
// q.select(_T("comment")).optimize(queryBase::joinHasOneOrHasMany),
|
|
88
|
-
// _T("id"));
|
|
89
87
|
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
q.select(_T("group_name"));
|
|
94
|
-
for (int i=0;i<m_rs.size();++i)
|
|
95
|
-
q.addSeekKeyValuePtr(m_rs[i][(short)0].ptr());
|
|
96
|
-
m_atg->table()->setQuery(&q);
|
|
97
|
-
m_atg->index(0).keyValue(0).read(rs2, q);
|
|
98
|
-
*/
|
|
88
|
+
q.reset();
|
|
89
|
+
|
|
99
90
|
m_atg->index(0).join(m_rs, q.select(_T("group_name")), _T("group"));
|
|
100
91
|
if (m_rs.size() != TRD_RECORDSET_COUNT)
|
|
101
92
|
printf("query read error! id = %d size = %d\n", m_id, m_rs.size());
|
|
@@ -143,6 +134,7 @@ public:
|
|
|
143
134
|
_TCHAR tmp[30];
|
|
144
135
|
m_atu->alias(name_field_str(tmp), _T("name"));
|
|
145
136
|
m_atg->alias(_T("name"), _T("group_name"));
|
|
137
|
+
queryOne();
|
|
146
138
|
}
|
|
147
139
|
}
|
|
148
140
|
|
|
@@ -18,6 +18,7 @@
|
|
|
18
18
|
================================================================= */
|
|
19
19
|
//#define BOOST_TEST_MODULE
|
|
20
20
|
|
|
21
|
+
|
|
21
22
|
#include <boost/test/included/unit_test.hpp>
|
|
22
23
|
#include <bzs/db/protocol/tdap/client/database.h>
|
|
23
24
|
#include <bzs/db/protocol/tdap/client/table.h>
|
|
@@ -29,14 +30,19 @@
|
|
|
29
30
|
#include <bzs/db/protocol/tdap/client/filter.h>
|
|
30
31
|
#include <bzs/example/queryData.h>
|
|
31
32
|
#include <bzs/db/protocol/tdap/client/activeTable.h>
|
|
32
|
-
|
|
33
33
|
#include <bzs/db/protocol/tdap/client/pooledDatabaseManager.h>
|
|
34
|
+
#include <boost/thread.hpp>
|
|
34
35
|
|
|
35
36
|
using namespace bzs::db::protocol::tdap::client;
|
|
36
37
|
using namespace bzs::db::protocol::tdap;
|
|
37
38
|
using namespace std;
|
|
38
39
|
|
|
40
|
+
#define TDAP
|
|
41
|
+
#ifdef TDAP
|
|
39
42
|
#define PROTOCOL _T("tdap")
|
|
43
|
+
#else
|
|
44
|
+
#define PROTOCOL _T("btrv")
|
|
45
|
+
#endif
|
|
40
46
|
static _TCHAR HOSTNAME[MAX_PATH] = { _T("127.0.0.1") };
|
|
41
47
|
#define DBNAME _T("test")
|
|
42
48
|
#define BDFNAME _T("test.bdf")
|
|
@@ -62,6 +68,9 @@ boost::unit_test::test_suite* init_unit_test_suite(int argc, char* argv[])
|
|
|
62
68
|
#endif
|
|
63
69
|
}
|
|
64
70
|
}
|
|
71
|
+
printf("Transactd test ... \nMay look like progress is stopped, \n"
|
|
72
|
+
"but it is such as record lock test, please wait.\n");
|
|
73
|
+
|
|
65
74
|
return 0;
|
|
66
75
|
}
|
|
67
76
|
|
|
@@ -194,6 +203,7 @@ void testCreateNewDataBase(database* db)
|
|
|
194
203
|
dbdef* def = db->dbDef();
|
|
195
204
|
if (def)
|
|
196
205
|
{
|
|
206
|
+
/* user table */
|
|
197
207
|
tabledef td;
|
|
198
208
|
memset(&td, 0, sizeof(tabledef));
|
|
199
209
|
td.setTableName(_T("user"));
|
|
@@ -248,6 +258,48 @@ void testCreateNewDataBase(database* db)
|
|
|
248
258
|
def->updateTableDef(1);
|
|
249
259
|
BOOST_CHECK_MESSAGE(0 == def->stat(),
|
|
250
260
|
"updateTableDef 3 stat = " << def->stat());
|
|
261
|
+
|
|
262
|
+
/* group table */
|
|
263
|
+
memset(&td, 0, sizeof(tabledef));
|
|
264
|
+
td.setTableName(_T("group"));
|
|
265
|
+
td.setFileName(_T("group"));
|
|
266
|
+
td.id = 2;
|
|
267
|
+
td.primaryKeyNum = -1;
|
|
268
|
+
td.parentKeyNum = -1;
|
|
269
|
+
td.replicaKeyNum = -1;
|
|
270
|
+
td.pageSize = 2048;
|
|
271
|
+
def->insertTable(&td);
|
|
272
|
+
BOOST_CHECK_MESSAGE(0 == def->stat(),
|
|
273
|
+
"insertTable stat = " << def->stat());
|
|
274
|
+
|
|
275
|
+
fd = def->insertField(2, 0);
|
|
276
|
+
fd->setName(_T("id"));
|
|
277
|
+
fd->type = ft_integer;
|
|
278
|
+
fd->len = (ushort_td)4;
|
|
279
|
+
def->updateTableDef(2);
|
|
280
|
+
BOOST_CHECK_MESSAGE(0 == def->stat(),
|
|
281
|
+
"updateTableDef 1 stat = " << def->stat());
|
|
282
|
+
|
|
283
|
+
fd = def->insertField(2, 1);
|
|
284
|
+
fd->setName(_T("name"));
|
|
285
|
+
fd->type = ft_zstring;
|
|
286
|
+
fd->len = (ushort_td)33;
|
|
287
|
+
def->updateTableDef(2);
|
|
288
|
+
BOOST_CHECK_MESSAGE(0 == def->stat(),
|
|
289
|
+
"updateTableDef 2 stat = " << def->stat());
|
|
290
|
+
|
|
291
|
+
kd = def->insertKey(2, 0);
|
|
292
|
+
kd->segments[0].fieldNum = 0;
|
|
293
|
+
kd->segments[0].flags.bit8 = 1; // extended key type
|
|
294
|
+
kd->segments[0].flags.bit1 = 1; // changeable
|
|
295
|
+
kd->segmentCount = 1;
|
|
296
|
+
|
|
297
|
+
def->updateTableDef(2);
|
|
298
|
+
BOOST_CHECK_MESSAGE(0 == def->stat(),
|
|
299
|
+
"updateTableDef 3 stat = " << def->stat());
|
|
300
|
+
|
|
301
|
+
|
|
302
|
+
|
|
251
303
|
}
|
|
252
304
|
}
|
|
253
305
|
|
|
@@ -330,6 +382,20 @@ void testInsert(database* db)
|
|
|
330
382
|
tb->release();
|
|
331
383
|
}
|
|
332
384
|
|
|
385
|
+
void findNextLoop(table* tb, int start, int end)
|
|
386
|
+
{
|
|
387
|
+
while (start < end)
|
|
388
|
+
{
|
|
389
|
+
BOOST_CHECK_MESSAGE(0 == tb->stat(), "find stat = " << tb->stat());
|
|
390
|
+
if (tb->stat()) break;
|
|
391
|
+
|
|
392
|
+
BOOST_CHECK_MESSAGE(start == tb->getFVint(fdi_id), "find value " << start << " bad = " << tb->getFVint(fdi_id));
|
|
393
|
+
tb->findNext(true);
|
|
394
|
+
++start;
|
|
395
|
+
}
|
|
396
|
+
BOOST_CHECK_MESSAGE(0 != tb->stat(), "findNext end stat = " << tb->stat());
|
|
397
|
+
}
|
|
398
|
+
|
|
333
399
|
void testFind(database* db)
|
|
334
400
|
{
|
|
335
401
|
|
|
@@ -340,24 +406,18 @@ void testFind(database* db)
|
|
|
340
406
|
int v = 10;
|
|
341
407
|
tb->setFV((short)0, v);
|
|
342
408
|
tb->find(table::findForword);
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
{
|
|
346
|
-
BOOST_CHECK_MESSAGE(0 == tb->stat(), "find stat");
|
|
347
|
-
BOOST_CHECK_MESSAGE(i == tb->getFVint(fdi_id), "find value " << i);
|
|
348
|
-
tb->findNext(true); // 11 ~ 19
|
|
349
|
-
++i;
|
|
350
|
-
}
|
|
351
|
-
|
|
409
|
+
findNextLoop(tb, v, 20000);
|
|
410
|
+
|
|
352
411
|
// backforword
|
|
353
412
|
tb->clearBuffer();
|
|
354
413
|
v = 19999;
|
|
355
414
|
tb->setFV((short)0, v);
|
|
356
415
|
tb->find(table::findBackForword);
|
|
357
|
-
i = v;
|
|
416
|
+
int i = v;
|
|
358
417
|
while (i >= 10)
|
|
359
418
|
{
|
|
360
|
-
BOOST_CHECK_MESSAGE(0 == tb->stat(), "find stat");
|
|
419
|
+
BOOST_CHECK_MESSAGE(0 == tb->stat(), "find stat = " << tb->stat());
|
|
420
|
+
if (tb->stat()) break;
|
|
361
421
|
BOOST_CHECK_MESSAGE(i == tb->getFVint(fdi_id), "find value " << i);
|
|
362
422
|
tb->findPrev(true); // 11 ~ 19
|
|
363
423
|
--i;
|
|
@@ -384,7 +444,8 @@ void testFindNext(database* db)
|
|
|
384
444
|
for (int i = v + 1; i < 20000; i++)
|
|
385
445
|
{
|
|
386
446
|
tb->findNext(true); // 11 ~ 19
|
|
387
|
-
BOOST_CHECK_MESSAGE(0 == tb->stat(), "findNext stat()");
|
|
447
|
+
BOOST_CHECK_MESSAGE(0 == tb->stat(), "findNext stat()" << tb->stat());
|
|
448
|
+
if (tb->stat()) break;
|
|
388
449
|
BOOST_CHECK_MESSAGE(i == tb->getFVint(fdi_id), "findNext value");
|
|
389
450
|
}
|
|
390
451
|
tb->release();
|
|
@@ -435,26 +496,25 @@ void testFindIn(database* db)
|
|
|
435
496
|
|
|
436
497
|
// Many params
|
|
437
498
|
_TCHAR buf[20];
|
|
438
|
-
|
|
439
|
-
q.addSeekKeyValue(buf, true);
|
|
440
|
-
|
|
441
|
-
for (int i = 2; i <= 10000; ++i)
|
|
499
|
+
for (int j = 1; j <= 10000; ++j)
|
|
442
500
|
{
|
|
443
|
-
_ltot_s(
|
|
444
|
-
q.addSeekKeyValue(buf);
|
|
501
|
+
_ltot_s(j, buf, 20, 10);
|
|
502
|
+
q.addSeekKeyValue(buf, (j == 1)/* reset */);
|
|
445
503
|
}
|
|
446
504
|
tb->setQuery(&q);
|
|
447
505
|
BOOST_CHECK_MESSAGE(0 == tb->stat(), "find in stat = " << tb->stat());
|
|
448
|
-
|
|
449
|
-
tb->find();
|
|
450
506
|
int i = 0;
|
|
507
|
+
tb->find();
|
|
508
|
+
|
|
451
509
|
while (0 == tb->stat())
|
|
452
510
|
{
|
|
453
|
-
|
|
454
|
-
BOOST_CHECK_MESSAGE(
|
|
511
|
+
++i;
|
|
512
|
+
BOOST_CHECK_MESSAGE(i == tb->getFVint(fdi_id), "findNext in value " << i << " = " << tb->getFVint(fdi_id));
|
|
513
|
+
if (i==9999)
|
|
514
|
+
i = 9999;
|
|
455
515
|
tb->findNext(true);
|
|
456
516
|
}
|
|
457
|
-
BOOST_CHECK_MESSAGE(i == 10000, "findNext in count");
|
|
517
|
+
BOOST_CHECK_MESSAGE(i == 10000, "findNext in count 10000 != " << i);
|
|
458
518
|
BOOST_CHECK_MESSAGE(9 == tb->stat(), "find in end stat = " << tb->stat());
|
|
459
519
|
|
|
460
520
|
// LogicalCountLimit
|
|
@@ -475,6 +535,142 @@ void testFindIn(database* db)
|
|
|
475
535
|
tb->release();
|
|
476
536
|
}
|
|
477
537
|
|
|
538
|
+
void testPrepare(database* db)
|
|
539
|
+
{
|
|
540
|
+
table* tb = openTable(db);
|
|
541
|
+
queryBase q;
|
|
542
|
+
q.queryString(_T("id >= ? and id < ?"));
|
|
543
|
+
q.reject(1).limit(0);
|
|
544
|
+
pq_handle stmt = tb->prepare(&q);
|
|
545
|
+
const _TCHAR* vs[2];
|
|
546
|
+
int nn = makeSupplyValues(vs, 2, _T("10"), _T("20000"));
|
|
547
|
+
|
|
548
|
+
//Test too short supply values
|
|
549
|
+
bool ret = supplyValues(stmt, vs, nn -1); //stmt->supplyValues(vs, nn); Bad
|
|
550
|
+
BOOST_CHECK_MESSAGE(ret == false, "supplyValues short");
|
|
551
|
+
|
|
552
|
+
//Test supply values
|
|
553
|
+
ret = supplyValues(stmt, vs, nn);
|
|
554
|
+
BOOST_CHECK_MESSAGE(ret == true, "supplyValues true");
|
|
555
|
+
|
|
556
|
+
int v = 10;
|
|
557
|
+
tb->setFV((short)0, v);
|
|
558
|
+
tb->find(table::findForword);
|
|
559
|
+
findNextLoop(tb, v, 20000);
|
|
560
|
+
|
|
561
|
+
supplyValues(stmt, vs, makeSupplyValues(vs, 2, _T("100"), _T("10000"))); //stmt->supplyValues(vs, nn); Bad
|
|
562
|
+
tb->setPrepare(stmt);
|
|
563
|
+
v = 100;
|
|
564
|
+
tb->setFV((short)0, v);
|
|
565
|
+
tb->find(table::findForword);
|
|
566
|
+
findNextLoop(tb, v, 10000);
|
|
567
|
+
|
|
568
|
+
const _TCHAR* values[11];
|
|
569
|
+
int n = makeSupplyValues(values, 11, _T("abc"), _T("efg"), _T("efg")
|
|
570
|
+
, _T("abc"), _T("efg"), _T("efg")
|
|
571
|
+
, _T("abc"), _T("efg"), _T("efg")
|
|
572
|
+
, _T("abc"), _T("efg"));
|
|
573
|
+
|
|
574
|
+
BOOST_CHECK_MESSAGE(n == 11, "makeSupplyValues");
|
|
575
|
+
|
|
576
|
+
tb->release();
|
|
577
|
+
}
|
|
578
|
+
|
|
579
|
+
void testPrepareServer(database* db)
|
|
580
|
+
{
|
|
581
|
+
table* tb = openTable(db);
|
|
582
|
+
queryBase q;
|
|
583
|
+
q.queryString(_T("id >= ? and id < ?"));
|
|
584
|
+
q.reject(0xFFFF).limit(0);
|
|
585
|
+
pq_handle stmt = tb->prepare(&q, true);
|
|
586
|
+
BOOST_CHECK_MESSAGE(0 == tb->stat(), "prepare stat");
|
|
587
|
+
if (tb->stat()) return ;
|
|
588
|
+
|
|
589
|
+
const _TCHAR* vs[2];
|
|
590
|
+
|
|
591
|
+
bool ret = supplyValues(stmt, vs, makeSupplyValues(vs, 2, _T("10"), _T("200"))); //stmt->supplyValues(vs, nn); Bad
|
|
592
|
+
BOOST_CHECK_MESSAGE(ret == true, "supplyValues true");
|
|
593
|
+
|
|
594
|
+
tb->setPrepare(stmt);
|
|
595
|
+
BOOST_CHECK_MESSAGE(tb->stat() == 0, "setQuery stmt");
|
|
596
|
+
|
|
597
|
+
int v = 10;
|
|
598
|
+
tb->setFV((short)0, v);
|
|
599
|
+
|
|
600
|
+
// Test Bad direction
|
|
601
|
+
tb->find(table::findBackForword);
|
|
602
|
+
BOOST_CHECK_MESSAGE(1 == tb->stat(), "find direction not equal prepare");
|
|
603
|
+
|
|
604
|
+
tb->find(table::findForword);
|
|
605
|
+
findNextLoop(tb, v, 200);
|
|
606
|
+
|
|
607
|
+
ret = supplyValues(stmt, vs, makeSupplyValues(vs, 2, _T("100"), _T("3000")));
|
|
608
|
+
BOOST_CHECK_MESSAGE(ret == true, "supplyValues true");
|
|
609
|
+
|
|
610
|
+
tb->setPrepare(stmt);
|
|
611
|
+
BOOST_CHECK_MESSAGE(tb->stat() == 0, "setQuery stmt");
|
|
612
|
+
|
|
613
|
+
v = 100;
|
|
614
|
+
tb->setFV((short)0, v);
|
|
615
|
+
tb->find(table::findForword);
|
|
616
|
+
findNextLoop(tb, v, 3000);
|
|
617
|
+
|
|
618
|
+
// No seek with
|
|
619
|
+
ret = supplyValues(stmt, vs, makeSupplyValues(vs, 2, _T("50"), _T("100")));
|
|
620
|
+
BOOST_CHECK_MESSAGE(ret == true, "supplyValues ");
|
|
621
|
+
tb->setPrepare(stmt);
|
|
622
|
+
v = 50;
|
|
623
|
+
tb->setFV((short)0, v);
|
|
624
|
+
tb->seek();
|
|
625
|
+
BOOST_CHECK_MESSAGE(0 == tb->stat(), "seek");
|
|
626
|
+
tb->findNext(false);
|
|
627
|
+
findNextLoop(tb, v, 100);
|
|
628
|
+
|
|
629
|
+
// RecordCount
|
|
630
|
+
ret = supplyValues(stmt, vs, makeSupplyValues(vs, 2, _T("50"), _T("100")));
|
|
631
|
+
BOOST_CHECK_MESSAGE(ret == true, "supplyValues ");
|
|
632
|
+
tb->setPrepare(stmt);
|
|
633
|
+
uint_td num = tb->recordCount(false);
|
|
634
|
+
BOOST_CHECK_MESSAGE(num == 50, "recordCount ");
|
|
635
|
+
|
|
636
|
+
// Multi prepare statement
|
|
637
|
+
q.reset();
|
|
638
|
+
q.queryString(_T("id < ?"));
|
|
639
|
+
q.reject(0xFFFF).limit(0);
|
|
640
|
+
pq_handle stmt2 = tb->prepare(&q, true);
|
|
641
|
+
ret = supplyValues(stmt2, vs, makeSupplyValues(vs, 1, _T("50")));
|
|
642
|
+
BOOST_CHECK_MESSAGE(ret == true, "supplyValues ");
|
|
643
|
+
tb->setPrepare(stmt2);
|
|
644
|
+
v = 1;
|
|
645
|
+
tb->setFV((short)0, v);
|
|
646
|
+
tb->find();
|
|
647
|
+
findNextLoop(tb, v, 50);
|
|
648
|
+
|
|
649
|
+
ret = supplyValues(stmt, vs, makeSupplyValues(vs, 2, _T("100"), _T("3000")));
|
|
650
|
+
BOOST_CHECK_MESSAGE(ret == true, "supplyValues ");
|
|
651
|
+
tb->setPrepare(stmt);
|
|
652
|
+
v = 100;
|
|
653
|
+
tb->setFV((short)0, v);
|
|
654
|
+
tb->find(table::findForword);
|
|
655
|
+
findNextLoop(tb, v, 3000);
|
|
656
|
+
|
|
657
|
+
// Seeks prepare statement
|
|
658
|
+
/*q.reset();
|
|
659
|
+
q.queryString(_T("select id"));
|
|
660
|
+
pq_handle stmt3 = tb->prepare(&q, true);
|
|
661
|
+
const _TCHAR* vsi[6];
|
|
662
|
+
makeSupplyValues(vsi, 6, _T("10"), _T("11"), _T("12"), _T("13"),
|
|
663
|
+
_T("14"), _T("15"));
|
|
664
|
+
int keySegments = 1;
|
|
665
|
+
ret = supplyInValues(stmt3, vsi, 6, keySegments);
|
|
666
|
+
BOOST_CHECK_MESSAGE(ret == true, "supplyValues ");
|
|
667
|
+
tb->setPrepare(stmt3);
|
|
668
|
+
tb->find();
|
|
669
|
+
findNextLoop(tb, 10, 16);
|
|
670
|
+
*/
|
|
671
|
+
tb->release();
|
|
672
|
+
}
|
|
673
|
+
|
|
478
674
|
void testGetPercentage(database* db)
|
|
479
675
|
{
|
|
480
676
|
table* tb = openTable(db);
|
|
@@ -530,7 +726,12 @@ void testGetNext(database* db)
|
|
|
530
726
|
BOOST_CHECK_MESSAGE(vv == tb->getFVint(fdi_id), "GetNext");
|
|
531
727
|
|
|
532
728
|
for (int i = 3; i < 20002; i++)
|
|
729
|
+
{
|
|
533
730
|
tb->seekNext();
|
|
731
|
+
BOOST_CHECK_MESSAGE(i == tb->getFVint(fdi_id), "GetNext id: " << i << " bad = " << tb->getFVint(fdi_id));
|
|
732
|
+
if (i != tb->getFVint(fdi_id))
|
|
733
|
+
break;
|
|
734
|
+
}
|
|
534
735
|
db->endSnapshot();
|
|
535
736
|
}
|
|
536
737
|
tb->release();
|
|
@@ -539,6 +740,8 @@ void testGetNext(database* db)
|
|
|
539
740
|
void testGetPrevious(database* db)
|
|
540
741
|
{
|
|
541
742
|
table* tb = openTable(db);
|
|
743
|
+
|
|
744
|
+
// in-snapshot
|
|
542
745
|
db->beginSnapshot();
|
|
543
746
|
int vv = 20001;
|
|
544
747
|
tb->clearBuffer();
|
|
@@ -548,13 +751,33 @@ void testGetPrevious(database* db)
|
|
|
548
751
|
for (int i = 20000; i > 1; i--)
|
|
549
752
|
{
|
|
550
753
|
tb->seekPrev();
|
|
551
|
-
BOOST_CHECK_MESSAGE(i == tb->getFVint(fdi_id), "GetPrevious
|
|
754
|
+
BOOST_CHECK_MESSAGE(i == tb->getFVint(fdi_id), "GetPrevious id: " << i << " bad = " << tb->getFVint(fdi_id));
|
|
755
|
+
if (i != tb->getFVint(fdi_id))
|
|
756
|
+
break;
|
|
757
|
+
|
|
552
758
|
}
|
|
553
759
|
tb->seekPrev();
|
|
554
760
|
BOOST_CHECK_MESSAGE(_tstring(_T("kosaka")) == _tstring(tb->getFVstr(1)),
|
|
555
761
|
"GetPrevious kosaka");
|
|
556
|
-
|
|
557
762
|
db->endSnapshot();
|
|
763
|
+
|
|
764
|
+
//without snapshot
|
|
765
|
+
vv = 20001;
|
|
766
|
+
tb->clearBuffer();
|
|
767
|
+
tb->setFV((short)0, vv);
|
|
768
|
+
tb->seek();
|
|
769
|
+
BOOST_CHECK_MESSAGE(vv == tb->getFVint(fdi_id), "GetPrevious");
|
|
770
|
+
for (int i = 20000; i > 1; i--)
|
|
771
|
+
{
|
|
772
|
+
tb->seekPrev();
|
|
773
|
+
BOOST_CHECK_MESSAGE(i == tb->getFVint(fdi_id), "GetPrevious id: " << i << " bad = " << tb->getFVint(fdi_id));
|
|
774
|
+
if (i != tb->getFVint(fdi_id))
|
|
775
|
+
break;
|
|
776
|
+
}
|
|
777
|
+
tb->seekPrev();
|
|
778
|
+
BOOST_CHECK_MESSAGE(_tstring(_T("kosaka")) == _tstring(tb->getFVstr(1)),
|
|
779
|
+
"GetPrevious kosaka");
|
|
780
|
+
|
|
558
781
|
tb->release();
|
|
559
782
|
}
|
|
560
783
|
|
|
@@ -717,62 +940,140 @@ void testUpdate(database* db)
|
|
|
717
940
|
tb->release();
|
|
718
941
|
}
|
|
719
942
|
|
|
720
|
-
void
|
|
943
|
+
void testSnapshot(database* db)
|
|
721
944
|
{
|
|
945
|
+
table* tb = openTable(db);
|
|
946
|
+
table* tbg = db->openTable(_T("group"), TD_OPEN_NORMAL);
|
|
722
947
|
database* db2 = database::create();
|
|
723
|
-
db2->connect(makeUri(PROTOCOL, HOSTNAME, DBNAME), true);
|
|
724
948
|
BOOST_CHECK_MESSAGE(0 == db2->stat(), "connect");
|
|
725
|
-
|
|
949
|
+
db2->connect(makeUri(PROTOCOL, HOSTNAME, DBNAME), true);
|
|
726
950
|
table* tb2 = openTable(db2);
|
|
951
|
+
table* tbg2 = db2->openTable(_T("group"), TD_OPEN_NORMAL);
|
|
727
952
|
|
|
728
|
-
|
|
953
|
+
/* No locking repeatable read */
|
|
954
|
+
/* -------------------------------------------------- */
|
|
955
|
+
db->beginSnapshot(); // CONSISTENT_READ is default
|
|
729
956
|
BOOST_CHECK_MESSAGE(0 == db->stat(), "beginSnapShot");
|
|
957
|
+
db->beginTrn();
|
|
958
|
+
BOOST_CHECK_MESSAGE(STATUS_ALREADY_INSNAPSHOT == db->stat(), "Invalid beginSnapshot");
|
|
959
|
+
|
|
960
|
+
|
|
730
961
|
tb->setKeyNum(0);
|
|
731
|
-
tb->seekFirst();
|
|
962
|
+
tb->seekFirst();
|
|
732
963
|
BOOST_CHECK_MESSAGE(0 == tb->stat(), "seekFirst");
|
|
733
|
-
|
|
964
|
+
_tstring firstValue = tb->getFVstr(fdi_name);
|
|
734
965
|
tb->seekNext();
|
|
735
|
-
|
|
736
|
-
|
|
966
|
+
BOOST_CHECK_MESSAGE(0 == tb->stat(), "seekNext");
|
|
967
|
+
BOOST_CHECK_MESSAGE(2 == tb->getFVint(fdi_id), "seekNext");
|
|
968
|
+
tbg->seekFirst();
|
|
969
|
+
BOOST_CHECK_MESSAGE(STATUS_EOF == tbg->stat(), "seekFirst tbg");
|
|
970
|
+
BOOST_CHECK_MESSAGE(0 == tbg->recordCount(false), "seekFirst tbg");
|
|
971
|
+
|
|
972
|
+
// Change data by another connection. change 2 tables.
|
|
737
973
|
tb2->setKeyNum(0);
|
|
738
974
|
tb2->seekFirst();
|
|
739
975
|
BOOST_CHECK_MESSAGE(0 == tb2->stat(), "tb2->seekFirst");
|
|
740
976
|
tb2->setFV(fdi_name, tb2->getFVint(fdi_name) + 1);
|
|
741
|
-
tb2->update();
|
|
742
|
-
|
|
743
|
-
BOOST_CHECK_MESSAGE(0 == tb2->stat(), "tb2->update stat = " << tb2->stat());
|
|
744
|
-
#else
|
|
745
|
-
#ifdef ISOLATION_REPEATABLE_READ
|
|
746
|
-
BOOST_CHECK_MESSAGE(STATUS_LOCK_ERROR == tb2->stat(),
|
|
977
|
+
tb2->update(); //Change success
|
|
978
|
+
BOOST_CHECK_MESSAGE(0 == tb2->stat(),
|
|
747
979
|
"tb2->update stat = " << tb2->stat());
|
|
748
|
-
|
|
749
|
-
|
|
750
|
-
|
|
980
|
+
tbg2->setFV(fdi_id, 1);
|
|
981
|
+
tbg2->setFV(fdi_name, _T("ABC"));
|
|
982
|
+
tbg2->insert();
|
|
983
|
+
BOOST_CHECK_MESSAGE(0 == tbg2->stat(), "tbg2->insert");
|
|
751
984
|
|
|
985
|
+
// in-snapshot repeatable read check same value
|
|
752
986
|
tb->seekFirst();
|
|
753
|
-
|
|
987
|
+
_tstring secondValue = tb->getFVstr(fdi_name);
|
|
754
988
|
BOOST_CHECK_MESSAGE(0 == tb->stat(), "secondValue");
|
|
755
|
-
|
|
989
|
+
BOOST_CHECK_MESSAGE(secondValue == firstValue, "repeatableRead");
|
|
990
|
+
|
|
991
|
+
tbg->seekFirst();
|
|
992
|
+
BOOST_CHECK_MESSAGE(STATUS_EOF == tbg->stat(), "seekFirst tbg");
|
|
993
|
+
BOOST_CHECK_MESSAGE(0 == tbg->recordCount(false), "seekFirst tbg");
|
|
756
994
|
|
|
995
|
+
// test update in snapshot
|
|
996
|
+
tb->update();
|
|
997
|
+
BOOST_CHECK_MESSAGE(STATUS_INVALID_LOCKTYPE == tb->stat(), "snapshot update stat = " << tb->stat());
|
|
998
|
+
|
|
999
|
+
// test insert in snapshot
|
|
1000
|
+
tb->setFV(fdi_id, 0);
|
|
1001
|
+
tb->insert();
|
|
1002
|
+
BOOST_CHECK_MESSAGE(STATUS_INVALID_LOCKTYPE == tb->stat(), "snapshot insert stat = " << tb->stat());
|
|
1003
|
+
|
|
1004
|
+
//test phantom read
|
|
1005
|
+
tb2->setFV(fdi_id, 29999);
|
|
1006
|
+
tb2->insert();
|
|
1007
|
+
BOOST_CHECK_MESSAGE(0 == tb2->stat(), "phantom insert");
|
|
1008
|
+
tb->setFV(fdi_id, 29999);
|
|
1009
|
+
tb->seek();
|
|
1010
|
+
BOOST_CHECK_MESSAGE(STATUS_NOT_FOUND_TI == tb->stat(), "phantom read");
|
|
1011
|
+
|
|
1012
|
+
// clean up
|
|
1013
|
+
tb2->del();
|
|
1014
|
+
BOOST_CHECK_MESSAGE(0 == tb2->stat(), "del");
|
|
1015
|
+
|
|
1016
|
+
db->endSnapshot();
|
|
757
1017
|
BOOST_CHECK_MESSAGE(0 == db->stat(), "endSnapShot");
|
|
758
|
-
|
|
759
|
-
|
|
760
|
-
|
|
761
|
-
BOOST_CHECK_MESSAGE(
|
|
762
|
-
|
|
1018
|
+
|
|
1019
|
+
// After snapshot, db can read new versions.
|
|
1020
|
+
tb->seekFirst();
|
|
1021
|
+
BOOST_CHECK_MESSAGE(0 == tb->stat(), "tb->seekFirst");
|
|
1022
|
+
BOOST_CHECK_MESSAGE(1 == tb->getFVint(fdi_name), "read new value = 1");
|
|
1023
|
+
tbg->seekFirst();
|
|
1024
|
+
BOOST_CHECK_MESSAGE(0 == tbg->stat(), "seekFirst tbg");
|
|
1025
|
+
BOOST_CHECK_MESSAGE(1 == tbg->recordCount(false), "seekFirst tbg");
|
|
763
1026
|
|
|
764
|
-
|
|
1027
|
+
|
|
1028
|
+
//test gap lock
|
|
1029
|
+
db->beginSnapshot(MULTILOCK_GAP_SHARE);
|
|
1030
|
+
tb->seekLast(); // id = 30000
|
|
1031
|
+
BOOST_CHECK_MESSAGE(0 == tb->stat(), "seekLast");
|
|
1032
|
+
tb->seekPrev(); // id = 20002
|
|
1033
|
+
BOOST_CHECK_MESSAGE(0 == tb->stat(), "seekPrev");
|
|
1034
|
+
tb->seekPrev(); // id = 20001
|
|
1035
|
+
BOOST_CHECK_MESSAGE(0 == tb->stat(), "seekPrev");
|
|
1036
|
+
|
|
1037
|
+
tb2->setFV(fdi_id, 29999);
|
|
1038
|
+
tb2->insert();
|
|
1039
|
+
BOOST_CHECK_MESSAGE(STATUS_LOCK_ERROR == tb2->stat(), "GAP insert");
|
|
1040
|
+
|
|
1041
|
+
db->endSnapshot();
|
|
1042
|
+
|
|
1043
|
+
//test gap lock
|
|
1044
|
+
db->beginSnapshot(MULTILOCK_NOGAP_SHARE);
|
|
1045
|
+
tb->seekLast(); // id = 30000
|
|
1046
|
+
BOOST_CHECK_MESSAGE(0 == tb->stat(), "seekLast");
|
|
1047
|
+
tb->seekPrev(); // id = 20002
|
|
1048
|
+
BOOST_CHECK_MESSAGE(0 == tb->stat(), "seekPrev");
|
|
1049
|
+
tb->seekPrev(); // id = 20001
|
|
1050
|
+
BOOST_CHECK_MESSAGE(0 == tb->stat(), "seekPrev");
|
|
1051
|
+
|
|
1052
|
+
tb2->setFV(fdi_id, 20002);
|
|
1053
|
+
tb2->seek(ROW_LOCK_X);
|
|
1054
|
+
BOOST_CHECK_MESSAGE(STATUS_LOCK_ERROR == tb2->stat(), "GAP insert");
|
|
1055
|
+
|
|
1056
|
+
|
|
1057
|
+
tb2->seekLast(ROW_LOCK_X);
|
|
1058
|
+
BOOST_CHECK_MESSAGE(STATUS_LOCK_ERROR == tb2->stat(), "GAP insert");
|
|
1059
|
+
|
|
1060
|
+
|
|
1061
|
+
db->endSnapshot();
|
|
1062
|
+
|
|
1063
|
+
tbg->release();
|
|
1064
|
+
tbg2->release();
|
|
765
1065
|
tb->release();
|
|
766
1066
|
tb2->release();
|
|
1067
|
+
|
|
767
1068
|
database::destroy(db2);
|
|
768
1069
|
}
|
|
769
1070
|
|
|
770
1071
|
void testConflict(database* db)
|
|
771
1072
|
{
|
|
1073
|
+
table* tb = openTable(db);
|
|
772
1074
|
database* db2 = database::create();
|
|
773
1075
|
db2->connect(makeUri(PROTOCOL, HOSTNAME, DBNAME), true);
|
|
774
1076
|
BOOST_CHECK_MESSAGE(0 == db2->stat(), "connect");
|
|
775
|
-
table* tb = openTable(db);
|
|
776
1077
|
table* tb2 = openTable(db2);
|
|
777
1078
|
|
|
778
1079
|
tb->setKeyNum(0);
|
|
@@ -795,9 +1096,9 @@ void testConflict(database* db)
|
|
|
795
1096
|
BOOST_CHECK_MESSAGE(STATUS_CHANGE_CONFLICT == tb->stat(), "tb->update(");
|
|
796
1097
|
/* -------------------------------------------------- */
|
|
797
1098
|
|
|
798
|
-
/* --------------------------------------------------
|
|
799
|
-
|
|
800
|
-
|
|
1099
|
+
/* -------------------------------------------------- */
|
|
1100
|
+
/* Change Non index field */
|
|
1101
|
+
/* -------------------------------------------------- */
|
|
801
1102
|
// Change data by another connection
|
|
802
1103
|
tb->seekFirst();
|
|
803
1104
|
BOOST_CHECK_MESSAGE(0 == tb->stat(), "tb->seekFirst");
|
|
@@ -817,188 +1118,851 @@ void testConflict(database* db)
|
|
|
817
1118
|
database::destroy(db2);
|
|
818
1119
|
}
|
|
819
1120
|
|
|
820
|
-
|
|
1121
|
+
/* isoration Level ISO_REPEATABLE_READ */
|
|
1122
|
+
void testTransactionLockRepeatable(database* db)
|
|
821
1123
|
{
|
|
822
|
-
|
|
1124
|
+
table* tb = openTable(db);
|
|
823
1125
|
database* db2 = database::create();
|
|
824
1126
|
db2->connect(makeUri(PROTOCOL, HOSTNAME, DBNAME), true);
|
|
825
1127
|
BOOST_CHECK_MESSAGE(0 == db2->stat(), "connect");
|
|
826
|
-
table* tb = openTable(db);
|
|
827
1128
|
table* tb2 = openTable(db2);
|
|
828
1129
|
|
|
829
|
-
|
|
830
|
-
|
|
831
|
-
//
|
|
832
|
-
db->
|
|
833
|
-
|
|
1130
|
+
db->beginTrn(MULTILOCK_REPEATABLE_READ);
|
|
1131
|
+
BOOST_CHECK_MESSAGE(0 == db->stat(), "beginTrn");
|
|
1132
|
+
// Test Invalid operation
|
|
1133
|
+
db->beginSnapshot();
|
|
1134
|
+
BOOST_CHECK_MESSAGE(STATUS_ALREADY_INTRANSACTION == db->stat(), "Invalid beginSnapshot");
|
|
1135
|
+
|
|
1136
|
+
/* -------------------------------------------------*/
|
|
1137
|
+
/* Test Read with lock */
|
|
1138
|
+
/* -------------------------------------------------*/
|
|
1139
|
+
// lock(X) the first record
|
|
834
1140
|
tb->seekFirst();
|
|
835
1141
|
BOOST_CHECK_MESSAGE(0 == tb->stat(), "tb->seekFirst");
|
|
836
1142
|
|
|
837
|
-
//
|
|
1143
|
+
// Add lock(X) the second record
|
|
838
1144
|
tb->seekNext();
|
|
839
1145
|
|
|
1146
|
+
// No transaction user can read allways. Use consistent_read
|
|
840
1147
|
tb2->seekFirst();
|
|
841
1148
|
BOOST_CHECK_MESSAGE(0 == tb2->stat(), "tb->seekFirst");
|
|
842
1149
|
|
|
1150
|
+
tb2->seekNext();
|
|
1151
|
+
BOOST_CHECK_MESSAGE(0 == tb2->stat(), "tb->seekFirst");
|
|
1152
|
+
|
|
1153
|
+
// The second transaction user can not lock same record.
|
|
843
1154
|
db2->beginTrn();
|
|
844
1155
|
tb2->setKeyNum(0);
|
|
1156
|
+
|
|
1157
|
+
// Try lock(X)
|
|
845
1158
|
tb2->seekFirst();
|
|
846
|
-
BOOST_CHECK_MESSAGE(
|
|
1159
|
+
BOOST_CHECK_MESSAGE(STATUS_LOCK_ERROR == tb2->stat(), "tb->seekFirst");
|
|
847
1160
|
db2->endTrn();
|
|
848
1161
|
db->endTrn();
|
|
849
1162
|
|
|
850
|
-
|
|
851
|
-
|
|
852
|
-
|
|
853
|
-
|
|
854
|
-
|
|
1163
|
+
/* -------------------------------------------------*/
|
|
1164
|
+
/* Test single record lock and Transaction lock */
|
|
1165
|
+
/* -------------------------------------------------*/
|
|
1166
|
+
// lock(X) non-transaction
|
|
1167
|
+
tb2->seekFirst(ROW_LOCK_X);
|
|
1168
|
+
|
|
1169
|
+
db->beginTrn(MULTILOCK_REPEATABLE_READ);
|
|
1170
|
+
BOOST_CHECK_MESSAGE(0 == db->stat(), "beginTrn");
|
|
1171
|
+
|
|
1172
|
+
// Try lock(X)
|
|
1173
|
+
tb->seekFirst();
|
|
1174
|
+
BOOST_CHECK_MESSAGE(STATUS_LOCK_ERROR == tb->stat(), "tb->seekFirst");
|
|
1175
|
+
|
|
1176
|
+
// Remove lock(X)
|
|
1177
|
+
tb2->seekFirst();
|
|
1178
|
+
|
|
1179
|
+
// Retry lock(X)
|
|
855
1180
|
tb->seekFirst();
|
|
856
1181
|
BOOST_CHECK_MESSAGE(0 == tb->stat(), "tb->seekFirst");
|
|
857
1182
|
|
|
858
|
-
|
|
859
|
-
tb->
|
|
1183
|
+
tb->setFV(fdi_name, _T("ABC"));
|
|
1184
|
+
tb->update();
|
|
1185
|
+
BOOST_CHECK_MESSAGE(0 == tb->stat(), "update");
|
|
860
1186
|
|
|
861
|
-
//
|
|
1187
|
+
// No transaction user read can read allways. Use consistent_read
|
|
862
1188
|
tb2->seekFirst();
|
|
863
|
-
BOOST_CHECK_MESSAGE(
|
|
1189
|
+
BOOST_CHECK_MESSAGE(0 == tb2->stat(), "tb->seekFirst");
|
|
1190
|
+
BOOST_CHECK_MESSAGE(_tstring(_T("ABC")) != _tstring(tb2->getFVstr(fdi_name)), "consistent_read");
|
|
864
1191
|
|
|
865
|
-
|
|
1192
|
+
/* -------------------------------------------------*/
|
|
1193
|
+
/* Test Transaction lock and Transaction lock */
|
|
1194
|
+
/* -------------------------------------------------*/
|
|
866
1195
|
db2->beginTrn();
|
|
867
|
-
|
|
1196
|
+
BOOST_CHECK_MESSAGE(0 == db2->stat(), "beginTrn");
|
|
1197
|
+
|
|
1198
|
+
// try lock(X)
|
|
1199
|
+
tb2->seekFirst();
|
|
1200
|
+
BOOST_CHECK_MESSAGE(STATUS_LOCK_ERROR == tb2->stat(), "tb->seekFirst");
|
|
1201
|
+
|
|
1202
|
+
// Try unlock updated record. Con not unlock updated record.
|
|
1203
|
+
tb->unlock();
|
|
1204
|
+
|
|
1205
|
+
// try lock(X)
|
|
868
1206
|
tb2->seekFirst();
|
|
869
1207
|
BOOST_CHECK_MESSAGE(STATUS_LOCK_ERROR == tb2->stat(), "tb->seekFirst");
|
|
1208
|
+
|
|
870
1209
|
db2->endTrn();
|
|
871
1210
|
db->endTrn();
|
|
872
1211
|
|
|
873
|
-
|
|
874
|
-
|
|
875
|
-
|
|
876
|
-
db->beginTrn(
|
|
877
|
-
|
|
1212
|
+
/* -------------------------------------------------*/
|
|
1213
|
+
/* Test phantom read */
|
|
1214
|
+
/* -------------------------------------------------*/
|
|
1215
|
+
db->beginTrn(MULTILOCK_REPEATABLE_READ);
|
|
1216
|
+
BOOST_CHECK_MESSAGE(0 == db->stat(), "beginTrn");
|
|
1217
|
+
|
|
1218
|
+
// read last row
|
|
1219
|
+
tb->seekLast(); //lock(X) last id = 30000
|
|
1220
|
+
BOOST_CHECK_MESSAGE(0 == tb->stat(), "tb->seekLast");
|
|
1221
|
+
tb->seekPrev(); //Add lock(X)
|
|
1222
|
+
BOOST_CHECK_MESSAGE(0 == tb->stat(), "tb->seekPrev");
|
|
1223
|
+
int last2 = tb->getFVint(fdi_id);
|
|
1224
|
+
|
|
1225
|
+
// insert test row
|
|
1226
|
+
tb2->setFV(fdi_id, 29999);
|
|
1227
|
+
tb2->insert(); //Can not insert by gap lock
|
|
1228
|
+
BOOST_CHECK_MESSAGE(STATUS_LOCK_ERROR == tb2->stat(), "tb2->insert");
|
|
1229
|
+
|
|
1230
|
+
tb->seekLast();
|
|
1231
|
+
BOOST_CHECK_MESSAGE(0 == tb->stat(), "tb->seekLast");
|
|
1232
|
+
tb->seekPrev();
|
|
1233
|
+
BOOST_CHECK_MESSAGE(0 == tb->stat(), "tb->seekPrev");
|
|
1234
|
+
BOOST_CHECK_MESSAGE(last2 == tb->getFVint(fdi_id), "phantom read");
|
|
1235
|
+
db->endTrn();
|
|
1236
|
+
|
|
1237
|
+
/* -------------------------------------------------*/
|
|
1238
|
+
/* Test use shared lock option */
|
|
1239
|
+
/* -------------------------------------------------*/
|
|
1240
|
+
|
|
1241
|
+
db->beginTrn(MULTILOCK_REPEATABLE_READ);
|
|
1242
|
+
BOOST_CHECK_MESSAGE(0 == db->stat(), "beginTrn1");
|
|
1243
|
+
|
|
1244
|
+
db2->beginTrn(MULTILOCK_REPEATABLE_READ);
|
|
1245
|
+
BOOST_CHECK_MESSAGE(0 == db2->stat(), "beginTrn2");
|
|
1246
|
+
|
|
1247
|
+
tb->seekLast(ROW_LOCK_S);
|
|
1248
|
+
BOOST_CHECK_MESSAGE(0 == tb->stat(), "tb->seekLast");
|
|
1249
|
+
tb2->seekLast(ROW_LOCK_S);
|
|
1250
|
+
BOOST_CHECK_MESSAGE(0 == tb2->stat(), "tb->seekLast");
|
|
1251
|
+
|
|
1252
|
+
tb->seekPrev();//Lock(X)
|
|
1253
|
+
BOOST_CHECK_MESSAGE(0 == tb->stat(), "tb->seekPrev");
|
|
1254
|
+
|
|
1255
|
+
tb2->seekPrev(ROW_LOCK_S);
|
|
1256
|
+
BOOST_CHECK_MESSAGE(STATUS_LOCK_ERROR == tb2->stat(), "tb2->seekPrev");
|
|
1257
|
+
|
|
1258
|
+
tb->seekPrev(ROW_LOCK_S);
|
|
1259
|
+
BOOST_CHECK_MESSAGE(0 == tb->stat(), "tb->seekPrev");
|
|
1260
|
+
int id = tb->getFVint(fdi_id);
|
|
1261
|
+
|
|
1262
|
+
tb2->setFV(fdi_id, id);
|
|
1263
|
+
tb2->seek(ROW_LOCK_S);
|
|
1264
|
+
BOOST_CHECK_MESSAGE(0 == tb2->stat(), "tb2->seek");
|
|
1265
|
+
|
|
1266
|
+
db2->endTrn();
|
|
1267
|
+
db->endTrn();
|
|
1268
|
+
|
|
1269
|
+
/* -------------------------------------------------*/
|
|
1270
|
+
/* Test Abort */
|
|
1271
|
+
/* -------------------------------------------------*/
|
|
1272
|
+
db->beginTrn(MULTILOCK_REPEATABLE_READ);
|
|
1273
|
+
BOOST_CHECK_MESSAGE(0 == db->stat(), "beginTrn");
|
|
1274
|
+
|
|
1275
|
+
// lock(X)
|
|
878
1276
|
tb->seekFirst();
|
|
879
1277
|
BOOST_CHECK_MESSAGE(0 == tb->stat(), "tb->seekFirst");
|
|
880
|
-
tb->setFV(fdi_name, _T("
|
|
1278
|
+
tb->setFV(fdi_name, _T("EFG"));
|
|
881
1279
|
tb->update();
|
|
882
1280
|
BOOST_CHECK_MESSAGE(0 == tb->stat(), "update");
|
|
883
1281
|
|
|
884
1282
|
// move from first record.
|
|
885
1283
|
tb->seekNext();
|
|
1284
|
+
db->abortTrn();
|
|
886
1285
|
|
|
1286
|
+
tb2->setKeyNum(0);
|
|
887
1287
|
tb2->seekFirst();
|
|
888
|
-
BOOST_CHECK_MESSAGE(
|
|
1288
|
+
BOOST_CHECK_MESSAGE(_tcscmp(tb2->getFVstr(fdi_name), _T("ABC")) == 0,
|
|
1289
|
+
"tb->seekFirst");
|
|
1290
|
+
|
|
1291
|
+
|
|
1292
|
+
/* -------------------------------------------------*/
|
|
1293
|
+
/* Test Query and locks Multi record lock */
|
|
1294
|
+
/* -------------------------------------------------*/
|
|
1295
|
+
db->beginTrn(MULTILOCK_REPEATABLE_READ);
|
|
1296
|
+
|
|
1297
|
+
// Test find records are lock.
|
|
1298
|
+
query q;
|
|
1299
|
+
q.where(_T("id"), _T("<="), 15).and_(_T("id"), _T("<>"), 13)
|
|
1300
|
+
.reject(0xFFFF);
|
|
1301
|
+
tb->setQuery(&q);
|
|
1302
|
+
tb->setFV(fdi_id, 12);
|
|
1303
|
+
tb->find();
|
|
1304
|
+
while (tb->stat() == 0)
|
|
1305
|
+
tb->findNext();
|
|
1306
|
+
BOOST_CHECK_MESSAGE(15 == tb->getFVint(fdi_id), "find last id");
|
|
1307
|
+
|
|
1308
|
+
//all records locked
|
|
1309
|
+
for (int i = 12 ; i <= 16; ++i)
|
|
1310
|
+
{
|
|
1311
|
+
tb2->setFV(fdi_id, i);
|
|
1312
|
+
tb2->seek(ROW_LOCK_X);
|
|
1313
|
+
BOOST_CHECK_MESSAGE(STATUS_LOCK_ERROR == tb2->stat(), "tb2->seek");
|
|
1314
|
+
}
|
|
1315
|
+
db->endTrn();
|
|
1316
|
+
|
|
1317
|
+
|
|
1318
|
+
tb->release();
|
|
1319
|
+
tb2->release();
|
|
1320
|
+
database::destroy(db2);
|
|
1321
|
+
}
|
|
1322
|
+
|
|
1323
|
+
/* isoration Level ISO_READ_COMMITED */
|
|
1324
|
+
void testTransactionLockReadCommited(database* db)
|
|
1325
|
+
{
|
|
1326
|
+
table* tb = openTable(db);
|
|
1327
|
+
database* db2 = database::create();
|
|
1328
|
+
db2->connect(makeUri(PROTOCOL, HOSTNAME, DBNAME), true);
|
|
1329
|
+
BOOST_CHECK_MESSAGE(0 == db2->stat(), "connect");
|
|
1330
|
+
table* tb2 = openTable(db2);
|
|
1331
|
+
|
|
1332
|
+
/* -------------------------------------------------*/
|
|
1333
|
+
/* Test single record lock Transaction and read */
|
|
1334
|
+
/* -------------------------------------------------*/
|
|
1335
|
+
db->beginTrn(SINGLELOCK_READ_COMMITED);
|
|
1336
|
+
BOOST_CHECK_MESSAGE(0 == db->stat(), "beginTrn");
|
|
1337
|
+
db->beginSnapshot();
|
|
1338
|
+
BOOST_CHECK_MESSAGE(STATUS_ALREADY_INTRANSACTION == db->stat(), "Invalid beginSnapshot");
|
|
1339
|
+
|
|
1340
|
+
tb->setKeyNum(0);
|
|
1341
|
+
tb->seekFirst(); // lock(X)
|
|
1342
|
+
BOOST_CHECK_MESSAGE(0 == tb->stat(), "tb->seekFirst");
|
|
889
1343
|
|
|
1344
|
+
// Try lock(X)
|
|
1345
|
+
tb2->seekFirst(ROW_LOCK_X);
|
|
1346
|
+
BOOST_CHECK_MESSAGE(STATUS_LOCK_ERROR == tb2->stat(), "tb2->seekFirst");
|
|
1347
|
+
|
|
1348
|
+
// consistent read
|
|
1349
|
+
tb2->seekFirst();
|
|
1350
|
+
BOOST_CHECK_MESSAGE(0 == tb2->stat(), "tb2->seekFirst");
|
|
1351
|
+
|
|
1352
|
+
// Unlock first record. And lock(X) second record
|
|
1353
|
+
tb->seekNext();
|
|
1354
|
+
|
|
1355
|
+
// test unlocked first record
|
|
1356
|
+
tb2->seekFirst();
|
|
1357
|
+
BOOST_CHECK_MESSAGE(0 == tb2->stat(), "tb->seekFirst");
|
|
1358
|
+
tb2->update();
|
|
1359
|
+
BOOST_CHECK_MESSAGE(0 == tb2->stat(), "tb->update");
|
|
1360
|
+
|
|
1361
|
+
// The second record, consistent read
|
|
1362
|
+
tb2->seekNext();
|
|
1363
|
+
BOOST_CHECK_MESSAGE(0 == tb2->stat(), "tb->seekNext");
|
|
1364
|
+
// Try lock(X) whith lock(IX)
|
|
1365
|
+
tb2->update();
|
|
1366
|
+
BOOST_CHECK_MESSAGE(STATUS_LOCK_ERROR == tb2->stat(), "tb->update");
|
|
1367
|
+
|
|
1368
|
+
/* ---------------------------------------------------------*/
|
|
1369
|
+
/* Test single record lock Transaction and Transaction lock */
|
|
1370
|
+
/* ---------------------------------------------------------*/
|
|
890
1371
|
db2->beginTrn();
|
|
891
|
-
|
|
1372
|
+
// Try lock(X)
|
|
1373
|
+
tb2->seekFirst();
|
|
1374
|
+
BOOST_CHECK_MESSAGE(0 == tb2->stat(), "tb->seekFirst");
|
|
1375
|
+
// Try lock(X)
|
|
1376
|
+
tb2->seekNext();
|
|
1377
|
+
BOOST_CHECK_MESSAGE(STATUS_LOCK_ERROR == tb2->stat(), "tb->seekNext");
|
|
1378
|
+
db2->endTrn();
|
|
1379
|
+
db->endTrn();
|
|
1380
|
+
|
|
1381
|
+
/* ------------------------------------------------------------*/
|
|
1382
|
+
/* Test multi record lock Transaction and non-transaction read */
|
|
1383
|
+
/* ------------------------------------------------------------*/
|
|
1384
|
+
db->beginTrn(MULTILOCK_READ_COMMITED);
|
|
1385
|
+
BOOST_CHECK_MESSAGE(0 == db->stat(), "beginTrn");
|
|
1386
|
+
|
|
1387
|
+
// lock(X) the first record
|
|
1388
|
+
tb->seekFirst();
|
|
1389
|
+
BOOST_CHECK_MESSAGE(0 == tb->stat(), "tb->seekFirst");
|
|
1390
|
+
|
|
1391
|
+
// Add lock(X) the second record
|
|
1392
|
+
tb->seekNext();
|
|
1393
|
+
|
|
1394
|
+
// No transaction user read can read allways. Use consistent_read
|
|
1395
|
+
tb2->seekFirst();
|
|
1396
|
+
BOOST_CHECK_MESSAGE(0 == tb2->stat(), "tb->seekFirst");
|
|
1397
|
+
|
|
1398
|
+
tb2->seekNext();
|
|
1399
|
+
BOOST_CHECK_MESSAGE(0 == tb2->stat(), "tb->seekNext");
|
|
1400
|
+
|
|
1401
|
+
/* --------------------------------------*/
|
|
1402
|
+
/* Test unlock */
|
|
1403
|
+
/* --------------------------------------*/
|
|
1404
|
+
tb2->seekFirst();
|
|
1405
|
+
tb2->seekNext(ROW_LOCK_X);
|
|
1406
|
+
BOOST_CHECK_MESSAGE(STATUS_LOCK_ERROR == tb2->stat(), "tb2->seekNext");
|
|
1407
|
+
|
|
1408
|
+
tb->unlock();
|
|
1409
|
+
// retry seekNext. Before operation is failed but do not lost currency.
|
|
1410
|
+
tb2->seekNext(ROW_LOCK_X);
|
|
1411
|
+
BOOST_CHECK_MESSAGE(0 == tb2->stat(), "unlock");
|
|
1412
|
+
tb2->seekNext();
|
|
1413
|
+
/* --------------------------------------*/
|
|
1414
|
+
/* Test undate record unlock */
|
|
1415
|
+
/* --------------------------------------*/
|
|
1416
|
+
tb->seekFirst();
|
|
1417
|
+
BOOST_CHECK_MESSAGE(0 == tb->stat(), "tb->seekFirst");
|
|
1418
|
+
tb->seekNext();
|
|
1419
|
+
BOOST_CHECK_MESSAGE(0 == tb->stat(), "tb->seekFirst");
|
|
1420
|
+
tb->update();
|
|
1421
|
+
BOOST_CHECK_MESSAGE(0 == tb->stat(), "tb->seekFirst");
|
|
1422
|
+
tb->unlock();// Can not unlock updated record
|
|
1423
|
+
BOOST_CHECK_MESSAGE(0 == tb->stat(), "tb->unlock");
|
|
1424
|
+
tb2->seekFirst();
|
|
1425
|
+
tb2->seekNext(ROW_LOCK_X);
|
|
1426
|
+
BOOST_CHECK_MESSAGE(STATUS_LOCK_ERROR == tb2->stat(), "undate unlock");
|
|
1427
|
+
|
|
1428
|
+
/* ---------------------------------------------------------*/
|
|
1429
|
+
/* Test multi record lock Transaction and Transaction */
|
|
1430
|
+
/* ---------------------------------------------------------*/
|
|
1431
|
+
db2->beginTrn();
|
|
1432
|
+
BOOST_CHECK_MESSAGE(0 == db2->stat(), "beginTrn");
|
|
1433
|
+
|
|
1434
|
+
// Try lock(X)
|
|
892
1435
|
tb2->seekFirst();
|
|
893
1436
|
BOOST_CHECK_MESSAGE(STATUS_LOCK_ERROR == tb2->stat(), "tb->seekFirst");
|
|
894
1437
|
db2->endTrn();
|
|
895
1438
|
db->endTrn();
|
|
896
1439
|
|
|
897
|
-
|
|
898
|
-
|
|
899
|
-
|
|
900
|
-
|
|
901
|
-
|
|
1440
|
+
/* -------------------------------------------------------------------*/
|
|
1441
|
+
/* Test multi record lock Transaction and non-transaction record lock */
|
|
1442
|
+
/* -------------------------------------------------------------------*/
|
|
1443
|
+
// lock(X) non-transaction
|
|
1444
|
+
tb2->seekFirst(ROW_LOCK_X);
|
|
1445
|
+
|
|
1446
|
+
db->beginTrn(SINGLELOCK_READ_COMMITED);
|
|
1447
|
+
BOOST_CHECK_MESSAGE(0 == db->stat(), "beginTrn");
|
|
1448
|
+
|
|
1449
|
+
// Try lock(X)
|
|
1450
|
+
tb->seekFirst();
|
|
1451
|
+
BOOST_CHECK_MESSAGE(STATUS_LOCK_ERROR == tb->stat(), "tb->seekFirst");
|
|
1452
|
+
|
|
1453
|
+
// Remove lock(X)
|
|
1454
|
+
tb2->seekFirst();
|
|
1455
|
+
|
|
1456
|
+
// Retry lock(X)
|
|
902
1457
|
tb->seekFirst();
|
|
903
1458
|
BOOST_CHECK_MESSAGE(0 == tb->stat(), "tb->seekFirst");
|
|
904
|
-
|
|
1459
|
+
|
|
1460
|
+
// update in transaction
|
|
1461
|
+
tb->setFV(fdi_name, _T("ABC"));
|
|
905
1462
|
tb->update();
|
|
906
1463
|
BOOST_CHECK_MESSAGE(0 == tb->stat(), "update");
|
|
907
1464
|
|
|
908
1465
|
// move from first record.
|
|
909
1466
|
tb->seekNext();
|
|
910
|
-
db->abortTrn();
|
|
911
1467
|
|
|
1468
|
+
// No transaction read can read allways. Use consistent_read
|
|
1469
|
+
tb2->seekFirst();
|
|
1470
|
+
BOOST_CHECK_MESSAGE(0 == tb2->stat(), "tb2->seekFirst");
|
|
1471
|
+
tb2->update();
|
|
1472
|
+
BOOST_CHECK_MESSAGE(STATUS_LOCK_ERROR == tb2->stat(), "tb2->update");
|
|
1473
|
+
|
|
1474
|
+
db->endTrn();
|
|
1475
|
+
/* -------------------------------------------------*/
|
|
1476
|
+
/* Test phantom read */
|
|
1477
|
+
/* -------------------------------------------------*/
|
|
1478
|
+
db->beginTrn(MULTILOCK_READ_COMMITED);
|
|
1479
|
+
BOOST_CHECK_MESSAGE(0 == db->stat(), "beginTrn");
|
|
1480
|
+
|
|
1481
|
+
//read last row
|
|
1482
|
+
tb->seekLast(); //lock(X) last id = 30000
|
|
1483
|
+
BOOST_CHECK_MESSAGE(0 == tb->stat(), "tb->seekLast");
|
|
1484
|
+
tb->seekPrev(); //Add lock(X)
|
|
1485
|
+
BOOST_CHECK_MESSAGE(0 == tb->stat(), "tb->seekPrev");
|
|
1486
|
+
int last2 = tb->getFVint(fdi_id);
|
|
1487
|
+
|
|
1488
|
+
//insert test row
|
|
1489
|
+
tb2->setFV(fdi_id, 29999);
|
|
1490
|
+
tb2->insert();
|
|
1491
|
+
BOOST_CHECK_MESSAGE(0 == tb2->stat(), "tb2->insert");
|
|
1492
|
+
|
|
1493
|
+
tb->seekLast();
|
|
1494
|
+
BOOST_CHECK_MESSAGE(0 == tb->stat(), "tb->seekLast");
|
|
1495
|
+
tb->seekPrev();
|
|
1496
|
+
BOOST_CHECK_MESSAGE(0 == tb->stat(), "tb->seekPrev");
|
|
1497
|
+
BOOST_CHECK_MESSAGE(last2 != tb->getFVint(fdi_id), "phantom read");
|
|
1498
|
+
db->endTrn();
|
|
1499
|
+
|
|
1500
|
+
//cleanup
|
|
1501
|
+
tb2->del(); // last id = 29999
|
|
1502
|
+
BOOST_CHECK_MESSAGE(0 == tb->stat(), "tb->del");
|
|
1503
|
+
|
|
1504
|
+
/* -------------------------------------------------*/
|
|
1505
|
+
/* TAbort test */
|
|
1506
|
+
/* -------------------------------------------------*/
|
|
1507
|
+
db->beginTrn(SINGLELOCK_READ_COMMITED);
|
|
1508
|
+
BOOST_CHECK_MESSAGE(0 == db->stat(), "beginTrn");
|
|
1509
|
+
|
|
1510
|
+
tb->seekFirst();
|
|
1511
|
+
BOOST_CHECK_MESSAGE(0 == tb->stat(), "tb->seekFirst");
|
|
1512
|
+
tb->setFV(fdi_name, _T("EFG"));
|
|
1513
|
+
tb->update();
|
|
1514
|
+
BOOST_CHECK_MESSAGE(0 == tb->stat(), "update");
|
|
1515
|
+
|
|
1516
|
+
tb->seekNext();
|
|
1517
|
+
db->abortTrn();
|
|
912
1518
|
tb2->setKeyNum(0);
|
|
913
1519
|
tb2->seekFirst();
|
|
914
1520
|
BOOST_CHECK_MESSAGE(_tcscmp(tb2->getFVstr(fdi_name), _T("ABC")) == 0,
|
|
915
1521
|
"tb->seekFirst");
|
|
916
1522
|
|
|
1523
|
+
/* -------------------------------------------------*/
|
|
1524
|
+
/* Test Query and locks Single record lock */
|
|
1525
|
+
/* -------------------------------------------------*/
|
|
1526
|
+
db->beginTrn(SINGLELOCK_READ_COMMITED);
|
|
1527
|
+
|
|
1528
|
+
// Test find last record locked
|
|
1529
|
+
query q;
|
|
1530
|
+
q.where(_T("id"), _T("<="), _T("100"));
|
|
1531
|
+
tb->setQuery(&q);
|
|
1532
|
+
tb->setFV(fdi_id, 1);
|
|
1533
|
+
tb->find();
|
|
1534
|
+
while (tb->stat() == 0)
|
|
1535
|
+
tb->findNext();
|
|
1536
|
+
BOOST_CHECK_MESSAGE(100 == tb->getFVint(fdi_id), "find last id");
|
|
1537
|
+
|
|
1538
|
+
// find read last is record of id = 101.
|
|
1539
|
+
// Would be difficult to identify the last
|
|
1540
|
+
// access to records at SINGLELOCK_READ_COMMITED.
|
|
1541
|
+
// No match records are unlocked.
|
|
1542
|
+
tb2->setFV(fdi_id, 100);
|
|
1543
|
+
tb2->seek(ROW_LOCK_X);
|
|
1544
|
+
BOOST_CHECK_MESSAGE(0 == tb2->stat(), "tb2->seek");
|
|
1545
|
+
tb2->setFV(fdi_id, 101);
|
|
1546
|
+
tb2->seek(ROW_LOCK_X);
|
|
1547
|
+
BOOST_CHECK_MESSAGE(0 == tb2->stat(), "tb2->seek");
|
|
1548
|
+
tb2->unlock();
|
|
1549
|
+
db->endTrn();
|
|
1550
|
+
|
|
1551
|
+
/* -------------------------------------------------*/
|
|
1552
|
+
/* Test Query and locks Multi record lock */
|
|
1553
|
+
/* -------------------------------------------------*/
|
|
1554
|
+
db->beginTrn(MULTILOCK_READ_COMMITED);
|
|
1555
|
+
|
|
1556
|
+
// Test find records are lock.
|
|
1557
|
+
q.reset().where(_T("id"), _T("<="), 15).and_(_T("id"), _T("<>"), 13)
|
|
1558
|
+
.reject(0xFFFF);
|
|
1559
|
+
tb->setQuery(&q);
|
|
1560
|
+
tb->setFV(fdi_id, 12);
|
|
1561
|
+
tb->find();
|
|
1562
|
+
while (tb->stat() == 0)
|
|
1563
|
+
tb->findNext();
|
|
1564
|
+
BOOST_CHECK_MESSAGE(15 == tb->getFVint(fdi_id), "find last id");
|
|
1565
|
+
|
|
1566
|
+
|
|
1567
|
+
for (int i = 12 ; i <= 16; ++i)
|
|
1568
|
+
{
|
|
1569
|
+
tb2->setFV(fdi_id, i);
|
|
1570
|
+
tb2->seek(ROW_LOCK_X);
|
|
1571
|
+
if ((i == 16)|| (i == 13))
|
|
1572
|
+
BOOST_CHECK_MESSAGE(0 == tb2->stat(), "tb2->seek");
|
|
1573
|
+
else
|
|
1574
|
+
BOOST_CHECK_MESSAGE(STATUS_LOCK_ERROR == tb2->stat(), "tb2->seek");
|
|
1575
|
+
}
|
|
1576
|
+
db->endTrn();
|
|
917
1577
|
tb->release();
|
|
918
1578
|
tb2->release();
|
|
919
1579
|
database::destroy(db2);
|
|
920
1580
|
}
|
|
921
1581
|
|
|
922
|
-
void
|
|
1582
|
+
void testRecordLock(database* db)
|
|
923
1583
|
{
|
|
1584
|
+
table* tb = openTable(db);
|
|
1585
|
+
database* db2 = database::create();
|
|
1586
|
+
db2->connect(makeUri(PROTOCOL, HOSTNAME, DBNAME), true);
|
|
1587
|
+
BOOST_CHECK_MESSAGE(0 == db2->stat(), "connect");
|
|
1588
|
+
table* tb2 = openTable(db2);
|
|
924
1589
|
|
|
1590
|
+
tb->setKeyNum(0);
|
|
1591
|
+
tb2->setKeyNum(0);
|
|
1592
|
+
|
|
1593
|
+
//Single record lock
|
|
1594
|
+
tb->seekFirst(ROW_LOCK_X); // lock(X)
|
|
1595
|
+
BOOST_CHECK_MESSAGE(0 == tb->stat(), "tb->seekFirst");
|
|
1596
|
+
tb2->seekFirst(); // Use consistent_read
|
|
1597
|
+
BOOST_CHECK_MESSAGE(0 == tb2->stat(), "tb2->seekFirst");
|
|
1598
|
+
|
|
1599
|
+
tb2->seekFirst(ROW_LOCK_X); // Try lock(X) single
|
|
1600
|
+
BOOST_CHECK_MESSAGE(STATUS_LOCK_ERROR == tb2->stat(), "tb2->seekFirst");
|
|
1601
|
+
|
|
1602
|
+
// try consistent_read. Check ended that before auto transaction
|
|
1603
|
+
tb2->seekFirst();
|
|
1604
|
+
BOOST_CHECK_MESSAGE(0 == tb2->stat(), "tb2->seekFirst");
|
|
1605
|
+
|
|
1606
|
+
tb2->seekNext(ROW_LOCK_X); // lock(X) second
|
|
1607
|
+
BOOST_CHECK_MESSAGE(0 == tb2->stat(), "tb2->seekFirst");
|
|
1608
|
+
|
|
1609
|
+
tb2->seekNext(ROW_LOCK_X); // lock(X) third second lock freed
|
|
1610
|
+
BOOST_CHECK_MESSAGE(0 == tb2->stat(), "tb2->seekFirst");
|
|
1611
|
+
|
|
1612
|
+
|
|
1613
|
+
tb->seekNext(); // nobody lock second.
|
|
1614
|
+
BOOST_CHECK_MESSAGE(0 == tb->stat(), "tb->seekFirst");
|
|
1615
|
+
tb->seekNext(ROW_LOCK_X); // Try lock(X) third
|
|
1616
|
+
BOOST_CHECK_MESSAGE(STATUS_LOCK_ERROR == tb->stat(), "tb->seekFirst");
|
|
1617
|
+
|
|
1618
|
+
//Update test change third with lock(X)
|
|
1619
|
+
tb2->setFV(fdi_name, _T("The 3rd"));
|
|
1620
|
+
tb2->update(); // auto trn commit and unlock all locks
|
|
1621
|
+
BOOST_CHECK_MESSAGE(0 == tb2->stat(), "tb2->update");
|
|
1622
|
+
tb2->seekNext(ROW_LOCK_X); // lock(X) 4th
|
|
1623
|
+
BOOST_CHECK_MESSAGE(0 == tb2->stat(), "tb->seekFirst");
|
|
1624
|
+
tb2->setFV(fdi_name, _T("The 4th"));
|
|
1625
|
+
tb2->update(); // auto trn commit and unlock all locks
|
|
1626
|
+
|
|
1627
|
+
// Test unlock all locks, after update
|
|
1628
|
+
tb->seekFirst(ROW_LOCK_X); // lock(X) first
|
|
1629
|
+
BOOST_CHECK_MESSAGE(0 == tb2->stat(), "tb->seekFirst");
|
|
1630
|
+
tb->seekNext(ROW_LOCK_X); // lock(X) second
|
|
1631
|
+
BOOST_CHECK_MESSAGE(0 == tb2->stat(), "tb->seekNext");
|
|
1632
|
+
tb->seekNext(ROW_LOCK_X); // lock(X) third
|
|
1633
|
+
BOOST_CHECK_MESSAGE(0 == tb2->stat(), "tb->seekNext");
|
|
1634
|
+
BOOST_CHECK_MESSAGE(_tcscmp(tb->getFVstr(fdi_name), _T("The 3rd")) == 0,
|
|
1635
|
+
"tb->seekNext");
|
|
1636
|
+
//Test Insert, After record lock operation
|
|
1637
|
+
tb->setFV(fdi_id, 21000);
|
|
1638
|
+
tb->insert();
|
|
1639
|
+
BOOST_CHECK_MESSAGE(0 == tb->stat(), "tb->insert");
|
|
1640
|
+
tb->del();
|
|
1641
|
+
BOOST_CHECK_MESSAGE(0 == tb->stat(), "tb->del");
|
|
1642
|
+
|
|
1643
|
+
/* --------- Unlock test ----------------------------*/
|
|
1644
|
+
// 1 unlock()
|
|
1645
|
+
tb->seekFirst(ROW_LOCK_X);
|
|
1646
|
+
BOOST_CHECK_MESSAGE(0 == tb->stat(), "tb->seekFirst");
|
|
1647
|
+
|
|
1648
|
+
tb->unlock();
|
|
1649
|
+
|
|
1650
|
+
tb2->seekFirst(ROW_LOCK_X);
|
|
1651
|
+
BOOST_CHECK_MESSAGE(0 == tb2->stat(), "tb2->seekFirst");
|
|
1652
|
+
tb2->unlock();
|
|
1653
|
+
|
|
1654
|
+
//2 auto tran ended
|
|
1655
|
+
table* tb3 = openTable(db2);
|
|
1656
|
+
tb2->seekFirst(ROW_LOCK_X);
|
|
1657
|
+
BOOST_CHECK_MESSAGE(0 == tb2->stat(), "tb2->seekFirst");
|
|
1658
|
+
|
|
1659
|
+
tb3->seekLast(); //This operation is another table handle, then auto tran ended
|
|
1660
|
+
BOOST_CHECK_MESSAGE(0 == tb3->stat(), "tb3->seekLast");
|
|
1661
|
+
|
|
1662
|
+
tb->seekFirst(ROW_LOCK_X);
|
|
1663
|
+
BOOST_CHECK_MESSAGE(0 == tb->stat(), "tb->seekFirst");
|
|
1664
|
+
tb->unlock();
|
|
1665
|
+
|
|
1666
|
+
// begin trn
|
|
1667
|
+
tb3->seekFirst(ROW_LOCK_X);
|
|
1668
|
+
BOOST_CHECK_MESSAGE(0 == tb3->stat(), "tb3->seekFirst");
|
|
1669
|
+
|
|
1670
|
+
tb->seekFirst(ROW_LOCK_X);
|
|
1671
|
+
BOOST_CHECK_MESSAGE(STATUS_LOCK_ERROR == tb->stat(), "tb->seekFirst");
|
|
1672
|
+
db2->beginTrn();
|
|
1673
|
+
|
|
1674
|
+
tb->seekFirst(ROW_LOCK_X);
|
|
1675
|
+
BOOST_CHECK_MESSAGE(0 == tb->stat(), "tb->seekFirst");
|
|
1676
|
+
db2->endTrn();
|
|
1677
|
+
tb->unlock();
|
|
1678
|
+
// begin snapshot
|
|
1679
|
+
tb3->seekFirst(ROW_LOCK_X);
|
|
1680
|
+
BOOST_CHECK_MESSAGE(0 == tb3->stat(), "tb3->seekFirst");
|
|
1681
|
+
|
|
1682
|
+
tb->seekFirst(ROW_LOCK_X);
|
|
1683
|
+
BOOST_CHECK_MESSAGE(STATUS_LOCK_ERROR == tb->stat(), "tb->seekFirst");
|
|
1684
|
+
db2->beginSnapshot();
|
|
1685
|
+
tb->seekFirst(ROW_LOCK_X);
|
|
1686
|
+
BOOST_CHECK_MESSAGE(0 == tb->stat(), "tb->seekFirst");
|
|
1687
|
+
db2->endSnapshot();
|
|
1688
|
+
tb->unlock();
|
|
1689
|
+
// close Table
|
|
1690
|
+
tb->seekFirst(ROW_LOCK_X);
|
|
1691
|
+
BOOST_CHECK_MESSAGE(0 == tb->stat(), "tb->seekFirst");
|
|
1692
|
+
|
|
1693
|
+
tb2->seekFirst(ROW_LOCK_X);
|
|
1694
|
+
BOOST_CHECK_MESSAGE(STATUS_LOCK_ERROR == tb2->stat(), "tb2->seekFirst");
|
|
1695
|
+
tb->release();
|
|
1696
|
+
tb2->seekFirst(ROW_LOCK_X);
|
|
1697
|
+
BOOST_CHECK_MESSAGE(0 == tb2->stat(), "tb2->seekFirst");
|
|
1698
|
+
tb2->unlock();
|
|
1699
|
+
/* --------- End Unlock test ----------------------------*/
|
|
1700
|
+
|
|
1701
|
+
/* --------- Invalid lock type test ----------------------------*/
|
|
1702
|
+
tb2->seekFirst(ROW_LOCK_S);
|
|
1703
|
+
BOOST_CHECK_MESSAGE(STATUS_INVALID_LOCKTYPE == tb2->stat(), "tb2->seekFirst");
|
|
1704
|
+
|
|
1705
|
+
tb2->release();
|
|
1706
|
+
tb3->release();
|
|
1707
|
+
database::destroy(db2);
|
|
1708
|
+
|
|
1709
|
+
}
|
|
1710
|
+
|
|
1711
|
+
void testExclusive()
|
|
1712
|
+
{
|
|
925
1713
|
// db mode exclusive
|
|
926
1714
|
database* db = database::create();
|
|
1715
|
+
/* -------------------------------------------------*/
|
|
1716
|
+
/* database WRITE EXCLUSIVE */
|
|
1717
|
+
/* -------------------------------------------------*/
|
|
927
1718
|
table* tb = openTable(db, TD_OPEN_EXCLUSIVE);
|
|
928
1719
|
BOOST_CHECK_MESSAGE(0 == db->stat(), "Exclusive opened 1 ");
|
|
929
1720
|
|
|
930
1721
|
// Can not open another connections.
|
|
931
1722
|
database* db2 = database::create();
|
|
932
|
-
db2->connect(makeUri(PROTOCOL, HOSTNAME, DBNAME), true);
|
|
933
|
-
BOOST_CHECK_MESSAGE(0 == db2->stat(), "connect");
|
|
934
|
-
db2->open(makeUri(PROTOCOL, HOSTNAME, DBNAME, BDFNAME), TYPE_SCHEMA_BDF);
|
|
935
|
-
|
|
936
|
-
|
|
1723
|
+
db2->connect(makeUri(PROTOCOL, HOSTNAME, DBNAME), true);
|
|
1724
|
+
BOOST_CHECK_MESSAGE(0 == db2->stat(), "connect");
|
|
1725
|
+
db2->open(makeUri(PROTOCOL, HOSTNAME, DBNAME, BDFNAME), TYPE_SCHEMA_BDF);
|
|
1726
|
+
//database open error. Check database::stat()
|
|
1727
|
+
BOOST_CHECK_MESSAGE(STATUS_CANNOT_LOCK_TABLE == db2->stat(),
|
|
1728
|
+
"open db->stat = " << db->stat());
|
|
1729
|
+
dbdef* def = db->dbDef();
|
|
1730
|
+
tabledef* td = def->tableDefs(1);
|
|
1731
|
+
td->iconIndex = 3;
|
|
1732
|
+
def->updateTableDef(1);
|
|
1733
|
+
BOOST_CHECK_MESSAGE(0 == def->stat(), "updateTableDef");
|
|
1734
|
+
tb->release();
|
|
1735
|
+
db->close();
|
|
1736
|
+
db2->close();
|
|
1737
|
+
|
|
1738
|
+
/* -------------------------------------------------*/
|
|
1739
|
+
/* database READ EXCLUSIVE */
|
|
1740
|
+
/* -------------------------------------------------*/
|
|
1741
|
+
tb = openTable(db, TD_OPEN_READONLY_EXCLUSIVE);
|
|
1742
|
+
|
|
1743
|
+
// Read only open
|
|
1744
|
+
db2->open(makeUri(PROTOCOL, HOSTNAME, DBNAME, BDFNAME), TYPE_SCHEMA_BDF);
|
|
1745
|
+
BOOST_CHECK_MESSAGE(0 == db2->stat(), "read only open");
|
|
1746
|
+
db2->close();
|
|
1747
|
+
|
|
1748
|
+
// Normal open
|
|
1749
|
+
db2->connect(makeUri(PROTOCOL, HOSTNAME, DBNAME), true);
|
|
1750
|
+
db2->open(makeUri(PROTOCOL, HOSTNAME, DBNAME, BDFNAME),
|
|
1751
|
+
TYPE_SCHEMA_BDF, TD_OPEN_NORMAL);
|
|
1752
|
+
BOOST_CHECK_MESSAGE(0 == db2->stat()
|
|
1753
|
+
, "Normal open");
|
|
1754
|
+
db2->close();
|
|
1755
|
+
|
|
1756
|
+
// Write Exclusive open
|
|
1757
|
+
db2->open(makeUri(PROTOCOL, HOSTNAME, DBNAME, BDFNAME),
|
|
1758
|
+
TYPE_SCHEMA_BDF, TD_OPEN_EXCLUSIVE);
|
|
1759
|
+
BOOST_CHECK_MESSAGE(STATUS_CANNOT_LOCK_TABLE == db2->stat()
|
|
1760
|
+
, "Write Exclusive open");
|
|
1761
|
+
db2->close();
|
|
1762
|
+
|
|
1763
|
+
// Read Exclusive open
|
|
1764
|
+
db2->open(makeUri(PROTOCOL, HOSTNAME, DBNAME, BDFNAME),
|
|
1765
|
+
TYPE_SCHEMA_BDF, TD_OPEN_READONLY_EXCLUSIVE);
|
|
1766
|
+
BOOST_CHECK_MESSAGE(0 == db2->stat()
|
|
1767
|
+
, "Read Exclusive open");
|
|
1768
|
+
db2->close();
|
|
1769
|
+
tb->release();
|
|
1770
|
+
db->close();
|
|
1771
|
+
|
|
1772
|
+
/* -------------------------------------------------*/
|
|
1773
|
+
/* Nnomal and Exclusive opend tables mix use */
|
|
1774
|
+
/* -------------------------------------------------*/
|
|
1775
|
+
tb = openTable(db, TD_OPEN_NORMAL);
|
|
1776
|
+
db2->open(makeUri(PROTOCOL, HOSTNAME, DBNAME, BDFNAME), TYPE_SCHEMA_BDF);
|
|
1777
|
+
|
|
1778
|
+
table* tb2 = db->openTable(_T("group"), TD_OPEN_EXCLUSIVE);
|
|
1779
|
+
//Check tb2 Exclusive
|
|
1780
|
+
table* tb3 = db2->openTable(_T("group"), TD_OPEN_NORMAL);
|
|
1781
|
+
BOOST_CHECK_MESSAGE(STATUS_CANNOT_LOCK_TABLE == db2->stat()
|
|
1782
|
+
, "Write Exclusive open");
|
|
1783
|
+
//if (tb2->recordCount(false) == 0)
|
|
1784
|
+
{
|
|
1785
|
+
for (int i = 1 ; i < 5 ; ++i)
|
|
1786
|
+
{
|
|
1787
|
+
tb2->setFV(fdi_id, i + 1);
|
|
1788
|
+
tb2->setFV(fdi_name, i + 1);
|
|
1789
|
+
tb2->insert();
|
|
1790
|
+
BOOST_CHECK_MESSAGE(0 == tb2->stat(), "tb2->insert");
|
|
1791
|
+
}
|
|
1792
|
+
}
|
|
1793
|
+
tb2->seekFirst();
|
|
1794
|
+
BOOST_CHECK_MESSAGE(0 == tb2->stat(), "tb2->seekFirst");
|
|
1795
|
+
tb->seekFirst();
|
|
1796
|
+
BOOST_CHECK_MESSAGE(0 == tb->stat(), "tb->seekFirst");
|
|
1797
|
+
tb2->seekLast();
|
|
1798
|
+
BOOST_CHECK_MESSAGE(0 == tb2->stat(), "tb2->seekLast");
|
|
1799
|
+
tb->seekLast();
|
|
1800
|
+
BOOST_CHECK_MESSAGE(0 == tb->stat(), "tb2->seekLast");
|
|
1801
|
+
// Normal close first
|
|
1802
|
+
tb->close();
|
|
1803
|
+
tb2->seekLast();
|
|
1804
|
+
BOOST_CHECK_MESSAGE(0 == tb2->stat(), "tb2->seekLast");
|
|
1805
|
+
tb2->seekFirst();
|
|
1806
|
+
BOOST_CHECK_MESSAGE(0 == tb2->stat(), "tb2->seekFirst");
|
|
1807
|
+
|
|
1808
|
+
//Reopen Normal
|
|
1809
|
+
tb = db->openTable(_T("user"));
|
|
1810
|
+
tb2->seekFirst();
|
|
1811
|
+
BOOST_CHECK_MESSAGE(0 == tb2->stat(), "tb2->seekFirst");
|
|
1812
|
+
tb->seekFirst();
|
|
1813
|
+
BOOST_CHECK_MESSAGE(0 == tb->stat(), "tb->seekFirst");
|
|
1814
|
+
tb2->seekLast();
|
|
1815
|
+
BOOST_CHECK_MESSAGE(0 == tb2->stat(), "tb2->seekLast");
|
|
1816
|
+
tb->seekLast();
|
|
1817
|
+
BOOST_CHECK_MESSAGE(0 == tb->stat(), "tb2->seekLast");
|
|
1818
|
+
// Exclusive close first
|
|
1819
|
+
tb2->close();
|
|
1820
|
+
tb->seekFirst();
|
|
1821
|
+
BOOST_CHECK_MESSAGE(0 == tb->stat(), "tb->seekFirst");
|
|
1822
|
+
tb->seekLast();
|
|
1823
|
+
BOOST_CHECK_MESSAGE(0 == tb->stat(), "tb2->seekLast");
|
|
1824
|
+
|
|
1825
|
+
/* ---------------------------------------------------*/
|
|
1826
|
+
/* Nnomal and Exclusive opend tables mix transaction */
|
|
1827
|
+
/* ---------------------------------------------------*/
|
|
1828
|
+
tb2 = db->openTable(_T("group"), TD_OPEN_EXCLUSIVE);
|
|
1829
|
+
//Check tb2 Exclusive
|
|
1830
|
+
tb3 = db2->openTable(_T("group"), TD_OPEN_NORMAL);
|
|
1831
|
+
BOOST_CHECK_MESSAGE(STATUS_CANNOT_LOCK_TABLE == db2->stat()
|
|
1832
|
+
, "Write Exclusive open");
|
|
1833
|
+
db->beginTrn();
|
|
1834
|
+
tb->seekFirst();
|
|
1835
|
+
BOOST_CHECK_MESSAGE(0 == tb->stat(), "tb->seekFirst");
|
|
1836
|
+
tb->setFV(fdi_name, _T("mix trn"));
|
|
1837
|
+
tb->update();
|
|
1838
|
+
BOOST_CHECK_MESSAGE(0 == tb->stat(), "tb->update");
|
|
1839
|
+
|
|
1840
|
+
tb2->seekFirst();
|
|
1841
|
+
BOOST_CHECK_MESSAGE(0 == tb2->stat(), "tb2->seekFirst");
|
|
1842
|
+
tb2->setFV(fdi_name, _T("first mix trn tb2"));
|
|
1843
|
+
tb2->update();
|
|
1844
|
+
BOOST_CHECK_MESSAGE(0 == tb2->stat(), "tb2->update");
|
|
1845
|
+
|
|
1846
|
+
tb2->seekNext();
|
|
1847
|
+
tb2->setFV(fdi_name, _T("second mix trn tb2"));
|
|
1848
|
+
tb2->update();
|
|
1849
|
+
BOOST_CHECK_MESSAGE(0 == tb2->stat(), "tb2->update");
|
|
1850
|
+
db->endTrn();
|
|
1851
|
+
tb2->seekFirst();
|
|
1852
|
+
_tstring v = tb2->getFVstr(fdi_name);
|
|
1853
|
+
BOOST_CHECK_MESSAGE(v == _T("first mix trn tb2"), "check first");
|
|
1854
|
+
tb2->seekNext();
|
|
1855
|
+
v = tb2->getFVstr(fdi_name);
|
|
1856
|
+
BOOST_CHECK_MESSAGE(v == _T("second mix trn tb2"), "check second");
|
|
1857
|
+
|
|
1858
|
+
database::destroy(db);
|
|
1859
|
+
database::destroy(db2);
|
|
1860
|
+
}
|
|
1861
|
+
|
|
1862
|
+
|
|
1863
|
+
/* Multi database */
|
|
1864
|
+
void testMultiDatabase(database* db)
|
|
1865
|
+
{
|
|
1866
|
+
table* tb = openTable(db);
|
|
1867
|
+
database* db2 = database::create();
|
|
1868
|
+
db2->open(makeUri(PROTOCOL, HOSTNAME, DBNAME, BDFNAME), TYPE_SCHEMA_BDF); // not new connection
|
|
1869
|
+
BOOST_CHECK_MESSAGE(0 == db2->stat(), "db2->open");
|
|
1870
|
+
table* tb2 = db2->openTable(_T("group"));
|
|
937
1871
|
|
|
938
|
-
|
|
939
|
-
|
|
1872
|
+
db->beginTrn();
|
|
1873
|
+
db2->beginTrn();
|
|
940
1874
|
|
|
941
|
-
tb->setKeyNum(0);
|
|
942
1875
|
tb->seekFirst();
|
|
943
|
-
BOOST_CHECK_MESSAGE(0 == tb->stat(), "
|
|
944
|
-
|
|
945
|
-
tb->setFV(fdi_name, _T("
|
|
1876
|
+
BOOST_CHECK_MESSAGE(0 == tb->stat(), "seekFirst");
|
|
1877
|
+
_tstring v = tb->getFVstr(fdi_name);
|
|
1878
|
+
tb->setFV(fdi_name, _T("MultiDatabase"));
|
|
946
1879
|
tb->update();
|
|
947
|
-
BOOST_CHECK_MESSAGE(0 == tb->stat(), "update");
|
|
948
1880
|
|
|
949
|
-
tb2->setKeyNum(0);
|
|
950
1881
|
tb2->seekFirst();
|
|
951
|
-
BOOST_CHECK_MESSAGE(0 == tb2->stat(), "
|
|
952
|
-
tb2->setFV(fdi_name, _T("
|
|
1882
|
+
BOOST_CHECK_MESSAGE(0 == tb2->stat(), "seekFirst");
|
|
1883
|
+
tb2->setFV(fdi_name, _T("MultiDatabase"));
|
|
953
1884
|
tb2->update();
|
|
954
1885
|
BOOST_CHECK_MESSAGE(0 == tb2->stat(), "update");
|
|
1886
|
+
db2->endTrn();
|
|
1887
|
+
db->abortTrn();
|
|
955
1888
|
|
|
956
|
-
tb->
|
|
957
|
-
|
|
958
|
-
|
|
959
|
-
|
|
1889
|
+
tb->seekFirst();
|
|
1890
|
+
BOOST_CHECK_MESSAGE(0 == tb->stat(), "seekFirst");
|
|
1891
|
+
_tstring v2 = tb->getFVstr(fdi_name);
|
|
1892
|
+
BOOST_CHECK_MESSAGE(v == v2, "check value");
|
|
1893
|
+
|
|
1894
|
+
tb->release();
|
|
1895
|
+
tb2->release();
|
|
1896
|
+
database::destroy(db2);
|
|
1897
|
+
}
|
|
1898
|
+
|
|
1899
|
+
class worker
|
|
1900
|
+
{
|
|
1901
|
+
table* m_tb;
|
|
1902
|
+
public:
|
|
1903
|
+
worker(table* tb):m_tb(tb){}
|
|
1904
|
+
void run(){m_tb->seekLessThan(false, ROW_LOCK_X);}
|
|
1905
|
+
};
|
|
1906
|
+
/* Getting missing value by lock wait */
|
|
1907
|
+
void testMissingUpdate(database* db)
|
|
1908
|
+
{
|
|
960
1909
|
|
|
961
|
-
// table mode exclusive
|
|
962
|
-
db = database::create();
|
|
963
|
-
tb = openTable(db, TD_OPEN_READONLY, TD_OPEN_EXCLUSIVE);
|
|
964
1910
|
|
|
965
|
-
|
|
1911
|
+
|
|
1912
|
+
table* tb = openTable(db);
|
|
1913
|
+
database* db2 = database::create();
|
|
966
1914
|
db2->connect(makeUri(PROTOCOL, HOSTNAME, DBNAME), true);
|
|
967
1915
|
BOOST_CHECK_MESSAGE(0 == db2->stat(), "connect");
|
|
968
|
-
db2->open(makeUri(PROTOCOL, HOSTNAME, DBNAME, BDFNAME), TYPE_SCHEMA_BDF);
|
|
969
|
-
BOOST_CHECK_MESSAGE(0 == db2->stat(), "open
|
|
970
|
-
|
|
971
|
-
|
|
972
|
-
|
|
973
|
-
|
|
974
|
-
|
|
975
|
-
|
|
976
|
-
|
|
977
|
-
|
|
978
|
-
|
|
979
|
-
|
|
980
|
-
|
|
981
|
-
|
|
982
|
-
|
|
983
|
-
|
|
984
|
-
|
|
985
|
-
|
|
986
|
-
|
|
987
|
-
|
|
988
|
-
|
|
989
|
-
|
|
990
|
-
|
|
991
|
-
|
|
992
|
-
|
|
993
|
-
|
|
994
|
-
|
|
995
|
-
|
|
996
|
-
|
|
997
|
-
|
|
998
|
-
|
|
999
|
-
|
|
1916
|
+
db2->open(makeUri(PROTOCOL, HOSTNAME, DBNAME, BDFNAME), TYPE_SCHEMA_BDF);
|
|
1917
|
+
BOOST_CHECK_MESSAGE(0 == db2->stat(), "db2->open");
|
|
1918
|
+
table* tb2 = db2->openTable(_T("user"));
|
|
1919
|
+
{
|
|
1920
|
+
boost::scoped_ptr<worker> w(new worker(tb2));
|
|
1921
|
+
|
|
1922
|
+
// Inserting target, The InnoDB is good!
|
|
1923
|
+
tb->setFV(fdi_id, 300000);
|
|
1924
|
+
tb2->setFV(fdi_id, 300000);
|
|
1925
|
+
tb->seekLessThan(false, ROW_LOCK_X);
|
|
1926
|
+
BOOST_CHECK_MESSAGE(0 == tb->stat(), "tb->seekLessThan");
|
|
1927
|
+
if (tb->stat() == 0)
|
|
1928
|
+
{
|
|
1929
|
+
// Get lock(X) same record in parallel.
|
|
1930
|
+
boost::scoped_ptr<boost::thread> t(new boost::thread(boost::bind(&worker::run, w.get())));
|
|
1931
|
+
int v = tb->getFVint(fdi_id);
|
|
1932
|
+
tb->setFV(fdi_id, ++v);
|
|
1933
|
+
tb->insert();
|
|
1934
|
+
t->join();
|
|
1935
|
+
BOOST_CHECK_MESSAGE(0 == tb->stat(), "tb->insert");
|
|
1936
|
+
BOOST_CHECK_MESSAGE(0 == tb2->stat(), "tb2->seekLessThan");
|
|
1937
|
+
int v2 = tb2->getFVint(fdi_id);
|
|
1938
|
+
BOOST_CHECK_MESSAGE(v == v2 , "value v = " << v
|
|
1939
|
+
<< " bad = " << v2);
|
|
1940
|
+
tb2->unlock();
|
|
1941
|
+
}
|
|
1942
|
+
|
|
1943
|
+
// Deleting target, The InnoDB is good!
|
|
1944
|
+
tb->setFV(fdi_id, 300000);
|
|
1945
|
+
tb2->setFV(fdi_id, 300000);
|
|
1946
|
+
tb->seekLessThan(false, ROW_LOCK_X);
|
|
1947
|
+
BOOST_CHECK_MESSAGE(0 == tb->stat(), "tb->seekLessThan");
|
|
1948
|
+
if (tb->stat() == 0)
|
|
1949
|
+
{
|
|
1950
|
+
// Get lock(X) same record in parallel.
|
|
1951
|
+
boost::scoped_ptr<boost::thread> t(new boost::thread(boost::bind(&worker::run, w.get())));
|
|
1952
|
+
int v = tb->getFVint(fdi_id);
|
|
1953
|
+
tb->del();
|
|
1954
|
+
t->join();
|
|
1955
|
+
BOOST_CHECK_MESSAGE(0 == tb->stat(), "tb->insert");
|
|
1956
|
+
BOOST_CHECK_MESSAGE(0 == tb2->stat(), "tb2->seekLessThan");
|
|
1957
|
+
int v2 = tb2->getFVint(fdi_id);
|
|
1958
|
+
BOOST_CHECK_MESSAGE(v != v2 , "value v = " << v
|
|
1959
|
+
<< " bad = " << v2);
|
|
1960
|
+
tb2->unlock();
|
|
1961
|
+
}
|
|
1962
|
+
}
|
|
1000
1963
|
tb->release();
|
|
1001
|
-
|
|
1964
|
+
tb2->release();
|
|
1965
|
+
database::destroy(db2);
|
|
1002
1966
|
}
|
|
1003
1967
|
|
|
1004
1968
|
void testInsert2(database* db)
|
|
@@ -1109,7 +2073,7 @@ void testLogin(database* db)
|
|
|
1109
2073
|
database* db2 = database::create();
|
|
1110
2074
|
db2->connect(makeUri(PROTOCOL, HOSTNAME, _T("")), true);
|
|
1111
2075
|
BOOST_CHECK_MESSAGE(
|
|
1112
|
-
0 ==
|
|
2076
|
+
0 == db2->stat(),
|
|
1113
2077
|
"new connection connect db->stat() = " << db->stat());
|
|
1114
2078
|
database::destroy(db2);
|
|
1115
2079
|
|
|
@@ -2015,9 +2979,15 @@ void doTestSF(table* tb)
|
|
|
2015
2979
|
tb->clearBuffer();
|
|
2016
2980
|
|
|
2017
2981
|
tb->setFilter(_T("name = 'あい*'"), 0, 10);
|
|
2982
|
+
|
|
2018
2983
|
BOOST_CHECK_MESSAGE(0 == tb->stat(), "doTestReadSF1");
|
|
2984
|
+
|
|
2019
2985
|
tb->seekFirst();
|
|
2020
2986
|
BOOST_CHECK_MESSAGE(0 == tb->stat(), "doTestReadSF1");
|
|
2987
|
+
/*
|
|
2988
|
+
If this point segmentation fult. Then drop database teststring.
|
|
2989
|
+
*/
|
|
2990
|
+
|
|
2021
2991
|
tb->findNext(false);
|
|
2022
2992
|
BOOST_CHECK_MESSAGE(0 == tb->stat(), "doTestReadSF1");
|
|
2023
2993
|
BOOST_CHECK_MESSAGE(_tstring(_T("あいうえおかきくこ")) ==
|
|
@@ -2139,9 +3109,23 @@ void doTestStringFileter(database* db, int id, const _TCHAR* name,
|
|
|
2139
3109
|
tb->release();
|
|
2140
3110
|
}
|
|
2141
3111
|
|
|
3112
|
+
void testDropDataBaseStr(database* db)
|
|
3113
|
+
{
|
|
3114
|
+
db->open(makeUri(PROTOCOL, HOSTNAME, _T("testString"), BDFNAME), 0, 0);
|
|
3115
|
+
BOOST_CHECK_MESSAGE(0 == db->stat(), "createNewDataBase 1");
|
|
3116
|
+
db->drop();
|
|
3117
|
+
BOOST_CHECK_MESSAGE(0 == db->stat(),
|
|
3118
|
+
"DropDataBaseTestString stat=" << db->stat());
|
|
3119
|
+
}
|
|
3120
|
+
|
|
2142
3121
|
void testStringFileter(database* db)
|
|
2143
3122
|
{
|
|
2144
3123
|
db->create(makeUri(PROTOCOL, HOSTNAME, _T("testString"), BDFNAME));
|
|
3124
|
+
if (db->stat() == STATUS_TABLE_EXISTS_ERROR)
|
|
3125
|
+
{
|
|
3126
|
+
testDropDataBaseStr(db);
|
|
3127
|
+
db->create(makeUri(PROTOCOL, HOSTNAME, _T("testString"), BDFNAME));
|
|
3128
|
+
}
|
|
2145
3129
|
BOOST_CHECK_MESSAGE(0 == db->stat(), "createNewDataBase");
|
|
2146
3130
|
|
|
2147
3131
|
db->open(makeUri(PROTOCOL, HOSTNAME, _T("testString"), BDFNAME), 0, 0);
|
|
@@ -2160,14 +3144,7 @@ void testStringFileter(database* db)
|
|
|
2160
3144
|
db->close();
|
|
2161
3145
|
}
|
|
2162
3146
|
|
|
2163
|
-
|
|
2164
|
-
{
|
|
2165
|
-
db->open(makeUri(PROTOCOL, HOSTNAME, _T("testString"), BDFNAME), 0, 0);
|
|
2166
|
-
BOOST_CHECK_MESSAGE(0 == db->stat(), "createNewDataBase 1");
|
|
2167
|
-
db->drop();
|
|
2168
|
-
BOOST_CHECK_MESSAGE(0 == db->stat(),
|
|
2169
|
-
"DropDataBaseTestString stat=" << db->stat());
|
|
2170
|
-
}
|
|
3147
|
+
|
|
2171
3148
|
// ------------------------------------------------------------------------
|
|
2172
3149
|
|
|
2173
3150
|
_TCHAR dbNmae[50] = { _T("テスト") };
|
|
@@ -2331,7 +3308,7 @@ void testResultField(database* db)
|
|
|
2331
3308
|
BOOST_CHECK_MESSAGE(rf.len == 33, " resultField.setParam");
|
|
2332
3309
|
BOOST_CHECK_MESSAGE(rf.pos == 4, " resultField.setParam");
|
|
2333
3310
|
|
|
2334
|
-
size_t len = rf.
|
|
3311
|
+
size_t len = rf.size();
|
|
2335
3312
|
BOOST_CHECK_MESSAGE(len == 4, " resultField.writeBuffer");
|
|
2336
3313
|
tb->release();
|
|
2337
3314
|
}
|
|
@@ -2344,7 +3321,7 @@ void testResultDef()
|
|
|
2344
3321
|
BOOST_CHECK_MESSAGE(rd.maxRows == 0, " resultDef.maxRows");
|
|
2345
3322
|
BOOST_CHECK_MESSAGE(rd.fieldCount == 0, " resultDef.fieldCount");
|
|
2346
3323
|
|
|
2347
|
-
size_t len = rd.
|
|
3324
|
+
size_t len = rd.size();
|
|
2348
3325
|
BOOST_CHECK_MESSAGE(len == 4, " resultDef.writeBuffer");
|
|
2349
3326
|
}
|
|
2350
3327
|
|
|
@@ -2362,7 +3339,7 @@ void testLogic(database* db)
|
|
|
2362
3339
|
BOOST_CHECK_MESSAGE(lc.opr == eCend, " logic.opr");
|
|
2363
3340
|
BOOST_CHECK_MESSAGE(strcmp((char*)lc.data, "abc") == 0, " logic.data");
|
|
2364
3341
|
|
|
2365
|
-
|
|
3342
|
+
int len = lc.size();
|
|
2366
3343
|
BOOST_CHECK_MESSAGE(len == 7 + 33, " logic.writeBuffer");
|
|
2367
3344
|
|
|
2368
3345
|
// compField invalid filed name
|
|
@@ -2379,7 +3356,7 @@ void testLogic(database* db)
|
|
|
2379
3356
|
" logic.logType compField");
|
|
2380
3357
|
BOOST_CHECK_MESSAGE(lc.opr == eCend, " logic.opr");
|
|
2381
3358
|
BOOST_CHECK_MESSAGE(*((short*)lc.data) == 0, " logic.data");
|
|
2382
|
-
len = lc.
|
|
3359
|
+
len = lc.size();
|
|
2383
3360
|
BOOST_CHECK_MESSAGE(len == 7 + 2, " logic.writeBuffer");
|
|
2384
3361
|
|
|
2385
3362
|
// invalid filed name
|
|
@@ -2395,14 +3372,14 @@ void testLogic(database* db)
|
|
|
2395
3372
|
BOOST_CHECK_MESSAGE(lc.opr == eCend, " logic.opr");
|
|
2396
3373
|
BOOST_CHECK_MESSAGE(strcmp((char*)lc.data, "abc") == 0, " logic.data");
|
|
2397
3374
|
|
|
2398
|
-
len = lc.
|
|
3375
|
+
len = lc.size();
|
|
2399
3376
|
BOOST_CHECK_MESSAGE(len == 7 + 3, " logic.writeBuffer");
|
|
2400
3377
|
|
|
2401
3378
|
lc.setParam(tb, _T("name"), _T("="), _T("漢字*"), eCend, false);
|
|
2402
3379
|
BOOST_CHECK_MESSAGE(strcmp((char*)lc.data, "漢字") == 0, " logic.data");
|
|
2403
3380
|
|
|
2404
|
-
len = lc.
|
|
2405
|
-
BOOST_CHECK_MESSAGE(len == 7 + (_tcslen(_T("漢字")) * sizeof(_TCHAR)),
|
|
3381
|
+
len = lc.size();
|
|
3382
|
+
BOOST_CHECK_MESSAGE(len == (int)(7 + (_tcslen(_T("漢字")) * sizeof(_TCHAR))),
|
|
2406
3383
|
" logic.writeBuffer len =" << len);
|
|
2407
3384
|
|
|
2408
3385
|
// combine
|
|
@@ -2451,8 +3428,16 @@ void testLogic(database* db)
|
|
|
2451
3428
|
|
|
2452
3429
|
BOOST_CHECK_MESSAGE(lc.opr == eCend, " logic joinAfter");
|
|
2453
3430
|
|
|
3431
|
+
// placeHolder
|
|
3432
|
+
lc.setParam(tb, _T("name"), _T("="), _T("?"), eCand);
|
|
3433
|
+
BOOST_CHECK_MESSAGE(lc.placeHolder == true, " logic placeHolder");
|
|
3434
|
+
|
|
3435
|
+
lc.setValue(tb, _T("abc*"));
|
|
3436
|
+
BOOST_CHECK_MESSAGE(strcmp((const char*)lc.data, "abc") == 0, "logic setValue");
|
|
3437
|
+
BOOST_CHECK_MESSAGE(lc.len == 3, "logic setValue");
|
|
3438
|
+
|
|
2454
3439
|
header hd;
|
|
2455
|
-
len = hd.
|
|
3440
|
+
len = hd.size();
|
|
2456
3441
|
BOOST_CHECK_MESSAGE(len == 8, " header.writeBuffer");
|
|
2457
3442
|
tb->release();
|
|
2458
3443
|
}
|
|
@@ -2773,7 +3758,7 @@ void teetNewDelete(database* db)
|
|
|
2773
3758
|
delete r; // All OK
|
|
2774
3759
|
}
|
|
2775
3760
|
|
|
2776
|
-
//
|
|
3761
|
+
//activeTable releaseTable
|
|
2777
3762
|
activeTable* at = new activeTable(db, _T("user"));
|
|
2778
3763
|
at->releaseTable();
|
|
2779
3764
|
BOOST_CHECK_MESSAGE(at->table() == NULL, " activeTable::releaseTable");
|
|
@@ -2795,9 +3780,7 @@ void testJoin(database* db)
|
|
|
2795
3780
|
#endif
|
|
2796
3781
|
|
|
2797
3782
|
activeTable atu(db, _T("user"));
|
|
2798
|
-
|
|
2799
3783
|
activeTable atg(db, _T("groups"));
|
|
2800
|
-
|
|
2801
3784
|
activeTable ate(db, _T("extention"));
|
|
2802
3785
|
recordset rs;
|
|
2803
3786
|
query q;
|
|
@@ -2806,14 +3789,16 @@ void testJoin(database* db)
|
|
|
2806
3789
|
q.select(_T("id"), _T("name"), _T("group"))
|
|
2807
3790
|
.where(_T("id"), _T("<="), 15000);
|
|
2808
3791
|
atu.index(0).keyValue(1).read(rs, q);
|
|
2809
|
-
BOOST_CHECK_MESSAGE(rs.size() == 15000, " rs.size()
|
|
3792
|
+
BOOST_CHECK_MESSAGE(rs.size() == 15000, " rs.size() 15000 bad = " << rs.size());
|
|
3793
|
+
BOOST_CHECK_MESSAGE(rs.fieldDefs()->size() == 3, " rs.fieldDefs()->size() 3 bad = " << rs.fieldDefs()->size());
|
|
2810
3794
|
|
|
2811
3795
|
// Join extention::comment
|
|
2812
3796
|
q.reset();
|
|
2813
3797
|
ate.index(0).join(
|
|
2814
3798
|
rs, q.select(_T("comment")).optimize(queryBase::joinHasOneOrHasMany),
|
|
2815
3799
|
_T("id"));
|
|
2816
|
-
BOOST_CHECK_MESSAGE(rs.size() == 15000, "join rs.size()
|
|
3800
|
+
BOOST_CHECK_MESSAGE(rs.size() == 15000, "join rs.size() 15000 bad = " << rs.size());
|
|
3801
|
+
BOOST_CHECK_MESSAGE(rs.fieldDefs()->size() == 4, " rs.fieldDefs()->size() 4 bad = " << rs.fieldDefs()->size());
|
|
2817
3802
|
|
|
2818
3803
|
// test reverse
|
|
2819
3804
|
|
|
@@ -2941,6 +3926,282 @@ void testJoin(database* db)
|
|
|
2941
3926
|
groupQuery* q3 = groupQuery::create();
|
|
2942
3927
|
q3->keyField(_T("group"), _T("id"));
|
|
2943
3928
|
q3->release();
|
|
3929
|
+
}
|
|
3930
|
+
|
|
3931
|
+
void testPrepareJoin(database* db)
|
|
3932
|
+
{
|
|
3933
|
+
#ifdef LINUX
|
|
3934
|
+
const char* fd_name = "名前";
|
|
3935
|
+
#else
|
|
3936
|
+
#ifdef _UNICODE
|
|
3937
|
+
const wchar_t fd_name[] = { L"名前" };
|
|
3938
|
+
#else
|
|
3939
|
+
char fd_name[30];
|
|
3940
|
+
WideCharToMultiByte(CP_UTF8, 0, L"名前", -1, fd_name, 30, NULL, NULL);
|
|
3941
|
+
#endif
|
|
3942
|
+
#endif
|
|
3943
|
+
|
|
3944
|
+
activeTable atu(db, _T("user"));
|
|
3945
|
+
atu.alias(fd_name, _T("name"));
|
|
3946
|
+
|
|
3947
|
+
activeTable atg(db, _T("groups"));
|
|
3948
|
+
atg.alias(_T("name"), _T("group_name"));
|
|
3949
|
+
|
|
3950
|
+
activeTable ate(db, _T("extention"));
|
|
3951
|
+
recordset rs;
|
|
3952
|
+
query q;
|
|
3953
|
+
|
|
3954
|
+
|
|
3955
|
+
q.select(_T("id"), _T("name"), _T("group")).where(_T("id"), _T("<="), _T("?"));
|
|
3956
|
+
pq_handle pq = atu.prepare(q);
|
|
3957
|
+
atu.index(0).keyValue(1).read(rs, pq, 15000);
|
|
3958
|
+
BOOST_CHECK_MESSAGE(rs.size() == 15000, " rs.size() 15000 bad = " << rs.size());
|
|
3959
|
+
BOOST_CHECK_MESSAGE(rs.fieldDefs()->size() == 3, " rs.fieldDefs()->size() 3 bad = " << rs.fieldDefs()->size());
|
|
3960
|
+
|
|
3961
|
+
// Join extention::comment
|
|
3962
|
+
q.reset().select(_T("comment")).optimize(queryBase::joinHasOneOrHasMany);
|
|
3963
|
+
pq = ate.prepare(q);
|
|
3964
|
+
ate.index(0).join(rs, pq, _T("id"));
|
|
3965
|
+
BOOST_CHECK_MESSAGE(rs.size() == 15000, "join rs.size() 15000 bad = " << rs.size());
|
|
3966
|
+
BOOST_CHECK_MESSAGE(rs.fieldDefs()->size() == 4, " rs.fieldDefs()->size() 4 bad = " << rs.fieldDefs()->size());
|
|
3967
|
+
|
|
3968
|
+
// test reverse
|
|
3969
|
+
row& last = rs.reverse().first();
|
|
3970
|
+
BOOST_CHECK_MESSAGE(last[_T("id")].i() == 15000, "last field id == 15000");
|
|
3971
|
+
BOOST_CHECK_MESSAGE(_tstring(last[_T("comment")].c_str()) ==
|
|
3972
|
+
_tstring(_T("15000 comment")),
|
|
3973
|
+
"last field comment");
|
|
3974
|
+
// Join group::name
|
|
3975
|
+
q.reset().select(_T("group_name"));
|
|
3976
|
+
pq = atg.prepare(q);
|
|
3977
|
+
atg.index(0).join(rs, pq, _T("group"));
|
|
3978
|
+
BOOST_CHECK_MESSAGE(rs.size() == 15000, "join2 rs.size()== 15000");
|
|
3979
|
+
row& first = rs.last();
|
|
3980
|
+
|
|
3981
|
+
BOOST_CHECK_MESSAGE(first[_T("id")].i() == 1, "first field id == 1");
|
|
3982
|
+
BOOST_CHECK_MESSAGE(_tstring(first[_T("comment")].c_str()) ==
|
|
3983
|
+
_tstring(_T("1 comment")),
|
|
3984
|
+
"first field comment");
|
|
3985
|
+
|
|
3986
|
+
BOOST_CHECK_MESSAGE(
|
|
3987
|
+
_tstring(first[_T("group_name")].c_str()) == _tstring(_T("1 group")),
|
|
3988
|
+
"first field group_name " << string(first[_T("group_name")].a_str()));
|
|
3989
|
+
BOOST_CHECK_MESSAGE(
|
|
3990
|
+
_tstring(first[_T("group_name")].c_str()) == _tstring(_T("1 group")),
|
|
3991
|
+
"first field group_name " << string(first[_T("group_name")].a_str()));
|
|
3992
|
+
// row_ptr row = rs[15000 - 9];
|
|
3993
|
+
row& rec = rs[15000 - 9];
|
|
3994
|
+
BOOST_CHECK_MESSAGE(
|
|
3995
|
+
_tstring(rec[_T("group_name")].c_str()) == _tstring(_T("4 group")),
|
|
3996
|
+
"group_name = 4 group " << string((rec)[_T("group_name")].a_str()));
|
|
3997
|
+
|
|
3998
|
+
}
|
|
3999
|
+
|
|
4000
|
+
void testServerPrepareJoin(database* db)
|
|
4001
|
+
{
|
|
4002
|
+
#ifdef LINUX
|
|
4003
|
+
const char* fd_name = "名前";
|
|
4004
|
+
#else
|
|
4005
|
+
#ifdef _UNICODE
|
|
4006
|
+
const wchar_t fd_name[] = { L"名前" };
|
|
4007
|
+
#else
|
|
4008
|
+
char fd_name[30];
|
|
4009
|
+
WideCharToMultiByte(CP_UTF8, 0, L"名前", -1, fd_name, 30, NULL, NULL);
|
|
4010
|
+
#endif
|
|
4011
|
+
#endif
|
|
4012
|
+
|
|
4013
|
+
activeTable atu(db, _T("user"));
|
|
4014
|
+
activeTable atg(db, _T("groups"));
|
|
4015
|
+
activeTable ate(db, _T("extention"));
|
|
4016
|
+
atu.alias(fd_name, _T("name"));
|
|
4017
|
+
atg.alias(_T("name"), _T("group_name"));
|
|
4018
|
+
query q;
|
|
4019
|
+
q.select(_T("id"), _T("name"), _T("group"))
|
|
4020
|
+
.where(_T("id"), _T("<="), _T("?"));
|
|
4021
|
+
pq_handle stmt1 = atu.prepare(q, true);
|
|
4022
|
+
BOOST_CHECK_MESSAGE(stmt1 != NULL, " stmt1");
|
|
4023
|
+
|
|
4024
|
+
q.reset().select(_T("comment")).optimize(queryBase::joinHasOneOrHasMany);
|
|
4025
|
+
pq_handle stmt2 = ate.prepare(q, true);
|
|
4026
|
+
BOOST_CHECK_MESSAGE(stmt2 != NULL, " stmt2");
|
|
4027
|
+
|
|
4028
|
+
q.reset().select(_T("group_name"));
|
|
4029
|
+
pq_handle stmt3 = atg.prepare(q, true);
|
|
4030
|
+
BOOST_CHECK_MESSAGE(stmt3 != NULL, " stmt3");
|
|
4031
|
+
|
|
4032
|
+
recordset rs;
|
|
4033
|
+
atu.index(0).keyValue(1).read(rs, stmt1, 15000);
|
|
4034
|
+
BOOST_CHECK_MESSAGE(rs.size() == 15000, " rs.size()== 15000 bad " << rs.size());
|
|
4035
|
+
|
|
4036
|
+
// Join extention::comment
|
|
4037
|
+
ate.index(0).join(rs, stmt2, _T("id"));
|
|
4038
|
+
BOOST_CHECK_MESSAGE(rs.size() == 15000, "join rs.size()== 15000");
|
|
4039
|
+
|
|
4040
|
+
// test reverse
|
|
4041
|
+
row& last = rs.reverse().first();
|
|
4042
|
+
BOOST_CHECK_MESSAGE(last[_T("id")].i() == 15000, "last field id == 15000");
|
|
4043
|
+
BOOST_CHECK_MESSAGE(_tstring(last[_T("comment")].c_str()) ==
|
|
4044
|
+
_tstring(_T("15000 comment")),
|
|
4045
|
+
"last field comment");
|
|
4046
|
+
|
|
4047
|
+
// Join group::name
|
|
4048
|
+
atg.index(0).join(rs, stmt3, _T("group"));
|
|
4049
|
+
BOOST_CHECK_MESSAGE(rs.size() == 15000, "join2 rs.size()== 15000");
|
|
4050
|
+
row& first = rs.last();
|
|
4051
|
+
|
|
4052
|
+
BOOST_CHECK_MESSAGE(first[_T("id")].i() == 1, "first field id == 1");
|
|
4053
|
+
BOOST_CHECK_MESSAGE(_tstring(first[_T("comment")].c_str()) ==
|
|
4054
|
+
_tstring(_T("1 comment")),
|
|
4055
|
+
"first field comment");
|
|
4056
|
+
|
|
4057
|
+
BOOST_CHECK_MESSAGE(
|
|
4058
|
+
_tstring(first[_T("group_name")].c_str()) == _tstring(_T("1 group")),
|
|
4059
|
+
"first field group_name " << string(first[_T("group_name")].a_str()));
|
|
4060
|
+
BOOST_CHECK_MESSAGE(
|
|
4061
|
+
_tstring(first[_T("group_name")].c_str()) == _tstring(_T("1 group")),
|
|
4062
|
+
"first field group_name " << string(first[_T("group_name")].a_str()));
|
|
4063
|
+
// row_ptr row = rs[15000 - 9];
|
|
4064
|
+
row& rec = rs[15000 - 9];
|
|
4065
|
+
BOOST_CHECK_MESSAGE(
|
|
4066
|
+
_tstring(rec[_T("group_name")].c_str()) == _tstring(_T("4 group")),
|
|
4067
|
+
"group_name = 4 group " << string((rec)[_T("group_name")].a_str()));
|
|
4068
|
+
|
|
4069
|
+
// Test orderby
|
|
4070
|
+
rs.orderBy(_T("group_name"));
|
|
4071
|
+
// rec = rs[(size_t)0];
|
|
4072
|
+
BOOST_CHECK_MESSAGE(_tstring(rs[(size_t)0][_T("group_name")].c_str()) ==
|
|
4073
|
+
_tstring(_T("1 group")),
|
|
4074
|
+
"group_name = 1 group "
|
|
4075
|
+
<< string(rs[(size_t)0][_T("group_name")].a_str()));
|
|
4076
|
+
|
|
4077
|
+
sortFields orderRv;
|
|
4078
|
+
orderRv.add(_T("group_name"), false);
|
|
4079
|
+
rs.orderBy(orderRv);
|
|
4080
|
+
|
|
4081
|
+
sortFields order;
|
|
4082
|
+
order.add(_T("group_name"), true);
|
|
4083
|
+
rs.orderBy(order);
|
|
4084
|
+
BOOST_CHECK_MESSAGE(_tstring(rs[(size_t)0][_T("group_name")].c_str()) ==
|
|
4085
|
+
_tstring(_T("1 group")),
|
|
4086
|
+
"group_name = 1 group "
|
|
4087
|
+
<< string(rs[(size_t)0][_T("group_name")].a_str()));
|
|
4088
|
+
|
|
4089
|
+
//All fields
|
|
4090
|
+
rs.clear();
|
|
4091
|
+
q.reset().all();
|
|
4092
|
+
q.where(_T("id"), _T("<="), _T("?"));
|
|
4093
|
+
stmt1 = atu.prepare(q, true);
|
|
4094
|
+
atu.keyValue(1).read(rs, stmt1, 15000);
|
|
4095
|
+
BOOST_CHECK_MESSAGE(rs.size() == 15000, "read rs.size()== 15000");
|
|
4096
|
+
if (rs.size() == 15000)
|
|
4097
|
+
{
|
|
4098
|
+
for (int i=0;i<15000;++i)
|
|
4099
|
+
BOOST_CHECK_MESSAGE(rs[i][_T("id")].i() == i+1, "All fields field Value");
|
|
4100
|
+
}
|
|
4101
|
+
|
|
4102
|
+
ate.join(rs, stmt2, _T("id"));
|
|
4103
|
+
BOOST_CHECK_MESSAGE(rs.size() == 15000, "join rs.size()== 15000");
|
|
4104
|
+
atg.join(rs, stmt3, _T("group"));
|
|
4105
|
+
BOOST_CHECK_MESSAGE(rs.size() == 15000, "join2 rs.size()== 15000");
|
|
4106
|
+
|
|
4107
|
+
// OuterJoin
|
|
4108
|
+
#define NO_RECORD_ID 5
|
|
4109
|
+
table_ptr tb = ate.table();
|
|
4110
|
+
tb->setFV(_T("id"), NO_RECORD_ID);
|
|
4111
|
+
tb->seek();
|
|
4112
|
+
if (tb->stat() == 0)
|
|
4113
|
+
tb->del();
|
|
4114
|
+
BOOST_CHECK_MESSAGE(tb->stat() == 0, "ate delete id = 5");
|
|
4115
|
+
q.reset().select(_T("comment"), _T("blob")).optimize(queryBase::joinHasOneOrHasMany);
|
|
4116
|
+
stmt2 = ate.prepare(q, true);
|
|
4117
|
+
|
|
4118
|
+
// Join is remove record(s) no join target record.
|
|
4119
|
+
rs.clear();
|
|
4120
|
+
atu.keyValue(1).read(rs, stmt1, 15000);
|
|
4121
|
+
ate.join(rs, stmt2, _T("id"));
|
|
4122
|
+
BOOST_CHECK_MESSAGE(rs.size() == 14999, "join rs.size()== 14999");
|
|
4123
|
+
BOOST_CHECK_MESSAGE(rs[NO_RECORD_ID-1][_T("comment")].i() == NO_RECORD_ID+1, "row of 5 : '6 comment'");
|
|
4124
|
+
const _TCHAR* vs = rs[NO_RECORD_ID-1][_T("blob")].c_str();
|
|
4125
|
+
bool ret = _tcscmp(vs, _T("6 blob")) == 0;
|
|
4126
|
+
BOOST_CHECK_MESSAGE(ret == true, "row of 5 : '6 blob'" );
|
|
4127
|
+
|
|
4128
|
+
// OuterJoin is no remove record(s) no join target record.
|
|
4129
|
+
rs.clear();
|
|
4130
|
+
atu.keyValue(1).read(rs, stmt1, 15000);
|
|
4131
|
+
ate.outerJoin(rs, stmt2, _T("id"));
|
|
4132
|
+
BOOST_CHECK_MESSAGE(rs.size() == 15000, "outerJoin rs.size()== 15000");
|
|
4133
|
+
atg.outerJoin(rs, stmt3, _T("group"));
|
|
4134
|
+
BOOST_CHECK_MESSAGE(rs.size() == 15000, "join2 rs.size()== 15000");
|
|
4135
|
+
|
|
4136
|
+
BOOST_CHECK_MESSAGE(rs[NO_RECORD_ID-1].isInvalidRecord() == true, "outerJoin isInvalidRecord");
|
|
4137
|
+
BOOST_CHECK_MESSAGE(rs[NO_RECORD_ID][_T("comment")].i() == NO_RECORD_ID+1, "row of 6 = '6 comment'");
|
|
4138
|
+
vs = rs[NO_RECORD_ID][_T("blob")].c_str();
|
|
4139
|
+
ret = _tcscmp(vs, _T("6 blob")) == 0;
|
|
4140
|
+
BOOST_CHECK_MESSAGE(ret == true, "row of 6 = '6 blob'");
|
|
4141
|
+
|
|
4142
|
+
// OuterJoin All Join fields
|
|
4143
|
+
q.reset().optimize(queryBase::joinHasOneOrHasMany).all();
|
|
4144
|
+
stmt2 = ate.prepare(q, true);
|
|
4145
|
+
rs.clear();
|
|
4146
|
+
atu.keyValue(1).read(rs, stmt1, 15000);
|
|
4147
|
+
ate.outerJoin(rs, stmt2, _T("id"));
|
|
4148
|
+
BOOST_CHECK_MESSAGE(rs.size() == 15000, "outerJoin rs.size()== 15000");
|
|
4149
|
+
BOOST_CHECK_MESSAGE(rs[NO_RECORD_ID-1].isInvalidRecord() == true, "outerJoin isInvalidRecord");
|
|
4150
|
+
BOOST_CHECK_MESSAGE(rs[NO_RECORD_ID][_T("comment")].i() == NO_RECORD_ID+1, "row of 6 = '6 comment'");
|
|
4151
|
+
vs = rs[NO_RECORD_ID][_T("blob")].c_str();
|
|
4152
|
+
ret = _tcscmp(vs, _T("6 blob")) == 0;
|
|
4153
|
+
BOOST_CHECK_MESSAGE(ret == true, "row of 6 = '6 blob'");
|
|
4154
|
+
|
|
4155
|
+
// Test clone blob field
|
|
4156
|
+
recordset& rs2 = *rs.clone();
|
|
4157
|
+
BOOST_CHECK_MESSAGE(rs2.size() == 15000, "outerJoin rs2.size()== 15000");
|
|
4158
|
+
BOOST_CHECK_MESSAGE(rs2[NO_RECORD_ID-1].isInvalidRecord() == true, "outerJoin isInvalidRecord");
|
|
4159
|
+
BOOST_CHECK_MESSAGE(rs2[NO_RECORD_ID][_T("comment")].i() == NO_RECORD_ID+1, "row of 6 = '6 comment'");
|
|
4160
|
+
vs = rs2[NO_RECORD_ID][_T("blob")].c_str();
|
|
4161
|
+
ret = _tcscmp(vs, _T("6 blob")) == 0;
|
|
4162
|
+
BOOST_CHECK_MESSAGE(ret == true, "row of 6 = '6 blob'");
|
|
4163
|
+
|
|
4164
|
+
|
|
4165
|
+
|
|
4166
|
+
|
|
4167
|
+
//hasManyJoin inner
|
|
4168
|
+
rs.clear();
|
|
4169
|
+
q.reset().reject(0xFFFF).limit(0).all();
|
|
4170
|
+
atg.keyValue(1).read(rs, q);
|
|
4171
|
+
BOOST_CHECK_MESSAGE(rs.size() == 100, "hasManyJoin rs.size()== 100");
|
|
4172
|
+
q.all().optimize(queryBase::joinHasOneOrHasMany);
|
|
4173
|
+
atu.index(1).join(rs, q, _T("code"));
|
|
4174
|
+
BOOST_CHECK_MESSAGE(rs.size() == 20000, "hasManyJoin rs.size()== 20000");
|
|
4175
|
+
|
|
4176
|
+
//hasManyJoin outer
|
|
4177
|
+
rs.clear();
|
|
4178
|
+
q.reset().reject(0xFFFF).limit(0).all();
|
|
4179
|
+
atg.keyValue(1).read(rs, q);
|
|
4180
|
+
BOOST_CHECK_MESSAGE(rs.size() == 100, "hasManyJoin rs.size()== 100");
|
|
4181
|
+
q.all().optimize(queryBase::joinHasOneOrHasMany);
|
|
4182
|
+
atu.index(1).outerJoin(rs, q, _T("code"));
|
|
4183
|
+
BOOST_CHECK_MESSAGE(rs.size() == 20095, "hasManyJoin rs.size()== 20095");
|
|
4184
|
+
|
|
4185
|
+
|
|
4186
|
+
// restore record
|
|
4187
|
+
tb->clearBuffer();
|
|
4188
|
+
tb->setFV(_T("id"), NO_RECORD_ID);
|
|
4189
|
+
tb->setFV(_T("comment"), _T("5 comment"));
|
|
4190
|
+
tb->setFV(_T("blob"), _T("5 blob"));
|
|
4191
|
+
tb->insert();
|
|
4192
|
+
BOOST_CHECK_MESSAGE(tb->stat() == 0, "ate insert id = 5");
|
|
4193
|
+
if (tb->stat())
|
|
4194
|
+
{
|
|
4195
|
+
atu.release();
|
|
4196
|
+
atg.release();
|
|
4197
|
+
ate.release();
|
|
4198
|
+
db->drop();
|
|
4199
|
+
}
|
|
4200
|
+
|
|
4201
|
+
|
|
4202
|
+
|
|
4203
|
+
|
|
4204
|
+
|
|
2944
4205
|
}
|
|
2945
4206
|
|
|
2946
4207
|
void testWirtableRecord(database* db)
|
|
@@ -3021,9 +4282,37 @@ void testDbPool()
|
|
|
3021
4282
|
|
|
3022
4283
|
connectParams pm(PROTOCOL, HOSTNAME, _T("querytest"), DBNAME);
|
|
3023
4284
|
poolMgr.use(&pm);
|
|
4285
|
+
BOOST_CHECK_MESSAGE(1 == poolMgr.usingCount(), "usingCount 1");
|
|
3024
4286
|
poolMgr.use(&pm);
|
|
4287
|
+
BOOST_CHECK_MESSAGE(2 == poolMgr.usingCount(), "usingCount 2");
|
|
3025
4288
|
poolMgr.use(&pm);
|
|
4289
|
+
BOOST_CHECK_MESSAGE(3 == poolMgr.usingCount(), "usingCount 3");
|
|
3026
4290
|
poolMgr.unUse();
|
|
4291
|
+
BOOST_CHECK_MESSAGE(0 == poolMgr.usingCount(), "usingCount 0");
|
|
4292
|
+
|
|
4293
|
+
//snapshot method
|
|
4294
|
+
{
|
|
4295
|
+
poolMgr.use(&pm);
|
|
4296
|
+
table_ptr tb2 = openTable(poolMgr.db(), _T("user"));
|
|
4297
|
+
|
|
4298
|
+
poolMgr.use(&pm);
|
|
4299
|
+
table_ptr tb = openTable(poolMgr.db(), _T("user"));
|
|
4300
|
+
|
|
4301
|
+
|
|
4302
|
+
poolMgr.beginSnapshot(MULTILOCK_GAP_SHARE);
|
|
4303
|
+
tb->seekFirst();
|
|
4304
|
+
BOOST_CHECK_MESSAGE(0 == tb->stat(), "tb->seekFirst");
|
|
4305
|
+
|
|
4306
|
+
tb2->seekFirst(ROW_LOCK_X);
|
|
4307
|
+
BOOST_CHECK_MESSAGE(STATUS_LOCK_ERROR == tb2->stat(),
|
|
4308
|
+
"tb2->seekFirst tb2 stat = " << tb2->stat());
|
|
4309
|
+
|
|
4310
|
+
poolMgr.endSnapshot();
|
|
4311
|
+
|
|
4312
|
+
tb2->seekFirst(ROW_LOCK_X);
|
|
4313
|
+
BOOST_CHECK_MESSAGE(0 == tb2->stat(), "tb2->seekFirst");
|
|
4314
|
+
}
|
|
4315
|
+
poolMgr.endSnapshot();
|
|
3027
4316
|
poolMgr.reset(0);
|
|
3028
4317
|
}
|
|
3029
4318
|
|
|
@@ -3062,6 +4351,8 @@ BOOST_FIXTURE_TEST_CASE(findNext, fixture)
|
|
|
3062
4351
|
{
|
|
3063
4352
|
testFindNext(db());
|
|
3064
4353
|
testFindIn(db());
|
|
4354
|
+
testPrepare(db());
|
|
4355
|
+
testPrepareServer(db());
|
|
3065
4356
|
}
|
|
3066
4357
|
|
|
3067
4358
|
BOOST_FIXTURE_TEST_CASE(getPercentage, fixture)
|
|
@@ -3121,7 +4412,7 @@ BOOST_FIXTURE_TEST_CASE(update, fixture)
|
|
|
3121
4412
|
|
|
3122
4413
|
BOOST_FIXTURE_TEST_CASE(snapShot, fixture)
|
|
3123
4414
|
{
|
|
3124
|
-
|
|
4415
|
+
testSnapshot(db());
|
|
3125
4416
|
}
|
|
3126
4417
|
|
|
3127
4418
|
BOOST_FIXTURE_TEST_CASE(conflict, fixture)
|
|
@@ -3129,9 +4420,24 @@ BOOST_FIXTURE_TEST_CASE(conflict, fixture)
|
|
|
3129
4420
|
testConflict(db());
|
|
3130
4421
|
}
|
|
3131
4422
|
|
|
4423
|
+
BOOST_FIXTURE_TEST_CASE(transactionLockRepeatable, fixture)
|
|
4424
|
+
{
|
|
4425
|
+
testTransactionLockRepeatable(db());
|
|
4426
|
+
}
|
|
4427
|
+
|
|
3132
4428
|
BOOST_FIXTURE_TEST_CASE(transactionLock, fixture)
|
|
3133
4429
|
{
|
|
3134
|
-
|
|
4430
|
+
testTransactionLockReadCommited(db());
|
|
4431
|
+
}
|
|
4432
|
+
|
|
4433
|
+
BOOST_FIXTURE_TEST_CASE(RecordLock, fixture)
|
|
4434
|
+
{
|
|
4435
|
+
testRecordLock(db());
|
|
4436
|
+
}
|
|
4437
|
+
|
|
4438
|
+
BOOST_FIXTURE_TEST_CASE(MultiDatabase, fixture)
|
|
4439
|
+
{
|
|
4440
|
+
testMultiDatabase(db());
|
|
3135
4441
|
}
|
|
3136
4442
|
|
|
3137
4443
|
BOOST_AUTO_TEST_CASE(Exclusive)
|
|
@@ -3139,6 +4445,11 @@ BOOST_AUTO_TEST_CASE(Exclusive)
|
|
|
3139
4445
|
testExclusive();
|
|
3140
4446
|
}
|
|
3141
4447
|
|
|
4448
|
+
BOOST_FIXTURE_TEST_CASE(MissingUpdate, fixture)
|
|
4449
|
+
{
|
|
4450
|
+
testMissingUpdate(db());
|
|
4451
|
+
}
|
|
4452
|
+
|
|
3142
4453
|
BOOST_FIXTURE_TEST_CASE(insert2, fixture)
|
|
3143
4454
|
{
|
|
3144
4455
|
testInsert2(db());
|
|
@@ -3234,7 +4545,7 @@ BOOST_FIXTURE_TEST_CASE(dropDataBaseVar, fixture)
|
|
|
3234
4545
|
|
|
3235
4546
|
BOOST_AUTO_TEST_SUITE_END()
|
|
3236
4547
|
// ------------------------------------------------------------------------
|
|
3237
|
-
|
|
4548
|
+
#ifdef TDAP
|
|
3238
4549
|
// ------------------------------------------------------------------------
|
|
3239
4550
|
BOOST_AUTO_TEST_SUITE(filter)
|
|
3240
4551
|
|
|
@@ -3250,7 +4561,7 @@ BOOST_FIXTURE_TEST_CASE(dropDataBaseStr, fixture)
|
|
|
3250
4561
|
|
|
3251
4562
|
BOOST_AUTO_TEST_SUITE_END()
|
|
3252
4563
|
// ------------------------------------------------------------------------
|
|
3253
|
-
|
|
4564
|
+
#endif
|
|
3254
4565
|
// ------------------------------------------------------------------------
|
|
3255
4566
|
BOOST_AUTO_TEST_SUITE(kanjiSchema)
|
|
3256
4567
|
|
|
@@ -3307,6 +4618,8 @@ BOOST_FIXTURE_TEST_CASE(new_delete, fixtureQuery)
|
|
|
3307
4618
|
BOOST_FIXTURE_TEST_CASE(join, fixtureQuery)
|
|
3308
4619
|
{
|
|
3309
4620
|
testJoin(db());
|
|
4621
|
+
testPrepareJoin(db());
|
|
4622
|
+
testServerPrepareJoin(db());
|
|
3310
4623
|
testWirtableRecord(db());
|
|
3311
4624
|
}
|
|
3312
4625
|
|