transactd 2.2.0 → 2.3.0

Sign up to get free protection for your applications and to get access to all the features.
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
  // ------------------------------------------------------------------------