transactd 1.0.1-x86-mswin32-100

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -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