transactd 2.0.1-x64-mswin64-100 → 2.1.0-x64-mswin64-100

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 7b7cdad808a2c93ec2b94e4037a9e451203a7cec
4
- data.tar.gz: b971b7a94531406c8b8d614146e31eb728de29a4
3
+ metadata.gz: 20a01e42c428aeaab4e743a3749d38b07ad6630a
4
+ data.tar.gz: b59b25870c2b23bd86ee6ee758c5aed9f92ea507
5
5
  SHA512:
6
- metadata.gz: 43d95f3644f3cf65e4299446b1cf37ffd2595453f8b543b443836b13a86507a8bfd61156a0c1d569414cd115b0241707e2b6d51d5b79cec4c43b96c3c36f1835
7
- data.tar.gz: 9a579a0822eb5c73cb4644bbcc8056c9815bd8d8890e27563853ff5fe4608b74b9ab86ecd814c6bdd62eb5d11737bb70151254372de6ecd76ffdd213dfd0bbac
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.0.0/transactd-source-2.0.0.zip
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.0.0/transactd-source-2.0.0.zip
79
- unzip -q transactd-source-2.0.0.zip -d transactd
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.0.0/transactd-source-2.0.0.zip
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.0.0/transactd-source-2.0.0.zip
127
- unzip -q transactd-source-2.0.0.zip -d transactd
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.0.0_[mysql-version].zip
49
- * Linux - transactd-linux-x86_64-2.0.0_[mysql-version].tar.gz
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.0.0/transactd-linux-x86_64-2.0.0_mysql-5.6.14.tar.gz
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.0.0_mysql-5.6.14.tar.gz
102
- cd transactd-linux-x86_64-2.0.0_mysql-5.6.14
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.0.0.zip
134
- * Linux - transactd-client-linux-x86_64_with_sdk-2.0.0.tar.gz
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.0.0.tar.gz
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.0.0.zip from explorer.
148
- 2. Select the root folder transactd-client-[platform]-with_sdk-2.0.0 and
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.0.0 folder.
151
- This command adds "transactd-client-[platform]_with_sdk-2.0.0\bin" folder to
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.0.0.tar.gz
182
- cd transactd-client-linux-x86_64_with_sdk-2.0.0
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.0.0
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.0.0
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.0.0_[mysql-version].zip
49
- * Linuxの場合 transactd-linux-x86_64-2.0.0_[mysql-version].tar.gz
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.0.0/transactd-linux-x86_64-2.0.0_mysql-5.6.14.tar.gz
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.0.0_mysql-5.6.14.tar.gz
101
- cd transactd-linux-x86_64-2.0.0_mysql-5.6.14
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.0.0.zip
133
- * Linuxの場合 transactd-client-linux-x86_64_with_sdk-2.0.0.tar.gz
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.0.0.tar.gz
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.0.0.zipを開きます。
147
- 2. ルートフォルダーのtransactd-client-[platform]_with_sdk-2.0.0ごと適当なフォルダに
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.0.0直下にあるinstall.cmdを実行します。
150
- これによりtransactd-client-[platform]_with_sdk-2.0.0\binフォルダをシステム環境変数
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.0.0.tar.gz
180
- cd transactd-client-linux-x86_64_with_sdk-2.0.0
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.0.0
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.0.0
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
@@ -83,17 +83,15 @@ end
83
83
  def deleteAll(db, tb, start, endid)
84
84
  db.beginTrn(TRANS_BIAS)
85
85
  tb.clearBuffer()
86
- for i in start..(endid - 1) do
87
- tb.setFV(FN_ID, i)
88
- tb.seek()
89
- if (tb.stat() == 0)
90
- tb.del()
91
- if (tb.stat() != 0)
92
- showTableError(tb, 'deleteAll')
93
- db.endTrn()
94
- return false
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 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, 'user', Transactd::TD_OPEN_NORMAL)
298
+ tb = openTable(db, 'users', Transactd::TD_OPEN_NORMAL)
301
299
  if tb == nil
