transactd 2.0.1-x64-mswin64-100 → 2.1.0-x64-mswin64-100
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/2.0/transactd.so +0 -0
- data/bin/2.1/transactd.so +0 -0
- data/bin/common/tdclc_64_2_1.dll +0 -0
- data/bin/common/tdclcpp_vc100_64mr_2_1.dll +0 -0
- data/source/bzs/test/tdclrb/bench_tdclcpp.rb +12 -14
- data/source/bzs/test/tdclrb/transactd_spec.rb +1127 -142
- data/transactd.gemspec +14 -27
- metadata +4 -4
- data/bin/common/tdclc_64_2_0.dll +0 -0
- data/bin/common/tdclcpp_vc100_64mr_2_0.dll +0 -0
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 20a01e42c428aeaab4e743a3749d38b07ad6630a
|
4
|
+
data.tar.gz: b59b25870c2b23bd86ee6ee758c5aed9f92ea507
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: b2b17feae5e1ab20a6571ad65a97d21f72091b0c5424a79bfb4f7375972afb1f3c9bc54d3021c5bbdc2e22a993d4ca615cb19c9e931f1dd6f4b7d1148f9c2c42
|
7
|
+
data.tar.gz: 8b7bd15aca75b67417d935f9f9adb9323e98ea64dc5732f3a1976493b48f418f67df70fc2c02930400a49ba76b4bafc2b5a75c4bf20eb4425a1ab4d479878446
|
data/BUILD_UNIX-JA
CHANGED
@@ -73,10 +73,10 @@ tar xzf mysql-5.6.20.tar.gz
|
|
73
73
|
pluginディレクトリに展開します。
|
74
74
|
```
|
75
75
|
cd ~
|
76
|
-
wget http://www.bizstation.jp/al/transactd/download/transactd-2.
|
76
|
+
wget http://www.bizstation.jp/al/transactd/download/transactd-2.1.0/transactd-source-2.1.0.zip
|
77
77
|
#Mac OS Xでは
|
78
|
-
#curl -O http://www.bizstation.jp/al/transactd/download/transactd-2.
|
79
|
-
unzip -q transactd-source-2.
|
78
|
+
#curl -O http://www.bizstation.jp/al/transactd/download/transactd-2.1.0/transactd-source-2.1.0.zip
|
79
|
+
unzip -q transactd-source-2.1.0.zip -d transactd
|
80
80
|
mv transactd ~/mysql-5.6.20/plugin/
|
81
81
|
```
|
82
82
|
|
@@ -121,10 +121,10 @@ make install
|
|
121
121
|
からソースコードをダウンロードします。
|
122
122
|
```
|
123
123
|
cd ~
|
124
|
-
wget http://www.bizstation.jp/al/transactd/download/transactd-2.
|
124
|
+
wget http://www.bizstation.jp/al/transactd/download/transactd-2.1.0/transactd-source-2.1.0.zip
|
125
125
|
#Mac OS Xでは
|
126
|
-
#curl curl -O http://www.bizstation.jp/al/transactd/download/transactd-2.
|
127
|
-
unzip -q transactd-source-2.
|
126
|
+
#curl curl -O http://www.bizstation.jp/al/transactd/download/transactd-2.1.0/transactd-source-2.1.0.zip
|
127
|
+
unzip -q transactd-source-2.1.0.zip -d transactd
|
128
128
|
```
|
129
129
|
|
130
130
|
### 5-2 CMakeの実行
|
data/README
CHANGED
@@ -45,13 +45,13 @@ mysql>show variables like 'version';
|
|
45
45
|
```
|
46
46
|
The names of file to download are formed under following rules:
|
47
47
|
|
48
|
-
* Windows - transactd-[platform]-2.
|
49
|
-
* Linux - transactd-linux-x86_64-2.
|
48
|
+
* Windows - transactd-[platform]-2.1.0_[mysql-version].zip
|
49
|
+
* Linux - transactd-linux-x86_64-2.1.0_[mysql-version].tar.gz
|
50
50
|
|
51
51
|
[platform] is win32 or win64, [mysql-version] is mysql-5.x.x or mariadb-5.5.x.
|
52
52
|
For example, the URL for Linux-x86_64bit mysql-5.6.14 is as follows:
|
53
53
|
|
54
|
-
http://www.bizstation.jp/al/transactd/download/transactd-2.
|
54
|
+
http://www.bizstation.jp/al/transactd/download/transactd-2.1.0/transactd-linux-x86_64-2.1.0_mysql-5.6.14.tar.gz
|
55
55
|
|
56
56
|
You also can download source code archive and build from it.
|
57
57
|
In this case, the source code of MySQL/MariaDB is also required.
|
@@ -98,8 +98,8 @@ administrator authority.
|
|
98
98
|
|
99
99
|
2. Extract the tar.gz file and move into it.
|
100
100
|
```
|
101
|
-
tar zxf transactd-linux-x86_64-2.
|
102
|
-
cd transactd-linux-x86_64-2.
|
101
|
+
tar zxf transactd-linux-x86_64-2.1.0_mysql-5.6.14.tar.gz
|
102
|
+
cd transactd-linux-x86_64-2.1.0_mysql-5.6.14
|
103
103
|
```
|
104
104
|
|
105
105
|
3. Copy libtransactd.so to `[MySQL|MariaDB installed directory]/lib/plugin`.
|
@@ -130,13 +130,13 @@ The Transactd clients are required to access data through Transactd Plugin.
|
|
130
130
|
Download the Transactd client binaries for your platform.
|
131
131
|
The names of file to download are formed under following rules:
|
132
132
|
|
133
|
-
* Windows - transactd-client-[platform]_with_sdk-2.
|
134
|
-
* Linux - transactd-client-linux-x86_64_with_sdk-2.
|
133
|
+
* Windows - transactd-client-[platform]_with_sdk-2.1.0.zip
|
134
|
+
* Linux - transactd-client-linux-x86_64_with_sdk-2.1.0.tar.gz
|
135
135
|
|
136
136
|
[platform] is win32 or win64.
|
137
137
|
For example, the URL for Linux-x86_64bit is as follows:
|
138
138
|
|
139
|
-
http://www.bizstation.jp/al/transactd/download/transactd-client/transactd-client-linux-x86_64_with_sdk-2.
|
139
|
+
http://www.bizstation.jp/al/transactd/download/transactd-client/transactd-client-linux-x86_64_with_sdk-2.1.0.tar.gz
|
140
140
|
|
141
141
|
|
142
142
|
|
@@ -144,11 +144,11 @@ Installing Transactd clients
|
|
144
144
|
-------------------------------------------------------------------------------
|
145
145
|
|
146
146
|
### Installing on Windows
|
147
|
-
1. Open transactd-client-[platform]_with_sdk-2.
|
148
|
-
2. Select the root folder transactd-client-[platform]-with_sdk-2.
|
147
|
+
1. Open transactd-client-[platform]_with_sdk-2.1.0.zip from explorer.
|
148
|
+
2. Select the root folder transactd-client-[platform]-with_sdk-2.1.0 and
|
149
149
|
copy to a folder of your choice.
|
150
|
-
3. Run the "install.cmd" in the transactd-client-[platform]_with_sdk-2.
|
151
|
-
This command adds "transactd-client-[platform]_with_sdk-2.
|
150
|
+
3. Run the "install.cmd" in the transactd-client-[platform]_with_sdk-2.1.0 folder.
|
151
|
+
This command adds "transactd-client-[platform]_with_sdk-2.1.0\bin" folder to
|
152
152
|
the system environment variables "PATH".
|
153
153
|
|
154
154
|
C++ clients contains the following three files which is placed in bin folder.
|
@@ -178,8 +178,8 @@ There are binaries which is compiled with following 7 compilers:
|
|
178
178
|
|
179
179
|
2. Extract the tar.gz file and move into it.
|
180
180
|
```
|
181
|
-
tar zxf transactd-client-linux-x86_64_with_sdk-2.
|
182
|
-
cd transactd-client-linux-x86_64_with_sdk-2.
|
181
|
+
tar zxf transactd-client-linux-x86_64_with_sdk-2.1.0.tar.gz
|
182
|
+
cd transactd-client-linux-x86_64_with_sdk-2.1.0
|
183
183
|
```
|
184
184
|
|
185
185
|
3. Run the install script.
|
@@ -249,7 +249,7 @@ Test script executes the tests in following order:
|
|
249
249
|
### Executing on Windows
|
250
250
|
1. Move to the client directory.
|
251
251
|
```
|
252
|
-
cd transactd-client-[platform]_with_sdk-2.
|
252
|
+
cd transactd-client-[platform]_with_sdk-2.1.0
|
253
253
|
```
|
254
254
|
|
255
255
|
2. run test:
|
@@ -277,7 +277,7 @@ Test script executes the tests in following order:
|
|
277
277
|
### Executing on Linux
|
278
278
|
1. Move to the client directory.
|
279
279
|
```
|
280
|
-
cd transactd-client-linux-x86_64_with_sdk-2.
|
280
|
+
cd transactd-client-linux-x86_64_with_sdk-2.1.0
|
281
281
|
```
|
282
282
|
|
283
283
|
2. run test:
|
data/README-JA
CHANGED
@@ -45,14 +45,14 @@ show variables like 'version';
|
|
45
45
|
```
|
46
46
|
ダウンロードするファイルは
|
47
47
|
|
48
|
-
* Windowsの場合 transactd-[platform]-2.
|
49
|
-
* Linuxの場合 transactd-linux-x86_64-2.
|
48
|
+
* Windowsの場合 transactd-[platform]-2.1.0_[mysql-version].zip
|
49
|
+
* Linuxの場合 transactd-linux-x86_64-2.1.0_[mysql-version].tar.gz
|
50
50
|
|
51
51
|
といった形式です。
|
52
52
|
[platform]はwin32またはwin64、[mysql-version]はmysql-5.x.xまたはmariadb-5.5.xです。
|
53
53
|
たとえば、Linux-x86_64bit mysql-5.6.14用の完全なURLは以下の通りです。
|
54
54
|
|
55
|
-
http://www.bizstation.jp/al/transactd/download/transactd-2.
|
55
|
+
http://www.bizstation.jp/al/transactd/download/transactd-2.1.0/transactd-linux-x86_64-2.1.0_mysql-5.6.14.tar.gz
|
56
56
|
|
57
57
|
また、ソースをダウンロードしてビルドすることもできます。その場合は、
|
58
58
|
MySQL/MariaDBのソースコードも必要です。ビルド方法はソースコード内の
|
@@ -97,8 +97,8 @@ MySQL/MariaDBのバイナリに変更を加えることなく、所定の位置
|
|
97
97
|
|
98
98
|
2. ダウンロードしたtar.gzを解凍し、解凍したフォルダに移動します。
|
99
99
|
```
|
100
|
-
tar zxf transactd-linux-x86_64-2.
|
101
|
-
cd transactd-linux-x86_64-2.
|
100
|
+
tar zxf transactd-linux-x86_64-2.1.0_mysql-5.6.14.tar.gz
|
101
|
+
cd transactd-linux-x86_64-2.1.0_mysql-5.6.14
|
102
102
|
```
|
103
103
|
|
104
104
|
3. [MySQL|MariaDBインストールフォルダ]/lib/pluginに、libtransactd.soをコピー
|
@@ -129,13 +129,13 @@ Transactd Pluginを介してデータにアクセスするにはTransactdクラ
|
|
129
129
|
プラットフォームに合ったビルド済Transactdクライアントをダウンロードします。
|
130
130
|
ダウンロードするファイルは
|
131
131
|
|
132
|
-
* Windowsの場合 transactd-client-[platform]_with_sdk-2.
|
133
|
-
* Linuxの場合 transactd-client-linux-x86_64_with_sdk-2.
|
132
|
+
* Windowsの場合 transactd-client-[platform]_with_sdk-2.1.0.zip
|
133
|
+
* Linuxの場合 transactd-client-linux-x86_64_with_sdk-2.1.0.tar.gz
|
134
134
|
|
135
135
|
といった形式です。[platform]はwin32またはwin64です。
|
136
136
|
たとえば、LINUXの完全なURLは以下の通りです。
|
137
137
|
|
138
|
-
http://www.bizstation.jp/al/transactd/download/transactd-client/transactd-client-linux-x86_64_with_sdk-2.
|
138
|
+
http://www.bizstation.jp/al/transactd/download/transactd-client/transactd-client-linux-x86_64_with_sdk-2.1.0.tar.gz
|
139
139
|
|
140
140
|
|
141
141
|
|
@@ -143,11 +143,11 @@ Transactdクライアントのインストール
|
|
143
143
|
-------------------------------------------------------------------------------
|
144
144
|
|
145
145
|
### Windowsでのインストール
|
146
|
-
1. ダウンロードしたtransactd-client-[platform]_with_sdk-2.
|
147
|
-
2. ルートフォルダーのtransactd-client-[platform]_with_sdk-2.
|
146
|
+
1. ダウンロードしたtransactd-client-[platform]_with_sdk-2.1.0.zipを開きます。
|
147
|
+
2. ルートフォルダーのtransactd-client-[platform]_with_sdk-2.1.0ごと適当なフォルダに
|
148
148
|
コピーします。
|
149
|
-
3. transactd-client-[platform]_with_sdk-2.
|
150
|
-
これによりtransactd-client-[platform]_with_sdk-2.
|
149
|
+
3. transactd-client-[platform]_with_sdk-2.1.0直下にあるinstall.cmdを実行します。
|
150
|
+
これによりtransactd-client-[platform]_with_sdk-2.1.0\binフォルダをシステム環境変数
|
151
151
|
PATHに追加します。
|
152
152
|
|
153
153
|
C++クライアントは binフォルダに配置された以下の3つのDLLからなります。
|
@@ -176,8 +176,8 @@ C++クライアントは binフォルダに配置された以下の3つのDLL
|
|
176
176
|
|
177
177
|
2. ダウンロードしたtar.gzを解凍し、解凍したフォルダに移動します。
|
178
178
|
```
|
179
|
-
tar zxf transactd-client-linux-x86_64_with_sdk-2.
|
180
|
-
cd transactd-client-linux-x86_64_with_sdk-2.
|
179
|
+
tar zxf transactd-client-linux-x86_64_with_sdk-2.1.0.tar.gz
|
180
|
+
cd transactd-client-linux-x86_64_with_sdk-2.1.0
|
181
181
|
```
|
182
182
|
|
183
183
|
3. インストールスクリプトを実行します。
|
@@ -252,7 +252,7 @@ Transactd Pluginとクライアントのインストールが済んだら、テ
|
|
252
252
|
### Windowsでの起動
|
253
253
|
1. クライアントのインストールで解凍したフォルダに移動します
|
254
254
|
```
|
255
|
-
cd transactd-client-[platform]_with_sdk-2.
|
255
|
+
cd transactd-client-[platform]_with_sdk-2.1.0
|
256
256
|
```
|
257
257
|
|
258
258
|
2. テストの起動
|
@@ -279,7 +279,7 @@ Transactd Pluginとクライアントのインストールが済んだら、テ
|
|
279
279
|
### Linuxでの起動
|
280
280
|
1. クライアントのインストールで解凍したフォルダに移動します
|
281
281
|
```
|
282
|
-
cd transactd-client-linux-x86_64_with_sdk-2.
|
282
|
+
cd transactd-client-linux-x86_64_with_sdk-2.1.0
|
283
283
|
```
|
284
284
|
|
285
285
|
2. テストの起動
|
data/bin/2.0/transactd.so
CHANGED
Binary file
|
data/bin/2.1/transactd.so
CHANGED
Binary file
|
Binary file
|
Binary file
|
@@ -83,17 +83,15 @@ end
|
|
83
83
|
def deleteAll(db, tb, start, endid)
|
84
84
|
db.beginTrn(TRANS_BIAS)
|
85
85
|
tb.clearBuffer()
|
86
|
-
|
87
|
-
|
88
|
-
|
89
|
-
|
90
|
-
|
91
|
-
|
92
|
-
|
93
|
-
|
94
|
-
|
95
|
-
end
|
96
|
-
end
|
86
|
+
tb.stepFirst()
|
87
|
+
while tb.stat() == 0
|
88
|
+
tb.del();
|
89
|
+
if (tb.stat() != 0)
|
90
|
+
showTableError(tb, 'deleteAll')
|
91
|
+
db.endTrn()
|
92
|
+
return false
|
93
|
+
end
|
94
|
+
tb.stepNext()
|
97
95
|
end
|
98
96
|
db.endTrn()
|
99
97
|
return true
|
@@ -273,7 +271,7 @@ def main(argv)
|
|
273
271
|
puts("\t 6: read range with snapshpot. 20rec x 1000times")
|
274
272
|
puts("\t 7: update")
|
275
273
|
puts("\t 8: update in transaction. 20rec x 1000times")
|
276
|
-
puts("example : ruby bench_tdclcpp.rb \"tdap://localhost/test?dbfile=test.bdf\" 0 -1
|
274
|
+
puts("example : ruby bench_tdclcpp.rb \"tdap://localhost/test?dbfile=test.bdf\" 0 -1 0")
|
277
275
|
return
|
278
276
|
end
|
279
277
|
uri = argv[1] # "tdap://localhost/test?dbfile=test.bdf"
|
@@ -297,9 +295,9 @@ def main(argv)
|
|
297
295
|
if (!db.open(uri, Transactd::TYPE_SCHEMA_BDF, Transactd::TD_OPEN_NORMAL, '', ''))
|
298
296
|
puts("open table erorr No:#{db.stat().to_s}")
|
299
297
|
else
|
300
|
-
tb = openTable(db, '
|
298
|
+
tb = openTable(db, 'users', Transactd::TD_OPEN_NORMAL)
|
301
299
|
if tb == nil
|
302
|
-
puts "can not open table '
|
300
|
+
puts "can not open table 'users'"
|
303
301
|
db.close()
|
304
302
|
return
|
305
303
|
end
|
@@ -24,7 +24,7 @@ require 'rbconfig'
|
|
24
24
|
IS_WINDOWS = (RbConfig::CONFIG['host_os'] =~ /mswin|mingw|cygwin/)
|
25
25
|
|
26
26
|
def getHost()
|
27
|
-
hostname = '
|
27
|
+
hostname = 'localhost/'
|
28
28
|
if (ENV['TRANSACTD_RSPEC_HOST'] != nil && ENV['TRANSACTD_RSPEC_HOST'] != '')
|
29
29
|
hostname = ENV['TRANSACTD_RSPEC_HOST']
|
30
30
|
end
|
@@ -54,8 +54,7 @@ TEST_COUNT = 20000
|
|
54
54
|
FIVE_PERCENT_OF_TEST_COUNT = TEST_COUNT / 20
|
55
55
|
ALLOWABLE_ERROR_DISTANCE_IN_ESTIMATE_COUNT = TEST_COUNT / 4
|
56
56
|
|
57
|
-
|
58
|
-
ISOLATION_REPEATABLE_READ = false
|
57
|
+
NO_RECORD_ID = 5
|
59
58
|
|
60
59
|
def testDropDatabase(db)
|
61
60
|
db.open(URL)
|
@@ -95,6 +94,7 @@ def testCreateTable(db)
|
|
95
94
|
fd.len = 4
|
96
95
|
dbdef.updateTableDef(1)
|
97
96
|
expect(dbdef.stat()).to eq 0
|
97
|
+
|
98
98
|
fd = dbdef.insertField(1, 1)
|
99
99
|
fd.setName('name')
|
100
100
|
fd.type = Transactd::Ft_zstring
|
@@ -116,13 +116,45 @@ def testCreateTable(db)
|
|
116
116
|
dbdef.updateTableDef(1)
|
117
117
|
expect(dbdef.stat()).to eq 0
|
118
118
|
|
119
|
-
kd = dbdef.insertKey(1,0)
|
119
|
+
kd = dbdef.insertKey(1, 0)
|
120
120
|
kd.segment(0).fieldNum = 0
|
121
121
|
kd.segment(0).flags.bit8 = 1
|
122
122
|
kd.segment(0).flags.bit1 = 1
|
123
123
|
kd.segmentCount = 1
|
124
124
|
dbdef.updateTableDef(1)
|
125
125
|
expect(dbdef.stat()).to eq 0
|
126
|
+
|
127
|
+
# group table
|
128
|
+
td = Transactd::Tabledef.new()
|
129
|
+
td.setTableName('group')
|
130
|
+
td.setFileName('group.dat')
|
131
|
+
table_id = 2
|
132
|
+
td.id = table_id
|
133
|
+
td.pageSize = 2048
|
134
|
+
dbdef.insertTable(td)
|
135
|
+
expect(dbdef.stat()).to eq 0
|
136
|
+
|
137
|
+
fd = dbdef.insertField(table_id, 0)
|
138
|
+
fd.setName('id')
|
139
|
+
fd.type = Transactd::Ft_integer
|
140
|
+
fd.len = 4
|
141
|
+
dbdef.updateTableDef(table_id)
|
142
|
+
expect(dbdef.stat()).to eq 0
|
143
|
+
|
144
|
+
fd = dbdef.insertField(table_id, 1)
|
145
|
+
fd.setName('name')
|
146
|
+
fd.type = Transactd::Ft_zstring
|
147
|
+
fd.len = 33
|
148
|
+
dbdef.updateTableDef(table_id)
|
149
|
+
expect(dbdef.stat()).to eq 0
|
150
|
+
|
151
|
+
kd = dbdef.insertKey(table_id, 0)
|
152
|
+
kd.segment(0).fieldNum = 0
|
153
|
+
kd.segment(0).flags.bit8 = 1
|
154
|
+
kd.segment(0).flags.bit1 = 1
|
155
|
+
kd.segmentCount = 1
|
156
|
+
dbdef.updateTableDef(table_id)
|
157
|
+
expect(dbdef.stat()).to eq 0
|
126
158
|
end
|
127
159
|
|
128
160
|
def testOpenTable(db)
|
@@ -203,6 +235,7 @@ end
|
|
203
235
|
def testFind()
|
204
236
|
db = Transactd::Database.new()
|
205
237
|
tb = testOpenTable(db)
|
238
|
+
expect(tb).not_to be nil
|
206
239
|
tb.setKeyNum(0)
|
207
240
|
tb.clearBuffer()
|
208
241
|
tb.setFilter('id >= 10 and id < ' + TEST_COUNT.to_s, 1, 0)
|
@@ -212,6 +245,7 @@ def testFind()
|
|
212
245
|
i = v
|
213
246
|
while i < TEST_COUNT do
|
214
247
|
expect(tb.stat()).to eq 0
|
248
|
+
break unless tb.stat() == 0
|
215
249
|
expect(tb.getFVint(FDI_ID)).to eq i
|
216
250
|
tb.findNext(true) # 11 - 19
|
217
251
|
i = i + 1
|
@@ -224,6 +258,7 @@ def testFind()
|
|
224
258
|
i = v
|
225
259
|
while i >= 10 do
|
226
260
|
expect(tb.stat()).to eq 0
|
261
|
+
break unless tb.stat() == 0
|
227
262
|
expect(tb.getFVint(FDI_ID)).to eq i
|
228
263
|
tb.findPrev(true) # 11 - 19
|
229
264
|
i = i - 1
|
@@ -250,6 +285,7 @@ def testFindNext()
|
|
250
285
|
expect(tb.getFVint(FDI_ID)).to eq v
|
251
286
|
for i in (v + 1)..(TEST_COUNT - 1) do
|
252
287
|
tb.findNext(true) # 11 - 19
|
288
|
+
break unless tb.stat() == 0
|
253
289
|
expect(tb.stat()).to eq 0
|
254
290
|
expect(tb.getFVint(FDI_ID)).to eq i
|
255
291
|
end
|
@@ -297,9 +333,8 @@ def testFindIn()
|
|
297
333
|
expect(tb.stat()).to eq Transactd::STATUS_EOF
|
298
334
|
|
299
335
|
# Many params
|
300
|
-
|
301
|
-
|
302
|
-
q.addSeekKeyValue(i.to_s)
|
336
|
+
1.upto(10000) do |i|
|
337
|
+
q.addSeekKeyValue(i.to_s, (i == 1))
|
303
338
|
end
|
304
339
|
tb.setQuery(q)
|
305
340
|
expect(tb.stat()).to eq 0
|
@@ -387,6 +422,7 @@ def testGetNext()
|
|
387
422
|
for i in 3..(TEST_COUNT + 1)
|
388
423
|
tb.seekNext()
|
389
424
|
expect(tb.getFVint(FDI_ID)).to eq i
|
425
|
+
break unless tb.getFVint(FDI_ID) == i
|
390
426
|
end
|
391
427
|
db.endSnapshot()
|
392
428
|
tb.close()
|
@@ -405,10 +441,24 @@ def testGetPrevious()
|
|
405
441
|
for i in TEST_COUNT.downto(2) do
|
406
442
|
tb.seekPrev()
|
407
443
|
expect(tb.getFVint(FDI_ID)).to eq i
|
444
|
+
break unless tb.getFVint(FDI_ID) == i
|
408
445
|
end
|
409
446
|
tb.seekPrev()
|
410
447
|
expect(tb.getFVstr(FDI_NAME)).to eq 'kosaka'
|
411
448
|
db.endSnapshot()
|
449
|
+
# without snapshot
|
450
|
+
vv = TEST_COUNT + 1
|
451
|
+
tb.clearBuffer()
|
452
|
+
tb.setFV(FDI_ID, vv)
|
453
|
+
tb.seek()
|
454
|
+
expect(tb.getFVint(FDI_ID)).to eq vv
|
455
|
+
for i in TEST_COUNT.downto(2) do
|
456
|
+
tb.seekPrev()
|
457
|
+
expect(tb.getFVint(FDI_ID)).to eq i
|
458
|
+
break unless tb.getFVint(FDI_ID) == i
|
459
|
+
end
|
460
|
+
tb.seekPrev()
|
461
|
+
expect(tb.getFVstr(FDI_NAME)).to eq 'kosaka'
|
412
462
|
tb.close()
|
413
463
|
db.close()
|
414
464
|
end
|
@@ -564,142 +614,713 @@ def testUpdate()
|
|
564
614
|
db.close()
|
565
615
|
end
|
566
616
|
|
567
|
-
def
|
617
|
+
def testSnapshot()
|
568
618
|
db = Transactd::Database.new()
|
619
|
+
tb = testOpenTable(db)
|
620
|
+
expect(tb).not_to be nil
|
621
|
+
tbg = db.openTable('group')
|
622
|
+
expect(db.stat()).to eq 0
|
623
|
+
expect(tbg).not_to be nil
|
569
624
|
db2 = Transactd::Database.new()
|
570
625
|
db2.connect(PROTOCOL + HOSTNAME + DBNAME , true)
|
571
626
|
expect(db2.stat()).to eq 0
|
572
|
-
tb = testOpenTable(db)
|
573
627
|
tb2 = testOpenTable(db2)
|
574
|
-
|
628
|
+
expect(tb2).not_to be nil
|
629
|
+
tbg2 = db2.openTable('group')
|
630
|
+
expect(db2.stat()).to eq 0
|
631
|
+
expect(tbg2).not_to be nil
|
632
|
+
|
633
|
+
# No locking repeatable read
|
634
|
+
# ----------------------------------------------------
|
635
|
+
db.beginSnapshot() # CONSISTENT_READ is default
|
575
636
|
expect(db.stat()).to eq 0
|
637
|
+
db.beginTrn()
|
638
|
+
expect(db.stat()).to eq Transactd::STATUS_ALREADY_INSNAPSHOT
|
639
|
+
|
576
640
|
tb.setKeyNum(0)
|
577
641
|
tb.seekFirst()
|
578
642
|
expect(tb.stat()).to eq 0
|
579
643
|
firstValue = tb.getFVint(FDI_NAME)
|
580
644
|
tb.seekNext()
|
581
|
-
|
582
|
-
|
645
|
+
expect(tb.stat()).to eq 0
|
646
|
+
expect(tb.getFVint(FDI_ID)).to eq 2
|
647
|
+
tbg.seekFirst()
|
648
|
+
expect(tbg.stat()).to eq Transactd::STATUS_EOF
|
649
|
+
expect(tbg.recordCount(false)).to eq 0
|
650
|
+
|
651
|
+
# Change data on 2 tables by another connection
|
583
652
|
tb2.setKeyNum(0)
|
584
653
|
tb2.seekFirst()
|
585
654
|
expect(tb2.stat()).to eq 0
|
586
655
|
tb2.setFV(FDI_NAME, tb2.getFVint(FDI_ID) + 1)
|
587
|
-
tb2.update()
|
588
|
-
|
589
|
-
|
590
|
-
|
591
|
-
|
592
|
-
|
593
|
-
|
656
|
+
tb2.update() # Change success
|
657
|
+
expect(tb2.stat()).to eq 0
|
658
|
+
tbg2.setFV(FDI_ID, 1)
|
659
|
+
tbg2.setFV(FDI_NAME, 'ABC')
|
660
|
+
tbg2.insert()
|
661
|
+
expect(tbg2.stat()).to eq 0
|
662
|
+
|
663
|
+
# in-snapshot repeatable read check same value
|
594
664
|
tb.seekFirst()
|
595
665
|
secondValue = tb.getFVint(FDI_NAME)
|
596
666
|
expect(tb.stat()).to eq 0
|
667
|
+
expect(secondValue).to eq firstValue
|
668
|
+
|
669
|
+
tbg.seekFirst()
|
670
|
+
expect(tbg.stat()).to eq Transactd::STATUS_EOF
|
671
|
+
expect(tbg.recordCount(false)).to eq 0
|
672
|
+
|
673
|
+
# in-snapshot update
|
674
|
+
tb.update()
|
675
|
+
expect(tb.stat()).to eq Transactd::STATUS_INVALID_LOCKTYPE
|
676
|
+
|
677
|
+
# in-snapshot insert
|
678
|
+
tb.setFV(FDI_ID, 0)
|
679
|
+
tb.insert()
|
680
|
+
expect(tb.stat()).to eq Transactd::STATUS_INVALID_LOCKTYPE
|
681
|
+
|
682
|
+
# phantom read
|
683
|
+
tb2.setFV(FDI_ID, 29999)
|
684
|
+
tb2.insert()
|
685
|
+
expect(tb2.stat()).to eq 0
|
686
|
+
tb.setFV(FDI_ID, 29999)
|
687
|
+
tb.seek()
|
688
|
+
expect(tb.stat()).to eq Transactd::STATUS_NOT_FOUND_TI
|
689
|
+
|
690
|
+
# clean up
|
691
|
+
tb2.del()
|
692
|
+
expect(tb2.stat()).to eq 0
|
693
|
+
|
597
694
|
db.endSnapshot()
|
598
695
|
expect(db.stat()).to eq 0
|
599
|
-
|
600
|
-
|
601
|
-
|
602
|
-
|
603
|
-
|
604
|
-
|
696
|
+
|
697
|
+
# After snapshot, db can read new versions.
|
698
|
+
tb.seekFirst()
|
699
|
+
expect(tb.stat()).to eq 0
|
700
|
+
expect(tb.getFVint(FDI_ID)).to eq 1
|
701
|
+
tbg.seekFirst()
|
702
|
+
expect(tbg.stat()).to eq 0
|
703
|
+
expect(tbg.recordCount(false)).to eq 1
|
704
|
+
|
705
|
+
# gap lock
|
706
|
+
db.beginSnapshot(Transactd::MULTILOCK_GAP_SHARE)
|
707
|
+
tb.seekLast() # id = 30000
|
708
|
+
expect(tb.stat()).to eq 0
|
709
|
+
tb.seekPrev() # id = 20002
|
710
|
+
expect(tb.stat()).to eq 0
|
711
|
+
tb.seekPrev() # id = 20001
|
712
|
+
expect(tb.stat()).to eq 0
|
713
|
+
|
714
|
+
tb2.setFV(FDI_ID, 29999)
|
715
|
+
tb2.insert()
|
716
|
+
expect(tb2.stat()).to eq Transactd::STATUS_LOCK_ERROR
|
717
|
+
|
718
|
+
db.endSnapshot()
|
719
|
+
tbg2.close()
|
720
|
+
tbg.close()
|
605
721
|
tb2.close()
|
606
722
|
tb.close()
|
607
723
|
db2.close()
|
608
724
|
db.close()
|
609
725
|
end
|
610
726
|
|
611
|
-
|
727
|
+
# isolation Level ISO_REPEATABLE_READ
|
728
|
+
def testTransactionLockRepeatable()
|
612
729
|
db = Transactd::Database.new()
|
730
|
+
tb = testOpenTable(db)
|
731
|
+
expect(tb).not_to be nil
|
613
732
|
db2 = Transactd::Database.new()
|
614
733
|
db2.connect(PROTOCOL + HOSTNAME + DBNAME, true)
|
615
734
|
expect(db2.stat()).to eq 0
|
616
|
-
tb = testOpenTable(db)
|
617
735
|
tb2 = testOpenTable(db2)
|
736
|
+
expect(tb2).not_to be nil
|
737
|
+
|
738
|
+
db.beginTrn(Transactd::MULTILOCK_REPEATABLE_READ)
|
739
|
+
expect(db.stat()).to eq 0
|
740
|
+
# Test Invalid operation
|
741
|
+
db.beginSnapshot()
|
742
|
+
expect(db.stat()).to eq Transactd::STATUS_ALREADY_INTRANSACTION
|
743
|
+
|
618
744
|
# ----------------------------------------------------
|
619
|
-
#
|
745
|
+
# Test Read with lock
|
620
746
|
# ----------------------------------------------------
|
621
|
-
|
622
|
-
tb.setKeyNum(0)
|
747
|
+
# lock(X) the first record
|
623
748
|
tb.seekFirst()
|
624
749
|
expect(tb.stat()).to eq 0
|
625
|
-
|
750
|
+
|
751
|
+
# Add lock(X) the second record
|
626
752
|
tb.seekNext()
|
753
|
+
|
754
|
+
# No transaction user can read allways. Use consistent_read
|
627
755
|
tb2.seekFirst()
|
628
756
|
expect(tb2.stat()).to eq 0
|
757
|
+
|
758
|
+
tb2.seekNext()
|
759
|
+
expect(tb2.stat()).to eq 0
|
760
|
+
|
761
|
+
# The second transaction user can not lock same record.
|
629
762
|
db2.beginTrn()
|
630
763
|
tb2.setKeyNum(0)
|
764
|
+
|
765
|
+
# Try lock(X)
|
766
|
+
tb2.seekFirst()
|
767
|
+
expect(tb2.stat()).to eq Transactd::STATUS_LOCK_ERROR
|
768
|
+
db2.endTrn()
|
769
|
+
db.endTrn()
|
770
|
+
|
771
|
+
# ----------------------------------------------------
|
772
|
+
# Test single record lock and Transaction lock
|
773
|
+
# ----------------------------------------------------
|
774
|
+
# lock(X) non-transaction
|
775
|
+
tb2.seekFirst(Transactd::ROW_LOCK_X)
|
776
|
+
|
777
|
+
db.beginTrn(Transactd::MULTILOCK_REPEATABLE_READ)
|
778
|
+
expect(db.stat()).to eq 0
|
779
|
+
|
780
|
+
# Try lock(X)
|
781
|
+
tb.seekFirst()
|
782
|
+
expect(tb.stat()).to eq Transactd::STATUS_LOCK_ERROR
|
783
|
+
|
784
|
+
# Remove lock(X)
|
785
|
+
tb2.seekFirst()
|
786
|
+
|
787
|
+
# Retry lock(X)
|
788
|
+
tb.seekFirst()
|
789
|
+
expect(tb.stat()).to eq 0
|
790
|
+
|
791
|
+
tb.setFV(FDI_NAME, 'ABC')
|
792
|
+
tb.update()
|
793
|
+
expect(tb.stat()).to eq 0
|
794
|
+
|
795
|
+
# No transaction user can read allways. Use consistent_read
|
631
796
|
tb2.seekFirst()
|
632
797
|
expect(tb2.stat()).to eq 0
|
798
|
+
expect(tb2.getFVstr(FDI_NAME)).not_to eq 'ABC'
|
799
|
+
|
800
|
+
# ----------------------------------------------------
|
801
|
+
# Test Transaction lock and Transaction lock
|
802
|
+
# ----------------------------------------------------
|
803
|
+
db2.beginTrn()
|
804
|
+
expect(db2.stat()).to eq 0
|
805
|
+
|
806
|
+
# try lock(X)
|
807
|
+
tb2.seekFirst()
|
808
|
+
expect(tb2.stat()).to eq Transactd::STATUS_LOCK_ERROR
|
809
|
+
|
810
|
+
# Try unlock updated record. Can not unlock updated record.
|
811
|
+
tb.unlock()
|
812
|
+
|
813
|
+
# try lock(X)
|
814
|
+
tb2.seekFirst()
|
815
|
+
expect(tb2.stat()).to eq Transactd::STATUS_LOCK_ERROR
|
816
|
+
|
633
817
|
db2.endTrn()
|
634
818
|
db.endTrn()
|
819
|
+
|
635
820
|
# ----------------------------------------------------
|
636
|
-
#
|
821
|
+
# Test phantom read
|
637
822
|
# ----------------------------------------------------
|
638
|
-
db.beginTrn(Transactd::
|
639
|
-
|
823
|
+
db.beginTrn(Transactd::MULTILOCK_REPEATABLE_READ)
|
824
|
+
expect(db.stat()).to eq 0
|
825
|
+
|
826
|
+
# read last row
|
827
|
+
tb.seekLast() # lock(X) last id = 30000
|
828
|
+
expect(tb.stat()).to eq 0
|
829
|
+
tb.seekPrev() # Add lock(X)
|
830
|
+
expect(tb.stat()).to eq 0
|
831
|
+
last2 = tb.getFVint(FDI_ID)
|
832
|
+
|
833
|
+
# insert test row
|
834
|
+
tb2.setFV(FDI_ID, 29999)
|
835
|
+
tb2.insert() # Can not insert by gap lock
|
836
|
+
expect(tb2.stat()).to eq Transactd::STATUS_LOCK_ERROR
|
837
|
+
|
838
|
+
tb.seekLast()
|
839
|
+
expect(tb.stat()).to eq 0
|
840
|
+
tb.seekPrev()
|
841
|
+
expect(tb.stat()).to eq 0
|
842
|
+
expect(tb.getFVint(FDI_ID)).to eq last2
|
843
|
+
db.endTrn()
|
844
|
+
|
845
|
+
# ----------------------------------------------------
|
846
|
+
# Test use shared lock option
|
847
|
+
# ----------------------------------------------------
|
848
|
+
db.beginTrn(Transactd::MULTILOCK_REPEATABLE_READ)
|
849
|
+
expect(db.stat()).to eq 0
|
850
|
+
|
851
|
+
db2.beginTrn(Transactd::MULTILOCK_REPEATABLE_READ)
|
852
|
+
expect(db2.stat()).to eq 0
|
853
|
+
|
854
|
+
tb.seekLast(Transactd::ROW_LOCK_S)
|
855
|
+
expect(tb.stat()).to eq 0
|
856
|
+
tb2.seekLast(Transactd::ROW_LOCK_S)
|
857
|
+
expect(tb2.stat()).to eq 0
|
858
|
+
|
859
|
+
tb.seekPrev() # Lock(X)
|
860
|
+
expect(tb.stat()).to eq 0
|
861
|
+
|
862
|
+
tb2.seekPrev(Transactd::ROW_LOCK_S)
|
863
|
+
expect(tb2.stat()).to eq Transactd::STATUS_LOCK_ERROR
|
864
|
+
|
865
|
+
tb.seekPrev(Transactd::ROW_LOCK_S)
|
866
|
+
expect(tb.stat()).to eq 0
|
867
|
+
id = tb.getFVint(FDI_ID)
|
868
|
+
|
869
|
+
tb2.setFV(FDI_ID, id)
|
870
|
+
tb2.seek(Transactd::ROW_LOCK_S)
|
871
|
+
expect(tb2.stat()).to eq 0
|
872
|
+
|
873
|
+
db2.endTrn()
|
874
|
+
db.endTrn()
|
875
|
+
|
876
|
+
# ----------------------------------------------------
|
877
|
+
# Test Abort
|
878
|
+
# ----------------------------------------------------
|
879
|
+
db.beginTrn(Transactd::MULTILOCK_REPEATABLE_READ)
|
880
|
+
expect(db.stat()).to eq 0
|
881
|
+
|
882
|
+
# lock(X)
|
640
883
|
tb.seekFirst()
|
641
884
|
expect(tb.stat()).to eq 0
|
885
|
+
tb.setFV(FDI_NAME, 'EFG')
|
886
|
+
tb.update()
|
887
|
+
expect(tb.stat()).to eq 0
|
888
|
+
|
642
889
|
# move from first record.
|
643
890
|
tb.seekNext()
|
644
|
-
|
891
|
+
db.abortTrn()
|
892
|
+
|
893
|
+
tb2.setKeyNum(0)
|
645
894
|
tb2.seekFirst()
|
895
|
+
expect(tb2.getFVstr(FDI_NAME)).to eq 'ABC'
|
896
|
+
|
897
|
+
# ----------------------------------------------------
|
898
|
+
# Test Query and locks Multi record lock
|
899
|
+
# ----------------------------------------------------
|
900
|
+
db.beginTrn(Transactd::MULTILOCK_REPEATABLE_READ)
|
901
|
+
expect(db.stat()).to eq 0
|
902
|
+
|
903
|
+
# Test find records are lock.
|
904
|
+
q = Transactd::Query.new()
|
905
|
+
q.where('id', '<=', 15).and_('id', '<>', 13).reject(0xFFFF)
|
906
|
+
tb.setQuery(q)
|
907
|
+
tb.setFV(FDI_ID, 12)
|
908
|
+
tb.find()
|
909
|
+
while (tb.stat() == 0) do
|
910
|
+
tb.findNext()
|
911
|
+
end
|
912
|
+
expect(tb.getFVint(FDI_ID)).to eq 15
|
913
|
+
|
914
|
+
# all records locked
|
915
|
+
for i in 12..16 do
|
916
|
+
tb2.setFV(FDI_ID, i)
|
917
|
+
tb2.seek(Transactd::ROW_LOCK_X)
|
918
|
+
expect(tb2.stat()).to eq Transactd::STATUS_LOCK_ERROR
|
919
|
+
end
|
920
|
+
db.endTrn()
|
921
|
+
|
922
|
+
tb2.close()
|
923
|
+
tb.close()
|
924
|
+
db2.close()
|
925
|
+
db.close()
|
926
|
+
end
|
927
|
+
|
928
|
+
def testTransactionLockReadCommited()
|
929
|
+
db = Transactd::Database.new()
|
930
|
+
tb = testOpenTable(db)
|
931
|
+
expect(tb).not_to be nil
|
932
|
+
db2 = Transactd::Database.new()
|
933
|
+
db2.connect(PROTOCOL + HOSTNAME + DBNAME, true)
|
934
|
+
expect(db2.stat()).to eq 0
|
935
|
+
tb2 = testOpenTable(db2)
|
936
|
+
expect(tb2).not_to be nil
|
937
|
+
|
938
|
+
# ----------------------------------------------------
|
939
|
+
# Test single record lock Transaction and read
|
940
|
+
# ----------------------------------------------------
|
941
|
+
db.beginTrn(Transactd::SINGLELOCK_READ_COMMITED)
|
942
|
+
expect(db.stat()).to eq 0
|
943
|
+
# Test Invalid operation
|
944
|
+
db.beginSnapshot()
|
945
|
+
expect(db.stat()).to eq Transactd::STATUS_ALREADY_INTRANSACTION
|
946
|
+
|
947
|
+
tb.setKeyNum(0)
|
948
|
+
tb.seekFirst() # lock(X)
|
949
|
+
expect(tb.stat()).to eq 0
|
950
|
+
|
951
|
+
# Try lock(X)
|
952
|
+
tb2.seekFirst(Transactd::ROW_LOCK_X)
|
953
|
+
expect(tb2.stat()).to eq Transactd::STATUS_LOCK_ERROR
|
954
|
+
|
955
|
+
# consistent read
|
956
|
+
tb2.seekFirst()
|
957
|
+
expect(tb2.stat()).to eq 0
|
958
|
+
|
959
|
+
# Unlock first record. And lock(X) second record
|
960
|
+
tb.seekNext()
|
961
|
+
|
962
|
+
# test unlocked first record
|
963
|
+
tb2.seekFirst()
|
964
|
+
expect(tb2.stat()).to eq 0
|
965
|
+
tb2.update()
|
966
|
+
expect(tb2.stat()).to eq 0
|
967
|
+
|
968
|
+
# The second record, consistent read
|
969
|
+
tb2.seekNext()
|
970
|
+
expect(tb2.stat()).to eq 0
|
971
|
+
# Try lock(X) whith lock(IX)
|
972
|
+
tb2.update()
|
646
973
|
expect(tb2.stat()).to eq Transactd::STATUS_LOCK_ERROR
|
647
|
-
|
974
|
+
|
975
|
+
# ----------------------------------------------------
|
976
|
+
# Test single record lock Transaction and Transaction lock
|
977
|
+
# ----------------------------------------------------
|
648
978
|
db2.beginTrn()
|
649
|
-
|
979
|
+
# Try lock(X)
|
650
980
|
tb2.seekFirst()
|
981
|
+
expect(tb2.stat()).to eq 0
|
982
|
+
# Try lock(X)
|
983
|
+
tb2.seekNext()
|
651
984
|
expect(tb2.stat()).to eq Transactd::STATUS_LOCK_ERROR
|
652
985
|
db2.endTrn()
|
653
986
|
db.endTrn()
|
987
|
+
|
654
988
|
# ----------------------------------------------------
|
655
|
-
#
|
989
|
+
# Test multi record lock Transaction and non-transaction read
|
656
990
|
# ----------------------------------------------------
|
657
|
-
db.beginTrn(Transactd::
|
658
|
-
|
991
|
+
db.beginTrn(Transactd::MULTILOCK_READ_COMMITED)
|
992
|
+
expect(db.stat()).to eq 0
|
993
|
+
|
994
|
+
# lock(X) the first record
|
659
995
|
tb.seekFirst()
|
660
996
|
expect(tb.stat()).to eq 0
|
997
|
+
|
998
|
+
# Add lock(X) the second record
|
999
|
+
tb.seekNext()
|
1000
|
+
|
1001
|
+
# No transaction user read can read allways. Use consistent_read
|
1002
|
+
tb2.seekFirst()
|
1003
|
+
expect(tb2.stat()).to eq 0
|
1004
|
+
|
1005
|
+
tb2.seekNext()
|
1006
|
+
expect(tb2.stat()).to eq 0
|
1007
|
+
|
1008
|
+
# ----------------------------------------------------
|
1009
|
+
# Test unlock
|
1010
|
+
# ----------------------------------------------------
|
1011
|
+
tb2.seekFirst()
|
1012
|
+
tb2.seekNext(Transactd::ROW_LOCK_X)
|
1013
|
+
expect(tb2.stat()).to eq Transactd::STATUS_LOCK_ERROR
|
1014
|
+
|
1015
|
+
tb.unlock()
|
1016
|
+
# retry seekNext. Before operation is failed but do not lost currency.
|
1017
|
+
tb2.seekNext(Transactd::ROW_LOCK_X)
|
1018
|
+
expect(tb2.stat()).to eq 0
|
1019
|
+
tb2.seekNext()
|
1020
|
+
# ----------------------------------------------------
|
1021
|
+
# Test undate record unlock
|
1022
|
+
# ----------------------------------------------------
|
1023
|
+
tb.seekFirst()
|
1024
|
+
expect(tb.stat()).to eq 0
|
1025
|
+
tb.seekNext()
|
1026
|
+
expect(tb.stat()).to eq 0
|
1027
|
+
tb.update()
|
1028
|
+
expect(tb.stat()).to eq 0
|
1029
|
+
tb.unlock() # Can not unlock updated record
|
1030
|
+
expect(tb.stat()).to eq 0
|
1031
|
+
tb2.seekFirst()
|
1032
|
+
tb2.seekNext(Transactd::ROW_LOCK_X)
|
1033
|
+
expect(tb2.stat()).to eq Transactd::STATUS_LOCK_ERROR
|
1034
|
+
|
1035
|
+
# ----------------------------------------------------
|
1036
|
+
# Test undate record unlock
|
1037
|
+
# ----------------------------------------------------
|
1038
|
+
db2.beginTrn()
|
1039
|
+
expect(db2.stat()).to eq 0
|
1040
|
+
|
1041
|
+
# Try lock(X)
|
1042
|
+
tb2.seekFirst()
|
1043
|
+
expect(tb2.stat()).to eq Transactd::STATUS_LOCK_ERROR
|
1044
|
+
db2.endTrn()
|
1045
|
+
db.endTrn()
|
1046
|
+
|
1047
|
+
# ----------------------------------------------------
|
1048
|
+
# Test multi record lock Transaction and non-transaction record lock
|
1049
|
+
# ----------------------------------------------------
|
1050
|
+
# lock(X) non-transaction
|
1051
|
+
tb2.seekFirst(Transactd::ROW_LOCK_X)
|
1052
|
+
|
1053
|
+
db.beginTrn(Transactd::SINGLELOCK_READ_COMMITED)
|
1054
|
+
expect(db.stat()).to eq 0
|
1055
|
+
|
1056
|
+
# Try lock(X)
|
1057
|
+
tb.seekFirst()
|
1058
|
+
expect(tb.stat()).to eq Transactd::STATUS_LOCK_ERROR
|
1059
|
+
|
1060
|
+
# Remove lock(X)
|
1061
|
+
tb2.seekFirst()
|
1062
|
+
|
1063
|
+
# Retry lock(X)
|
1064
|
+
tb.seekFirst()
|
1065
|
+
expect(tb.stat()).to eq 0
|
1066
|
+
|
1067
|
+
# update in transaction
|
661
1068
|
tb.setFV(FDI_NAME, 'ABC')
|
662
1069
|
tb.update()
|
663
1070
|
expect(tb.stat()).to eq 0
|
1071
|
+
|
664
1072
|
# move from first record.
|
665
1073
|
tb.seekNext()
|
1074
|
+
|
1075
|
+
# No transaction read can read allways. Use consistent_read
|
666
1076
|
tb2.seekFirst()
|
1077
|
+
expect(tb2.stat()).to eq 0
|
1078
|
+
tb2.update()
|
667
1079
|
expect(tb2.stat()).to eq Transactd::STATUS_LOCK_ERROR
|
668
|
-
|
1080
|
+
|
1081
|
+
db.endTrn()
|
1082
|
+
|
1083
|
+
# ----------------------------------------------------
|
1084
|
+
# Test phantom read
|
1085
|
+
# ----------------------------------------------------
|
1086
|
+
db.beginTrn(Transactd::MULTILOCK_READ_COMMITED)
|
1087
|
+
expect(db.stat()).to eq 0
|
1088
|
+
|
1089
|
+
# read last row
|
1090
|
+
tb.seekLast() # lock(X) last id = 30000
|
1091
|
+
expect(tb.stat()).to eq 0
|
1092
|
+
tb.seekPrev() # Add lock(X)
|
1093
|
+
expect(tb.stat()).to eq 0
|
1094
|
+
last2 = tb.getFVint(FDI_ID)
|
1095
|
+
|
1096
|
+
# insert test row
|
1097
|
+
tb2.setFV(FDI_ID, 29999)
|
1098
|
+
tb2.insert()
|
1099
|
+
expect(tb2.stat()).to eq 0
|
1100
|
+
|
1101
|
+
tb.seekLast()
|
1102
|
+
expect(tb.stat()).to eq 0
|
1103
|
+
tb.seekPrev()
|
1104
|
+
expect(tb.stat()).to eq 0
|
1105
|
+
expect(tb.getFVint(FDI_ID)).not_to eq last2
|
1106
|
+
db.endTrn()
|
1107
|
+
|
1108
|
+
# cleanup
|
1109
|
+
tb2.del() # last id = 29999
|
1110
|
+
expect(tb.stat()).to eq 0
|
1111
|
+
|
1112
|
+
# ----------------------------------------------------
|
1113
|
+
# Abort test
|
1114
|
+
# ----------------------------------------------------
|
1115
|
+
db.beginTrn(Transactd::SINGLELOCK_READ_COMMITED)
|
1116
|
+
expect(db.stat()).to eq 0
|
1117
|
+
|
1118
|
+
tb.seekFirst()
|
1119
|
+
expect(tb.stat()).to eq 0
|
1120
|
+
tb.setFV(FDI_NAME, 'EFG')
|
1121
|
+
tb.update()
|
1122
|
+
expect(tb.stat()).to eq 0
|
1123
|
+
|
1124
|
+
tb.seekNext()
|
1125
|
+
db.abortTrn()
|
669
1126
|
tb2.setKeyNum(0)
|
670
1127
|
tb2.seekFirst()
|
1128
|
+
expect(tb2.getFVstr(FDI_NAME)).to eq 'ABC'
|
1129
|
+
|
1130
|
+
# ----------------------------------------------------
|
1131
|
+
# Test Query and locks Single record lock
|
1132
|
+
# ----------------------------------------------------
|
1133
|
+
db.beginTrn(Transactd::SINGLELOCK_READ_COMMITED)
|
1134
|
+
expect(db.stat()).to eq 0
|
1135
|
+
|
1136
|
+
# Test find last record locked
|
1137
|
+
q = Transactd::Query.new()
|
1138
|
+
q.where('id', '<=', '100')
|
1139
|
+
tb.setQuery(q)
|
1140
|
+
tb.setFV(FDI_ID, 1)
|
1141
|
+
tb.find()
|
1142
|
+
while (tb.stat() == 0) do
|
1143
|
+
tb.findNext()
|
1144
|
+
end
|
1145
|
+
expect(tb.getFVint(FDI_ID)).to eq 100
|
1146
|
+
|
1147
|
+
# find read last is record of id = 101.
|
1148
|
+
# Would be difficult to identify the last
|
1149
|
+
# access to records at SINGLELOCK_READ_COMMITED.
|
1150
|
+
# No match records are unlocked.
|
1151
|
+
tb2.setFV(FDI_ID, 100)
|
1152
|
+
tb2.seek(Transactd::ROW_LOCK_X)
|
1153
|
+
expect(tb2.stat()).to eq 0
|
1154
|
+
tb2.unlock()
|
1155
|
+
db.endTrn()
|
1156
|
+
|
1157
|
+
# ----------------------------------------------------
|
1158
|
+
# Test Query and locks Multi record lock
|
1159
|
+
# ----------------------------------------------------
|
1160
|
+
db.beginTrn(Transactd::MULTILOCK_READ_COMMITED)
|
1161
|
+
expect(db.stat()).to eq 0
|
1162
|
+
|
1163
|
+
# Test find records are lock.
|
1164
|
+
q.reset().where('id', '<=', 15).and_('id', '<>', 13).reject(0xFFFF)
|
1165
|
+
tb.setQuery(q)
|
1166
|
+
tb.setFV(FDI_ID, 12)
|
1167
|
+
tb.find()
|
1168
|
+
while (tb.stat() == 0) do
|
1169
|
+
tb.findNext()
|
1170
|
+
end
|
1171
|
+
expect(tb.getFVint(FDI_ID)).to eq 15
|
1172
|
+
|
1173
|
+
for i in 12..16 do
|
1174
|
+
tb2.setFV(FDI_ID, i)
|
1175
|
+
tb2.seek(Transactd::ROW_LOCK_X)
|
1176
|
+
if ((i == 16) || (i == 13)) then
|
1177
|
+
expect(tb2.stat()).to eq 0
|
1178
|
+
else
|
1179
|
+
expect(tb2.stat()).to eq Transactd::STATUS_LOCK_ERROR
|
1180
|
+
end
|
1181
|
+
end
|
1182
|
+
db.endTrn()
|
1183
|
+
|
1184
|
+
tb2.close()
|
1185
|
+
tb.close()
|
1186
|
+
db2.close()
|
1187
|
+
db.close()
|
1188
|
+
end
|
1189
|
+
|
1190
|
+
def testRecordLock()
|
1191
|
+
db = Transactd::Database.new()
|
1192
|
+
tb = testOpenTable(db)
|
1193
|
+
expect(tb).not_to be nil
|
1194
|
+
db2 = Transactd::Database.new()
|
1195
|
+
db2.connect(PROTOCOL + HOSTNAME + DBNAME, true)
|
1196
|
+
expect(db2.stat()).to eq 0
|
1197
|
+
tb2 = testOpenTable(db2)
|
1198
|
+
expect(tb2).not_to be nil
|
1199
|
+
|
1200
|
+
tb.setKeyNum(0)
|
1201
|
+
tb2.setKeyNum(0)
|
1202
|
+
|
1203
|
+
# Single record lock
|
1204
|
+
tb.seekFirst(Transactd::ROW_LOCK_X) # lock(X)
|
1205
|
+
expect(tb.stat()).to eq 0
|
1206
|
+
tb2.seekFirst() # Use consistent_read
|
1207
|
+
expect(tb2.stat()).to eq 0
|
1208
|
+
|
1209
|
+
tb2.seekFirst(Transactd::ROW_LOCK_X) # Try lock(X) single
|
671
1210
|
expect(tb2.stat()).to eq Transactd::STATUS_LOCK_ERROR
|
1211
|
+
|
1212
|
+
# try consistent_read. Check ended that before auto transaction
|
1213
|
+
tb2.seekFirst()
|
1214
|
+
expect(tb2.stat()).to eq 0
|
1215
|
+
|
1216
|
+
tb2.seekNext(Transactd::ROW_LOCK_X) # lock(X) second
|
1217
|
+
expect(tb2.stat()).to eq 0
|
1218
|
+
|
1219
|
+
tb2.seekNext(Transactd::ROW_LOCK_X) # lock(X) third, second lock freed
|
1220
|
+
expect(tb2.stat()).to eq 0
|
1221
|
+
|
1222
|
+
tb.seekNext() # nobody lock second.
|
1223
|
+
expect(tb.stat()).to eq 0
|
1224
|
+
tb.seekNext(Transactd::ROW_LOCK_X) # Try lock(X) third
|
1225
|
+
expect(tb.stat()).to eq Transactd::STATUS_LOCK_ERROR
|
1226
|
+
|
1227
|
+
# Update test change third with lock(X)
|
1228
|
+
tb2.setFV(FDI_NAME, 'The 3rd')
|
1229
|
+
tb2.update() # auto trn commit and unlock all locks
|
1230
|
+
expect(tb2.stat()).to eq 0
|
1231
|
+
tb2.seekNext(Transactd::ROW_LOCK_X) # lock(X) 4th
|
1232
|
+
expect(tb2.stat()).to eq 0
|
1233
|
+
tb2.setFV(FDI_NAME, 'The 4th')
|
1234
|
+
tb2.update() # auto trn commit and unlock all locks
|
1235
|
+
|
1236
|
+
# Test unlock all locks, after update
|
1237
|
+
tb.seekFirst(Transactd::ROW_LOCK_X) # lock(X) first
|
1238
|
+
expect(tb2.stat()).to eq 0
|
1239
|
+
tb.seekNext(Transactd::ROW_LOCK_X) # lock(X) second
|
1240
|
+
expect(tb2.stat()).to eq 0
|
1241
|
+
tb.seekNext(Transactd::ROW_LOCK_X) # lock(X) third
|
1242
|
+
expect(tb2.stat()).to eq 0
|
1243
|
+
expect(tb.getFVstr(FDI_NAME)).to eq 'The 3rd'
|
1244
|
+
|
1245
|
+
# Test Insert, After record lock operation
|
1246
|
+
tb.setFV(FDI_ID, 21000)
|
1247
|
+
tb.insert()
|
1248
|
+
expect(tb.stat()).to eq 0
|
1249
|
+
tb.del()
|
1250
|
+
expect(tb.stat()).to eq 0
|
1251
|
+
|
1252
|
+
# --------- Unlock test ----------------------------
|
1253
|
+
# 1 unlock()
|
1254
|
+
tb.seekFirst(Transactd::ROW_LOCK_X)
|
1255
|
+
expect(tb.stat()).to eq 0
|
1256
|
+
|
1257
|
+
tb.unlock()
|
1258
|
+
|
1259
|
+
tb2.seekFirst(Transactd::ROW_LOCK_X)
|
1260
|
+
expect(tb2.stat()).to eq 0
|
1261
|
+
tb2.unlock()
|
1262
|
+
|
1263
|
+
# 2 auto tran ended
|
1264
|
+
tb3 = testOpenTable(db2)
|
1265
|
+
tb2.seekFirst(Transactd::ROW_LOCK_X)
|
1266
|
+
expect(tb2.stat()).to eq 0
|
1267
|
+
|
1268
|
+
tb3.seekLast() #This operation is another table handle, then auto tran ended
|
1269
|
+
expect(tb3.stat()).to eq 0
|
1270
|
+
|
1271
|
+
tb.seekFirst(Transactd::ROW_LOCK_X)
|
1272
|
+
expect(tb.stat()).to eq 0
|
1273
|
+
tb.unlock()
|
1274
|
+
|
1275
|
+
# begin trn
|
1276
|
+
tb3.seekFirst(Transactd::ROW_LOCK_X)
|
1277
|
+
expect(tb3.stat()).to eq 0
|
1278
|
+
|
1279
|
+
tb.seekFirst(Transactd::ROW_LOCK_X)
|
1280
|
+
expect(tb.stat()).to eq Transactd::STATUS_LOCK_ERROR
|
1281
|
+
db2.beginTrn()
|
1282
|
+
|
1283
|
+
tb.seekFirst(Transactd::ROW_LOCK_X)
|
1284
|
+
expect(tb.stat()).to eq 0
|
672
1285
|
db2.endTrn()
|
673
|
-
|
674
|
-
#
|
675
|
-
|
676
|
-
|
677
|
-
|
678
|
-
tb.
|
679
|
-
tb.
|
1286
|
+
tb.unlock()
|
1287
|
+
# begin snapshot
|
1288
|
+
tb3.seekFirst(Transactd::ROW_LOCK_X)
|
1289
|
+
expect(tb3.stat()).to eq 0
|
1290
|
+
|
1291
|
+
tb.seekFirst(Transactd::ROW_LOCK_X)
|
1292
|
+
expect(tb.stat()).to eq Transactd::STATUS_LOCK_ERROR
|
1293
|
+
db2.beginSnapshot()
|
1294
|
+
tb.seekFirst(Transactd::ROW_LOCK_X)
|
680
1295
|
expect(tb.stat()).to eq 0
|
681
|
-
|
682
|
-
tb.
|
1296
|
+
db2.endSnapshot()
|
1297
|
+
tb.unlock()
|
1298
|
+
# close Table
|
1299
|
+
tb.seekFirst(Transactd::ROW_LOCK_X)
|
683
1300
|
expect(tb.stat()).to eq 0
|
684
|
-
|
685
|
-
|
686
|
-
|
687
|
-
tb2.setKeyNum(0)
|
688
|
-
tb2.seekFirst()
|
689
|
-
expect(tb2.getFVstr(FDI_NAME)).to eq 'ABC'
|
690
|
-
tb2.close()
|
1301
|
+
|
1302
|
+
tb2.seekFirst(Transactd::ROW_LOCK_X)
|
1303
|
+
expect(tb2.stat()).to eq Transactd::STATUS_LOCK_ERROR
|
691
1304
|
tb.close()
|
1305
|
+
tb2.seekFirst(Transactd::ROW_LOCK_X)
|
1306
|
+
expect(tb2.stat()).to eq 0
|
1307
|
+
tb2.unlock()
|
1308
|
+
# --------- End Unlock test ----------------------------
|
1309
|
+
tb3.close()
|
1310
|
+
tb2.close()
|
692
1311
|
db2.close()
|
693
1312
|
db.close()
|
694
1313
|
end
|
695
1314
|
|
696
1315
|
def testConflict()
|
697
1316
|
db = Transactd::Database.new()
|
1317
|
+
tb = testOpenTable(db)
|
698
1318
|
db2 = Transactd::Database.new()
|
699
1319
|
db2.connect(PROTOCOL + HOSTNAME + DBNAME , true)
|
700
1320
|
expect(db2.stat()).to eq 0
|
701
|
-
tb
|
1321
|
+
expect(tb).not_to be nil
|
702
1322
|
tb2 = testOpenTable(db2)
|
1323
|
+
expect(tb2).not_to be nil
|
703
1324
|
tb.setKeyNum(0)
|
704
1325
|
tb.seekFirst()
|
705
1326
|
expect(tb.stat()).to eq 0
|
@@ -744,6 +1365,9 @@ end
|
|
744
1365
|
def testExclusive()
|
745
1366
|
# db mode exclusive
|
746
1367
|
db = Transactd::Database.new()
|
1368
|
+
# ------------------------------------------------------
|
1369
|
+
# database WRITE EXCLUSIVE
|
1370
|
+
# ------------------------------------------------------
|
747
1371
|
db.open(URL, Transactd::TYPE_SCHEMA_BDF, Transactd::TD_OPEN_EXCLUSIVE)
|
748
1372
|
expect(db.stat()).to eq 0
|
749
1373
|
tb = db.openTable(TABLENAME)
|
@@ -755,73 +1379,176 @@ def testExclusive()
|
|
755
1379
|
expect(db2.stat()).to eq 0
|
756
1380
|
db2.open(URL, Transactd::TYPE_SCHEMA_BDF)
|
757
1381
|
expect(db2.stat()).to eq Transactd::STATUS_CANNOT_LOCK_TABLE
|
1382
|
+
tb.close()
|
1383
|
+
db.close()
|
1384
|
+
db2.close()
|
758
1385
|
|
759
|
-
|
1386
|
+
# ------------------------------------------------------
|
1387
|
+
# database WRITE EXCLUSIVE
|
1388
|
+
# ------------------------------------------------------
|
1389
|
+
# table mode exclusive
|
1390
|
+
db = Transactd::Database.new()
|
1391
|
+
db.open(URL, Transactd::TYPE_SCHEMA_BDF, Transactd::TD_OPEN_READONLY_EXCLUSIVE)
|
1392
|
+
expect(db.stat()).to eq 0
|
1393
|
+
tb = db.openTable(TABLENAME, Transactd::TD_OPEN_READONLY_EXCLUSIVE)
|
760
1394
|
expect(db.stat()).to eq 0
|
761
1395
|
|
762
|
-
|
1396
|
+
# Read only open
|
1397
|
+
db2 = Transactd::Database.new()
|
1398
|
+
db2.open(URL, Transactd::TYPE_SCHEMA_BDF)
|
1399
|
+
expect(db2.stat()).to eq 0
|
1400
|
+
db2.close()
|
1401
|
+
|
1402
|
+
# Normal open
|
1403
|
+
db2.connect(PROTOCOL + HOSTNAME + DBNAME, true)
|
1404
|
+
db2.open(URL, Transactd::TYPE_SCHEMA_BDF, Transactd::TD_OPEN_NORMAL)
|
1405
|
+
expect(db2.stat()).to eq 0
|
1406
|
+
db2.close()
|
1407
|
+
|
1408
|
+
# Write Exclusive open
|
1409
|
+
db2.open(URL, Transactd::TYPE_SCHEMA_BDF, Transactd::TD_OPEN_EXCLUSIVE)
|
1410
|
+
expect(db2.stat()).to eq Transactd::STATUS_CANNOT_LOCK_TABLE
|
1411
|
+
db2.close()
|
1412
|
+
|
1413
|
+
# Read Exclusive open
|
1414
|
+
db2.open(URL, Transactd::TYPE_SCHEMA_BDF, Transactd::TD_OPEN_READONLY_EXCLUSIVE)
|
1415
|
+
expect(db2.stat()).to eq 0
|
1416
|
+
db2.close()
|
1417
|
+
tb.close()
|
1418
|
+
db.close()
|
1419
|
+
|
1420
|
+
# ------------------------------------------------------
|
1421
|
+
# Normal and Exclusive open tables mix use
|
1422
|
+
# ------------------------------------------------------
|
1423
|
+
db.open(URL, Transactd::TYPE_SCHEMA_BDF, Transactd::TD_OPEN_NORMAL)
|
1424
|
+
expect(db.stat()).to eq 0
|
1425
|
+
tb = db.openTable(TABLENAME, Transactd::TD_OPEN_NORMAL)
|
1426
|
+
expect(db.stat()).to eq 0
|
1427
|
+
db2.open(URL, Transactd::TYPE_SCHEMA_BDF)
|
1428
|
+
expect(db2.stat()).to eq 0
|
1429
|
+
|
1430
|
+
tb2 = db.openTable('group', Transactd::TD_OPEN_EXCLUSIVE)
|
1431
|
+
expect(db.stat()).to eq 0
|
1432
|
+
# Check tb2 Exclusive
|
1433
|
+
tb3 = db2.openTable('group', Transactd::TD_OPEN_NORMAL)
|
1434
|
+
expect(db2.stat()).to eq Transactd::STATUS_CANNOT_LOCK_TABLE
|
1435
|
+
|
1436
|
+
for i in 1..4 do
|
1437
|
+
tb2.setFV(FDI_ID, i + 1)
|
1438
|
+
tb2.setFV(FDI_NAME, i + 1)
|
1439
|
+
tb2.insert()
|
1440
|
+
expect(tb2.stat()).to eq 0
|
1441
|
+
end
|
1442
|
+
tb2.seekFirst()
|
1443
|
+
expect(tb2.stat()).to eq 0
|
1444
|
+
tb.seekFirst()
|
1445
|
+
expect(tb.stat()).to eq 0
|
1446
|
+
tb2.seekLast()
|
1447
|
+
expect(tb2.stat()).to eq 0
|
1448
|
+
tb.seekLast()
|
1449
|
+
expect(tb.stat()).to eq 0
|
1450
|
+
# Normal close first
|
1451
|
+
tb.close()
|
1452
|
+
tb2.seekLast()
|
1453
|
+
expect(tb2.stat()).to eq 0
|
1454
|
+
tb2.seekFirst()
|
1455
|
+
expect(tb2.stat()).to eq 0
|
1456
|
+
|
1457
|
+
# Reopen Normal
|
1458
|
+
tb = db.openTable('user')
|
1459
|
+
tb2.seekFirst()
|
1460
|
+
expect(tb2.stat()).to eq 0
|
1461
|
+
tb.seekFirst()
|
1462
|
+
expect(tb.stat()).to eq 0
|
1463
|
+
tb2.seekLast()
|
1464
|
+
expect(tb2.stat()).to eq 0
|
1465
|
+
tb.seekLast()
|
1466
|
+
expect(tb.stat()).to eq 0
|
1467
|
+
# Exclusive close first
|
1468
|
+
tb2.close()
|
763
1469
|
tb.seekFirst()
|
764
1470
|
expect(tb.stat()).to eq 0
|
1471
|
+
tb.seekLast()
|
1472
|
+
expect(tb.stat()).to eq 0
|
1473
|
+
|
1474
|
+
tb2.close()
|
765
1475
|
|
766
|
-
|
1476
|
+
# ------------------------------------------------------
|
1477
|
+
# Normal and Exclusive opend tables mix transaction
|
1478
|
+
# ------------------------------------------------------
|
1479
|
+
tb2 = db.openTable('group', Transactd::TD_OPEN_EXCLUSIVE)
|
1480
|
+
expect(tb2.stat()).to eq 0
|
1481
|
+
# Check tb2 Exclusive
|
1482
|
+
tb3 = db2.openTable('group', Transactd::TD_OPEN_NORMAL)
|
1483
|
+
expect(db2.stat()).to eq Transactd::STATUS_CANNOT_LOCK_TABLE
|
1484
|
+
|
1485
|
+
db.beginTrn()
|
1486
|
+
tb.seekFirst()
|
1487
|
+
expect(tb.stat()).to eq 0
|
1488
|
+
tb.setFV(FDI_NAME, 'mix trn')
|
767
1489
|
tb.update()
|
768
1490
|
expect(tb.stat()).to eq 0
|
769
1491
|
|
770
|
-
tb2.setKeyNum(0)
|
771
1492
|
tb2.seekFirst()
|
772
1493
|
expect(tb2.stat()).to eq 0
|
773
|
-
tb2.setFV(FDI_NAME, '
|
1494
|
+
tb2.setFV(FDI_NAME, 'first mix trn tb2')
|
1495
|
+
tb2.update()
|
1496
|
+
expect(tb2.stat()).to eq 0
|
1497
|
+
|
1498
|
+
tb2.seekNext()
|
1499
|
+
tb2.setFV(FDI_NAME, 'second mix trn tb2')
|
774
1500
|
tb2.update()
|
775
1501
|
expect(tb2.stat()).to eq 0
|
1502
|
+
db.endTrn()
|
1503
|
+
tb2.seekFirst()
|
1504
|
+
v = tb2.getFVstr(FDI_NAME)
|
1505
|
+
expect(v).to eq 'first mix trn tb2'
|
1506
|
+
tb2.seekNext()
|
1507
|
+
v = tb2.getFVstr(FDI_NAME)
|
1508
|
+
expect(v).to eq 'second mix trn tb2'
|
776
1509
|
|
777
1510
|
tb2.close()
|
778
1511
|
tb.close()
|
779
1512
|
db2.close()
|
780
1513
|
db.close()
|
781
|
-
|
782
|
-
|
1514
|
+
end
|
1515
|
+
|
1516
|
+
def testMultiDatabase()
|
783
1517
|
db = Transactd::Database.new()
|
784
|
-
|
785
|
-
expect(
|
786
|
-
tb = db.openTable(TABLENAME, Transactd::TD_OPEN_EXCLUSIVE)
|
787
|
-
expect(db.stat()).to eq 0
|
788
|
-
|
1518
|
+
tb = testOpenTable(db)
|
1519
|
+
expect(tb).not_to be nil
|
789
1520
|
db2 = Transactd::Database.new()
|
790
|
-
db2
|
1521
|
+
testOpenDatabase(db2)
|
791
1522
|
expect(db2.stat()).to eq 0
|
792
|
-
db2.
|
1523
|
+
tb2 = db2.openTable('group')
|
793
1524
|
expect(db2.stat()).to eq 0
|
1525
|
+
expect(tb2).not_to be nil
|
794
1526
|
|
795
|
-
|
796
|
-
|
797
|
-
expect(db2.stat()).to eq Transactd::STATUS_CANNOT_LOCK_TABLE
|
798
|
-
|
799
|
-
# Can open table from the same connection.
|
800
|
-
tb3 = db.openTable(TABLENAME)
|
801
|
-
expect(db.stat()).to eq 0
|
802
|
-
|
803
|
-
tb3.close()
|
804
|
-
tb2.close() if tb2 != nil
|
805
|
-
tb.close()
|
806
|
-
db2.close()
|
807
|
-
db.close()
|
808
|
-
|
809
|
-
# reopen and update
|
810
|
-
db = Transactd::Database.new()
|
811
|
-
db.open(URL)
|
812
|
-
expect(db.stat()).to eq 0
|
813
|
-
tb = db.openTable(TABLENAME)
|
814
|
-
expect(db.stat()).to eq 0
|
1527
|
+
db.beginTrn()
|
1528
|
+
db2.beginTrn()
|
815
1529
|
|
816
|
-
tb.setKeyNum(0)
|
817
1530
|
tb.seekFirst()
|
818
1531
|
expect(tb.stat()).to eq 0
|
819
|
-
|
820
|
-
tb.setFV(FDI_NAME, '
|
1532
|
+
v = tb.getFVstr(FDI_NAME)
|
1533
|
+
tb.setFV(FDI_NAME, 'MultiDatabase')
|
821
1534
|
tb.update()
|
1535
|
+
|
1536
|
+
tb2.seekFirst()
|
1537
|
+
expect(tb2.stat()).to eq 0
|
1538
|
+
tb2.setFV(FDI_NAME, 'MultiDatabase')
|
1539
|
+
tb2.update()
|
1540
|
+
expect(tb2.stat()).to eq 0
|
1541
|
+
db2.endTrn()
|
1542
|
+
db.abortTrn()
|
1543
|
+
|
1544
|
+
tb.seekFirst()
|
822
1545
|
expect(tb.stat()).to eq 0
|
1546
|
+
v2 = tb.getFVstr(FDI_NAME)
|
1547
|
+
expect(v).to eq v2
|
823
1548
|
|
1549
|
+
tb2.close()
|
824
1550
|
tb.close()
|
1551
|
+
db2.close()
|
825
1552
|
db.close()
|
826
1553
|
end
|
827
1554
|
|
@@ -917,10 +1644,9 @@ def testLogin()
|
|
917
1644
|
if db.stat() == 0
|
918
1645
|
# second connection
|
919
1646
|
db2 = Transactd::Database.new()
|
920
|
-
db2.connect(PROTOCOL + HOSTNAME
|
921
|
-
expect(
|
922
|
-
db2.
|
923
|
-
db2 = nil
|
1647
|
+
db2.connect(PROTOCOL + HOSTNAME, true)
|
1648
|
+
expect(db2.stat()).to eq 0
|
1649
|
+
db2.disconnect(PROTOCOL + HOSTNAME)
|
924
1650
|
db.disconnect(PROTOCOL + HOSTNAME)
|
925
1651
|
expect(db.stat()).to eq 0
|
926
1652
|
end
|
@@ -1125,98 +1851,98 @@ def testSetGetVar(tb, unicodeField, varCharField)
|
|
1125
1851
|
#end
|
1126
1852
|
### Set Ansi Get Wide
|
1127
1853
|
# too long string
|
1128
|
-
tb.
|
1854
|
+
tb.setFV(FDI_NAME, '1234567')
|
1129
1855
|
if (varCharField)
|
1130
|
-
expect(tb.
|
1856
|
+
expect(tb.getFVstr(FDI_NAME)).to eq '123'
|
1131
1857
|
else
|
1132
|
-
expect(tb.
|
1858
|
+
expect(tb.getFVstr(FDI_NAME)).to eq '123456'
|
1133
1859
|
end
|
1134
1860
|
#if IS_WINDOWS
|
1135
1861
|
# expect(tb.getFVWstr(FDI_GROUP)).to eq '68'
|
1136
1862
|
#else
|
1137
|
-
expect(tb.
|
1863
|
+
expect(tb.getFVstr(FDI_GROUP)).to eq '68'
|
1138
1864
|
#end
|
1139
1865
|
# short string
|
1140
|
-
tb.
|
1141
|
-
expect(tb.
|
1866
|
+
tb.setFV(FDI_NAME, '13 ')
|
1867
|
+
expect(tb.getFVstr(FDI_NAME)).to eq '13 '
|
1142
1868
|
#if IS_WINDOWS
|
1143
1869
|
# expect(tb.getFVWstr(FDI_GROUP)).to eq '68'
|
1144
1870
|
#else
|
1145
|
-
expect(tb.
|
1871
|
+
expect(tb.getFVstr(FDI_GROUP)).to eq '68'
|
1146
1872
|
#end
|
1147
1873
|
# too long kanji
|
1148
1874
|
if (unicodeField)
|
1149
1875
|
if !IS_WINDOWS
|
1150
|
-
tb.
|
1876
|
+
tb.setFV(FDI_NAME, 'あいうえお𩸽') # hiragana 'aiueo' kanji 'hokke'
|
1151
1877
|
if (varCharField)
|
1152
|
-
expect(tb.
|
1878
|
+
expect(tb.getFVstr(FDI_NAME)).to eq 'あいう'
|
1153
1879
|
else
|
1154
|
-
expect(tb.
|
1880
|
+
expect(tb.getFVstr(FDI_NAME)).to eq 'あいうえお'
|
1155
1881
|
end
|
1156
1882
|
end
|
1157
1883
|
else
|
1158
|
-
tb.
|
1159
|
-
is_valid_value = tb.
|
1884
|
+
tb.setFV(FDI_NAME, '0松本市') # numeric '0' kanji 'matumostoshi'
|
1885
|
+
is_valid_value = tb.getFVstr(FDI_NAME) == '0松本'
|
1160
1886
|
expect(is_valid_value).to be true
|
1161
|
-
puts tb.
|
1887
|
+
puts tb.getFVstr(FDI_NAME) if (!is_valid_value)
|
1162
1888
|
end
|
1163
|
-
expect(tb.
|
1889
|
+
expect(tb.getFVstr(FDI_GROUP)).to eq '68'
|
1164
1890
|
### Set Wide Get Ansi
|
1165
1891
|
#if IS_WINDOWS
|
1166
1892
|
# # too long string
|
1167
1893
|
# tb.setFVW(FDI_NAME, '1234567')
|
1168
1894
|
# if (varCharField)
|
1169
|
-
# expect(tb.
|
1895
|
+
# expect(tb.getFVstr(FDI_NAME)).to eq '123'
|
1170
1896
|
# else
|
1171
|
-
# expect(tb.
|
1897
|
+
# expect(tb.getFVstr(FDI_NAME)).to eq '123456'
|
1172
1898
|
# end
|
1173
1899
|
# expect(tb.getFVWstr(FDI_GROUP)).to eq '68'
|
1174
1900
|
# # short string
|
1175
1901
|
# tb.setFVW(1, '23 ')
|
1176
|
-
# expect(tb.
|
1902
|
+
# expect(tb.getFVstr(FDI_NAME)).to eq '23 '
|
1177
1903
|
# expect(tb.getFVWstr(FDI_GROUP)).to eq '68'
|
1178
1904
|
# # too long kanji
|
1179
1905
|
# if (unicodeField)
|
1180
1906
|
# tb.setFVW(FDI_NAME, 'あいうえお𩸽') # hiragana 'aiueo' kanji 'hokke'
|
1181
1907
|
# if (varCharField)
|
1182
|
-
# expect(tb.
|
1908
|
+
# expect(tb.getFVstr(FDI_NAME)).to eq 'あいう'
|
1183
1909
|
# else
|
1184
|
-
# expect(tb.
|
1910
|
+
# expect(tb.getFVstr(FDI_NAME)).to eq 'あいうえお'
|
1185
1911
|
# end
|
1186
1912
|
# else
|
1187
1913
|
# tb.setFVW(FDI_NAME, '0松本市') # numeric '0' kanji 'matumostoshi'
|
1188
|
-
# expect(tb.
|
1914
|
+
# expect(tb.getFVstr(FDI_NAME)).to eq '0松本'
|
1189
1915
|
# end
|
1190
1916
|
# expect(tb.getFVWstr(FDI_GROUP)).to eq '68'
|
1191
1917
|
#end
|
1192
1918
|
### Set Ansi Get Ansi
|
1193
1919
|
# too long string
|
1194
|
-
tb.
|
1920
|
+
tb.setFV(FDI_NAME, '1234567')
|
1195
1921
|
if (varCharField)
|
1196
|
-
expect(tb.
|
1922
|
+
expect(tb.getFVstr(FDI_NAME)).to eq '123'
|
1197
1923
|
else
|
1198
|
-
expect(tb.
|
1924
|
+
expect(tb.getFVstr(FDI_NAME)).to eq '123456'
|
1199
1925
|
end
|
1200
|
-
expect(tb.
|
1926
|
+
expect(tb.getFVstr(FDI_GROUP)).to eq '68'
|
1201
1927
|
# short string
|
1202
|
-
tb.
|
1203
|
-
expect(tb.
|
1204
|
-
expect(tb.
|
1928
|
+
tb.setFV(FDI_NAME, '13 ')
|
1929
|
+
expect(tb.getFVstr(FDI_NAME)).to eq '13 '
|
1930
|
+
expect(tb.getFVstr(FDI_GROUP)).to eq '68'
|
1205
1931
|
# too long lanji
|
1206
1932
|
if (unicodeField)
|
1207
1933
|
if !IS_WINDOWS
|
1208
|
-
tb.
|
1934
|
+
tb.setFV(FDI_NAME, 'あいうえお𩸽') # hiragana 'aiueo' kanji 'hokke'
|
1209
1935
|
if (varCharField)
|
1210
|
-
expect(tb.
|
1936
|
+
expect(tb.getFVstr(FDI_NAME)).to eq 'あいう'
|
1211
1937
|
else
|
1212
|
-
expect(tb.
|
1938
|
+
expect(tb.getFVstr(FDI_NAME)).to eq 'あいうえお'
|
1213
1939
|
end
|
1214
1940
|
end
|
1215
1941
|
else
|
1216
|
-
tb.
|
1217
|
-
expect(tb.
|
1942
|
+
tb.setFV(FDI_NAME, '0松本市') # numeric '0' kanji 'matumostoshi'
|
1943
|
+
expect(tb.getFVstr(FDI_NAME)).to eq '0松本'
|
1218
1944
|
end
|
1219
|
-
expect(tb.
|
1945
|
+
expect(tb.getFVstr(FDI_GROUP)).to eq '68'
|
1220
1946
|
end
|
1221
1947
|
|
1222
1948
|
def testVarField()
|
@@ -1827,7 +2553,7 @@ def createQTuser(db)
|
|
1827
2553
|
td.id = id
|
1828
2554
|
td.pageSize = 2048
|
1829
2555
|
td.schemaCodePage = Transactd::CP_UTF8
|
1830
|
-
td.charsetIndex = Transactd::
|
2556
|
+
td.charsetIndex = Transactd::CHARSET_UTF8
|
1831
2557
|
dbdef.insertTable(td)
|
1832
2558
|
expect(dbdef.stat()).to eq 0
|
1833
2559
|
# id field
|
@@ -1884,7 +2610,7 @@ def createQTgroups(db)
|
|
1884
2610
|
td.id = id
|
1885
2611
|
td.pageSize = 2048
|
1886
2612
|
td.schemaCodePage = Transactd::CP_UTF8
|
1887
|
-
td.charsetIndex = Transactd::
|
2613
|
+
td.charsetIndex = Transactd::CHARSET_UTF8
|
1888
2614
|
dbdef.insertTable(td)
|
1889
2615
|
expect(dbdef.stat()).to eq 0
|
1890
2616
|
# code field
|
@@ -1924,7 +2650,7 @@ def createQTextention(db)
|
|
1924
2650
|
td.id = id
|
1925
2651
|
td.pageSize = 2048
|
1926
2652
|
td.schemaCodePage = Transactd::CP_UTF8
|
1927
|
-
td.charsetIndex = Transactd::
|
2653
|
+
td.charsetIndex = Transactd::CHARSET_UTF8
|
1928
2654
|
dbdef.insertTable(td)
|
1929
2655
|
expect(dbdef.stat()).to eq 0
|
1930
2656
|
# id field
|
@@ -1937,6 +2663,11 @@ def createQTextention(db)
|
|
1937
2663
|
fd.setName('comment')
|
1938
2664
|
fd.type = Transactd::Ft_myvarchar
|
1939
2665
|
fd.setLenByCharnum(60)
|
2666
|
+
# blob field
|
2667
|
+
fd = dbdef.insertField(id, 2)
|
2668
|
+
fd.setName('blob')
|
2669
|
+
fd.type = Transactd::Ft_myblob
|
2670
|
+
fd.len = 10
|
1940
2671
|
# key 0 (primary) id
|
1941
2672
|
kd = dbdef.insertKey(id, 0)
|
1942
2673
|
kd.segment(0).fieldNum = 0
|
@@ -1960,6 +2691,7 @@ def insertQT(db, maxId)
|
|
1960
2691
|
# insert user data
|
1961
2692
|
tb = db.openTable('user', Transactd::TD_OPEN_NORMAL)
|
1962
2693
|
expect(db.stat()).to eq 0
|
2694
|
+
expect(tb).not_to be nil
|
1963
2695
|
tb.clearBuffer()
|
1964
2696
|
for i in 1..maxId
|
1965
2697
|
tb.setFV(0, i)
|
@@ -1972,6 +2704,7 @@ def insertQT(db, maxId)
|
|
1972
2704
|
# insert groups data
|
1973
2705
|
tb = db.openTable('groups', Transactd::TD_OPEN_NORMAL)
|
1974
2706
|
expect(db.stat()).to eq 0
|
2707
|
+
expect(tb).not_to be nil
|
1975
2708
|
tb.clearBuffer()
|
1976
2709
|
for i in 1..100
|
1977
2710
|
tb.setFV(0, i)
|
@@ -1983,10 +2716,12 @@ def insertQT(db, maxId)
|
|
1983
2716
|
# insert extention data
|
1984
2717
|
tb = db.openTable('extention', Transactd::TD_OPEN_NORMAL)
|
1985
2718
|
expect(db.stat()).to eq 0
|
2719
|
+
expect(tb).not_to be nil
|
1986
2720
|
tb.clearBuffer()
|
1987
2721
|
for i in 1..maxId
|
1988
2722
|
tb.setFV(0, i)
|
1989
2723
|
tb.setFV(1, "#{i} comment")
|
2724
|
+
tb.setFV(2, "#{i} blob")
|
1990
2725
|
tb.insert()
|
1991
2726
|
expect(tb.stat()).to eq 0
|
1992
2727
|
end
|
@@ -1998,11 +2733,21 @@ def testCreateQueryTest()
|
|
1998
2733
|
# check database existence
|
1999
2734
|
db = Transactd::Database.new()
|
2000
2735
|
db.open(URL_QT, Transactd::TYPE_SCHEMA_BDF, Transactd::TD_OPEN_NORMAL)
|
2001
|
-
if (db.stat()
|
2002
|
-
|
2003
|
-
|
2736
|
+
if (db.stat() != 0) then
|
2737
|
+
puts "\nDatabase " + DBNAME_QT + " not found\n"
|
2738
|
+
else
|
2739
|
+
dbdef = db.dbDef()
|
2740
|
+
td = dbdef.tableDefs(3)
|
2741
|
+
if (td != nil && td.fieldCount == 3) then
|
2742
|
+
tb = db.openTable('extention')
|
2743
|
+
if (db.stat() == 0 && tb.recordCount(false) == TEST_COUNT)
|
2744
|
+
return
|
2745
|
+
end
|
2746
|
+
tb.close()
|
2747
|
+
end
|
2748
|
+
db.drop()
|
2004
2749
|
end
|
2005
|
-
puts "\
|
2750
|
+
puts "\nCreate database " + DBNAME_QT + "\n"
|
2006
2751
|
db.create(URL_QT)
|
2007
2752
|
expect(db.stat()).to eq 0
|
2008
2753
|
db.open(URL_QT, Transactd::TYPE_SCHEMA_BDF, Transactd::TD_OPEN_NORMAL)
|
@@ -2173,6 +2918,231 @@ def testJoin()
|
|
2173
2918
|
db.close()
|
2174
2919
|
end
|
2175
2920
|
|
2921
|
+
def testPrepareJoin()
|
2922
|
+
db = Transactd::Database.new()
|
2923
|
+
db.open(URL_QT)
|
2924
|
+
expect(db.stat()).to eq 0
|
2925
|
+
|
2926
|
+
atu = Transactd::ActiveTable.new(db, 'user')
|
2927
|
+
atu.alias('名前', 'name')
|
2928
|
+
atg = Transactd::ActiveTable.new(db, 'groups')
|
2929
|
+
atg.alias('name', 'group_name')
|
2930
|
+
ate = Transactd::ActiveTable.new(db, 'extention')
|
2931
|
+
q = Transactd::Query.new()
|
2932
|
+
|
2933
|
+
q.select('id', 'name', 'group').where('id', '<=', '?')
|
2934
|
+
pq = atu.prepare(q)
|
2935
|
+
|
2936
|
+
# integer value
|
2937
|
+
rs = atu.index(0).keyValue('1').read(pq, 15000)
|
2938
|
+
expect(rs.size()).to eq 15000
|
2939
|
+
# float value
|
2940
|
+
rs = atu.index(0).keyValue('1').read(pq, 15000.000)
|
2941
|
+
expect(rs.size()).to eq 15000
|
2942
|
+
# String value
|
2943
|
+
rs = atu.index(0).keyValue('1').read(pq, '15000')
|
2944
|
+
expect(rs.size()).to eq 15000
|
2945
|
+
# Using supply value
|
2946
|
+
pq.supplyValue(0, 15000)
|
2947
|
+
rs = atu.index(0).keyValue('1').read(pq)
|
2948
|
+
expect(rs.size()).to eq 15000
|
2949
|
+
|
2950
|
+
# Join extention::comment
|
2951
|
+
q.reset().select('comment').optimize(Transactd::QueryBase::JoinHasOneOrHasMany)
|
2952
|
+
pq = ate.prepare(q)
|
2953
|
+
ate.index(0).join(rs, pq, 'id')
|
2954
|
+
expect(rs.size()).to eq 15000
|
2955
|
+
|
2956
|
+
# reverse and get first (so it means 'get last')
|
2957
|
+
last = rs.reverse().first()
|
2958
|
+
expect(last['id']).to eq 15000
|
2959
|
+
expect(last['comment']).to eq '15000 comment'
|
2960
|
+
|
2961
|
+
# Join group::name
|
2962
|
+
q.reset().select('group_name')
|
2963
|
+
pq = atg.prepare(q)
|
2964
|
+
atg.index(0).join(rs, pq, 'group')
|
2965
|
+
expect(rs.size()).to eq 15000
|
2966
|
+
|
2967
|
+
# get last (the rs is reversed, so it means 'get first')
|
2968
|
+
first = rs.last()
|
2969
|
+
expect(first['id']).to eq 1
|
2970
|
+
expect(first['comment']).to eq '1 comment'
|
2971
|
+
expect(first['group_name']).to eq '1 group'
|
2972
|
+
|
2973
|
+
# row in rs[15000 - 9]
|
2974
|
+
rec = rs[15000 - 9]
|
2975
|
+
expect(rec['group_name']).to eq '4 group'
|
2976
|
+
|
2977
|
+
atu.release()
|
2978
|
+
atg.release()
|
2979
|
+
ate.release()
|
2980
|
+
db.close()
|
2981
|
+
end
|
2982
|
+
|
2983
|
+
def testServerPrepareJoin()
|
2984
|
+
db = Transactd::Database.new()
|
2985
|
+
db.open(URL_QT)
|
2986
|
+
expect(db.stat()).to eq 0
|
2987
|
+
|
2988
|
+
atu = Transactd::ActiveTable.new(db, 'user')
|
2989
|
+
atu.alias('名前', 'name')
|
2990
|
+
atg = Transactd::ActiveTable.new(db, 'groups')
|
2991
|
+
atg.alias('name', 'group_name')
|
2992
|
+
ate = Transactd::ActiveTable.new(db, 'extention')
|
2993
|
+
q = Transactd::Query.new()
|
2994
|
+
|
2995
|
+
q.select('id', 'name', 'group').where('id', '<=', '?')
|
2996
|
+
stmt1 = atu.prepare(q, true)
|
2997
|
+
expect(stmt1).not_to eq nil
|
2998
|
+
|
2999
|
+
q.reset().select('comment').optimize(Transactd::QueryBase::JoinHasOneOrHasMany)
|
3000
|
+
stmt2 = ate.prepare(q, true)
|
3001
|
+
expect(stmt2).not_to eq nil
|
3002
|
+
|
3003
|
+
q.reset().select('group_name')
|
3004
|
+
stmt3 = atg.prepare(q, true)
|
3005
|
+
expect(stmt3).not_to eq nil
|
3006
|
+
|
3007
|
+
rs = atu.index(0).keyValue(1).read(stmt1, 15000)
|
3008
|
+
expect(rs.size()).to eq 15000
|
3009
|
+
|
3010
|
+
# Join extention::comment
|
3011
|
+
ate.index(0).join(rs, stmt2, 'id')
|
3012
|
+
expect(rs.size()).to eq 15000
|
3013
|
+
|
3014
|
+
# test reverse
|
3015
|
+
last = rs.reverse().first()
|
3016
|
+
expect(last['id']).to eq 15000
|
3017
|
+
expect(last['comment']).to eq '15000 comment'
|
3018
|
+
|
3019
|
+
# Join group::name
|
3020
|
+
atg.index(0).join(rs, stmt3, 'group')
|
3021
|
+
expect(rs.size()).to eq 15000
|
3022
|
+
first = rs.last()
|
3023
|
+
|
3024
|
+
expect(first['id']).to eq 1
|
3025
|
+
expect(first['comment']).to eq '1 comment'
|
3026
|
+
expect(first['group_name']).to eq '1 group'
|
3027
|
+
|
3028
|
+
# rs[15000 - 9]
|
3029
|
+
rec = rs[15000 - 9]
|
3030
|
+
expect(rec['group_name']).to eq '4 group'
|
3031
|
+
|
3032
|
+
# Test orderby
|
3033
|
+
rs.orderBy('group_name')
|
3034
|
+
# rs[0]
|
3035
|
+
expect(rs[0]['group_name']).to eq '1 group'
|
3036
|
+
|
3037
|
+
=begin
|
3038
|
+
sortFields orderRv
|
3039
|
+
orderRv.add('group_name', false)
|
3040
|
+
rs.orderBy(orderRv)
|
3041
|
+
|
3042
|
+
sortFields order
|
3043
|
+
order.add('group_name', true)
|
3044
|
+
rs.orderBy(order)
|
3045
|
+
BOOST_CHECK_MESSAGE(_tstring(rs[(size_t)0]['group_name'].c_str()) ==
|
3046
|
+
_tstring('1 group'),
|
3047
|
+
"group_name = 1 group "
|
3048
|
+
<< string(rs[(size_t)0]['group_name'].a_str()))
|
3049
|
+
=end
|
3050
|
+
|
3051
|
+
# All fields
|
3052
|
+
rs.clear()
|
3053
|
+
q.reset().all()
|
3054
|
+
q.where('id', '<=', '?')
|
3055
|
+
stmt1 = atu.prepare(q, true)
|
3056
|
+
rs = atu.keyValue(1).read(stmt1, 15000)
|
3057
|
+
expect(rs.size()).to eq 15000
|
3058
|
+
if (rs.size() == 15000) then
|
3059
|
+
for i in 0..14999 do
|
3060
|
+
expect(rs[i]['id']).to eq i + 1
|
3061
|
+
end
|
3062
|
+
end
|
3063
|
+
|
3064
|
+
ate.join(rs, stmt2, 'id')
|
3065
|
+
expect(rs.size()).to eq 15000
|
3066
|
+
atg.join(rs, stmt3, 'group')
|
3067
|
+
expect(rs.size()).to eq 15000
|
3068
|
+
|
3069
|
+
# OuterJoin
|
3070
|
+
tb = ate.table()
|
3071
|
+
tb.setFV('id', NO_RECORD_ID)
|
3072
|
+
tb.seek()
|
3073
|
+
expect(tb.stat()).to eq 0
|
3074
|
+
tb.del() if (tb.stat() == 0)
|
3075
|
+
expect(tb.stat()).to eq 0
|
3076
|
+
q.reset().select('comment', 'blob').optimize(Transactd::QueryBase::JoinHasOneOrHasMany)
|
3077
|
+
stmt2 = ate.prepare(q, true)
|
3078
|
+
|
3079
|
+
# Join is remove record(s) no join target record.
|
3080
|
+
rs.clear()
|
3081
|
+
rs = atu.keyValue(1).read(stmt1, 15000)
|
3082
|
+
ate.join(rs, stmt2, 'id')
|
3083
|
+
expect(rs.size()).to eq 14999
|
3084
|
+
expect(rs[NO_RECORD_ID - 1]['id']).to eq (NO_RECORD_ID + 1)
|
3085
|
+
expect(rs[NO_RECORD_ID - 1]['comment']).to eq "#{NO_RECORD_ID + 1} comment"
|
3086
|
+
expect(rs[NO_RECORD_ID - 1]['blob']).to eq "#{NO_RECORD_ID + 1} blob"
|
3087
|
+
|
3088
|
+
# OuterJoin is no remove record(s) no join target record.
|
3089
|
+
rs.clear()
|
3090
|
+
rs = atu.keyValue(1).read(stmt1, 15000)
|
3091
|
+
ate.outerJoin(rs, stmt2, 'id')
|
3092
|
+
expect(rs.size()).to eq 15000
|
3093
|
+
atg.outerJoin(rs, stmt3, 'group')
|
3094
|
+
expect(rs.size()).to eq 15000
|
3095
|
+
|
3096
|
+
expect(rs[NO_RECORD_ID - 1].isInvalidRecord()).to eq true
|
3097
|
+
expect(rs[NO_RECORD_ID]['comment']).to eq "#{NO_RECORD_ID + 1} comment"
|
3098
|
+
expect(rs[NO_RECORD_ID]['blob']).to eq "#{NO_RECORD_ID + 1} blob"
|
3099
|
+
|
3100
|
+
# OuterJoin All Join fields
|
3101
|
+
q.reset().optimize(Transactd::QueryBase::JoinHasOneOrHasMany).all()
|
3102
|
+
stmt2 = ate.prepare(q, true)
|
3103
|
+
rs.clear()
|
3104
|
+
rs = atu.keyValue(1).read(stmt1, 15000)
|
3105
|
+
ate.outerJoin(rs, stmt2, 'id')
|
3106
|
+
expect(rs.size()).to eq 15000
|
3107
|
+
expect(rs[NO_RECORD_ID - 1].isInvalidRecord()).to eq true
|
3108
|
+
expect(rs[NO_RECORD_ID]['comment']).to eq "#{NO_RECORD_ID + 1} comment"
|
3109
|
+
expect(rs[NO_RECORD_ID]['blob']).to eq "#{NO_RECORD_ID + 1} blob"
|
3110
|
+
|
3111
|
+
# Test clone blob field
|
3112
|
+
rs2 = rs.clone()
|
3113
|
+
expect(rs2.size()).to eq 15000
|
3114
|
+
expect(rs2[NO_RECORD_ID - 1].isInvalidRecord()).to eq true
|
3115
|
+
expect(rs2[NO_RECORD_ID]['comment']).to eq "#{NO_RECORD_ID + 1} comment"
|
3116
|
+
expect(rs2[NO_RECORD_ID]['blob']).to eq "#{NO_RECORD_ID + 1} blob"
|
3117
|
+
|
3118
|
+
# hasManyJoin inner
|
3119
|
+
rs.clear()
|
3120
|
+
q.reset().reject(0xFFFF).limit(0).all()
|
3121
|
+
rs = atg.keyValue(1).read(q)
|
3122
|
+
expect(rs.size()).to eq 100
|
3123
|
+
q.all().optimize(Transactd::QueryBase::JoinHasOneOrHasMany)
|
3124
|
+
atu.index(1).join(rs, q, 'code')
|
3125
|
+
expect(rs.size()).to eq 20000
|
3126
|
+
|
3127
|
+
# hasManyJoin outer
|
3128
|
+
rs.clear()
|
3129
|
+
q.reset().reject(0xFFFF).limit(0).all()
|
3130
|
+
rs = atg.keyValue(1).read(q)
|
3131
|
+
expect(rs.size()).to eq 100
|
3132
|
+
q.all().optimize(Transactd::QueryBase::JoinHasOneOrHasMany)
|
3133
|
+
atu.index(1).outerJoin(rs, q, 'code')
|
3134
|
+
expect(rs.size()).to eq 20095
|
3135
|
+
|
3136
|
+
# restore record
|
3137
|
+
tb.clearBuffer()
|
3138
|
+
tb.setFV('id', NO_RECORD_ID)
|
3139
|
+
tb.setFV('comment', '5 comment')
|
3140
|
+
tb.setFV('blob', '5 blob')
|
3141
|
+
tb.insert()
|
3142
|
+
expect(tb.stat()).to eq 0
|
3143
|
+
db.drop() unless (tb.stat() == 0)
|
3144
|
+
end
|
3145
|
+
|
2176
3146
|
def testWirtableRecord()
|
2177
3147
|
db = Transactd::Database.new()
|
2178
3148
|
db.open(URL_QT)
|
@@ -2302,17 +3272,26 @@ describe Transactd do
|
|
2302
3272
|
testUpdate()
|
2303
3273
|
end
|
2304
3274
|
it 'snapshot' do
|
2305
|
-
|
3275
|
+
testSnapshot()
|
2306
3276
|
end
|
2307
3277
|
it 'send conflict error' do
|
2308
3278
|
testConflict()
|
2309
3279
|
end
|
2310
|
-
it 'transaction' do
|
2311
|
-
|
3280
|
+
it 'transaction (REPEATABLE_READ)' do
|
3281
|
+
testTransactionLockRepeatable()
|
3282
|
+
end
|
3283
|
+
it 'transaction (READ_COMMITED)' do
|
3284
|
+
testTransactionLockReadCommited()
|
3285
|
+
end
|
3286
|
+
it 'record lock' do
|
3287
|
+
testRecordLock()
|
2312
3288
|
end
|
2313
3289
|
it 'exclusive' do
|
2314
3290
|
testExclusive()
|
2315
3291
|
end
|
3292
|
+
it 'multi database' do
|
3293
|
+
testMultiDatabase()
|
3294
|
+
end
|
2316
3295
|
it 'insert2' do
|
2317
3296
|
testInsert2()
|
2318
3297
|
end
|
@@ -2345,6 +3324,12 @@ describe Transactd do
|
|
2345
3324
|
it 'activetable and join' do
|
2346
3325
|
testJoin()
|
2347
3326
|
end
|
3327
|
+
it 'activetable and prepare' do
|
3328
|
+
testPrepareJoin()
|
3329
|
+
end
|
3330
|
+
it 'activetable and prepare (server)' do
|
3331
|
+
testServerPrepareJoin()
|
3332
|
+
end
|
2348
3333
|
it 'write with writableRecord' do
|
2349
3334
|
testWirtableRecord()
|
2350
3335
|
end
|