transactd 1.0.1-x86-mswin32-100

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,1536 @@
1
+ # coding : utf-8
2
+ =begin ============================================================
3
+ Copyright (C) 2013 BizStation Corp All rights reserved.
4
+
5
+ This program is free software; you can redistribute it and/or
6
+ modify it under the terms of the GNU General Public License
7
+ as published by the Free Software Foundation; either version 2
8
+ of the License, or (at your option) any later version.
9
+
10
+ This program is distributed in the hope that it will be useful,
11
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
12
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13
+ GNU General Public License for more details.
14
+
15
+ You should have received a copy of the GNU General Public License
16
+ along with this program; if not, write to the Free Software
17
+ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
18
+ 02111-1307, USA.
19
+ ===================================================================
20
+ =end
21
+ require 'transactd'
22
+
23
+ require 'rbconfig'
24
+ IS_WINDOWS = (RbConfig::CONFIG['host_os'] =~ /mswin|mingw|cygwin/)
25
+
26
+ def getHost()
27
+ hostname = '127.0.0.1/'
28
+ if (ENV['TRANSACTD_RSPEC_HOST'] != nil && ENV['TRANSACTD_RSPEC_HOST'] != '')
29
+ hostname = ENV['TRANSACTD_RSPEC_HOST']
30
+ end
31
+ hostname = hostname + '/' unless (hostname =~ /\/$/)
32
+ return hostname
33
+ end
34
+
35
+ HOSTNAME = getHost()
36
+ DBNAME = 'test'
37
+ DBNAME_VAR = 'testvar'
38
+ DBNAME_SF = 'testString'
39
+ TABLENAME = 'user'
40
+ PROTOCOL = 'tdap://'
41
+ BDFNAME = '?dbfile=test.bdf'
42
+ URL = PROTOCOL + HOSTNAME + DBNAME + BDFNAME
43
+ URL_VAR = PROTOCOL + HOSTNAME + DBNAME_VAR + BDFNAME
44
+ URL_SF = PROTOCOL + HOSTNAME + DBNAME_SF + BDFNAME
45
+ FDI_ID = 0
46
+ FDI_NAME = 1
47
+ FDI_GROUP = 2
48
+ FDI_NAMEW = 2
49
+
50
+ BULKBUFSIZE = 65535 - 1000
51
+ TEST_COUNT = 20000
52
+ FIVE_PERCENT_OF_TEST_COUNT = TEST_COUNT / 20
53
+
54
+ TYPE_SCHEMA_BDF = 0
55
+
56
+ ISOLATION_READ_COMMITTED = true
57
+ ISOLATION_REPEATABLE_READ = false
58
+
59
+ def testDropDatabase(db)
60
+ db.open(URL)
61
+ expect(db.stat()).to eq 0
62
+ db.drop()
63
+ expect(db.stat()).to eq 0
64
+ end
65
+
66
+ def testCreateDatabase(db)
67
+ db.create(URL)
68
+ if db.stat() == Transactd::STATUS_TABLE_EXISTS_ERROR
69
+ testDropDatabase(db)
70
+ db.create(URL)
71
+ end
72
+ expect(db.stat()).to eq 0
73
+ end
74
+
75
+ def testOpenDatabase(db)
76
+ db.open(URL, TYPE_SCHEMA_BDF, Transactd::TD_OPEN_NORMAL)
77
+ expect(db.stat()).to eq 0
78
+ end
79
+
80
+ def testCreateTable(db)
81
+ testOpenDatabase(db)
82
+ dbdef = db.dbDef()
83
+ expect(dbdef).not_to be nil
84
+ td = Transactd::Tabledef.new()
85
+ td.setTableName(TABLENAME)
86
+ td.setFileName(TABLENAME + '.dat')
87
+ td.id = 1
88
+ td.pageSize = 2048
89
+ dbdef.insertTable(td)
90
+ expect(dbdef.stat()).to eq 0
91
+ fd = dbdef.insertField(1, 0)
92
+ fd.setName('id')
93
+ fd.type = Transactd::Ft_integer
94
+ fd.len = 4
95
+ dbdef.updateTableDef(1)
96
+ expect(dbdef.stat()).to eq 0
97
+ fd = dbdef.insertField(1, 1)
98
+ fd.setName('name')
99
+ fd.type = Transactd::Ft_zstring
100
+ fd.len = 33
101
+ dbdef.updateTableDef(1)
102
+ expect(dbdef.stat()).to eq 0
103
+ kd = dbdef.insertKey(1,0)
104
+ kd.segment(0).fieldNum = 0
105
+ kd.segment(0).flags.bit8 = 1
106
+ kd.segment(0).flags.bit1 = 1
107
+ kd.segmentCount = 1
108
+ dbdef.updateTableDef(1)
109
+ expect(dbdef.stat()).to eq 0
110
+ end
111
+
112
+ def testOpenTable(db)
113
+ testOpenDatabase(db)
114
+ tb = db.openTable(TABLENAME)
115
+ expect(db.stat()).to eq 0
116
+ return tb
117
+ end
118
+
119
+ def testVersion(db)
120
+ db.connect(PROTOCOL + HOSTNAME)
121
+ expect(db.stat()).to eq 0
122
+ vv = Transactd::BtrVersions.new()
123
+ db.getBtrVersion(vv)
124
+ expect(db.stat()).to eq 0
125
+ client_ver = vv.version(0)
126
+ server_ver = vv.version(1)
127
+ engine_ver = vv.version(2)
128
+ expect(client_ver.majorVersion.to_s).to eq Transactd::CPP_INTERFACE_VER_MAJOR.to_s
129
+ expect(client_ver.minorVersion.to_s).to eq Transactd::CPP_INTERFACE_VER_MINOR.to_s
130
+ expect(client_ver.type.chr).to eq 'N'
131
+ expect(server_ver.majorVersion).to be >= 5
132
+ expect(server_ver.minorVersion).to be >= 5
133
+ expect(server_ver.type.chr).to eq 'M'
134
+ expect(engine_ver.majorVersion.to_s).to eq Transactd::TRANSACTD_VER_MAJOR.to_s
135
+ expect(engine_ver.minorVersion.to_s).to eq Transactd::TRANSACTD_VER_MINOR.to_s
136
+ expect(engine_ver.type.chr).to eq 'T'
137
+ end
138
+
139
+ def testInsert(db)
140
+ tb = testOpenTable(db)
141
+ expect(tb).not_to be nil
142
+ if tb.recordCount() == 0
143
+ tb.clearBuffer()
144
+ tb.setFV(FDI_ID, 1)
145
+ tb.setFV(FDI_NAME, 'kosaka')
146
+ tb.insert()
147
+ expect(tb.stat()).to eq 0
148
+ end
149
+ db.beginTrn()
150
+ n = 1
151
+ tb.seekLast()
152
+ n = tb.getFVint(FDI_ID) + 1 if tb.stat()==0
153
+ tb.beginBulkInsert(BULKBUFSIZE)
154
+ for i in n..(TEST_COUNT + n) do
155
+ tb.clearBuffer()
156
+ tb.setFV(FDI_ID, i)
157
+ tb.setFV(FDI_NAME, i.to_s)
158
+ tb.insert()
159
+ end
160
+ tb.commitBulkInsert()
161
+ db.endTrn()
162
+ expect(tb.stat()).to eq 0
163
+ tb.close()
164
+ end
165
+
166
+ def testFind(db)
167
+ tb = testOpenTable(db)
168
+ tb.setKeyNum(0)
169
+ tb.clearBuffer()
170
+ tb.setFilter('id >= 10 and id < ' + TEST_COUNT.to_s, 1, 0)
171
+ v = 10
172
+ tb.setFV(FDI_ID, v)
173
+ tb.find(Transactd::Table::FindForword)
174
+ i = v
175
+ while i < TEST_COUNT do
176
+ expect(tb.stat()).to eq 0
177
+ expect(tb.getFVint(FDI_ID)).to eq i
178
+ tb.findNext(true) # 11 - 19
179
+ i = i + 1
180
+ end
181
+ # backforword
182
+ tb.clearBuffer()
183
+ v = TEST_COUNT - 1
184
+ tb.setFV(FDI_ID, v)
185
+ tb.find(Transactd::Table::FindBackForword)
186
+ i = v
187
+ while i >= 10 do
188
+ expect(tb.stat()).to eq 0
189
+ expect(tb.getFVint(FDI_ID)).to eq i
190
+ tb.findPrev(true) # 11 - 19
191
+ i = i - 1
192
+ end
193
+ # out of filter range (EOF)
194
+ v = TEST_COUNT
195
+ tb.setFV(FDI_ID, v)
196
+ tb.find(Transactd::Table::FindForword)
197
+ expect(tb.stat()).to eq Transactd::STATUS_EOF
198
+ tb.close()
199
+ end
200
+
201
+ def testFindNext(db)
202
+ tb = testOpenTable(db)
203
+ tb.setKeyNum(0)
204
+ tb.clearBuffer()
205
+ tb.setFilter('id >= 10 and id < ' + TEST_COUNT.to_s, 1, 0)
206
+ v = 10
207
+ tb.setFV(FDI_ID, v)
208
+ tb.seekGreater(true)
209
+ expect(tb.getFVint(FDI_ID)).to eq v
210
+ for i in (v + 1)..(TEST_COUNT - 1) do
211
+ tb.findNext(true) # 11 - 19
212
+ expect(tb.stat()).to eq 0
213
+ expect(tb.getFVint(FDI_ID)).to eq i
214
+ end
215
+ tb.close()
216
+ end
217
+
218
+ def testGetPercentage(db)
219
+ tb = testOpenTable(db)
220
+ tb.clearBuffer()
221
+ vv = TEST_COUNT / 2 + 1
222
+ tb.setFV(FDI_ID, vv)
223
+ tb.seek()
224
+ expect(tb.stat()).to eq 0
225
+ per = tb.getPercentage()
226
+ expect((5000 - per).abs).to be < 500 # 500 = 5%
227
+ tb.close()
228
+ end
229
+
230
+ def testMovePercentage(db)
231
+ tb = testOpenTable(db)
232
+ tb.clearBuffer()
233
+ tb.seekByPercentage(5000) # 50%
234
+ expect(tb.stat()).to eq 0
235
+ v = tb.getFVint(FDI_ID)
236
+ expect(tb.stat()).to eq 0
237
+ expect((TEST_COUNT / 2 + 1 - v).abs).to be < FIVE_PERCENT_OF_TEST_COUNT
238
+ tb.close()
239
+ end
240
+
241
+ def testGetEqual(db)
242
+ tb = testOpenTable(db)
243
+ db.beginSnapshot()
244
+ vv = 1
245
+ for i in 2..(TEST_COUNT + 1) do
246
+ tb.clearBuffer()
247
+ tb.setFV(FDI_ID, i)
248
+ tb.seek()
249
+ expect(tb.getFVint(FDI_ID)).to eq i
250
+ end
251
+ db.endSnapshot()
252
+ tb.close()
253
+ end
254
+
255
+ def testGetNext(db)
256
+ tb = testOpenTable(db)
257
+ db.beginSnapshot()
258
+ vv = 2
259
+ tb.clearBuffer()
260
+ tb.setFV(FDI_ID, vv)
261
+ tb.seek()
262
+ expect(tb.getFVint(FDI_ID)).to eq vv
263
+ for i in 3..(TEST_COUNT + 1)
264
+ tb.seekNext()
265
+ expect(tb.getFVint(FDI_ID)).to eq i
266
+ end
267
+ db.endSnapshot()
268
+ tb.close()
269
+ end
270
+
271
+ def testGetPrevious(db)
272
+ tb = testOpenTable(db)
273
+ db.beginSnapshot()
274
+ vv = TEST_COUNT + 1
275
+ tb.clearBuffer()
276
+ tb.setFV(FDI_ID, vv)
277
+ tb.seek()
278
+ expect(tb.getFVint(FDI_ID)).to eq vv
279
+ for i in TEST_COUNT.downto(2) do
280
+ tb.seekPrev()
281
+ expect(tb.getFVint(FDI_ID)).to eq i
282
+ end
283
+ tb.seekPrev()
284
+ expect(tb.getFVstr(FDI_NAME)).to eq 'kosaka'
285
+ db.endSnapshot()
286
+ tb.close()
287
+ end
288
+
289
+ def testGetGreater(db)
290
+ tb = testOpenTable(db)
291
+ vv = TEST_COUNT * 3 / 4
292
+ tb.clearBuffer()
293
+ tb.setFV(FDI_ID, vv)
294
+ tb.seekGreater(true)
295
+ expect(tb.getFVint(FDI_ID)).to eq vv
296
+ tb.seekNext()
297
+ expect(tb.getFVint(FDI_ID)).to eq vv + 1
298
+ vv = vv - FIVE_PERCENT_OF_TEST_COUNT
299
+ tb.clearBuffer()
300
+ tb.setFV(FDI_ID, vv)
301
+ tb.seekGreater(false)
302
+ expect(tb.getFVint(FDI_ID)).to eq vv + 1
303
+ tb.seekPrev()
304
+ expect(tb.getFVint(FDI_ID)).to eq vv
305
+ tb.close()
306
+ end
307
+
308
+ def testGetLessThan(db)
309
+ tb = testOpenTable(db)
310
+ vv = TEST_COUNT * 3 / 4
311
+ tb.clearBuffer()
312
+ tb.setFV(FDI_ID, vv)
313
+ tb.seekLessThan(true)
314
+ expect(tb.getFVint(FDI_ID)).to eq vv
315
+ tb.seekNext()
316
+ expect(tb.getFVint(FDI_ID)).to eq vv + 1
317
+ vv = vv - FIVE_PERCENT_OF_TEST_COUNT
318
+ tb.clearBuffer()
319
+ tb.setFV(FDI_ID, vv)
320
+ tb.seekLessThan(false)
321
+ expect(tb.getFVint(FDI_ID)).to eq vv - 1
322
+ tb.seekPrev()
323
+ expect(tb.getFVint(FDI_ID)).to eq vv - 2
324
+ tb.close()
325
+ end
326
+
327
+ def testGetFirst(db)
328
+ tb = testOpenTable(db)
329
+ tb.clearBuffer()
330
+ tb.seekFirst()
331
+ expect(tb.getFVstr(FDI_NAME)).to eq 'kosaka'
332
+ tb.close()
333
+ end
334
+
335
+ def testGetLast(db)
336
+ tb = testOpenTable(db)
337
+ tb.clearBuffer()
338
+ tb.seekLast()
339
+ expect(tb.getFVint(FDI_ID)).to eq TEST_COUNT + 2
340
+ tb.close()
341
+ end
342
+
343
+ def testMovePosition(db)
344
+ tb = testOpenTable(db)
345
+ tb.clearBuffer()
346
+ vv = TEST_COUNT * 3 / 4
347
+ tb.clearBuffer()
348
+ tb.setFV(FDI_ID, vv)
349
+ tb.seekLessThan(true)
350
+ expect(tb.getFVint(FDI_ID)).to eq vv
351
+ pos = tb.bookmark()
352
+ pos_vv = vv
353
+ expect(tb.stat()).to eq 0
354
+ vv = vv - FIVE_PERCENT_OF_TEST_COUNT
355
+ tb.clearBuffer()
356
+ tb.setFV(FDI_ID, vv)
357
+ tb.seekLessThan(false)
358
+ expect(tb.getFVint(FDI_ID)).to eq vv - 1
359
+ tb.seekPrev()
360
+ expect(tb.getFVint(FDI_ID)).to eq vv - 2
361
+ tb.seekByBookmark(pos)
362
+ expect(tb.getFVint(FDI_ID)).to eq pos_vv
363
+ tb.close()
364
+ end
365
+
366
+ def testUpdate(db)
367
+ tb = testOpenTable(db)
368
+ db.beginTrn()
369
+ # test of ncc
370
+ v = 5
371
+ tb.clearBuffer()
372
+ tb.setFV(FDI_ID, v)
373
+ tb.seek()
374
+ expect(tb.stat()).to eq 0
375
+ v = TEST_COUNT + TEST_COUNT / 2
376
+ tb.setFV(FDI_ID, v)
377
+ tb.update(Transactd::Table::ChangeCurrentNcc) # 5 . 30000 cur 5
378
+ expect(tb.stat()).to eq 0
379
+ tb.seekNext() # next 5
380
+ expect(tb.getFVint(FDI_ID)).to eq 6
381
+ v = TEST_COUNT - 1
382
+ tb.setFV(FDI_ID, v)
383
+ tb.seek()
384
+ expect(tb.getFVint(FDI_ID)).to eq v
385
+ v = 5
386
+ tb.setFV(FDI_ID, v)
387
+ tb.update(Transactd::Table::ChangeCurrentCc) # 19999 . 5 cur 5
388
+ expect(tb.stat()).to eq 0
389
+ tb.seekNext()
390
+ expect(tb.stat()).to eq 0
391
+ expect(tb.getFVint(FDI_ID)).to eq 6
392
+ v = TEST_COUNT - 1
393
+ tb.setFV(FDI_ID, v)
394
+ tb.update(Transactd::Table::ChangeCurrentCc) # 6 . 19999 cur 19999
395
+ tb.seekPrev() # prev 19999
396
+ expect(tb.getFVint(FDI_ID)).to eq v - 1
397
+ v = 10
398
+ tb.clearBuffer()
399
+ tb.setFV(FDI_ID, v)
400
+ tb.seek()
401
+ expect(tb.stat()).to eq 0
402
+ tb.seekNext()
403
+ expect(tb.getFVint(FDI_ID)).to eq 11
404
+ for i in 10..(TEST_COUNT - 2)
405
+ tb.clearBuffer()
406
+ tb.setFV(FDI_ID, i)
407
+ tb.seek()
408
+ expect(tb.stat()).to eq 0
409
+ v = i + 1
410
+ tb.setFV(FDI_NAME, v)
411
+ tb.update()
412
+ expect(tb.stat()).to eq 0
413
+ end
414
+ db.endTrn()
415
+ # check update in key
416
+ v = 8
417
+ tb.setFV(FDI_ID, v)
418
+ tb.setFV(FDI_NAME, 'ABC')
419
+ tb.update(Transactd::Table::ChangeInKey)
420
+ expect(tb.stat()).to eq 0
421
+ tb.clearBuffer()
422
+ tb.setFV(FDI_ID, v)
423
+ tb.seek()
424
+ expect(tb.getFVstr(FDI_NAME)).to eq 'ABC'
425
+ tb.close()
426
+ end
427
+
428
+ def testSnapShot(db)
429
+ db2 = Transactd::Database::createObject()
430
+ db2.connect(PROTOCOL + HOSTNAME + DBNAME , true)
431
+ expect(db2.stat()).to eq 0
432
+ tb = testOpenTable(db)
433
+ tb2 = testOpenTable(db2)
434
+ db.beginSnapshot()
435
+ expect(db.stat()).to eq 0
436
+ tb.setKeyNum(0)
437
+ tb.seekFirst()
438
+ expect(tb.stat()).to eq 0
439
+ firstValue = tb.getFVint(FDI_NAME)
440
+ tb.seekNext()
441
+ # ----------------------------------------------------
442
+ # Change data by another connection
443
+ tb2.setKeyNum(0)
444
+ tb2.seekFirst()
445
+ expect(tb2.stat()).to eq 0
446
+ tb2.setFV(FDI_NAME, tb2.getFVint(FDI_ID) + 1)
447
+ tb2.update()
448
+ if ISOLATION_READ_COMMITTED
449
+ expect(tb2.stat()).to eq 0
450
+ elsif ISOLATION_REPEATABLE_READ
451
+ expect(tb2.stat()).to eq STATUS_LOCK_ERROR
452
+ end
453
+ # ----------------------------------------------------
454
+ tb.seekFirst()
455
+ secondValue = tb.getFVint(FDI_NAME)
456
+ expect(tb.stat()).to eq 0
457
+ db.endSnapshot()
458
+ expect(db.stat()).to eq 0
459
+ if ISOLATION_READ_COMMITTED
460
+ expect(secondValue).not_to eq firstValue
461
+ else
462
+ expect(secondValue).to eq firstValue
463
+ end
464
+ # ----------------------------------------------------
465
+ tb.close()
466
+ tb2.close()
467
+ db2.close()
468
+ end
469
+
470
+ def testTransactionLock(db)
471
+ db2 = Transactd::Database::createObject()
472
+ db2.connect(PROTOCOL + HOSTNAME + DBNAME, true)
473
+ expect(db2.stat()).to eq 0
474
+ tb = testOpenTable(db)
475
+ tb2 = testOpenTable(db2)
476
+ # ----------------------------------------------------
477
+ # Read test that single record lock with read
478
+ # ----------------------------------------------------
479
+ db.beginTrn(Transactd::LOCK_SINGLE_NOWAIT)
480
+ tb.setKeyNum(0)
481
+ tb.seekFirst()
482
+ expect(tb.stat()).to eq 0
483
+ # unlock first record.
484
+ tb.seekNext()
485
+ tb2.seekFirst()
486
+ expect(tb2.stat()).to eq 0
487
+ db2.beginTrn()
488
+ tb2.setKeyNum(0)
489
+ tb2.seekFirst()
490
+ expect(tb2.stat()).to eq 0
491
+ db2.endTrn()
492
+ db.endTrn()
493
+ # ----------------------------------------------------
494
+ # Can't read test that multi record lock with read
495
+ # ----------------------------------------------------
496
+ db.beginTrn(Transactd::LOCK_MULTI_NOWAIT)
497
+ tb.setKeyNum(0)
498
+ tb.seekFirst()
499
+ expect(tb.stat()).to eq 0
500
+ # move from first record.
501
+ tb.seekNext()
502
+ # not transactional user can not read
503
+ tb2.seekFirst()
504
+ expect(tb2.stat()).to eq Transactd::STATUS_LOCK_ERROR
505
+ # The second transactional user can not lock same record
506
+ db2.beginTrn()
507
+ tb2.setKeyNum(0)
508
+ tb2.seekFirst()
509
+ expect(tb2.stat()).to eq Transactd::STATUS_LOCK_ERROR
510
+ db2.endTrn()
511
+ db.endTrn()
512
+ # ----------------------------------------------------
513
+ # Can't read test that single record lock with change
514
+ # ----------------------------------------------------
515
+ db.beginTrn(Transactd::LOCK_SINGLE_NOWAIT)
516
+ tb.setKeyNum(0)
517
+ tb.seekFirst()
518
+ expect(tb.stat()).to eq 0
519
+ tb.setFV(FDI_NAME, 'ABC')
520
+ tb.update()
521
+ expect(tb.stat()).to eq 0
522
+ # move from first record.
523
+ tb.seekNext()
524
+ tb2.seekFirst()
525
+ expect(tb2.stat()).to eq Transactd::STATUS_LOCK_ERROR
526
+ db2.beginTrn()
527
+ tb2.setKeyNum(0)
528
+ tb2.seekFirst()
529
+ expect(tb2.stat()).to eq Transactd::STATUS_LOCK_ERROR
530
+ db2.endTrn()
531
+ db.endTrn()
532
+ # ----------------------------------------------------
533
+ # Abort test that Single record lock transaction
534
+ # ----------------------------------------------------
535
+ db.beginTrn(Transactd::LOCK_SINGLE_NOWAIT)
536
+ tb.setKeyNum(0)
537
+ tb.seekFirst()
538
+ expect(tb.stat()).to eq 0
539
+ tb.setFV(FDI_NAME, 'EFG')
540
+ tb.update()
541
+ expect(tb.stat()).to eq 0
542
+ # move from first record.
543
+ tb.seekNext()
544
+ db.abortTrn()
545
+ tb2.setKeyNum(0)
546
+ tb2.seekFirst()
547
+ expect(tb2.getFVstr(FDI_NAME)).to eq 'ABC'
548
+ tb.close()
549
+ tb2.close()
550
+ db2.close()
551
+ end
552
+
553
+ def testConflict(db)
554
+ db2 = Transactd::Database::createObject()
555
+ db2.connect(PROTOCOL + HOSTNAME + DBNAME , true)
556
+ expect(db2.stat()).to eq 0
557
+ tb = testOpenTable(db)
558
+ tb2 = testOpenTable(db2)
559
+ tb.setKeyNum(0)
560
+ tb.seekFirst()
561
+ expect(tb.stat()).to eq 0
562
+ # ----------------------------------------------------
563
+ # Change Index field
564
+ # ----------------------------------------------------
565
+ # Change data by another connection
566
+ tb2.setKeyNum(0)
567
+ tb2.seekFirst()
568
+ expect(tb2.stat()).to eq 0
569
+ tb2.setFV(FDI_ID, tb2.getFVint(FDI_ID) - 10)
570
+ tb2.update()
571
+ expect(tb2.stat()).to eq 0
572
+ # ----------------------------------------------------
573
+ # Change same record data by original connection
574
+ tb.setFV(FDI_ID, tb.getFVint(FDI_ID) - 8)
575
+ tb.update()
576
+ expect(tb.stat()).to eq Transactd::STATUS_CHANGE_CONFLICT
577
+ # ----------------------------------------------------
578
+ # Change Non index field
579
+ # ----------------------------------------------------
580
+ # Change data by another connection
581
+ tb.seekFirst()
582
+ expect(tb.stat()).to eq 0
583
+ tb2.seekFirst()
584
+ expect(tb2.stat()).to eq 0
585
+ tb2.setFV(FDI_NAME, tb2.getFVint(FDI_ID) - 10)
586
+ tb2.update()
587
+ expect(tb2.stat()).to eq 0
588
+ # ----------------------------------------------------
589
+ # Change same record data by original connection
590
+ tb.setFV(FDI_NAME, tb.getFVint(FDI_NAME) - 8)
591
+ tb.update()
592
+ expect(tb.stat()).to eq Transactd::STATUS_CHANGE_CONFLICT
593
+ # ----------------------------------------------------
594
+ tb.close()
595
+ tb2.close()
596
+ db2.close()
597
+ end
598
+
599
+ def testInsert2(db)
600
+ tb = testOpenTable(db)
601
+ v = TEST_COUNT * 2
602
+ db.beginTrn()
603
+ tb.clearBuffer()
604
+ tb.setFV(FDI_ID, v)
605
+ tb.insert()
606
+ expect(tb.stat()).to eq 0
607
+ v = 10
608
+ tb.clearBuffer()
609
+ tb.setFV(FDI_ID, v)
610
+ tb.seek()
611
+ expect(tb.stat()).to eq 0
612
+ tb.seekNext()
613
+ expect(tb.getFVint(FDI_ID)).to eq 11
614
+ db.endTrn()
615
+ tb.close()
616
+ end
617
+
618
+ def testDelete(db)
619
+ tb = testOpenTable(db)
620
+ # estimate count
621
+ count = tb.recordCount(true)
622
+ is_valid_count = ((count - TEST_COUNT - 3).abs < FIVE_PERCENT_OF_TEST_COUNT)
623
+ expect(is_valid_count).to be true
624
+ if !is_valid_count
625
+ puts "true record count = #{(TEST_COUNT + 3).to_s} and estimate recordCount count = #{count.to_s}"
626
+ end
627
+ expect(tb.recordCount(false)).to eq TEST_COUNT + 3 # true count
628
+ vv = TEST_COUNT * 3 / 4 + 1
629
+ tb.clearBuffer()
630
+ tb.setFV(FDI_ID, vv)
631
+ tb.seek()
632
+ expect(tb.getFVint(FDI_ID)).to eq vv
633
+ tb.del()
634
+ expect(tb.stat()).to eq 0
635
+ tb.setFV(FDI_ID, vv)
636
+ tb.seek()
637
+ expect(tb.stat()).to eq 4
638
+ # check update in key
639
+ vv = 8
640
+ tb.setFV(FDI_ID, vv)
641
+ tb.del(Transactd::Table::Inkey)
642
+ expect(tb.stat()).to eq 0
643
+ tb.clearBuffer()
644
+ tb.setFV(FDI_ID, vv)
645
+ tb.seek()
646
+ expect(tb.stat()).to eq Transactd::STATUS_NOT_FOUND_TI
647
+ db.beginTrn()
648
+ tb.stepFirst()
649
+ while tb.stat() == 0
650
+ tb.del()
651
+ expect(tb.stat()).to eq 0
652
+ tb.stepNext()
653
+ end
654
+ expect(tb.stat()).to eq 9
655
+ db.endTrn()
656
+ expect(tb.recordCount(false)).to eq 0
657
+ tb.close()
658
+ end
659
+
660
+ def testSetOwner(db)
661
+ tb = testOpenTable(db)
662
+ tb.setOwnerName('ABCDEFG')
663
+ expect(tb.stat()).to eq 0
664
+ tb.clearOwnerName()
665
+ expect(tb.stat()).to eq 0
666
+ tb.close()
667
+ end
668
+
669
+ def testDropIndex(db)
670
+ tb = testOpenTable(db)
671
+ tb.dropIndex(false)
672
+ expect(tb.stat()).to eq 0
673
+ tb.close()
674
+ end
675
+
676
+ def testLogin(db)
677
+ db.connect(PROTOCOL + HOSTNAME)
678
+ expect(db.stat()).to eq 0
679
+ if db.stat() == 0
680
+ # second connection
681
+ db2 = Transactd::Database::createObject()
682
+ db2.connect(PROTOCOL + HOSTNAME + DBNAME, true)
683
+ expect(db.stat()).to eq 0
684
+ db2.close()
685
+ db2 = nil
686
+ db.disconnect(PROTOCOL + HOSTNAME)
687
+ expect(db.stat()).to eq 0
688
+ end
689
+ # invalid host name
690
+ db.connect(PROTOCOL + 'localhost123/')
691
+ is_valid_stat = (db.stat() == Transactd::ERROR_TD_INVALID_CLINETHOST) ||
692
+ (db.stat() == Transactd::ERROR_TD_HOSTNAME_NOT_FOUND)
693
+ expect(is_valid_stat).to be true
694
+ if (!is_valid_stat)
695
+ puts 'bad host db.stat() = ' + db.stat().to_s
696
+ end
697
+ testCreateDatabase(db)
698
+ testCreateTable(db)
699
+ db.disconnect(PROTOCOL + HOSTNAME + DBNAME)
700
+ expect(db.stat()).to eq 0
701
+ # true database name
702
+ db.connect(PROTOCOL + HOSTNAME + DBNAME)
703
+ expect(db.stat()).to eq 0
704
+ if (db.stat() == 0)
705
+ db.disconnect(PROTOCOL + HOSTNAME + DBNAME)
706
+ expect(db.stat()).to eq 0
707
+ end
708
+ # invalid database name
709
+ testDropDatabase(db)
710
+ db.disconnect(PROTOCOL + HOSTNAME + DBNAME)
711
+ expect(db.stat()).to eq 0
712
+ db.connect(PROTOCOL + HOSTNAME + DBNAME)
713
+ expect(db.stat()).to eq (25000 + 1049)
714
+ db.disconnect(PROTOCOL + HOSTNAME + DBNAME)
715
+ expect(db.stat()).to eq 0
716
+ end
717
+
718
+ def isUtf16leSupport(db)
719
+ # CHARSET_UTF16LE supported on MySQL 5.6 or later
720
+ vv = Transactd::BtrVersions.new()
721
+ db.getBtrVersion(vv)
722
+ server_ver = vv.version(1)
723
+ if ('M' == server_ver.type.chr)
724
+ if (server_ver.majorVersion <= 4)
725
+ return false
726
+ elsif (server_ver.majorVersion == 5)
727
+ return false if (server_ver.minorVersion <= 5)
728
+ end
729
+ return true
730
+ end
731
+ return false
732
+ end
733
+
734
+ def testCreateVarTable(db, id, name, fieldType, charset)
735
+ # create table
736
+ dbdef = db.dbDef()
737
+ expect(dbdef).not_to be nil
738
+ td = Transactd::Tabledef.new()
739
+ td.setTableName(name)
740
+ td.setFileName(name + '.dat')
741
+ td.id =id
742
+ td.keyCount = 0
743
+ td.fieldCount = 0
744
+ td.flags.all = 0
745
+ td.pageSize = 2048
746
+ td.charsetIndex = charset
747
+ dbdef.insertTable(td)
748
+ expect(dbdef.stat()).to eq 0
749
+ # id
750
+ fd = dbdef.insertField(id, 0)
751
+ fd.setName('id')
752
+ fd.type = Transactd::Ft_integer
753
+ fd.len = 4
754
+ dbdef.updateTableDef(id)
755
+ expect(dbdef.stat()).to eq 0
756
+ # name
757
+ fd = dbdef.insertField(id, 1)
758
+ fd.setName('name')
759
+ fd.type = fieldType
760
+ if (fieldType == Transactd::Ft_mywvarchar)
761
+ fd.len = 1 + Transactd::charsize(Transactd::CHARSET_UTF16LE) * 3 # max 3 char len byte
762
+ elsif (fieldType == Transactd::Ft_mywvarbinary)
763
+ fd.len = 1 + Transactd::charsize(Transactd::CHARSET_UTF16LE) * 3 # max 6 char len byte
764
+ elsif (fieldType == Transactd::Ft_myvarchar)
765
+ if (charset == Transactd::CHARSET_CP932)
766
+ fd.len = 1 + Transactd::charsize(Transactd::CHARSET_CP932) * 3 # max 6 char len byte
767
+ elsif(charset == Transactd::CHARSET_UTF8B4)
768
+ fd.len = 1 + Transactd::charsize(Transactd::CHARSET_UTF8B4) * 3 # max 6 char len byte
769
+ end
770
+ else
771
+ fd.len = 7; # max 6 char len byte
772
+ end
773
+ dbdef.updateTableDef(id)
774
+ expect(dbdef.stat()).to eq 0
775
+ # groupid
776
+ fd = dbdef.insertField(id, 2)
777
+ fd.setName('groupid')
778
+ fd.type = Transactd::Ft_integer
779
+ fd.len = 4
780
+ dbdef.updateTableDef(id)
781
+ expect(dbdef.stat()).to eq 0
782
+ # key 1
783
+ kd = dbdef.insertKey(id, 0)
784
+ kd.segment(0).fieldNum = 0
785
+ kd.segment(0).flags.bit8 = 1 # extended key type
786
+ kd.segment(0).flags.bit1 = 1 # changeable
787
+ kd.segmentCount = 1
788
+ dbdef.updateTableDef(id)
789
+ expect(dbdef.stat()).to eq 0
790
+ # key 2
791
+ kd = dbdef.insertKey(id, 1)
792
+ kd.segment(0).fieldNum = 1
793
+ kd.segment(0).flags.bit8 = 1 # extended key type
794
+ kd.segment(0).flags.bit1 = 1 # changeable
795
+ kd.segment(0).flags.bit0 = 1 # duplicateable
796
+ kd.segment(0).flags.bit4 = 1 # not last segmnet
797
+ kd.segment(1).fieldNum = 2
798
+ kd.segment(1).flags.bit8 = 1 # extended key type
799
+ kd.segment(1).flags.bit1 = 1 # changeable
800
+ kd.segment(1).flags.bit0 = 1 # duplicateable
801
+ kd.segmentCount = 2
802
+ dbdef.updateTableDef(id)
803
+ expect(dbdef.stat()).to eq 0
804
+ # open
805
+ tb = db.openTable(id)
806
+ expect(db.stat()).to eq 0
807
+ tb.close() if tb != nil
808
+ end
809
+
810
+ def testCreateDatabaseVar(db)
811
+ db.create(URL_VAR)
812
+ if db.stat() == Transactd::STATUS_TABLE_EXISTS_ERROR
813
+ testDropDatabaseVar(db)
814
+ db.create(URL_VAR)
815
+ end
816
+ expect(db.stat()).to eq 0
817
+ if (0 == db.stat())
818
+ db.open(URL_VAR, 0, 0)
819
+ expect(db.stat()).to eq 0
820
+ end
821
+ if (0 == db.stat())
822
+ testCreateVarTable(db, 1, 'user1', Transactd::Ft_myvarchar, Transactd::CHARSET_CP932)
823
+ testCreateVarTable(db, 2, 'user2', Transactd::Ft_myvarbinary, Transactd::CHARSET_CP932)
824
+ if isUtf16leSupport(db)
825
+ testCreateVarTable(db, 3, 'user3', Transactd::Ft_mywvarchar, Transactd::CHARSET_CP932)
826
+ end
827
+ testCreateVarTable(db, 4, 'user4', Transactd::Ft_mywvarbinary, Transactd::CHARSET_CP932)
828
+ testCreateVarTable(db, 5, 'user5', Transactd::Ft_myvarchar, Transactd::CHARSET_UTF8B4)
829
+ db.close()
830
+ db.open(PROTOCOL + HOSTNAME + DBNAME_VAR + '?dbfile=transactd_schemaname', 0, 0)
831
+ expect(db.stat()).to eq 0
832
+ end
833
+ end
834
+
835
+ def testDropDatabaseVar(db)
836
+ db.open(URL_VAR)
837
+ expect(db.stat()).to eq 0
838
+ if (0 == db.stat())
839
+ db.drop()
840
+ expect(db.stat()).to eq 0
841
+ end
842
+ end
843
+
844
+ def dump(str, size)
845
+ p str.bytes.to_a
846
+ end
847
+
848
+ def testSetGetVar(tb, unicodeField, varCharField)
849
+ ### Set Wide Get Wide
850
+ #if IS_WINDOWS
851
+ # tb.setFVW(FDI_GROUP, '68')
852
+ # expect(tb.getFVWstr(FDI_GROUP)).to eq '68'
853
+ #else
854
+ tb.setFV(FDI_GROUP, '68')
855
+ expect(tb.getFVstr(FDI_GROUP)).to eq '68'
856
+ #end
857
+ #if IS_WINDOWS
858
+ # # too long string
859
+ # tb.setFVW(FDI_NAME, '1234567')
860
+ # if (varCharField)
861
+ # expect(tb.getFVWstr(FDI_NAME)).to eq '123'
862
+ # dump(tb.getFVWstr(FDI_NAME), 7) if (tb.getFVWstr(FDI_NAME) != '123')
863
+ # else
864
+ # expect(tb.getFVWstr(FDI_NAME)).to eq '123456'
865
+ # end
866
+ # expect(tb.getFVWstr(FDI_GROUP)).to eq '68'
867
+ # # short string
868
+ # tb.setFVW(FDI_NAME, '12 ')
869
+ # expect(tb.getFVWstr(FDI_NAME)).to eq '12 '
870
+ # expect(tb.getFVWstr(FDI_GROUP)).to eq '68'
871
+ # # too long kanji
872
+ # if (unicodeField)
873
+ # tb.setFVW(1, 'あいうえお𩸽') # hiragana 'aiueo' + kanji 'hokke'
874
+ # if (varCharField)
875
+ # expect(tb.getFVWstr(FDI_NAME)).to eq 'あいう'
876
+ # else
877
+ # expect(tb.getFVWstr(FDI_NAME)).to eq 'あいうえお'
878
+ # end
879
+ # else
880
+ # tb.setFVW(FDI_NAME, '0松本市') # numeric '0' kanji 'matumostoshi'
881
+ # expect(tb.getFVWstr(FDI_NAME)).to eq '0松本'
882
+ # end
883
+ # expect(tb.getFVWstr(FDI_GROUP)).to eq '68'
884
+ #end
885
+ ### Set Ansi Get Wide
886
+ # too long string
887
+ tb.setFVA(FDI_NAME, '1234567')
888
+ if (varCharField)
889
+ expect(tb.getFVAstr(FDI_NAME)).to eq '123'
890
+ else
891
+ expect(tb.getFVAstr(FDI_NAME)).to eq '123456'
892
+ end
893
+ #if IS_WINDOWS
894
+ # expect(tb.getFVWstr(FDI_GROUP)).to eq '68'
895
+ #else
896
+ expect(tb.getFVAstr(FDI_GROUP)).to eq '68'
897
+ #end
898
+ # short string
899
+ tb.setFVA(FDI_NAME, '13 ')
900
+ expect(tb.getFVAstr(FDI_NAME)).to eq '13 '
901
+ #if IS_WINDOWS
902
+ # expect(tb.getFVWstr(FDI_GROUP)).to eq '68'
903
+ #else
904
+ expect(tb.getFVAstr(FDI_GROUP)).to eq '68'
905
+ #end
906
+ # too long kanji
907
+ if (unicodeField)
908
+ if !IS_WINDOWS
909
+ tb.setFVA(FDI_NAME, 'あいうえお𩸽') # hiragana 'aiueo' kanji 'hokke'
910
+ if (varCharField)
911
+ expect(tb.getFVAstr(FDI_NAME)).to eq 'あいう'
912
+ else
913
+ expect(tb.getFVAstr(FDI_NAME)).to eq 'あいうえお'
914
+ end
915
+ end
916
+ else
917
+ tb.setFVA(FDI_NAME, '0松本市') # numeric '0' kanji 'matumostoshi'
918
+ is_valid_value = tb.getFVAstr(FDI_NAME) == '0松本'
919
+ expect(is_valid_value).to be true
920
+ puts tb.getFVAstr(FDI_NAME) if (!is_valid_value)
921
+ end
922
+ expect(tb.getFVAstr(FDI_GROUP)).to eq '68'
923
+ ### Set Wide Get Ansi
924
+ #if IS_WINDOWS
925
+ # # too long string
926
+ # tb.setFVW(FDI_NAME, '1234567')
927
+ # if (varCharField)
928
+ # expect(tb.getFVAstr(FDI_NAME)).to eq '123'
929
+ # else
930
+ # expect(tb.getFVAstr(FDI_NAME)).to eq '123456'
931
+ # end
932
+ # expect(tb.getFVWstr(FDI_GROUP)).to eq '68'
933
+ # # short string
934
+ # tb.setFVW(1, '23 ')
935
+ # expect(tb.getFVAstr(FDI_NAME)).to eq '23 '
936
+ # expect(tb.getFVWstr(FDI_GROUP)).to eq '68'
937
+ # # too long kanji
938
+ # if (unicodeField)
939
+ # tb.setFVW(FDI_NAME, 'あいうえお𩸽') # hiragana 'aiueo' kanji 'hokke'
940
+ # if (varCharField)
941
+ # expect(tb.getFVAstr(FDI_NAME)).to eq 'あいう'
942
+ # else
943
+ # expect(tb.getFVAstr(FDI_NAME)).to eq 'あいうえお'
944
+ # end
945
+ # else
946
+ # tb.setFVW(FDI_NAME, '0松本市') # numeric '0' kanji 'matumostoshi'
947
+ # expect(tb.getFVAstr(FDI_NAME)).to eq '0松本'
948
+ # end
949
+ # expect(tb.getFVWstr(FDI_GROUP)).to eq '68'
950
+ #end
951
+ ### Set Ansi Get Ansi
952
+ # too long string
953
+ tb.setFVA(FDI_NAME, '1234567')
954
+ if (varCharField)
955
+ expect(tb.getFVAstr(FDI_NAME)).to eq '123'
956
+ else
957
+ expect(tb.getFVAstr(FDI_NAME)).to eq '123456'
958
+ end
959
+ expect(tb.getFVAstr(FDI_GROUP)).to eq '68'
960
+ # short string
961
+ tb.setFVA(FDI_NAME, '13 ')
962
+ expect(tb.getFVAstr(FDI_NAME)).to eq '13 '
963
+ expect(tb.getFVAstr(FDI_GROUP)).to eq '68'
964
+ # too long lanji
965
+ if (unicodeField)
966
+ if !IS_WINDOWS
967
+ tb.setFVA(FDI_NAME, 'あいうえお𩸽') # hiragana 'aiueo' kanji 'hokke'
968
+ if (varCharField)
969
+ expect(tb.getFVAstr(FDI_NAME)).to eq 'あいう'
970
+ else
971
+ expect(tb.getFVAstr(FDI_NAME)).to eq 'あいうえお'
972
+ end
973
+ end
974
+ else
975
+ tb.setFVA(FDI_NAME, '0松本市') # numeric '0' kanji 'matumostoshi'
976
+ expect(tb.getFVAstr(FDI_NAME)).to eq '0松本'
977
+ end
978
+ expect(tb.getFVAstr(FDI_GROUP)).to eq '68'
979
+ end
980
+
981
+ def testVarField(db)
982
+ db.open(URL_VAR)
983
+ expect(db.stat()).to eq 0
984
+ tb = db.openTable('user1')
985
+ expect(db.stat()).to eq 0
986
+ # acp varchar
987
+ testSetGetVar(tb, false, true)
988
+ tb.close()
989
+ tb = db.openTable('user2')
990
+ expect(db.stat()).to eq 0
991
+ # acp varbinary
992
+ testSetGetVar(tb, false, false)
993
+ tb.close()
994
+ if (isUtf16leSupport(db))
995
+ tb = db.openTable('user3')
996
+ expect(db.stat()).to eq 0
997
+ # unicode varchar
998
+ testSetGetVar(tb, true, true)
999
+ tb.close()
1000
+ end
1001
+ tb = db.openTable('user4')
1002
+ expect(db.stat()).to eq 0
1003
+ # unicode varbinary'
1004
+ testSetGetVar(tb, true, false)
1005
+ tb.close()
1006
+ tb = db.openTable('user5')
1007
+ expect(db.stat()).to eq 0
1008
+ # utf8 varchar
1009
+ testSetGetVar(tb, true, true)
1010
+ tb.close()
1011
+ end
1012
+
1013
+ def doVarInsert(db, name, codePage, str, startid, endid, bulk)
1014
+ tb = db.openTable(name)
1015
+ expect(db.stat()).to eq 0
1016
+ tb.beginBulkInsert(BULKBUFSIZE) if (bulk)
1017
+ for i in startid..endid do
1018
+ tb.clearBuffer()
1019
+ tb.setFV(FDI_ID, i)
1020
+ tb.setFV(FDI_NAME, str + i.to_s)
1021
+ tb.setFV(FDI_GROUP, (i + 10))
1022
+ tb.insert()
1023
+ end
1024
+ tb.commitBulkInsert() if (bulk)
1025
+ tb.close()
1026
+ end
1027
+
1028
+ def testVarInsert(db)
1029
+ startid = 1
1030
+ bulk = false
1031
+ str = '漢字文字のテスト' # too long kanji
1032
+ str2 = '123'
1033
+ db.open(URL_VAR)
1034
+ expect(db.stat()).to eq 0
1035
+ if (0 == db.stat())
1036
+ utf16leSupport = isUtf16leSupport(db)
1037
+ doVarInsert(db, 'user1', Transactd::CP_ACP, str, startid, startid, bulk)
1038
+ doVarInsert(db, 'user2', Transactd::CP_ACP, str, startid, startid, bulk)
1039
+ doVarInsert(db, 'user3', Transactd::CP_ACP, str, startid, startid, bulk) if (utf16leSupport)
1040
+ doVarInsert(db, 'user4', Transactd::CP_ACP, str, startid, startid, bulk)
1041
+ doVarInsert(db, 'user5', Transactd::CP_UTF8, str, startid, startid, bulk)
1042
+ startid = startid + 1
1043
+ doVarInsert(db, 'user1', Transactd::CP_ACP, str2, startid, startid, bulk)
1044
+ doVarInsert(db, 'user2', Transactd::CP_ACP, str2, startid, startid, bulk)
1045
+ doVarInsert(db, 'user3', Transactd::CP_ACP, str2, startid, startid, bulk) if (utf16leSupport)
1046
+ doVarInsert(db, 'user4', Transactd::CP_ACP, str2, startid, startid, bulk)
1047
+ doVarInsert(db, 'user5', Transactd::CP_UTF8, str2, startid, startid, bulk)
1048
+ startid = startid + 1
1049
+ bulk = true
1050
+ endid = 1000
1051
+ doVarInsert(db, 'user1', Transactd::CP_ACP, '', startid, endid, bulk)
1052
+ doVarInsert(db, 'user2', Transactd::CP_ACP, '', startid, endid, bulk)
1053
+ doVarInsert(db, 'user3', Transactd::CP_ACP, '', startid, endid, bulk) if (utf16leSupport)
1054
+ doVarInsert(db, 'user4', Transactd::CP_ACP, '', startid, endid, bulk)
1055
+ doVarInsert(db, 'user5', Transactd::CP_UTF8, '', startid, endid, bulk)
1056
+ end
1057
+ end
1058
+
1059
+ def doVarRead(db, name, codePage, str, num, key)
1060
+ tb = db.openTable(name)
1061
+ expect(db.stat()).to eq 0
1062
+ tb.clearBuffer()
1063
+ tb.setKeyNum(key)
1064
+ if (key == 0)
1065
+ tb.setFV(FDI_ID, num)
1066
+ else
1067
+ v = num + 10
1068
+ tb.setFV(FDI_NAME, str)
1069
+ tb.setFV(FDI_GROUP, v)
1070
+ end
1071
+ tb.seek()
1072
+ expect(tb.stat()).to eq 0
1073
+ # test read of var field
1074
+ is_valid_value = (str == tb.getFVstr(FDI_NAME))
1075
+ expect(is_valid_value).to be true
1076
+ # test read of second field
1077
+ expect(tb.getFVint(FDI_GROUP)).to eq (num + 10)
1078
+ tb.close()
1079
+ end
1080
+
1081
+ def testVarRead(db)
1082
+ str = '漢字文'
1083
+ str3 = '漢字文字のテ'
1084
+ str2 ='123'
1085
+ str4 ='1232'
1086
+ db.open(URL_VAR)
1087
+ expect(db.stat()).to eq 0
1088
+ if (0 == db.stat())
1089
+ utf16leSupport = isUtf16leSupport(db)
1090
+ num = 1
1091
+ key = 0
1092
+ # too long string
1093
+ doVarRead(db, 'user1', Transactd::CP_ACP, str, num, key)
1094
+ doVarRead(db, 'user2', Transactd::CP_ACP, str, num, key)
1095
+ doVarRead(db, 'user3', Transactd::CP_ACP, str, num, key) if (utf16leSupport)
1096
+ doVarRead(db, 'user4', Transactd::CP_ACP, str3, num, key)
1097
+ doVarRead(db, 'user5', Transactd::CP_UTF8, str, num, key)
1098
+ # short string
1099
+ num = num + 1
1100
+ doVarRead(db, 'user1', Transactd::CP_ACP, str2, num, key)
1101
+ doVarRead(db, 'user2', Transactd::CP_ACP, str4, num, key)
1102
+ doVarRead(db, 'user3', Transactd::CP_ACP, str2, num, key) if (utf16leSupport)
1103
+ doVarRead(db, 'user4', Transactd::CP_ACP, str4, num, key)
1104
+ doVarRead(db, 'user5', Transactd::CP_UTF8, str2, num, key)
1105
+ key = 1
1106
+ doVarRead(db, 'user1', Transactd::CP_ACP, '120', 120, key)
1107
+ doVarRead(db, 'user2', Transactd::CP_ACP, '120', 120, key)
1108
+ doVarRead(db, 'user3', Transactd::CP_ACP, '120', 120, key) if (utf16leSupport)
1109
+ doVarRead(db, 'user4', Transactd::CP_ACP, '120', 120, key)
1110
+ doVarRead(db, 'user5', Transactd::CP_UTF8, '120', 120, key)
1111
+ end
1112
+ end
1113
+
1114
+ def doVarFilter(db, name, codePage, str, num, key)
1115
+ tb = db.openTable(name)
1116
+ expect(db.stat()).to eq 0
1117
+ tb.clearBuffer()
1118
+ tb.setKeyNum(key)
1119
+ if (key == 0)
1120
+ buf = 'id > ' + num.to_s + ' and id <= ' + (num + 10).to_s
1121
+ tb.setFilter(buf, 0, 10)
1122
+ # find forword
1123
+ tb.setFV(FDI_ID, num)
1124
+ tb.seekGreater(true)
1125
+ expect(tb.stat()).to eq 0
1126
+ for i in (num + 1)..(num + 10)
1127
+ tb.findNext()
1128
+ expect(tb.stat()).to eq 0
1129
+ # test read of var field
1130
+ expect(tb.getFVint(FDI_NAME)).to eq i
1131
+ # test read of second field
1132
+ expect(tb.getFVint(FDI_GROUP)).to eq (i + 10)
1133
+ end
1134
+ # find previous
1135
+ v = num + 10
1136
+ tb.setFilter(buf, 0, 10)
1137
+ tb.setFV(FDI_ID, v)
1138
+ tb.seekLessThan(true)
1139
+ expect(tb.stat()).to eq 0
1140
+ expect(tb.getFVint(FDI_ID)).to eq v
1141
+ for i in (num + 10).downto(num + 1) do
1142
+ tb.findPrev(false)
1143
+ expect(tb.stat()).to eq 0
1144
+ # test read of var field
1145
+ expect(tb.getFVint(FDI_NAME)).to eq i
1146
+ # test read of second field
1147
+ expect(tb.getFVint(FDI_GROUP)).to eq (i + 10)
1148
+ end
1149
+ # test record count
1150
+ expect(tb.recordCount()).to eq 10
1151
+ else
1152
+ v = num + 10
1153
+ tb.setFV(FDI_NAME, str)
1154
+ tb.setFV(FDI_GROUP, v)
1155
+ end
1156
+ tb.close()
1157
+ end
1158
+
1159
+ def testFilterVar(db)
1160
+ db.open(URL_VAR)
1161
+ expect(db.stat()).to eq 0
1162
+ if (0 == db.stat())
1163
+ str = '漢字文'
1164
+ str3 = '漢字文字のテ'
1165
+ str2 = '123'
1166
+ str4 = '1232'
1167
+ utf16leSupport = isUtf16leSupport(db)
1168
+ num = 10
1169
+ key = 0
1170
+ doVarFilter(db, 'user1', Transactd::CP_ACP, str, num, key)
1171
+ doVarFilter(db, 'user2', Transactd::CP_ACP, str, num, key)
1172
+ doVarFilter(db, 'user3', Transactd::CP_ACP, str, num, key) if (utf16leSupport)
1173
+ doVarFilter(db, 'user4', Transactd::CP_ACP, str3, num, key)
1174
+ doVarFilter(db, 'user5', Transactd::CP_UTF8, str, num, key)
1175
+ #ifdef _UNICODE
1176
+ # # short string
1177
+ # num = num + 1
1178
+ # doVarFilter(db, 'user1', Transactd::CP_ACP, str2, num, key)
1179
+ # doVarFilter(db, 'user2', Transactd::CP_ACP, str4, num, key)
1180
+ # doVarFilter(db, 'user3', Transactd::CP_ACP, str2, num, key) if (utf16leSupport)
1181
+ # doVarFilter(db, 'user4', Transactd::CP_ACP, str4, num, key)
1182
+ # doVarFilter(db, 'user5', Transactd::CP_UTF8, str2, num, key)
1183
+ #endif
1184
+ key = 1
1185
+ doVarFilter(db, 'user1', Transactd::CP_ACP, '120', 120, key)
1186
+ doVarFilter(db, 'user2', Transactd::CP_ACP, '120', 120, key)
1187
+ doVarFilter(db, 'user3', Transactd::CP_ACP, '120', 120, key) if (utf16leSupport)
1188
+ doVarFilter(db, 'user4', Transactd::CP_ACP, '120', 120, key)
1189
+ doVarFilter(db, 'user5', Transactd::CP_UTF8, '120', 120, key)
1190
+ end
1191
+ end
1192
+
1193
+
1194
+ def testCreateTableStringFilter(db, id, name, type, type2)
1195
+ # create table
1196
+ dbdef = db.dbDef()
1197
+ td = Transactd::Tabledef.new()
1198
+ td.setTableName(name)
1199
+ td.setFileName(name + '.dat')
1200
+ td.id =id
1201
+ td.pageSize = 2048
1202
+ td.charsetIndex = Transactd::CHARSET_UTF8B4
1203
+ # td.charsetIndex = Transactd::CHARSET_CP932
1204
+ dbdef.insertTable(td)
1205
+ expect(dbdef.stat()).to eq 0
1206
+ fd = dbdef.insertField(id, 0)
1207
+ fd.setName('id')
1208
+ fd.type = Transactd::Ft_integer
1209
+ fd.len = 4
1210
+ dbdef.updateTableDef(id)
1211
+ expect(dbdef.stat()).to eq 0
1212
+ fd = dbdef.insertField(id, 1)
1213
+ fd.setName('name')
1214
+ fd.type = type
1215
+ fd.len = 44
1216
+ if (fd.varLenBytes() != 0)
1217
+ fd.len = fd.varLenBytes() + 44
1218
+ fd.keylen = fd.len
1219
+ end
1220
+ if (fd.blobLenBytes() != 0)
1221
+ fd.len = 12 # 8+4
1222
+ end
1223
+ fd.keylen = fd.len
1224
+ dbdef.updateTableDef(id)
1225
+ expect(dbdef.stat()).to eq 0
1226
+ fd = dbdef.insertField(id, 2)
1227
+ fd.setName('namew')
1228
+ fd.type = type2
1229
+ fd.len = 44
1230
+ if (fd.varLenBytes() != 0)
1231
+ fd.len = fd.varLenBytes() + 44
1232
+ fd.keylen = fd.len
1233
+ end
1234
+ if (fd.blobLenBytes() != 0)
1235
+ fd.len = 12 # 8+4
1236
+ end
1237
+ fd.keylen = fd.len
1238
+ dbdef.updateTableDef(id)
1239
+ expect(dbdef.stat()).to eq 0
1240
+ kd = dbdef.insertKey(id, 0)
1241
+ kd.segment(0).fieldNum = 0
1242
+ kd.segment(0).flags.bit8 = 1 # extended key type
1243
+ kd.segment(0).flags.bit1 = 1 # changeable
1244
+ kd.segmentCount = 1
1245
+ dbdef.updateTableDef(id)
1246
+ expect(dbdef.stat()).to eq 0
1247
+ kd = dbdef.insertKey(id, 1)
1248
+ kd.segment(0).fieldNum = 1
1249
+ kd.segment(0).flags.bit8 = 1 # extended key type
1250
+ kd.segment(0).flags.bit1 = 1 # changeable
1251
+ kd.segment(0).flags.bit0 = 1 # duplicateable
1252
+ kd.segmentCount = 1
1253
+ dbdef.updateTableDef(id)
1254
+ expect(dbdef.stat()).to eq 0
1255
+ kd = dbdef.insertKey(id, 2)
1256
+ kd.segment(0).fieldNum = 2
1257
+ kd.segment(0).flags.bit8 = 1 # extended key type
1258
+ kd.segment(0).flags.bit1 = 1 # changeable
1259
+ kd.segment(0).flags.bit0 = 1 # duplicateable
1260
+ kd.segmentCount = 1
1261
+ dbdef.updateTableDef(id)
1262
+ expect(dbdef.stat()).to eq 0
1263
+ end
1264
+
1265
+ def doTestInsertStringFilter(tb)
1266
+ tb.clearBuffer()
1267
+ id = 1
1268
+ tb.setFV('id', id)
1269
+ tb.setFV('name', 'あいうえおかきくこ')
1270
+ tb.setFV('namew', 'あいうえおかきくこ')
1271
+ tb.insert()
1272
+ tb.clearBuffer()
1273
+ id = 2
1274
+ tb.setFV('id', id)
1275
+ tb.setFV('name', 'A123456')
1276
+ tb.setFV('namew', 'A123456')
1277
+ tb.insert()
1278
+ tb.clearBuffer()
1279
+ id = 3
1280
+ tb.setFV('id', id)
1281
+ tb.setFV('name', 'あいがあればOKです')
1282
+ tb.setFV('namew', 'あいがあればOKです')
1283
+ tb.insert()
1284
+ tb.clearBuffer()
1285
+ id = 4
1286
+ tb.setFV('id', id)
1287
+ tb.setFV('name', 'おはようございます')
1288
+ tb.setFV('namew', 'おはようございます')
1289
+ tb.insert()
1290
+ tb.clearBuffer()
1291
+ id = 5
1292
+ tb.setFV('id', id)
1293
+ tb.setFV('name', 'おめでとうございます。')
1294
+ tb.setFV('namew', 'おめでとうございます。')
1295
+ tb.insert()
1296
+ end
1297
+
1298
+ def doTestReadStringFilter(tb)
1299
+ tb.setKeyNum(0)
1300
+ tb.clearBuffer()
1301
+ id = 1
1302
+ tb.setFV('id', id)
1303
+ tb.seek()
1304
+ expect(tb.stat()).to eq 0
1305
+ expect(tb.getFVstr(FDI_NAME)).to eq 'あいうえおかきくこ'
1306
+ id =3
1307
+ tb.setFV('id', id)
1308
+ tb.seek()
1309
+ expect(tb.stat()).to eq 0
1310
+ expect(tb.getFVstr(FDI_NAME)).to eq 'あいがあればOKです'
1311
+ tb.setKeyNum(1)
1312
+ tb.clearBuffer()
1313
+ tb.setFV('name', 'A123456')
1314
+ tb.seek()
1315
+ expect(tb.stat()).to eq 0
1316
+ expect(tb.getFVstr(FDI_NAME)).to eq 'A123456'
1317
+ tb.setKeyNum(2)
1318
+ tb.clearBuffer()
1319
+ tb.setFV('namew', 'A123456')
1320
+ tb.seek()
1321
+ expect(tb.stat()).to eq 0
1322
+ expect(tb.getFVstr(FDI_NAMEW)).to eq 'A123456'
1323
+ end
1324
+
1325
+ def doTestSetStringFilter(tb)
1326
+ tb.setKeyNum(0)
1327
+ tb.clearBuffer()
1328
+ tb.setFilter("name = 'あい*'", 0, 10)
1329
+ tb.seekFirst()
1330
+ tb.findNext(false)
1331
+ expect(tb.stat()).to eq 0
1332
+ expect(tb.getFVstr(FDI_NAME)).to eq 'あいうえおかきくこ'
1333
+ expect(tb.recordCount()).to eq 2
1334
+ tb.setFilter("name <> 'あい*'", 0, 10)
1335
+ expect(tb.recordCount()).to eq 3
1336
+ tb.setFilter("name = 'あい'", 0, 10)
1337
+ expect(tb.recordCount()).to eq 0
1338
+ tb.setFilter("name <> ''", 0, 10)
1339
+ expect(tb.recordCount()).to eq 5
1340
+ end
1341
+
1342
+ def doTestStringFilter(db, id, name, type, type2)
1343
+ testCreateTableStringFilter(db, id, name, type, type2)
1344
+ tb = db.openTable(id)
1345
+ expect(db.stat()).to eq 0
1346
+ doTestInsertStringFilter(tb)
1347
+ doTestReadStringFilter(tb)
1348
+ doTestSetStringFilter(tb)
1349
+ tb.close()
1350
+ end
1351
+
1352
+ def testStringFilter(db)
1353
+ db.create(URL_SF)
1354
+ if db.stat() == Transactd::STATUS_TABLE_EXISTS_ERROR
1355
+ testDropDatabaseStringFilter(db)
1356
+ db.create(URL_SF)
1357
+ end
1358
+ expect(db.stat()).to eq 0
1359
+ db.open(URL_SF, 0, 0)
1360
+ expect(db.stat()).to eq 0
1361
+ doTestStringFilter( db, 1, 'zstring', Transactd::Ft_zstring, Transactd::Ft_wzstring)
1362
+ if (isUtf16leSupport(db))
1363
+ doTestStringFilter( db, 2, 'myvarchar', Transactd::Ft_myvarchar, Transactd::Ft_mywvarchar)
1364
+ else
1365
+ doTestStringFilter( db, 2, 'myvarchar', Transactd::Ft_myvarchar, Transactd::Ft_myvarchar)
1366
+ end
1367
+ doTestStringFilter( db, 3, 'mytext', Transactd::Ft_mytext, Transactd::Ft_myblob)
1368
+ end
1369
+
1370
+ def testDropDatabaseStringFilter(db)
1371
+ db.open(URL_SF, 0, 0)
1372
+ expect(db.stat()).to eq 0
1373
+ db.drop()
1374
+ expect(db.stat()).to eq 0
1375
+ end
1376
+
1377
+
1378
+ describe Transactd do
1379
+ before :each do
1380
+ @db = Transactd::Database.createObject()
1381
+ end
1382
+ after :each do
1383
+ @db.close()
1384
+ @db = nil
1385
+ end
1386
+ it 'create database' do
1387
+ testCreateDatabase(@db)
1388
+ end
1389
+ it 'create table' do
1390
+ testCreateDatabase(@db)
1391
+ testCreateTable(@db)
1392
+ end
1393
+ it 'open table' do
1394
+ testOpenTable(@db)
1395
+ end
1396
+ it 'version' do
1397
+ testVersion(@db)
1398
+ end
1399
+ it 'insert' do
1400
+ testInsert(@db)
1401
+ end
1402
+ it 'find' do
1403
+ testFind(@db)
1404
+ end
1405
+ it 'findNext' do
1406
+ testFindNext(@db)
1407
+ end
1408
+ it 'get percentage' do
1409
+ testGetPercentage(@db)
1410
+ end
1411
+ it 'move percentage' do
1412
+ testMovePercentage(@db)
1413
+ end
1414
+ it 'get equal' do
1415
+ testGetEqual(@db)
1416
+ end
1417
+ it 'get next' do
1418
+ testGetNext(@db)
1419
+ end
1420
+ it 'get previous' do
1421
+ testGetPrevious(@db)
1422
+ end
1423
+ it 'get greater' do
1424
+ testGetGreater(@db)
1425
+ end
1426
+ it 'get less than' do
1427
+ testGetLessThan(@db)
1428
+ end
1429
+ it 'get first' do
1430
+ testGetFirst(@db)
1431
+ end
1432
+ it 'get last' do
1433
+ testGetLast(@db)
1434
+ end
1435
+ it 'move position' do
1436
+ testMovePosition(@db)
1437
+ end
1438
+ it 'update' do
1439
+ testUpdate(@db)
1440
+ end
1441
+ it 'snapshot' do
1442
+ testSnapShot(@db)
1443
+ end
1444
+ it 'send conflict error' do
1445
+ testConflict(@db)
1446
+ end
1447
+ it 'transaction' do
1448
+ testTransactionLock(@db)
1449
+ end
1450
+ it 'insert2' do
1451
+ testInsert2(@db)
1452
+ end
1453
+ it 'delete' do
1454
+ testDelete(@db)
1455
+ end
1456
+ it 'set owner' do
1457
+ testSetOwner(@db)
1458
+ end
1459
+ it 'drop index' do
1460
+ testDropIndex(@db)
1461
+ end
1462
+ it 'drop database' do
1463
+ testDropDatabase(@db)
1464
+ end
1465
+ it 'login' do
1466
+ testLogin(@db)
1467
+ end
1468
+ end
1469
+
1470
+ describe Transactd, 'var tables' do
1471
+ before :each do
1472
+ @db = Transactd::Database.createObject()
1473
+ end
1474
+ after :each do
1475
+ @db.close()
1476
+ @db = nil
1477
+ end
1478
+ it 'create var database' do
1479
+ testCreateDatabaseVar(@db)
1480
+ end
1481
+ it 'set kanji char to field' do
1482
+ testVarField(@db)
1483
+ end
1484
+ it 'insert kanji char to field' do
1485
+ testVarInsert(@db)
1486
+ end
1487
+ it 'read kanji char from field' do
1488
+ testVarRead(@db)
1489
+ end
1490
+ it 'filter' do
1491
+ testFilterVar(@db)
1492
+ end
1493
+ it 'drop var database' do
1494
+ testDropDatabaseVar(@db)
1495
+ end
1496
+ end
1497
+
1498
+ describe Transactd, 'StringFilter' do
1499
+ before :each do
1500
+ @db = Transactd::Database.createObject()
1501
+ end
1502
+ after :each do
1503
+ @db.close()
1504
+ @db = nil
1505
+ end
1506
+ it 'string filter' do
1507
+ testStringFilter(@db)
1508
+ end
1509
+ it 'drop database' do
1510
+ testDropDatabaseStringFilter(@db)
1511
+ end
1512
+ end
1513
+
1514
+ describe Transactd, 'convert' do
1515
+ if !IS_WINDOWS
1516
+ it 'convert char' do
1517
+ dummy = ''
1518
+ u8 = '123'
1519
+ mbcArray = '123'.encode('Shift_JIS').bytes.to_a # bites Shift-JIS '漢字'
1520
+ ret = Transactd::u8tombc(u8, -1, dummy, 256)
1521
+ mbc = ret[1].force_encoding('Shift_JIS')
1522
+ expect(mbc.bytes.to_a).to eq mbcArray
1523
+
1524
+ u8 = '漢字'
1525
+ mbcArray = '漢字'.encode('Shift_JIS').bytes.to_a # bites Shift-JIS '漢字'
1526
+ ret = Transactd::u8tombc(u8, -1, dummy, 256)
1527
+ mbc = ret[1].force_encoding('Shift_JIS')
1528
+ expect(mbc.bytes.to_a).to eq mbcArray
1529
+
1530
+ u8Array = '漢字'.encode('UTF-8').bytes.to_a # bites UTF-8 '漢字'
1531
+ ret = Transactd::mbctou8(mbc, -1, dummy , 256)
1532
+ u8 = ret[1].force_encoding('UTF-8')
1533
+ expect(u8.bytes.to_a).to eq u8Array
1534
+ end
1535
+ end
1536
+ end