transactd 2.2.0 → 2.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (114) hide show
  1. checksums.yaml +4 -4
  2. data/BUILD_UNIX-JA +6 -6
  3. data/README +20 -18
  4. data/README-JA +19 -17
  5. data/RELEASE_NOTE +144 -0
  6. data/RELEASE_NOTE-JA +153 -0
  7. data/bin/common/tdclc_32_2_3.dll +0 -0
  8. data/bin/common/tdclc_64_2_3.dll +0 -0
  9. data/build/common/get_ruby_path.cmake +1 -1
  10. data/build/swig/ruby/ruby.swg +10 -9
  11. data/build/swig/ruby/tdclrb_wrap.cpp +1416 -561
  12. data/build/swig/tdcl.i +30 -3
  13. data/build/tdclc/tdclc.cbproj +1 -1
  14. data/build/tdclc/tdclc.rc +4 -4
  15. data/build/tdclcpp/BUILDNUMBER.txt +1 -0
  16. data/build/tdclcpp/tdclcpp.rc +4 -4
  17. data/build/tdclcpp/tdclcpp_bc.cbproj +1 -1
  18. data/build/tdclrb/BUILDNUMBER.txt +1 -0
  19. data/build/tdclrb/tdclrb.rc +4 -4
  20. data/source/bzs/db/engine/mysql/database.cpp +85 -41
  21. data/source/bzs/db/engine/mysql/database.h +35 -5
  22. data/source/bzs/db/engine/mysql/mysqlInternal.h +189 -37
  23. data/source/bzs/db/engine/mysql/mysqlThd.cpp +21 -21
  24. data/source/bzs/db/protocol/tdap/client/activeTable.cpp +11 -0
  25. data/source/bzs/db/protocol/tdap/client/activeTable.h +1 -1
  26. data/source/bzs/db/protocol/tdap/client/activeTableImple.h +11 -4
  27. data/source/bzs/db/protocol/tdap/client/client.h +30 -1
  28. data/source/bzs/db/protocol/tdap/client/dbDef.cpp +2 -1
  29. data/source/bzs/db/protocol/tdap/client/dllmain.cpp +35 -5
  30. data/source/bzs/db/protocol/tdap/client/field.cpp +100 -51
  31. data/source/bzs/db/protocol/tdap/client/field.h +7 -7
  32. data/source/bzs/db/protocol/tdap/client/filter.h +20 -6
  33. data/source/bzs/db/protocol/tdap/client/groupQuery.cpp +337 -58
  34. data/source/bzs/db/protocol/tdap/client/groupQuery.h +56 -13
  35. data/source/bzs/db/protocol/tdap/client/nsDatabase.cpp +83 -5
  36. data/source/bzs/db/protocol/tdap/client/nsDatabase.h +4 -1
  37. data/source/bzs/db/protocol/tdap/client/nsTable.cpp +2 -2
  38. data/source/bzs/db/protocol/tdap/client/nsTable.h +2 -1
  39. data/source/bzs/db/protocol/tdap/client/pooledDatabaseManager.h +20 -6
  40. data/source/bzs/db/protocol/tdap/client/recordset.cpp +7 -0
  41. data/source/bzs/db/protocol/tdap/client/recordsetImple.h +8 -4
  42. data/source/bzs/db/protocol/tdap/client/request.h +11 -1
  43. data/source/bzs/db/protocol/tdap/client/serializer.cpp +40 -2
  44. data/source/bzs/db/protocol/tdap/client/serializer.h +4 -2
  45. data/source/bzs/db/protocol/tdap/client/sqlBuilder.cpp +1 -0
  46. data/source/bzs/db/protocol/tdap/client/stringConverter.h +4 -4
  47. data/source/bzs/db/protocol/tdap/client/table.cpp +124 -71
  48. data/source/bzs/db/protocol/tdap/client/table.h +8 -7
  49. data/source/bzs/db/protocol/tdap/client/trdormapi.h +33 -1
  50. data/source/bzs/db/protocol/tdap/fieldComp.h +1 -1
  51. data/source/bzs/db/protocol/tdap/mysql/databaseSchema.cpp +3 -1
  52. data/source/bzs/db/protocol/tdap/mysql/recordsetReader.h +20 -4
  53. data/source/bzs/db/protocol/tdap/mysql/request.h +14 -0
  54. data/source/bzs/db/protocol/tdap/mysql/tdapCommandExecuter.cpp +132 -69
  55. data/source/bzs/db/protocol/tdap/tdapRequest.h +18 -4
  56. data/source/bzs/db/protocol/tdap/tdapSchema.cpp +32 -22
  57. data/source/bzs/db/protocol/tdap/tdapSchema.h +69 -4
  58. data/source/bzs/db/protocol/tdap/tdapcapi.h +13 -5
  59. data/source/bzs/db/protocol/tdap/uri.h +4 -4
  60. data/source/bzs/db/transactd/transactd.cpp +6 -5
  61. data/source/bzs/env/crosscompile.cpp +17 -0
  62. data/source/bzs/env/crosscompile.h +4 -1
  63. data/source/bzs/env/mbcswchrLinux.cpp +3 -0
  64. data/source/bzs/example/deleteRecords.cpp +13 -0
  65. data/source/bzs/example/deleteRecords_c.cpp +8 -1
  66. data/source/bzs/example/insertRecords.cpp +14 -0
  67. data/source/bzs/example/insertRecords_c.cpp +8 -1
  68. data/source/bzs/example/ormap_c.cpp +8 -1
  69. data/source/bzs/example/queryData.cpp +92 -2
  70. data/source/bzs/example/queryData.h +3 -1
  71. data/source/bzs/example/readRecords.cpp +13 -0
  72. data/source/bzs/example/readRecords_c.cpp +8 -1
  73. data/source/bzs/example/updateRecords.cpp +13 -0
  74. data/source/bzs/example/updateRecords_c.cpp +8 -1
  75. data/source/bzs/example/update_with_transaction.cpp +13 -0
  76. data/source/bzs/example/update_with_transaction_c.cpp +8 -1
  77. data/source/bzs/example/useORMRecord.cpp +9 -3
  78. data/source/bzs/netsvc/client/iconnection.h +8 -0
  79. data/source/bzs/netsvc/client/tcpClient.cpp +61 -16
  80. data/source/bzs/netsvc/client/tcpClient.h +430 -214
  81. data/source/bzs/netsvc/server/serverPipe.cpp +2 -2
  82. data/source/bzs/test/tdclphp/transactd_Test.php +115 -19
  83. data/source/bzs/test/tdclphp/transactd_blob_Test.php +33 -5
  84. data/source/bzs/test/tdclphp/transactd_kanjischema_Test.php +21 -3
  85. data/source/bzs/test/tdclphp/transactd_pool_Test.php +17 -3
  86. data/source/bzs/test/tdclrb/transactd_blob_spec.rb +26 -8
  87. data/source/bzs/test/tdclrb/transactd_kanjischema_spec.rb +13 -6
  88. data/source/bzs/test/tdclrb/transactd_pool_spec.rb +14 -8
  89. data/source/bzs/test/tdclrb/transactd_spec.rb +117 -27
  90. data/source/bzs/test/transactdBench/scaling_bench.cpp +5 -5
  91. data/source/bzs/test/transactdBench/workerBase.h +2 -2
  92. data/source/bzs/test/trdclengn/test_trdclengn.cpp +898 -51
  93. data/source/global/tdclatl/Database.cpp +12 -0
  94. data/source/global/tdclatl/Database.h +4 -0
  95. data/source/global/tdclatl/FieldDef.cpp +19 -0
  96. data/source/global/tdclatl/FieldDef.h +4 -0
  97. data/source/global/tdclatl/FieldDefs.cpp +14 -16
  98. data/source/global/tdclatl/GroupQuery.cpp +21 -16
  99. data/source/global/tdclatl/GroupQuery.h +1 -1
  100. data/source/global/tdclatl/QueryBase.cpp +14 -0
  101. data/source/global/tdclatl/QueryBase.h +2 -0
  102. data/source/global/tdclatl/Record.cpp +41 -10
  103. data/source/global/tdclatl/Record.h +1 -1
  104. data/source/global/tdclatl/Recordset.cpp +117 -31
  105. data/source/global/tdclatl/Recordset.h +6 -5
  106. data/source/global/tdclatl/Table.cpp +24 -28
  107. data/source/global/tdclatl/Table.h +3 -4
  108. data/source/global/tdclatl/activeTable.cpp +149 -103
  109. data/source/global/tdclatl/activeTable.h +1 -1
  110. data/source/global/tdclatl/tdclatl.idl +38 -18
  111. data/transactd.gemspec +1 -1
  112. metadata +8 -4
  113. data/bin/common/tdclc_32_2_2.dll +0 -0
  114. data/bin/common/tdclc_64_2_2.dll +0 -0
@@ -121,6 +121,7 @@ class fixture
121
121
  public:
122
122
  fixture() : m_db(NULL)
123
123
  {
124
+
124
125
  nsdatabase::setCheckTablePtr(true);
125
126
  m_db = database::create();
126
127
  if (!m_db)
@@ -141,6 +142,35 @@ public:
141
142
  ::database* db() const { return m_db; }
142
143
  };
143
144
 