302
- puts "can not open table 'user'"
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 = '127.0.0.1/'
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
- ISOLATION_READ_COMMITTED = true
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
- q.addSeekKeyValue('1', true)
301
- 2.upto(10000) do |i|
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 testSnapShot()
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
- db.beginSnapshot()
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
- # Change data by another connection
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
- if ISOLATION_READ_COMMITTED
589
- expect(tb2.stat()).to eq 0
590
- elsif ISOLATION_REPEATABLE_READ
591
- expect(tb2.stat()).to eq Transactd::STATUS_LOCK_ERROR
592
- end
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
- if ISOLATION_READ_COMMITTED
600
- expect(secondValue).not_to eq firstValue
601
- else
602
- expect(secondValue).to eq firstValue
603
- end
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
- def testTransactionLock()
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
- # Read test that single record lock with read
745
+ # Test Read with lock
620
746
  # ----------------------------------------------------
621
- db.beginTrn(Transactd::LOCK_SINGLE_NOWAIT)
622
- tb.setKeyNum(0)
747
+ # lock(X) the first record
623
748
  tb.seekFirst()
624
749
  expect(tb.stat()).to eq 0
625
- # unlock first record.
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
- # Can't read test that multi record lock with read
821
+ # Test phantom read
637
822
  # ----------------------------------------------------
638
- db.beginTrn(Transactd::LOCK_MULTI_NOWAIT)
639
- tb.setKeyNum(0)
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
- # not transactional user can not read
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
- # The second transactional user can not lock same record
974
+
975
+ # ----------------------------------------------------
976
+ # Test single record lock Transaction and Transaction lock
977
+ # ----------------------------------------------------
648
978
  db2.beginTrn()
649
- tb2.setKeyNum(0)
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
- # Can't read test that single record lock with change
989
+ # Test multi record lock Transaction and non-transaction read
656
990
  # ----------------------------------------------------
657
- db.beginTrn(Transactd::LOCK_SINGLE_NOWAIT)
658
- tb.setKeyNum(0)
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
- db2.beginTrn()
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
- db.endTrn()
674
- # ----------------------------------------------------
675
- # Abort test that Single record lock transaction
676
- # ----------------------------------------------------
677
- db.beginTrn(Transactd::LOCK_SINGLE_NOWAIT)
678
- tb.setKeyNum(0)
679
- tb.seekFirst()
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
- tb.setFV(FDI_NAME, 'EFG')
682
- tb.update()
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
- # move from first record.
685
- tb.seekNext()
686
- db.abortTrn()
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 = testOpenTable(db)
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
- tb2 = db.openTable(TABLENAME)
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
- tb.setKeyNum(0)
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
- tb.setFV(FDI_NAME, 'ABC123')
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, 'ABC124')
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
- # table mode exclusive
1514
+ end
1515
+
1516
+ def testMultiDatabase()
783
1517
  db = Transactd::Database.new()
784
- db.open(URL, Transactd::TYPE_SCHEMA_BDF, Transactd::TD_OPEN_READONLY)
785
- expect(db.stat()).to eq 0
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.connect(PROTOCOL + HOSTNAME + DBNAME, true)
1521
+ testOpenDatabase(db2)
791
1522
  expect(db2.stat()).to eq 0
792
- db2.open(URL, Transactd::TYPE_SCHEMA_BDF)
1523
+ tb2 = db2.openTable('group')
793
1524
  expect(db2.stat()).to eq 0
1525
+ expect(tb2).not_to be nil
794
1526
 
795
- # Can not open table from other connections.
796
- tb2 = db2.openTable(TABLENAME)
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, 'ABC123')
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 + DBNAME, true)
921
- expect(db.stat()).to eq 0
922
- db2.close()
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.setFVA(FDI_NAME, '1234567')
1854
+ tb.setFV(FDI_NAME, '1234567')
1129
1855
  if (varCharField)
1130
- expect(tb.getFVAstr(FDI_NAME)).to eq '123'
1856
+ expect(tb.getFVstr(FDI_NAME)).to eq '123'
1131
1857
  else
1132
- expect(tb.getFVAstr(FDI_NAME)).to eq '123456'
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.getFVAstr(FDI_GROUP)).to eq '68'
1863
+ expect(tb.getFVstr(FDI_GROUP)).to eq '68'
1138
1864
  #end
1139
1865
  # short string
1140
- tb.setFVA(FDI_NAME, '13 ')
1141
- expect(tb.getFVAstr(FDI_NAME)).to eq '13 '
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.getFVAstr(FDI_GROUP)).to eq '68'
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.setFVA(FDI_NAME, 'あいうえお𩸽') # hiragana 'aiueo' kanji 'hokke'
1876
+ tb.setFV(FDI_NAME, 'あいうえお𩸽') # hiragana 'aiueo' kanji 'hokke'
1151
1877
  if (varCharField)