145
+ #ifdef _WIN32
146
+ class fixtureKanji
147
+ {
148
+ mutable database* m_db;
149
+
150
+ public:
151
+ fixtureKanji() : m_db(NULL)
152
+ {
153
+ nsdatabase::setExecCodePage(932);
154
+ nsdatabase::setCheckTablePtr(true);
155
+ m_db = database::create();
156
+ if (!m_db)
157
+ printf("Error database::create()\n");
158
+ }
159
+
160
+ ~fixtureKanji()
161
+ {
162
+ if (m_db)
163
+ m_db->release();
164
+ }
165
+ ::database* db() const { return m_db; }
166
+ };
167
+ #else
168
+ typedef fixture fixtureKanji;
169
+ #endif
170
+
171
+
172
+
173
+
144
174
  class fixtureQuery
145
175
  {
146
176
  database_ptr m_db;
@@ -239,6 +269,12 @@ void testCreateNewDataBase(database* db)
239
269
  td.parentKeyNum = -1;
240
270
  td.replicaKeyNum = -1;
241
271
  td.pageSize = 2048;
272
+ #ifdef _WIN32
273
+ td.charsetIndex = CHARSET_CP932;
274
+ #else
275
+ td.charsetIndex = CHARSET_UTF8;
276
+ #endif
277
+
242
278
  def->insertTable(&td);
243
279
  BOOST_CHECK_MESSAGE(0 == def->stat(),
244
280
  "insertTable stat = " << def->stat());
@@ -253,8 +289,18 @@ void testCreateNewDataBase(database* db)
253
289
 
254
290
  fd = def->insertField(1, 1);
255
291
  fd->setName(_T("name"));
256
- fd->type = ft_zstring;
257
292
  fd->len = (ushort_td)33;
293
+
294
+ //test padChar only string or wstring
295
+ fd->type = ft_string;
296
+ fd->setPadCharSettings(true, false);
297
+ BOOST_CHECK(fd->usePadChar() == true);
298
+ BOOST_CHECK(fd->trimPadChar() == false);
299
+ fd->setPadCharSettings(false, true);
300
+ BOOST_CHECK(fd->usePadChar() == false);
301
+ BOOST_CHECK(fd->trimPadChar() == true);
302
+
303
+ fd->type = ft_zstring;
258
304
  def->updateTableDef(1);
259
305
  BOOST_CHECK_MESSAGE(0 == def->stat(),
260
306
  "updateTableDef 2 stat = " << def->stat());
@@ -382,6 +428,13 @@ void testInsert(database* db)
382
428
  tb->insert();
383
429
  BOOST_CHECK_MESSAGE(0 == tb->stat(), "insert");
384
430
  }
431
+ //test invalid keyNum
432
+ tb->clearBuffer();
433
+ tb->setFV((short)0, _T("2"));
434
+ tb->setKeyNum(10);
435
+ tb->insert();
436
+ BOOST_CHECK_MESSAGE(STATUS_INVALID_KEYNUM == tb->stat(), "Invalid keynum insert");
437
+ tb->setKeyNum(0);
385
438
 
386
439
  db->beginTrn();
387
440
  int n = 1;
@@ -423,12 +476,23 @@ void testFind(database* db)
423
476
  {
424
477
 
425
478
  table* tb = openTable(db);
426
- tb->setKeyNum(0);
479
+
480
+ //test invalid keyNum
427
481
  tb->clearBuffer();
482
+ tb->setKeyNum(10);
428
483
  tb->setFilter(_T("id >= 10 and id < 20000"), 1, 0);
429
484
  int v = 10;
430
485
  tb->setFV((short)0, v);
431
486
  tb->find(table::findForword);
487
+ BOOST_CHECK_MESSAGE(STATUS_INVALID_KEYNUM == tb->stat(), "Invalid keynum find");
488
+
489
+
490
+ tb->setKeyNum(0);
491
+ tb->clearBuffer();
492
+ tb->setFilter(_T("id >= 10 and id < 20000"), 1, 0);
493
+ v = 10;
494
+ tb->setFV((short)0, v);
495
+ tb->find(table::findForword);
432
496
  findNextLoop(tb, v, 20000);
433
497
 
434
498
  // backforword
@@ -478,10 +542,22 @@ void testFindIn(database* db)
478
542
  {
479
543
 
480
544
  table* tb = openTable(db);
481
- tb->setKeyNum(0);
545
+
546
+ //test invalid keyNum
482
547
  tb->clearBuffer();
483
548
  queryBase q;
484
549
  q.addSeekKeyValue(_T("10"), true);
550
+ tb->setQuery(&q);
551
+ BOOST_CHECK_MESSAGE(0 == tb->stat(), "find in stat = " << tb->stat());
552
+ tb->setKeyNum(10);
553
+ tb->find();
554
+ BOOST_CHECK_MESSAGE(STATUS_INVALID_KEYNUM == tb->stat(), "Invalid keynum seekKeyValue");
555
+
556
+
557
+ tb->setKeyNum(0);
558
+ tb->clearBuffer();
559
+ q.reset();
560
+ q.addSeekKeyValue(_T("10"), true);
485
561
  q.addSeekKeyValue(_T("300000"));
486
562
  q.addSeekKeyValue(_T("50"));
487
563
  q.addSeekKeyValue(_T("-1"));
@@ -603,9 +679,16 @@ void testPrepareServer(database* db)
603
679
  {
604
680
  table* tb = openTable(db);
605
681
  queryBase q;
606
- q.queryString(_T("id >= ? and id < ?"));
607
- q.reject(0xFFFF).limit(0);
682
+
683
+ //test invalid keyNum
684
+ tb->setKeyNum(10);
685
+ tb->clearBuffer();
686
+ q.queryString(_T("id >= ? and id < ?")).reject(0xFFFF).limit(0);
608
687
  pq_handle stmt = tb->prepare(&q, true);
688
+ BOOST_CHECK_MESSAGE(STATUS_INVALID_KEYNUM == tb->stat(), "Invalid keynum prepare");
689
+
690
+ tb->setKeyNum(0);
691
+ stmt = tb->prepare(&q, true);
609
692
  BOOST_CHECK_MESSAGE(0 == tb->stat(), "prepare stat");
610
693
  if (tb->stat()) return ;
611
694
 
@@ -677,20 +760,6 @@ void testPrepareServer(database* db)
677
760
  tb->find(table::findForword);
678
761
  findNextLoop(tb, v, 3000);
679
762
 
680
- // Seeks prepare statement
681
- /*q.reset();
682
- q.queryString(_T("select id"));
683
- pq_handle stmt3 = tb->prepare(&q, true);
684
- const _TCHAR* vsi[6];
685
- makeSupplyValues(vsi, 6, _T("10"), _T("11"), _T("12"), _T("13"),
686
- _T("14"), _T("15"));
687
- int keySegments = 1;
688
- ret = supplyInValues(stmt3, vsi, 6, keySegments);
689
- BOOST_CHECK_MESSAGE(ret == true, "supplyValues ");
690
- tb->setPrepare(stmt3);
691
- tb->find();
692
- findNextLoop(tb, 10, 16);
693
- */
694
763
  tb->release();
695
764
  }
696
765
 
@@ -712,6 +781,13 @@ void testMovePercentage(database* db)
712
781
  {
713
782
  table* tb = openTable(db);
714
783
  tb->clearBuffer();
784
+
785
+ //test invalid keyNum
786
+ tb->setKeyNum(10);
787
+ tb->seekByPercentage(5000); // 50%
788
+ BOOST_CHECK_MESSAGE(STATUS_INVALID_KEYNUM == tb->stat(), "Invalid keynum prepare");
789
+
790
+ tb->setKeyNum(0);
715
791
  tb->seekByPercentage(5000); // 50%
716
792
  BOOST_CHECK_MESSAGE(0 == tb->stat(), "MovePercentage");
717
793
  // If mainus is less than 500 then ok.
@@ -723,7 +799,16 @@ void testMovePercentage(database* db)
723
799
  void testGetEqual(database* db)
724
800
  {
725
801
  table* tb = openTable(db);
802
+
803
+ //test invalid keyNum
804
+ tb->setKeyNum(10);
805
+ tb->clearBuffer();
806
+ tb->setFV((short)0, 10);
807
+ tb->seek();
808
+ BOOST_CHECK_MESSAGE(STATUS_INVALID_KEYNUM == tb->stat(), "Invalid keynum seek");
809
+
726
810
  db->beginSnapshot();
811
+ tb->setKeyNum(0);
727
812
  for (int i = 2; i < 20002; i++)
728
813
  {
729
814
  tb->clearBuffer();
@@ -852,6 +937,13 @@ void testGetFirst(database* db)
852
937
  {
853
938
  table* tb = openTable(db);
854
939
  tb->clearBuffer();
940
+
941
+ //test invalid keyNum
942
+ tb->setKeyNum(10);
943
+ tb->seekFirst();
944
+ BOOST_CHECK_MESSAGE(STATUS_INVALID_KEYNUM == tb->stat(), "Invalid keynum seekFirst");
945
+
946
+ tb->setKeyNum(0);
855
947
  tb->seekFirst();
856
948
  BOOST_CHECK_MESSAGE(_tstring(_T("kosaka")) == _tstring(tb->getFVstr(1)),
857
949
  "GetFirst");
@@ -862,6 +954,13 @@ void testGetLast(database* db)
862
954
  {
863
955
  table* tb = openTable(db);
864
956
  tb->clearBuffer();
957
+
958
+ //test invalid keyNum
959
+ tb->setKeyNum(10);
960
+ tb->seekLast();
961
+ BOOST_CHECK_MESSAGE(STATUS_INVALID_KEYNUM == tb->stat(), "Invalid keynum seekFirst");
962
+
963
+ tb->setKeyNum(0);
865
964
  tb->seekLast();
866
965
  BOOST_CHECK_MESSAGE(20002 == tb->getFVint(fdi_id), "GetLast");
867
966
  tb->release();
@@ -870,7 +969,6 @@ void testGetLast(database* db)
870
969
  void testMovePosition(database* db)
871
970
  {
872
971
  table* tb = openTable(db);
873
- tb->clearBuffer();
874
972
  int vv = 15000;
875
973
  tb->clearBuffer();
876
974
  tb->setFV(fdi_id, vv);
@@ -891,6 +989,13 @@ void testMovePosition(database* db)
891
989
 
892
990
  tb->seekByBookmark(pos);
893
991
  BOOST_CHECK_MESSAGE(15000 == tb->getFVint(fdi_id), "MovePosition");
992
+
993
+ //test invalid keyNum
994
+ tb->setKeyNum(10);
995
+ tb->seekByBookmark(pos);
996
+ BOOST_CHECK_MESSAGE(STATUS_INVALID_KEYNUM == tb->stat(),
997
+ "Invalid keynum seekByBookmark stat = " << tb->stat());
998
+
894
999
  tb->release();
895
1000
  }
896
1001
 
@@ -1347,6 +1452,49 @@ void testTransactionLockRepeatable(database* db)
1347
1452
  database::destroy(db2);
1348
1453
  }
1349
1454
 
1455
+
1456
+ void testBug_015(database* db)
1457
+ {
1458
+ table* tb = openTable(db);
1459
+ db->beginTrn(SINGLELOCK_NOGAP);
1460
+ tb->seekFirst(); // lock(X)
1461
+ tb->unlock();
1462
+ tb->seekNext();
1463
+ /* Here! InnoDB issues an error message, please check the MySQL error log.
1464
+ [InnoDB: Error: unlock row could not find a 3 mode lock on the record]
1465
+ */
1466
+ db->endTrn();
1467
+ tb->release();
1468
+ }
1469
+ /* READ_COMMITTED support select lock type */
1470
+ void testIssue_016(database* db)
1471
+ {
1472
+ table* tb = openTable(db);
1473
+ db->beginTrn(MULTILOCK_NOGAP);
1474
+ tb->seekFirst(ROW_LOCK_S);
1475
+ BOOST_CHECK_MESSAGE(0 == tb->stat(), "seekFirst S");
1476
+ tb->seekNext(ROW_LOCK_S);
1477
+ BOOST_CHECK_MESSAGE(0 == tb->stat(), "seekNext S");
1478
+ tb->seekNext(ROW_LOCK_X);
1479
+ BOOST_CHECK_MESSAGE(0 == tb->stat(), "seekNext X");
1480
+ tb->update();
1481
+ BOOST_CHECK_MESSAGE(0 == tb->stat(), "update");
1482
+ db->endTrn();
1483
+
1484
+ db->beginTrn(MULTILOCK_GAP);
1485
+ tb->seekFirst(ROW_LOCK_S);
1486
+ BOOST_CHECK_MESSAGE(0 == tb->stat(), "seekFirst S");
1487
+ tb->seekNext(ROW_LOCK_S);
1488
+ BOOST_CHECK_MESSAGE(0 == tb->stat(), "seekNext S");
1489
+ tb->seekNext(ROW_LOCK_X);
1490
+ BOOST_CHECK_MESSAGE(0 == tb->stat(), "seekNext X");
1491
+ tb->update();
1492
+ BOOST_CHECK_MESSAGE(0 == tb->stat(), "update");
1493
+ db->endTrn();
1494
+ tb->release();
1495
+
1496
+ }
1497
+
1350
1498
  /* isoration Level ISO_READ_COMMITED */
1351
1499
  void testTransactionLockReadCommited(database* db)
1352
1500
  {
@@ -1569,10 +1717,10 @@ void testTransactionLockReadCommited(database* db)
1569
1717
  // No match records are unlocked.
1570
1718
  tb2->setFV(fdi_id, 100);
1571
1719
  tb2->seek(ROW_LOCK_X);
1572
- BOOST_CHECK_MESSAGE(0 == tb2->stat(), "tb2->seek");
1720
+ BOOST_CHECK_MESSAGE(0 == tb2->stat(), "tb2->seek stat = " << tb2->stat());
1573
1721
  tb2->setFV(fdi_id, 101);
1574
1722
  tb2->seek(ROW_LOCK_X);
1575
- BOOST_CHECK_MESSAGE(0 == tb2->stat(), "tb2->seek");
1723
+ BOOST_CHECK_MESSAGE(0 == tb2->stat(), "tb2->seek stat = " << tb2->stat());
1576
1724
  tb2->unlock();
1577
1725
  db->endTrn();
1578
1726
 
@@ -1738,20 +1886,37 @@ void testRecordLock(database* db)
1738
1886
  tb2->seekFirst(ROW_LOCK_S);
1739
1887
  BOOST_CHECK_MESSAGE(STATUS_INVALID_LOCKTYPE == tb2->stat(), "tb2->seekFirst");
1740
1888
 
1889
+ /* --------- Invalid unlock test ----------------------------*/
1890
+ tb2->seekFirst();
1891
+ BOOST_CHECK_MESSAGE(0 == tb2->stat(), "tb2->seekFirst");
1892
+ tb2->unlock();
1893
+ BOOST_CHECK_MESSAGE(0 == tb2->stat(), "tb2->seekFirst");
1894
+
1741
1895
  tb2->release();
1742
1896
  tb3->release();
1743
1897
  database::destroy(db2);
1744
1898
 
1745
1899
  }
1746
1900
 
1901
+ bool isMySQL5_7(database* db)
1902
+ {
1903
+ btrVersions vv;
1904
+ db->getBtrVersion(&vv);
1905
+ return (db->stat() == 0) &&
1906
+ ((5 == vv.versions[1].majorVersion) &&
1907
+ (7 == vv.versions[1].minorVersion));
1908
+
1909
+ }
1910
+
1747
1911
  void testExclusive()
1748
1912
  {
1913
+
1749
1914
  // db mode exclusive
1750
1915
  database* db = database::create();
1751
1916
  /* -------------------------------------------------*/
1752
1917
  /* database WRITE EXCLUSIVE */
1753
1918
  /* -------------------------------------------------*/
1754
- table* tb = openTable(db, TD_OPEN_EXCLUSIVE);
1919
+ table* tb = openTable(db, TD_OPEN_EXCLUSIVE);//DB TD_OPEN_EXCLUSIVE
1755
1920
  BOOST_CHECK_MESSAGE(0 == db->stat(), "Exclusive opened 1 ");
1756
1921
 
1757
1922
  // Can not open another connections.
@@ -1761,7 +1926,7 @@ void testExclusive()
1761
1926
  db2->open(makeUri(PROTOCOL, HOSTNAME, DBNAME, BDFNAME), TYPE_SCHEMA_BDF);
1762
1927
  //database open error. Check database::stat()
1763
1928
  BOOST_CHECK_MESSAGE(STATUS_CANNOT_LOCK_TABLE == db2->stat(),
1764
- "open db->stat = " << db->stat());
1929
+ "open db2->stat = " << db2->stat());
1765
1930
  dbdef* def = db->dbDef();
1766
1931
  tabledef* td = def->tableDefs(1);
1767
1932
  td->iconIndex = 3;
@@ -1775,17 +1940,25 @@ void testExclusive()
1775
1940
  /* database READ EXCLUSIVE */
1776
1941
  /* -------------------------------------------------*/
1777
1942
  tb = openTable(db, TD_OPEN_READONLY_EXCLUSIVE);
1778
-
1943
+
1944
+ // read mysql version
1945
+ bool MySQL5_7 = isMySQL5_7(db);
1946
+
1779
1947
  // Read only open
1780
1948
  db2->open(makeUri(PROTOCOL, HOSTNAME, DBNAME, BDFNAME), TYPE_SCHEMA_BDF);
1781
- BOOST_CHECK_MESSAGE(0 == db2->stat(), "read only open");
1949
+ BOOST_CHECK_MESSAGE(0 == db2->stat(),
1950
+ "read only open " << db2->stat());
1782
1951
  db2->close();
1783
1952
 
1784
1953
  // Normal open
1785
1954
  db2->connect(makeUri(PROTOCOL, HOSTNAME, DBNAME), true);
1786
1955
  db2->open(makeUri(PROTOCOL, HOSTNAME, DBNAME, BDFNAME),
1787
1956
  TYPE_SCHEMA_BDF, TD_OPEN_NORMAL);
1788
- BOOST_CHECK_MESSAGE(0 == db2->stat()
1957
+ if (MySQL5_7)
1958
+ BOOST_CHECK_MESSAGE(STATUS_CANNOT_LOCK_TABLE == db2->stat()
1959
+ , "Normal open");
1960
+ else
1961
+ BOOST_CHECK_MESSAGE(0 == db2->stat()
1789
1962
  , "Normal open");
1790
1963
  db2->close();
1791
1964
 
@@ -1964,12 +2137,13 @@ void testMissingUpdate(database* db)
1964
2137
  BOOST_CHECK_MESSAGE(STATUS_LOCK_ERROR == tb2->stat(), "tb2->seekLessThan");
1965
2138
  // Get lock(X) same record in parallel. The InnoDB is good!
1966
2139
  boost::scoped_ptr<boost::thread> t(new boost::thread(boost::bind(&worker::run, w.get())));
1967
- Sleep(5);
2140
+ Sleep(100);
1968
2141
  int v = tb->getFVint(fdi_id);//v = 30000
1969
2142
  tb->setFV(fdi_id, ++v); //v = 30001
1970
2143
  tb->insert();
2144
+ Sleep(1);
1971
2145
  t->join();
1972
-
2146
+ Sleep(1);
1973
2147
  if (db->trxIsolationServer() == SRV_ISO_REPEATABLE_READ)
1974
2148
  { /* When SRV_ISO_REPEATABLE_READ tb2 get gap lock first,
1975
2149
  tb can not insert, it is dedlock!
@@ -2112,6 +2286,42 @@ void testSetOwner(database* db)
2112
2286
  tb->release();
2113
2287
  }
2114
2288
 
2289
+ void testReconnect(database* db)
2290
+ {
2291
+ table* tb = openTable(db);
2292
+
2293
+ database* db2 = database::create();
2294
+ db2->connect(makeUri(PROTOCOL, HOSTNAME, DBNAME), true);
2295
+ BOOST_CHECK_MESSAGE(0 == db2->stat(), "connect");
2296
+ db2->open(makeUri(PROTOCOL, HOSTNAME, DBNAME, BDFNAME), TYPE_SCHEMA_BDF);
2297
+ BOOST_CHECK_MESSAGE(0 == db2->stat(), "db2->open");
2298
+ table* tb2 = db2->openTable(_T("user"));
2299
+
2300
+ //lock row
2301
+ tb->setFV(fdi_id, 10);
2302
+ tb->seek(ROW_LOCK_X);
2303
+ BOOST_CHECK_MESSAGE(0 == tb->stat(), "tb->seek stat = " << tb->stat());
2304
+ db->disconnectForReconnectTest();
2305
+ db->reconnect();
2306
+
2307
+ //Check restore lock
2308
+ tb2->setFV(fdi_id, 10);
2309
+ tb2->seek(ROW_LOCK_X);
2310
+ BOOST_CHECK_MESSAGE(STATUS_LOCK_ERROR == tb2->stat(), "tb->seek stat = " << tb2->stat());
2311
+
2312
+ tb->seekNext();
2313
+ BOOST_CHECK_MESSAGE(0 == tb->stat(), "tb->seek stat = " << tb->stat());
2314
+ BOOST_CHECK_MESSAGE(11 == tb->getFVint(fdi_id), "getFVint 11 bad = " << tb->getFVint(fdi_id));
2315
+
2316
+ tb2->setFV(fdi_id, 11);
2317
+ tb2->seek(ROW_LOCK_X);
2318
+ BOOST_CHECK_MESSAGE(0 == tb2->stat(), "tb->seek stat = " << tb2->stat());
2319
+
2320
+ tb->release();
2321
+ tb2->release();
2322
+ database::destroy(db2);
2323
+ }
2324
+
2115
2325
  void testCreateIndex(database* db)
2116
2326
  {
2117
2327
  table* tb = openTable(db);
@@ -3266,15 +3476,15 @@ void initKanjiName()
3266
3476
  if (!nameInited)
3267
3477
  {
3268
3478
  wchar_t tmp[50];
3269
- MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED, dbNmae, -1, tmp, 50);
3479
+ MultiByteToWideChar(932, MB_PRECOMPOSED, dbNmae, -1, tmp, 50);
3270
3480
  WideCharToMultiByte(CP_UTF8, 0, tmp, -1, dbNmae, 50, NULL, NULL);
3271
- MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED, bdfNmae, -1, tmp, 50);
3481
+ MultiByteToWideChar(932, MB_PRECOMPOSED, bdfNmae, -1, tmp, 50);
3272
3482
  WideCharToMultiByte(CP_UTF8, 0, tmp, -1, bdfNmae, 50, NULL, NULL);
3273
- MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED, tableNmae, -1, tmp, 50);
3483
+ MultiByteToWideChar(932, MB_PRECOMPOSED, tableNmae, -1, tmp, 50);
3274
3484
  WideCharToMultiByte(CP_UTF8, 0, tmp, -1, tableNmae, 50, NULL, NULL);
3275
- MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED, fdName1, -1, tmp, 50);
3485
+ MultiByteToWideChar(932, MB_PRECOMPOSED, fdName1, -1, tmp, 50);
3276
3486
  WideCharToMultiByte(CP_UTF8, 0, tmp, -1, fdName1, 50, NULL, NULL);
3277
- MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED, fdName2, -1, tmp, 50);
3487
+ MultiByteToWideChar(932, MB_PRECOMPOSED, fdName2, -1, tmp, 50);
3278
3488
  WideCharToMultiByte(CP_UTF8, 0, tmp, -1, fdName2, 50, NULL, NULL);
3279
3489
  nameInited = true;
3280
3490
  }
@@ -3284,14 +3494,15 @@ void initKanjiName()
3284
3494
  void testDropDatabaseKanji(database* db)
3285
3495
  {
3286
3496
  db->open(makeUri(PROTOCOL, HOSTNAME, dbNmae, bdfNmae));
3287
- BOOST_CHECK_MESSAGE(0 == db->stat(), "DropDataBaseKanji 1");
3497
+ BOOST_CHECK_MESSAGE(0 == db->stat(), "db->open stat = " << db->stat());
3288
3498
 
3289
3499
  db->drop();
3290
- BOOST_CHECK_MESSAGE(0 == db->stat(), "DropDataBaseKanji 2");
3500
+ BOOST_CHECK_MESSAGE(0 == db->stat(), "db->drop() stat = " << db->stat());
3291
3501
  }
3292
3502
 
3293
3503
  void testKnajiCreateSchema(database* db)
3294
3504
  {
3505
+
3295
3506
  initKanjiName();
3296
3507
  db->create(makeUri(PROTOCOL, HOSTNAME, dbNmae, bdfNmae));
3297
3508
  if (db->stat() == STATUS_TABLE_EXISTS_ERROR)
@@ -3314,6 +3525,10 @@ void testKnajiCreateSchema(database* db)
3314
3525
  memset(&td, 0, sizeof(tabledef));
3315
3526
  #ifndef _UNICODE
3316
3527
  td.schemaCodePage = CP_UTF8;
3528
+ td.charsetIndex = CHARSET_UTF8;
3529
+ #else
3530
+ td.schemaCodePage = CP_UTF8;
3531
+ td.charsetIndex = CHARSET_CP932;
3317
3532
  #endif
3318
3533
  td.setTableName(tableNmae);
3319
3534
  td.setFileName(tableNmae);
@@ -3360,14 +3575,15 @@ table* openKnajiTable(database* db)
3360
3575
 
3361
3576
  db->open(makeUri(PROTOCOL, HOSTNAME, dbNmae, bdfNmae), TYPE_SCHEMA_BDF,
3362
3577
  TD_OPEN_NORMAL);
3363
- BOOST_CHECK_MESSAGE(0 == db->stat(), "openKnajiTable 1");
3578
+ BOOST_CHECK_MESSAGE(0 == db->stat(), "openKnajiTable 1 stat = " << db->stat());
3364
3579
  table* tb = db->openTable(tableNmae);
3365
- BOOST_CHECK_MESSAGE(0 == db->stat(), "openKnajiTable 2");
3580
+ BOOST_CHECK_MESSAGE(0 == db->stat(), "openKnajiTable 2 stat = " << db->stat());
3366
3581
  return tb;
3367
3582
  }
3368
3583
 
3369
3584
  void testInsertKanji(database* db)
3370
3585
  {
3586
+
3371
3587
  table* tb = openKnajiTable(db);
3372
3588
 
3373
3589
  tb->clearBuffer();
@@ -3386,6 +3602,7 @@ void testInsertKanji(database* db)
3386
3602
 
3387
3603
  void testGetEqualKanji(database* db)
3388
3604
  {
3605
+
3389
3606
  table* tb = openKnajiTable(db);
3390
3607
  tb->clearBuffer();
3391
3608
  tb->setFV((short)0, 1);
@@ -3869,6 +4086,47 @@ void teetNewDelete(database* db)
3869
4086
  delete at;
3870
4087
  }
3871
4088
 
4089
+ void testRecordsetClone(database* db)
4090
+ {
4091
+
4092
+ #ifdef LINUX
4093
+ const char* fd_name = "名前";
4094
+ #else
4095
+ #ifdef _UNICODE
4096
+ const wchar_t fd_name[] = { L"名前" };
4097
+ #else
4098
+ char fd_name[30];
4099
+ WideCharToMultiByte(CP_UTF8, 0, L"名前", -1, fd_name, 30, NULL, NULL);
4100
+ #endif
4101
+ #endif
4102
+
4103
+ activeTable atu(db, _T("user"));
4104
+ //activeTable atg(db, _T("groups"));
4105
+ activeTable ate(db, _T("extention"));
4106
+ recordset* rs = recordset::create();
4107
+ query q;
4108
+
4109
+ atu.alias(fd_name, _T("name"));
4110
+ q.select(_T("id"), _T("name"), _T("group"))
4111
+ .where(_T("id"), _T("<="), 15000);
4112
+ atu.index(0).keyValue(1).read(*rs, q);
4113
+ BOOST_CHECK_MESSAGE(rs->size() == 15000, " rs.size() 15000 bad = " << rs->size());
4114
+ BOOST_CHECK_MESSAGE(rs->fieldDefs()->size() == 3, " rs.fieldDefs()->size() 3 bad = " << rs->fieldDefs()->size());
4115
+
4116
+ // Join extention::comment
4117
+ q.reset();
4118
+ ate.index(0).join(
4119
+ *rs, q.select(_T("comment")).optimize(queryBase::joinHasOneOrHasMany),
4120
+ _T("id"));
4121
+ BOOST_CHECK_MESSAGE(rs->size() == 15000, "join rs.size() 15000 bad = " << rs->size());
4122
+ BOOST_CHECK_MESSAGE(rs->fieldDefs()->size() == 4, " rs.fieldDefs()->size() 4 bad = " << rs->fieldDefs()->size());
4123
+
4124
+ recordset* rs2 = rs->clone();
4125
+ rs->release();
4126
+ rs2->release();
4127
+
4128
+ }
4129
+
3872
4130
  void testJoin(database* db)
3873
4131
  {
3874
4132
 
@@ -4255,6 +4513,10 @@ void testServerPrepareJoin(database* db)
4255
4513
  vs = rs[NO_RECORD_ID][_T("blob")].c_str();
4256
4514
  ret = _tcscmp(vs, _T("6 blob")) == 0;
4257
4515
  BOOST_CHECK_MESSAGE(ret == true, "row of 6 = '6 blob'");
4516
+ field fd = rs[NO_RECORD_ID][_T("binary")];
4517
+ ret = compBlobField(NO_RECORD_ID + 1, fd);
4518
+ BOOST_CHECK_MESSAGE(ret == true, "row of 6 = 'binary 256 byte'");
4519
+
4258
4520
 
4259
4521
  // Test clone blob field
4260
4522
  recordset& rs2 = *rs.clone();
@@ -4288,10 +4550,12 @@ void testServerPrepareJoin(database* db)
4288
4550
 
4289
4551
 
4290
4552
  // restore record
4553
+ unsigned char bin[256];
4291
4554
  tb->clearBuffer();
4292
4555
  tb->setFV(_T("id"), NO_RECORD_ID);
4293
4556
  tb->setFV(_T("comment"), _T("5 comment"));
4294
4557
  tb->setFV(_T("blob"), _T("5 blob"));
4558
+ fillBlobField(3, NO_RECORD_ID, tb.get(), bin);
4295
4559
  tb->insert();
4296
4560
  BOOST_CHECK_MESSAGE(tb->stat() == 0, "ate insert id = 5");
4297
4561
  if (tb->stat())
@@ -4301,13 +4565,115 @@ void testServerPrepareJoin(database* db)
4301
4565
  ate.release();
4302
4566
  db->drop();
4303
4567
  }
4304
-
4568
+ }
4569
+
4570
+ void testReadMore(database* db)
4571
+ {
4572
+ #ifdef LINUX
4573
+ const char* fd_name = "名前";
4574
+ #else
4575
+ #ifdef _UNICODE
4576
+ const wchar_t fd_name[] = { L"名前" };
4577
+ #else
4578
+ char fd_name[30];
4579
+ WideCharToMultiByte(CP_UTF8, 0, L"名前", -1, fd_name, 30, NULL, NULL);
4580
+ #endif
4581
+ #endif
4582
+
4583
+ activeTable atu(db, _T("user"));
4584
+ atu.alias(fd_name, _T("name"));
4585
+ query q;
4586
+ q.select(_T("id"), _T("name"), _T("group"))
4587
+ .where(_T("name"), _T("="), _T("1*"))
4588
+ .reject(70).limit(8).stopAtLimit(true);
4589
+ pq_handle stmt1 = atu.prepare(q, true);
4590
+ BOOST_CHECK_MESSAGE(stmt1 != NULL, " stmt1");
4591
+
4592
+ recordset rs;
4593
+ atu.index(0).keyValue(18).read(rs, stmt1);
4594
+ BOOST_CHECK_MESSAGE(rs.size() == 2, "read");
4595
+
4596
+ recordset rs2;
4597
+ atu.readMore(rs2);
4598
+ BOOST_CHECK_MESSAGE(rs2.size() == 8, "readMore");
4599
+
4600
+ rs += rs2;
4601
+ BOOST_CHECK_MESSAGE(rs.size() == 10, "union");
4602
+
4603
+ }
4604
+
4605
+ void testFirstLastGroupFunction(database* db)
4606
+ {
4607
+ #ifdef LINUX
4608
+ const char* fd_name = "名前";
4609
+ #else
4610
+ #ifdef _UNICODE
4611
+ const wchar_t fd_name[] = { L"名前" };
4612
+ #else
4613
+ char fd_name[30];
4614
+ WideCharToMultiByte(CP_UTF8, 0, L"名前", -1, fd_name, 30, NULL, NULL);
4615
+ #endif
4616
+ #endif
4305
4617
 
4618
+ activeTable atu(db, _T("user"));
4619
+ atu.alias(fd_name, _T("name"));
4620
+ query q;
4621
+ q.select(_T("id"), _T("name"), _T("group"))
4622
+ .where(_T("name"), _T("="), _T("1*"))
4623
+ .reject(70).limit(8).stopAtLimit(true);
4624
+ pq_handle stmt1 = atu.prepare(q, true);
4625
+ BOOST_CHECK_MESSAGE(stmt1 != NULL, " stmt1");
4306
4626
 
4627
+ recordset rs;
4628
+ atu.index(0).keyValue(0).read(rs, stmt1);
4629
+ BOOST_CHECK_MESSAGE(rs.size() == 8, "read");
4307
4630
 
4631
+ groupQuery gq;
4632
+ fieldNames target;
4633
+ target.addValue(_T("name"));
4634
+ client::last last(target, _T("last_rec_name"));
4635
+ client::first first(target, _T("first_rec_name"));
4636
+ gq.addFunction(&last);
4637
+ gq.addFunction(&first);
4638
+
4639
+ rs.groupBy(gq);
4640
+ BOOST_CHECK_MESSAGE(rs.size() == 1, "read");
4641
+
4642
+ BOOST_CHECK_MESSAGE(rs[0][_T("first_rec_name")].c_str() == std::_tstring(_T("1 user")), "first_rec_name");
4643
+ BOOST_CHECK_MESSAGE(rs[0][_T("last_rec_name")].c_str() == std::_tstring(_T("16 user")), "last_rec_name");
4308
4644
 
4309
4645
  }
4310
4646
 
4647
+ void testBlobOnlyTable(database* db)
4648
+ {
4649
+ // table access test
4650
+ table* tb = db->openTable(_T("blobonly"));
4651
+ BOOST_CHECK_MESSAGE(0 == db->stat(), "openTable stat = " << db->stat());
4652
+ tb->clearBuffer();
4653
+ static const int id = 1;
4654
+ tb->setFV((short)0, id);
4655
+ tb->seek();
4656
+ field fd = tb->fields()[_T("binary")];
4657
+
4658
+ bool ret = compBlobField(id, fd);
4659
+ BOOST_CHECK_MESSAGE(ret == true, "tb->seek binary 256 byte");
4660
+ tb->release();
4661
+
4662
+ // activeTable test
4663
+ activeTable at(db, _T("blobonly"));
4664
+ recordset rs;
4665
+ client::query q;
4666
+ q.where(_T("id"), _T("<"), 10);
4667
+ at.index(0).keyValue(1).read(rs, q);
4668
+ BOOST_CHECK_MESSAGE(rs.size() == 9, " rs.size() 9 bad = " << rs.size());
4669
+ for (int i= 0; i < 9; ++i)
4670
+ {
4671
+ fd = rs[i][_T("binary")];
4672
+ ret = compBlobField(i+1, fd);
4673
+ BOOST_CHECK_MESSAGE(ret == true, "rs[n][binary] binary 256 byte");
4674
+ }
4675
+ }
4676
+
4311
4677
  void testWirtableRecord(database* db)
4312
4678
  {
4313
4679
 
@@ -4420,6 +4786,428 @@ void testDbPool()
4420
4786
  poolMgr.reset(0);
4421
4787
  }
4422
4788
 
4789
+ //--------------------------------------------------------------------------------------
4790
+ // filter test
4791
+ //--------------------------------------------------------------------------------------
4792
+ #define FILTER_DB _T("filter_test")
4793
+
4794
+ const _TCHAR* fdf_names[] =
4795
+ {
4796
+ _T("ft_string"),
4797
+ _T("ft_wstring"),
4798
+ _T("ft_zstring"),
4799
+ _T("ft_wzstring"),
4800
+ _T("ft_mychar"),
4801
+ _T("ft_mywchar"),
4802
+ _T("ft_myvarchar"),
4803
+ _T("ft_mywvarchar"),
4804
+ _T("ft_myvarbinary"),
4805
+ _T("ft_mywvarbinary"),
4806
+ };
4807
+
4808
+ char fdf_types[] =
4809
+ {
4810
+ ft_string,
4811
+ ft_wstring,
4812
+ ft_zstring,
4813
+ ft_wzstring,
4814
+ ft_mychar,
4815
+ ft_mywchar,
4816
+ ft_myvarchar,
4817
+ ft_mywvarchar,
4818
+ ft_myvarbinary,
4819
+ ft_mywvarbinary,
4820
+ };
4821
+
4822
+ #define FILTER_RECORDS 15
4823
+ const _TCHAR* fd_values[15] =
4824
+ {
4825
+ _T("090-xxxx-xxx"),
4826
+ _T("090-xxxx-xxx"),
4827
+ _T(" "),
4828
+ _T("090-xxxx-xxx"),
4829
+ _T("080-xxxx-xxx"),
4830
+ _T("0"),
4831
+ _T(""),
4832
+ _T(""),
4833
+ _T("09"),
4834
+ _T("070"),
4835
+ _T(""),
4836
+ _T("090-xxxx-xxx"),
4837
+ _T("a90-xxxx-xxx"),
4838
+ _T("Aa0-xxxx-xxx"),
4839
+ _T("A90-xxxx-xxx"),
4840
+ };
4841
+
4842
+ void intFieldTypes(database* db)
4843
+ {
4844
+ if (!isUtf16leSupport(db))
4845
+ {
4846
+ for (int i = 0; i < 10; i++)
4847
+ {
4848
+ if ((i % 2) == 1)
4849
+ fdf_types[i] = fdf_types[i-1];
4850
+ }
4851
+ }
4852
+ }
4853
+
4854
+ void inserFilterTestRecords(database* db)
4855
+ {
4856
+
4857
+
4858
+ table* tb = db->openTable(_T("user"), TD_OPEN_NORMAL);
4859
+ BOOST_CHECK_MESSAGE(0 == db->stat(), "openTable stat = " << db->stat());
4860
+ db->beginTrn();
4861
+ for (int i = 0; i < FILTER_RECORDS; ++i)
4862
+ {
4863
+ tb->clearBuffer();
4864
+ tb->setFV((short)0, i);
4865
+ //set AllFields smae value
4866
+ for (int j=0;j<10;++j)
4867
+ tb->setFV(j+1, fd_values[i]);
4868
+ tb->insert();
4869
+ BOOST_CHECK_MESSAGE(0 == tb->stat(), "insert stat = " << tb->stat());
4870
+
4871
+ }
4872
+ db->endTrn();
4873
+ tb->release();
4874
+ }
4875
+
4876
+ void createFilterTestDb(database* db)
4877
+ {
4878
+
4879
+ db->create(makeUri(PROTOCOL, HOSTNAME, FILTER_DB, BDFNAME));
4880
+ if (db->stat() == STATUS_TABLE_EXISTS_ERROR)
4881
+ {
4882
+ db->open(makeUri(PROTOCOL, HOSTNAME, FILTER_DB, BDFNAME), TYPE_SCHEMA_BDF,
4883
+ TD_OPEN_NORMAL);
4884
+ BOOST_CHECK_MESSAGE(0 == db->stat(),
4885
+ "open stat = " << db->stat());
4886
+ db->drop();
4887
+ BOOST_CHECK_MESSAGE(0 == db->stat(),
4888
+ "drop stat = " << db->stat());
4889
+ db->create(makeUri(PROTOCOL, HOSTNAME, FILTER_DB, BDFNAME));
4890
+ }
4891
+
4892
+ BOOST_CHECK_MESSAGE(0 == db->stat(),
4893
+ "createFilterTestDb stat = " << db->stat());
4894
+ // create table
4895
+ db->open(makeUri(PROTOCOL, HOSTNAME, FILTER_DB, BDFNAME), TYPE_SCHEMA_BDF,
4896
+ TD_OPEN_NORMAL);
4897
+ BOOST_CHECK_MESSAGE(0 == db->stat(),
4898
+ "createFilterTestDb 1 stat = " << db->stat());
4899
+
4900
+ intFieldTypes(db);
4901
+
4902
+ dbdef* def = db->dbDef();
4903
+ if (def)
4904
+ {
4905
+ /* user table */
4906
+ tabledef td;
4907
+ memset(&td, 0, sizeof(tabledef));
4908
+ td.setTableName(_T("user"));
4909
+ td.setFileName(_T("user.dat"));
4910
+ td.id = 1;
4911
+ td.primaryKeyNum = -1;
4912
+ td.parentKeyNum = -1;
4913
+ td.replicaKeyNum = -1;
4914
+ td.pageSize = 2048;
4915
+ #ifdef _WIN32
4916
+ td.charsetIndex = CHARSET_CP932;
4917
+ #else
4918
+ td.charsetIndex = CHARSET_UTF8;
4919
+ #endif
4920
+
4921
+ def->insertTable(&td);
4922
+ BOOST_CHECK_MESSAGE(0 == def->stat(),
4923
+ "insertTable stat = " << def->stat());
4924
+
4925
+ fielddef* fd = def->insertField(1, 0);
4926
+ fd->setName(_T("id"));
4927
+ fd->type = ft_integer;
4928
+ fd->len = (ushort_td)4;
4929
+
4930
+ for (int i=0;i<10;++i)
4931
+ {
4932
+ fielddef* fd = def->insertField(1, i+1);
4933
+ fd->setName(fdf_names[i]);
4934
+ fd->type = fdf_types[i];
4935
+ fd->setLenByCharnum(20);
4936
+ }
4937
+ def->updateTableDef(1);
4938
+ BOOST_CHECK_MESSAGE(0 == def->stat(),
4939
+ "updateTableDef 1 stat = " << def->stat());
4940
+
4941
+ keydef* kd = def->insertKey(1, 0);
4942
+ kd->segments[0].fieldNum = 0;
4943
+ kd->segments[0].flags.bit8 = 1; // extended key type
4944
+ kd->segments[0].flags.bit1 = 1; // changeable
4945
+ kd->segmentCount = 1;
4946
+
4947
+ for (int i=0;i<10;++i)
4948
+ {
4949
+ kd = def->insertKey(1, i+1);
4950
+ kd->segments[0].fieldNum = i+1;
4951
+ kd->segments[0].flags.bit0 = 1; // duplicate
4952
+ kd->segments[0].flags.bit8 = 1; // extended key type
4953
+ kd->segments[0].flags.bit1 = 1; // changeable
4954
+ kd->segmentCount = 1;
4955
+ }
4956
+
4957
+ def->updateTableDef(1);
4958
+ BOOST_CHECK_MESSAGE(0 == def->stat(),
4959
+ "updateTableDef 3 stat = " << def->stat());
4960
+
4961
+ inserFilterTestRecords(db);
4962
+ }
4963
+ }
4964
+
4965
+ void setReject(query& q)
4966
+ {
4967
+ q.reject(0).limit(0);
4968
+ }
4969
+
4970
+ void setReject(pq_handle& q)
4971
+ {
4972
+
4973
+ }
4974
+
4975
+ template<class Q>
4976
+ void doTestReadByQuery(int num, activeTable& at, recordset& rs, Q& q,
4977
+ int compSize, const char* msg)
4978
+ {
4979
+ setReject(q);
4980
+ at.index(0).keyValue(0).read(rs, q);
4981
+ BOOST_CHECK_MESSAGE(compSize == (int)rs.size(),
4982
+ num << " " << msg << " rs.size() = " << rs.size());
4983
+ }
4984
+
4985
+ void testFilterOfServer(database* db)
4986
+ {
4987
+ intFieldTypes(db);
4988
+
4989
+ {
4990
+ activeTable atu(db, _T("user"));
4991
+ recordset rs;
4992
+ query q;
4993
+ for (int i = 0; i < 10; ++i)
4994
+ {
4995
+ // empty string
4996
+
4997
+ q.reset().where(fdf_names[i], _T("="), _T(""));
4998
+ int n = 3;
4999
+ if (atu.table()->tableDef()->fieldDefs[i+1].usePadChar())
5000
+ n += 1;
5001
+ doTestReadByQuery(i, atu, rs, q, n, "");
5002
+ q.where(fdf_names[i], _T("=i"), _T(""));
5003
+ doTestReadByQuery(i, atu, rs, q, n, "=i");
5004
+
5005
+ // match complate
5006
+ q.where(fdf_names[i], _T("="), _T("070"));
5007
+ doTestReadByQuery(i, atu, rs, q, 1, "= 070");
5008
+
5009
+ q.where(fdf_names[i], _T("=i"), _T("070"));
5010
+ doTestReadByQuery(i, atu, rs, q, 1, "=i 070");
5011
+
5012
+ // match complate
5013
+ q.where(fdf_names[i], _T("<"), _T("09"));
5014
+ doTestReadByQuery(i, atu, rs, q, 7, "< 09");
5015
+
5016
+ q.where(fdf_names[i], _T("<i"), _T("09"));
5017
+ doTestReadByQuery(i, atu, rs, q, 7, "<i 09");
5018
+
5019
+ // wildcard and prerare
5020
+ // 0:noprepare 1:prepare 2:prepareServer
5021
+ for (int j = 0 ; j < 3; ++j)
5022
+ {
5023
+ q.reset().reject(0).limit(0);
5024
+ if (j > 0)
5025
+ {
5026
+ q.where(fdf_names[i], _T("="), _T("?"));
5027
+ pq_handle pq = atu.prepare(q, (j == 2));
5028
+ supplyValue(pq, 0, _T("09*"));
5029
+ doTestReadByQuery(i, atu, rs, pq, 5, "prepare = 09*");
5030
+
5031
+ q.where(fdf_names[i], _T("=i"), _T("?"));
5032
+ pq_handle pq1 = atu.prepare(q, (j == 2));
5033
+ supplyValue(pq1, 0, _T("09*"));
5034
+ doTestReadByQuery(i, atu, rs, pq1, 5, "prepare =i 09*");
5035
+
5036
+ }else
5037
+ {
5038
+ q.where(fdf_names[i], _T("="), _T("09*"));
5039
+ doTestReadByQuery(i, atu, rs, q, 5, "= 09*");
5040
+
5041
+ q.where(fdf_names[i], _T("=i"), _T("09*"));
5042
+ doTestReadByQuery(i, atu, rs, q, 5, "=i 09*");
5043
+ }
5044
+ }
5045
+
5046
+ // ascii
5047
+ q.where(fdf_names[i], _T("="), _T("a*"));
5048
+ doTestReadByQuery(i, atu, rs, q, 1, " = a*");
5049
+
5050
+ q.where(fdf_names[i], _T("=i"), _T("a*"));
5051
+ doTestReadByQuery(i, atu, rs, q, 3, " =i a*");
5052
+
5053
+ q.where(fdf_names[i], _T("="), _T("A*"));
5054
+ doTestReadByQuery(i, atu, rs, q, 2, " = A*");
5055
+
5056
+ q.where(fdf_names[i], _T("=i"), _T("A*"));
5057
+ doTestReadByQuery(i, atu, rs, q, 3, " =i A*");
5058
+
5059
+ q.where(fdf_names[i], _T("="), _T("AA0*"));
5060
+ doTestReadByQuery(i, atu, rs, q, 0, " = AA0*");
5061
+
5062
+ q.where(fdf_names[i], _T("=i"), _T("AA0*"));
5063
+ doTestReadByQuery(i, atu, rs, q, 1, " =i Aa0*");
5064
+
5065
+ //case in-sencitive index no jaudge
5066
+
5067
+ for (int i = 0 ; i < 10 ; ++i)
5068
+ {
5069
+ q.where(fdf_names[i], _T("="), _T("A*"));
5070
+ setReject(q);
5071
+ atu.index(i+1).keyValue(_T("A")).read(rs, q);
5072
+ BOOST_CHECK_MESSAGE(2 == rs.size(),
5073
+ i << " " << "jaudge = A*" << " rs.size() = " << rs.size());
5074
+ BOOST_CHECK_MESSAGE(atu.table()->statReasonOfFind() == STATUS_REACHED_FILTER_COND,
5075
+ i << " " << "jaudge = A* FILTER_COND");
5076
+
5077
+ q.where(fdf_names[i], _T("=i"), _T("A*"));
5078
+ setReject(q);
5079
+ atu.index(i+1).keyValue(_T("A")).read(rs, q);
5080
+ BOOST_CHECK_MESSAGE(3 == rs.size(),
5081
+ i << " " << "jaudge = A*" << " rs.size() = " << rs.size());
5082
+ BOOST_CHECK_MESSAGE(atu.table()->statReasonOfFind() == STATUS_EOF,
5083
+ i << " " << "jaudge = A* STATUS_EOF");
5084
+
5085
+ }
5086
+ }
5087
+ }
5088
+ }
5089
+
5090
+ void doTestMatchBy(int num, recordset& rs, recordsetQuery& rq, int compSize, const _TCHAR* msg)
5091
+ {
5092
+ recordset* rss = rs.clone();
5093
+ rss->matchBy(rq);
5094
+ BOOST_CHECK_MESSAGE(compSize == (int)rss->size(),
5095
+ num << msg << _T(" rss->size = ") << rss->size());
5096
+ rss->release();
5097
+ }
5098
+
5099
+ void testFilterOfMatchBy(database* db)
5100
+ {
5101
+ intFieldTypes(db);
5102
+ {
5103
+ activeTable atu(db, _T("user"));
5104
+ query q;
5105
+ recordset rs;
5106
+ atu.index(0).keyValue(0).read(rs, q.all());
5107
+ BOOST_CHECK_MESSAGE(FILTER_RECORDS == rs.size(), " rs.size() = " << rs.size());
5108
+ for (int i = 0; i < 10; ++i)
5109
+ {
5110
+ // empty string
5111
+ recordsetQuery rq;
5112
+ rq.when(fdf_names[i], _T("="), _T(""));
5113
+ int n = 3;
5114
+ if (atu.table()->tableDef()->fieldDefs[i+1].usePadChar())
5115
+ n += 1;
5116
+ doTestMatchBy(i, rs, rq, n, _T(" = "));
5117
+ rq.reset().when(fdf_names[i], _T("=i"), _T(""));
5118
+ doTestMatchBy(i, rs, rq, n, _T(" =i "));
5119
+
5120
+
5121
+ // wildcard
5122
+ rq.reset().when(fdf_names[i], _T("="), _T("09*"));
5123
+ doTestMatchBy(i, rs, rq, 5, _T(" = 09*"));
5124
+ rq.reset().when(fdf_names[i], _T("=i"), _T("09*"));
5125
+ doTestMatchBy(i, rs, rq, 5, _T(" =i 09*"));
5126
+
5127
+ // match complate
5128
+ rq.reset().when(fdf_names[i], _T("="), _T("070"));
5129
+ doTestMatchBy(i, rs, rq, 1, _T(" = 070"));
5130
+ rq.reset().when(fdf_names[i], _T("=i"), _T("070"));
5131
+ doTestMatchBy(i, rs, rq, 1, _T(" =i 070"));
5132
+
5133
+ // match complate
5134
+ rq.reset().when(fdf_names[i], _T("<"), _T("09"));
5135
+ doTestMatchBy(i, rs, rq, 7, _T(" < 09"));
5136
+
5137
+ rq.reset().when(fdf_names[i], _T("<i"), _T("09"));
5138
+ doTestMatchBy(i, rs, rq, 7, _T(" <i 09"));
5139
+
5140
+ // ascii
5141
+ rq.reset().when(fdf_names[i], _T("="), _T("a*"));
5142
+ doTestMatchBy(i, rs, rq, 1, _T(" = a*"));
5143
+
5144
+ rq.reset().when(fdf_names[i], _T("=i"), _T("a*"));
5145
+ doTestMatchBy(i, rs, rq, 3, _T(" =i a*"));
5146
+
5147
+ rq.reset().when(fdf_names[i], _T("=i"), _T("A*"));
5148
+ doTestMatchBy(i, rs, rq, 3, _T(" =i A*"));
5149
+
5150
+ rq.reset().when(fdf_names[i], _T("="), _T("AA0*"));
5151
+ doTestMatchBy(i, rs, rq, 0, _T(" = AA0*"));
5152
+
5153
+ rq.reset().when(fdf_names[i], _T("=i"), _T("AA0*"));
5154
+ doTestMatchBy(i, rs, rq, 1, _T(" =i Aa0*"));
5155
+
5156
+
5157
+ BOOST_CHECK_MESSAGE(FILTER_RECORDS == rs.size(), " rs.size() = " << rs.size());
5158
+ }
5159
+ }
5160
+ db->drop();
5161
+ BOOST_CHECK_MESSAGE(0 == db->stat(), "drop stat = " << db->stat());
5162
+ }
5163
+
5164
+ unsigned char field_types[] =
5165
+ {
5166
+ ft_myvarbinary,
5167
+ ft_mywvarbinary,
5168
+ ft_myvarchar,
5169
+ ft_mywvarchar,
5170
+ ft_string,
5171
+ ft_wstring,
5172
+ ft_lstring,
5173
+ ft_lvar,
5174
+ ft_myblob,
5175
+ ft_mytext
5176
+ };
5177
+
5178
+ void testBinaryField()
5179
+ {
5180
+ unsigned char data[255], buf[255];
5181
+ for (int i = 0; i < 255 ;++i)
5182
+ data[i] = i;
5183
+
5184
+ fielddef fdd;
5185
+ fdd.type = ft_string;
5186
+ fdd.len = 255;
5187
+ fdd.pos = 0;
5188
+
5189
+ client::field fd(buf, fdd, NULL);
5190
+ for (int i = 0 ; i < 10; ++i)
5191
+ {
5192
+ fdd.type = field_types[i];
5193
+ int len = fdd.len - fdd.varLenBytes();
5194
+ if (i > 7)
5195
+ {
5196
+ fdd.len = 9; //blob type
5197
+ len = 255;
5198
+ }
5199
+ fd.setBin(data, len);
5200
+ uint_td size;
5201
+ void* p = fd.getBin(size);
5202
+ BOOST_CHECK_MESSAGE(len == (int)size, "binary size type = " << i);
5203
+
5204
+ BOOST_CHECK_MESSAGE(p != NULL, "binary ret type = " << i);
5205
+ int ret = memcmp(p, data, len);
5206
+ BOOST_CHECK_MESSAGE(0 == ret, "binary memcmp type = " << i);
5207
+ }
5208
+ }
5209
+
5210
+
4423
5211
  // ------------------------------------------------------------------------
4424
5212
  BOOST_AUTO_TEST_SUITE(btrv_nativ)
4425
5213
 
@@ -4529,6 +5317,17 @@ BOOST_FIXTURE_TEST_CASE(transactionLockRepeatable, fixture)
4529
5317
  testTransactionLockRepeatable(db());
4530
5318
  }
4531
5319
 
5320
+ BOOST_FIXTURE_TEST_CASE(bug_015, fixture)
5321
+ {
5322
+ testBug_015(db());
5323
+ }
5324
+
5325
+ BOOST_FIXTURE_TEST_CASE(issue_016, fixture)
5326
+ {
5327
+ testIssue_016(db());
5328
+ }
5329
+
5330
+
4532
5331
  BOOST_FIXTURE_TEST_CASE(transactionLock, fixture)
4533
5332
  {
4534
5333
  testTransactionLockReadCommited(db());
@@ -4554,6 +5353,11 @@ BOOST_FIXTURE_TEST_CASE(MissingUpdate, fixture)
4554
5353
  testMissingUpdate(db());
4555
5354
  }
4556
5355
 
5356
+ BOOST_FIXTURE_TEST_CASE(reconnect, fixture)
5357
+ {
5358
+ testReconnect(db());
5359
+ }
5360
+
4557
5361
  BOOST_FIXTURE_TEST_CASE(insert2, fixture)
4558
5362
  {
4559
5363
  testInsert2(db());
@@ -4569,6 +5373,7 @@ BOOST_FIXTURE_TEST_CASE(setOwner, fixture)
4569
5373
  testSetOwner(db());
4570
5374
  }
4571
5375
 
5376
+
4572
5377
  BOOST_FIXTURE_TEST_CASE(createIndex, fixture)
4573
5378
  {
4574
5379
  testCreateIndex(db());
@@ -4628,32 +5433,32 @@ BOOST_AUTO_TEST_SUITE_END()
4628
5433
  // ------------------------------------------------------------------------
4629
5434
  BOOST_AUTO_TEST_SUITE(var_field)
4630
5435
 
4631
- BOOST_FIXTURE_TEST_CASE(createDataBaseVar, fixture)
5436
+ BOOST_FIXTURE_TEST_CASE(createDataBaseVar, fixtureKanji)
4632
5437
  {
4633
5438
  testCreateDataBaseVar(db());
4634
5439
  }
4635
5440
 
4636
- BOOST_FIXTURE_TEST_CASE(varField, fixture)
5441
+ BOOST_FIXTURE_TEST_CASE(varField, fixtureKanji)
4637
5442
  {
4638
5443
  testVarField(db());
4639
5444
  }
4640
5445
 
4641
- BOOST_FIXTURE_TEST_CASE(varInsert, fixture)
5446
+ BOOST_FIXTURE_TEST_CASE(varInsert, fixtureKanji)
4642
5447
  {
4643
5448
  testVarInsert(db());
4644
5449
  }
4645
5450
 
4646
- BOOST_FIXTURE_TEST_CASE(varRead, fixture)
5451
+ BOOST_FIXTURE_TEST_CASE(varRead, fixtureKanji)
4647
5452
  {
4648
5453
  testVarRead(db());
4649
5454
  }
4650
5455
 
4651
- BOOST_FIXTURE_TEST_CASE(filterVar, fixture)
5456
+ BOOST_FIXTURE_TEST_CASE(filterVar, fixtureKanji)
4652
5457
  {
4653
5458
  testFilterVar(db());
4654
5459
  }
4655
5460
 
4656
- BOOST_FIXTURE_TEST_CASE(dropDataBaseVar, fixture)
5461
+ BOOST_FIXTURE_TEST_CASE(dropDataBaseVar, fixtureKanji)
4657
5462
  {
4658
5463
  testDropDataBaseVar(db());
4659
5464
  }
@@ -4664,12 +5469,12 @@ BOOST_AUTO_TEST_SUITE_END()
4664
5469
  // ------------------------------------------------------------------------
4665
5470
  BOOST_AUTO_TEST_SUITE(filter)
4666
5471
 
4667
- BOOST_FIXTURE_TEST_CASE(stringFileter, fixture)
5472
+ BOOST_FIXTURE_TEST_CASE(stringFileter, fixtureKanji)
4668
5473
  {
4669
5474
  testStringFileter(db());
4670
5475
  }
4671
5476
 
4672
- BOOST_FIXTURE_TEST_CASE(dropDataBaseStr, fixture)
5477
+ BOOST_FIXTURE_TEST_CASE(dropDataBaseStr, fixtureKanji)
4673
5478
  {
4674
5479
  testDropDataBaseStr(db());
4675
5480
  }
@@ -4678,24 +5483,25 @@ BOOST_AUTO_TEST_SUITE_END()
4678
5483
  // ------------------------------------------------------------------------
4679
5484
  #endif
4680
5485
  // ------------------------------------------------------------------------
5486
+
4681
5487
  BOOST_AUTO_TEST_SUITE(kanjiSchema)
4682
5488
 
4683
- BOOST_FIXTURE_TEST_CASE(knajiCreateSchema, fixture)
5489
+ BOOST_FIXTURE_TEST_CASE(knajiCreateSchema, fixtureKanji)
4684
5490
  {
4685
5491
  testKnajiCreateSchema(db());
4686
5492
  }
4687
5493
 
4688
- BOOST_FIXTURE_TEST_CASE(insertKanji, fixture)
5494
+ BOOST_FIXTURE_TEST_CASE(insertKanji, fixtureKanji)
4689
5495
  {
4690
5496
  testInsertKanji(db());
4691
5497
  }
4692
5498
 
4693
- BOOST_FIXTURE_TEST_CASE(getEqualKanji, fixture)
5499
+ BOOST_FIXTURE_TEST_CASE(getEqualKanji, fixtureKanji)
4694
5500
  {
4695
5501
  testGetEqualKanji(db());
4696
5502
  }
4697
5503
 
4698
- BOOST_FIXTURE_TEST_CASE(dropDatabaseKanji, fixture)
5504
+ BOOST_FIXTURE_TEST_CASE(dropDatabaseKanji, fixtureKanji)
4699
5505
  {
4700
5506
  testDropDatabaseKanji(db());
4701
5507
  }
@@ -4733,24 +5539,65 @@ BOOST_FIXTURE_TEST_CASE(new_delete, fixtureQuery)
4733
5539
  BOOST_FIXTURE_TEST_CASE(join, fixtureQuery)
4734
5540
  {
4735
5541
  testJoin(db());
5542
+ testRecordsetClone(db());
4736
5543
  testPrepareJoin(db());
4737
5544
  testServerPrepareJoin(db());
4738
5545
  testWirtableRecord(db());
4739
5546
  }
4740
5547
 
5548
+ BOOST_FIXTURE_TEST_CASE(readMore, fixtureQuery)
5549
+ {
5550
+ testReadMore(db());
5551
+ }
5552
+
5553
+ BOOST_FIXTURE_TEST_CASE(firstLastGropuFunction, fixtureQuery)
5554
+ {
5555
+ testFirstLastGroupFunction(db());
5556
+ }
5557
+
5558
+ BOOST_FIXTURE_TEST_CASE(blobOnly, fixtureQuery)
5559
+ {
5560
+ testBlobOnlyTable(db());
5561
+ }
5562
+
4741
5563
  BOOST_AUTO_TEST_SUITE_END()
4742
5564
 
5565
+
4743
5566
  BOOST_AUTO_TEST_SUITE(dbPool)
4744
5567
 
4745
5568
  BOOST_AUTO_TEST_CASE(pool)
4746
5569
  {
4747
5570
  testDbPool();
4748
5571
  }
5572
+
5573
+ BOOST_AUTO_TEST_SUITE_END()
5574
+
5575
+
5576
+ BOOST_AUTO_TEST_SUITE(filter)
5577
+
5578
+ BOOST_FIXTURE_TEST_CASE(serverFilter, fixture)
5579
+ {
5580
+ createFilterTestDb(db());
5581
+ testFilterOfServer(db());
5582
+ testFilterOfMatchBy(db());
5583
+
5584
+ }
5585
+
5586
+ BOOST_AUTO_TEST_SUITE_END()
5587
+
5588
+ BOOST_AUTO_TEST_SUITE(field)
5589
+
5590
+ BOOST_AUTO_TEST_CASE(binary)
5591
+ {
5592
+ testBinaryField();
5593
+ }
5594
+
4749
5595
  BOOST_AUTO_TEST_CASE(fuga)
4750
5596
  {
4751
5597
  BOOST_CHECK_EQUAL(2 * 3, 6);
4752
5598
  }
4753
5599
 
4754
5600
  BOOST_AUTO_TEST_SUITE_END()
5601
+
4755
5602
 
4756
5603
  // ------------------------------------------------------------------------