1152
- expect(tb.getFVAstr(FDI_NAME)).to eq 'あいう'
1878
+ expect(tb.getFVstr(FDI_NAME)).to eq 'あいう'
1153
1879
  else
1154
- expect(tb.getFVAstr(FDI_NAME)).to eq 'あいうえお'
1880
+ expect(tb.getFVstr(FDI_NAME)).to eq 'あいうえお'
1155
1881
  end
1156
1882
  end
1157
1883
  else
1158
- tb.setFVA(FDI_NAME, '0松本市') # numeric '0' kanji 'matumostoshi'
1159
- is_valid_value = tb.getFVAstr(FDI_NAME) == '0松本'
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.getFVAstr(FDI_NAME) if (!is_valid_value)
1887
+ puts tb.getFVstr(FDI_NAME) if (!is_valid_value)
1162
1888
  end
1163
- expect(tb.getFVAstr(FDI_GROUP)).to eq '68'
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.getFVAstr(FDI_NAME)).to eq '123'
1895
+ # expect(tb.getFVstr(FDI_NAME)).to eq '123'
1170
1896
  # else
1171
- # expect(tb.getFVAstr(FDI_NAME)).to eq '123456'
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.getFVAstr(FDI_NAME)).to eq '23 '
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.getFVAstr(FDI_NAME)).to eq 'あいう'
1908
+ # expect(tb.getFVstr(FDI_NAME)).to eq 'あいう'
1183
1909
  # else
1184
- # expect(tb.getFVAstr(FDI_NAME)).to eq 'あいうえお'
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.getFVAstr(FDI_NAME)).to eq '0松本'
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.setFVA(FDI_NAME, '1234567')
1920
+ tb.setFV(FDI_NAME, '1234567')
1195
1921
  if (varCharField)
1196
- expect(tb.getFVAstr(FDI_NAME)).to eq '123'
1922
+ expect(tb.getFVstr(FDI_NAME)).to eq '123'
1197
1923
  else
1198
- expect(tb.getFVAstr(FDI_NAME)).to eq '123456'
1924
+ expect(tb.getFVstr(FDI_NAME)).to eq '123456'
1199
1925
  end
1200
- expect(tb.getFVAstr(FDI_GROUP)).to eq '68'
1926
+ expect(tb.getFVstr(FDI_GROUP)).to eq '68'
1201
1927
  # short string
1202
- tb.setFVA(FDI_NAME, '13 ')
1203
- expect(tb.getFVAstr(FDI_NAME)).to eq '13 '
1204
- expect(tb.getFVAstr(FDI_GROUP)).to eq '68'
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.setFVA(FDI_NAME, 'あいうえお𩸽') # hiragana 'aiueo' kanji 'hokke'
1934
+ tb.setFV(FDI_NAME, 'あいうえお𩸽') # hiragana 'aiueo' kanji 'hokke'
1209
1935
  if (varCharField)
1210
- expect(tb.getFVAstr(FDI_NAME)).to eq 'あいう'
1936
+ expect(tb.getFVstr(FDI_NAME)).to eq 'あいう'
1211
1937
  else
1212
- expect(tb.getFVAstr(FDI_NAME)).to eq 'あいうえお'
1938
+ expect(tb.getFVstr(FDI_NAME)).to eq 'あいうえお'
1213
1939
  end
1214
1940
  end
1215
1941
  else
1216
- tb.setFVA(FDI_NAME, '0松本市') # numeric '0' kanji 'matumostoshi'
1217
- expect(tb.getFVAstr(FDI_NAME)).to eq '0松本'
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.getFVAstr(FDI_GROUP)).to eq '68'
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::CHARSET_UTF8B4
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::CHARSET_UTF8B4
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::CHARSET_UTF8B4
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() === 0)
2002
- db.close()
2003
- return
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 "\nDatabase " + DBNAME_QT + " not found\n"
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
- testSnapShot()
3275
+ testSnapshot()
2306
3276
  end
2307
3277
  it 'send conflict error' do
2308
3278
  testConflict()
2309
3279
  end
2310
- it 'transaction' do
2311
- testTransactionLock()
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