transactd 2.3.0 → 2.4.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 (106) hide show
  1. checksums.yaml +4 -4
  2. data/{BUILD_UNIX-JA → BUILD_UNIX-JA.md} +6 -6
  3. data/CMakeLists.txt +20 -15
  4. data/{README-JA → README-JA.md} +23 -23
  5. data/{README → README.md} +22 -24
  6. data/RELEASE_NOTE +120 -0
  7. data/RELEASE_NOTE-JA +110 -0
  8. data/bin/common/tdclc_32_2_4.dll +0 -0
  9. data/bin/common/tdclc_64_2_4.dll +0 -0
  10. data/build/common/get_ruby_path.cmake +1 -1
  11. data/build/swig/ruby/tdclrb_wrap.cpp +1319 -830
  12. data/build/swig/tdcl.i +22 -2
  13. data/build/tdclc/tdclc.cbproj +1 -1
  14. data/build/tdclc/tdclc.rc +4 -4
  15. data/build/tdclcpp/tdclcpp.rc +4 -4
  16. data/build/tdclcpp/tdclcpp_bc.cbproj +2 -1
  17. data/build/tdclrb/CMakeLists.txt +6 -1
  18. data/build/tdclrb/bldgem/extconf.rb +5 -1
  19. data/build/tdclrb/tdclrb.rc +4 -4
  20. data/source/bzs/db/engine/mysql/database.cpp +44 -40
  21. data/source/bzs/db/engine/mysql/database.h +28 -8
  22. data/source/bzs/db/engine/mysql/dbManager.cpp +2 -0
  23. data/source/bzs/db/engine/mysql/dbManager.h +2 -7
  24. data/source/bzs/db/engine/mysql/mysqlInternal.h +79 -7
  25. data/source/bzs/db/protocol/hs/hsCommandExecuter.h +5 -1
  26. data/source/bzs/db/protocol/tdap/client/activeTable.cpp +32 -8
  27. data/source/bzs/db/protocol/tdap/client/activeTable.h +17 -4
  28. data/source/bzs/db/protocol/tdap/client/activeTableImple.h +10 -4
  29. data/source/bzs/db/protocol/tdap/client/client.cpp +51 -6
  30. data/source/bzs/db/protocol/tdap/client/client.h +41 -11
  31. data/source/bzs/db/protocol/tdap/client/connMgr.cpp +51 -15
  32. data/source/bzs/db/protocol/tdap/client/connMgr.h +6 -1
  33. data/source/bzs/db/protocol/tdap/client/database.cpp +26 -5
  34. data/source/bzs/db/protocol/tdap/client/database.h +3 -2
  35. data/source/bzs/db/protocol/tdap/client/dbDef.cpp +38 -28
  36. data/source/bzs/db/protocol/tdap/client/dbDef.h +1 -1
  37. data/source/bzs/db/protocol/tdap/client/dllmain.cpp +2 -32
  38. data/source/bzs/db/protocol/tdap/client/field.cpp +0 -1
  39. data/source/bzs/db/protocol/tdap/client/filter.h +60 -33
  40. data/source/bzs/db/protocol/tdap/client/groupQuery.cpp +2 -5
  41. data/source/bzs/db/protocol/tdap/client/memRecord.cpp +9 -0
  42. data/source/bzs/db/protocol/tdap/client/memRecord.h +1 -0
  43. data/source/bzs/db/protocol/tdap/client/nsDatabase.cpp +99 -48
  44. data/source/bzs/db/protocol/tdap/client/nsDatabase.h +5 -2
  45. data/source/bzs/db/protocol/tdap/client/nsTable.cpp +76 -26
  46. data/source/bzs/db/protocol/tdap/client/nsTable.h +6 -4
  47. data/source/bzs/db/protocol/tdap/client/request.h +28 -11
  48. data/source/bzs/db/protocol/tdap/client/sqlBuilder.cpp +19 -11
  49. data/source/bzs/db/protocol/tdap/client/table.cpp +157 -70
  50. data/source/bzs/db/protocol/tdap/client/table.h +20 -5
  51. data/source/bzs/db/protocol/tdap/client/trdboostapi.h +57 -4
  52. data/source/bzs/db/protocol/tdap/client/trdormapi.h +55 -20
  53. data/source/bzs/db/protocol/tdap/mysql/databaseSchema.cpp +65 -31
  54. data/source/bzs/db/protocol/tdap/mysql/databaseSchema.h +2 -0
  55. data/source/bzs/db/protocol/tdap/mysql/recordsetReader.h +24 -36
  56. data/source/bzs/db/protocol/tdap/mysql/request.h +1 -1
  57. data/source/bzs/db/protocol/tdap/mysql/tdapCommandExecuter.cpp +98 -18
  58. data/source/bzs/db/protocol/tdap/mysql/tdapCommandExecuter.h +12 -7
  59. data/source/bzs/db/protocol/tdap/tdapRequest.h +3 -8
  60. data/source/bzs/db/protocol/tdap/tdapSchema.cpp +1 -9
  61. data/source/bzs/db/protocol/tdap/tdapSchema.h +31 -1
  62. data/source/bzs/db/protocol/tdap/tdapcapi.h +49 -6
  63. data/source/bzs/db/protocol/tdap/uri.h +41 -6
  64. data/source/bzs/db/transactd/appModule.cpp +0 -1
  65. data/source/bzs/db/transactd/appModule.h +0 -2
  66. data/source/bzs/db/transactd/connManager.cpp +202 -33
  67. data/source/bzs/db/transactd/connManager.h +11 -4
  68. data/source/bzs/db/transactd/connectionRecord.h +19 -5
  69. data/source/bzs/db/transactd/transactd.cpp +39 -8
  70. data/source/bzs/env/crosscompile.cpp +1 -1
  71. data/source/bzs/example/queryData.cpp +1 -1
  72. data/source/bzs/netsvc/client/iconnection.h +2 -0
  73. data/source/bzs/netsvc/client/tcpClient.cpp +48 -26
  74. data/source/bzs/netsvc/client/tcpClient.h +171 -106
  75. data/source/bzs/netsvc/server/IAppModule.h +0 -1
  76. data/source/bzs/netsvc/server/serverPipe.cpp +5 -1
  77. data/source/bzs/netsvc/server/serverPipe.h +2 -1
  78. data/source/bzs/test/tdclatl/test_query_atl.js +105 -0
  79. data/source/bzs/test/tdclphp/transactd_Test.php +129 -11
  80. data/source/bzs/test/tdclrb/transactd_spec.rb +74 -2
  81. data/source/bzs/test/transactdBench/scaling_bench.cpp +1 -1
  82. data/source/bzs/test/trdclengn/test_trdclengn.cpp +45 -20
  83. data/source/global/tdclatl/Bookmark.cpp +28 -0
  84. data/source/global/tdclatl/Bookmark.h +65 -0
  85. data/source/global/tdclatl/Database.cpp +2 -2
  86. data/source/global/tdclatl/Database.h +1 -3
  87. data/source/global/tdclatl/DbDef.cpp +6 -0
  88. data/source/global/tdclatl/DbDef.h +1 -0
  89. data/source/global/tdclatl/QueryBase.cpp +29 -0
  90. data/source/global/tdclatl/QueryBase.h +4 -0
  91. data/source/global/tdclatl/Record.cpp +14 -2
  92. data/source/global/tdclatl/Record.h +1 -1
  93. data/source/global/tdclatl/Table.cpp +80 -16
  94. data/source/global/tdclatl/Table.h +23 -8
  95. data/source/global/tdclatl/_IDatabaseEvents_CP.h +39 -0
  96. data/source/global/tdclatl/activeTable.cpp +2 -2
  97. data/source/global/tdclatl/activeTable.h +1 -1
  98. data/source/global/tdclatl/tdclatl.idl +64 -14
  99. metadata +12 -12
  100. data/bin/common/tdclc_32_2_3.dll +0 -0
  101. data/bin/common/tdclc_64_2_3.dll +0 -0
  102. data/build/tdclcpp/BUILDNUMBER.txt +0 -1
  103. data/build/tdclrb/BUILDNUMBER.txt +0 -1
  104. /data/{BUILD_WIN-JA → BUILD_WIN-JA.md} +0 -0
  105. /data/{README_ORMSRCGEN-JA → README_ORMSRCGEN-JA.md} +0 -0
  106. /data/{README_ORMSRCGEN → README_ORMSRCGEN.md} +0 -0
@@ -426,14 +426,26 @@ void database::doClose()
426
426
  m_impl->lockReadOnly = false;
427
427
  }
428
428
 
429
- void database::close()
429
+ void database::close(bool withDropDefaultSchema)
430
430
  {
431
431
  bool flag = (m_impl->dbDef != NULL);
432
+ if (m_impl && m_impl->dbDef)
433
+ m_impl->dbDef->setKeyNum(withDropDefaultSchema ? CR_SUBOP_DROP : 0);
432
434
  doClose();
433
435
  if (flag)
434
436
  nsdatabase::release();
435
437
  }
436
438
 
439
+ bool database::doReopenDatabaseSchema()
440
+ {
441
+ if (m_impl->dbDef && m_impl->dbDef->isOpen())
442
+ {
443
+ doReconnect(m_impl->dbDef);
444
+ return (m_stat == 0);
445
+ }
446
+ return true;
447
+ }
448
+
437
449
  _TCHAR* database::getTableUri(_TCHAR* buf, short FileNum)
438
450
  {
439
451
  m_stat = STATUS_SUCCESS;
@@ -569,6 +581,12 @@ table* database::openTable(short FileNum, short mode, bool AutoCreate,
569
581
 
570
582
  bool database::createTable(short FileNum, const _TCHAR* FilePath)
571
583
  {
584
+ tabledef* td = m_impl->dbDef->tableDefs(FileNum);
585
+ if (!td || td->fieldCount == 0)
586
+ {
587
+ m_stat = STATUS_INVALID_FIELD_OFFSET;
588
+ return false;
589
+ }
572
590
  if (isTransactdUri(FilePath))
573
591
  {
574
592
  if (setUseTransactd() == false)
@@ -580,7 +598,7 @@ bool database::createTable(short FileNum, const _TCHAR* FilePath)
580
598
  const char* p = toServerUri(buf2, MAX_PATH, FilePath, isUseTransactd());
581
599
 
582
600
  m_stat = m_btrcallid(
583
- TD_CREATETABLE, posblk, m_impl->dbDef->tableDefs(FileNum),
601
+ TD_CREATETABLE, posblk, td,
584
602
  &m_impl->dbDef->m_datalen, (void*)p, (uchar_td)strlen(p),
585
603
  CR_SUBOP_BY_TABLEDEF /* exists check */, clientID());
586
604
  }
@@ -597,7 +615,7 @@ bool database::createTable(short FileNum, const _TCHAR* FilePath)
597
615
  if (FilePath)
598
616
  buf = FilePath;
599
617
  else
600
- buf = m_impl->dbDef->tableDefs(FileNum)->fileName();
618
+ buf = td->fileName();
601
619
  nsdatabase::createTable(fs, 1024, buf, CR_SUBOP_BY_FILESPEC);
602
620
  free(fs);
603
621
  }
@@ -734,11 +752,13 @@ inline void copyEachFieldData(table* dest, table* src, filedChnageInfo* fci)
734
752
  inline int moveVaileRecord(table* src)
735
753
  {
736
754
  int count = 0;
737
- bookmark_td bm = 0;
755
+ bookmark_td bm;
738
756
  src->stepLast();
739
757
  while (src->stat() == STATUS_SUCCESS)
740
758
  {
741
759
  bm = src->bookmark();
760
+ if (src->stat() != STATUS_SUCCESS)
761
+ break;
742
762
  ++count;
743
763
  src->stepPrev();
744
764
  }
@@ -779,6 +799,7 @@ short database::copyTableData(table* dest, table* src, bool turbo, int offset,
779
799
  short keyNum, int maxSkip)
780
800
  {
781
801
  src->setKeyNum((char_td)keyNum);
802
+ dest->setKeyNum(-1);
782
803
  const tabledef* ddef = dest->tableDef();
783
804
  const tabledef* sdef = src->tableDef();
784
805
  ushort_td ins_rows = 0;
@@ -839,7 +860,7 @@ short database::copyTableData(table* dest, table* src, bool turbo, int offset,
839
860
  dest->tdap(TD_REC_INSERT);
840
861
  }
841
862
  else
842
- ins_rows += dest->insert();
863
+ ins_rows += dest->insert(true);
843
864
  if (dest->stat() == STATUS_INVALID_VALLEN)
844
865
  skipCount++;
845
866
  else if (dest->stat() == STATUS_DUPPLICATE_KEYVALUE)
@@ -35,7 +35,7 @@ class database;
35
35
  class table;
36
36
  class dbdef;
37
37
 
38
- #if (defined(__BORLANDC__) && !defined(__clang__))
38
+ #if (defined(__BORLANDC__) && !defined(__APPLE__) && !defined(__clang__))
39
39
  typedef bool __stdcall (*deleteRecordFn)(database* db, table* tb, bool inkey);
40
40
  typedef short __stdcall (*schemaMgrFn)(database* db);
41
41
  typedef void __stdcall (*copyDataFn)(database* db, int recordCount, int count,
@@ -84,6 +84,7 @@ protected:
84
84
  bool& cancel);
85
85
  virtual void doConvertTable(short tableIndex, bool turbo,
86
86
  const _TCHAR* ownerName);
87
+ virtual bool doReopenDatabaseSchema();
87
88
 
88
89
  public:
89
90
  virtual void release();
@@ -111,7 +112,7 @@ public:
111
112
  void create(const _TCHAR* uri, short type = TYPE_SCHEMA_BDF);
112
113
  void drop();
113
114
  void dropTable(const _TCHAR* tableName);
114
- void close();
115
+ void close(bool withDropDefaultSchema = false);
115
116
  short aclReload();
116
117
  short continuous(char_td op = TD_BACKUP_START, bool inclideRepfile = false);
117
118
  short assignSchemaData(dbdef* src);
@@ -42,6 +42,7 @@ namespace client
42
42
  #define FORMAT_VERSON_BTRV_DEF 0
43
43
  #define FORMAT_VERSON_CURRENT 1
44
44
 
45
+ /* BDFFORMAT_VERSION used in the databaseSchema.cpp listSchemaTable() */
45
46
  static const _TCHAR BDFFORMAT_VERSION[] = _T("2.000.00");
46
47
  static const _TCHAR ow0[11] = { 46, 46, 83, 67, 46, 46, 46, 46, 93, 4, 0 };
47
48
  static const _TCHAR ow1[11] = { 46, 46, 83, 67, 46, 46, 46, 46, 66, 5, 0 };
@@ -220,25 +221,23 @@ void dbdef::setCodePage(tabledef* td)
220
221
  }
221
222
  }
222
223
 
223
- void dbdef::updateTableDef(short TableIndex, bool forPsqlDdf)
224
+ short dbdef::validateTableDef(short TableIndex)
224
225
  {
225
226
  m_stat = STATUS_SUCCESS;
226
227
  tabledef* td = tableDefs(TableIndex);
227
- short i, j, ret, Fnum;
228
- uchar_td type;
229
228
 
230
229
  td->optionFlags.bitA = false; // reset valiable type
231
230
  td->optionFlags.bitB = false;
232
- for (i = 0; i < td->fieldCount; ++i)
231
+ for (short i = 0; i < td->fieldCount; ++i)
233
232
  {
234
- ret = fieldNumByName(TableIndex, td->fieldDefs[i].name());
233
+ short ret = fieldNumByName(TableIndex, td->fieldDefs[i].name());
235
234
  if ((ret != -1) && (ret != i))
236
235
  {
237
236
  m_stat = STATUS_DUPLICATE_FIELDNAME;
238
- return;
237
+ return m_stat;
239
238
  }
240
239
  // Check field length.
241
- type = td->fieldDefs[i].type;
240
+ uchar_td type = td->fieldDefs[i].type;
242
241
 
243
242
  // reset update indicator
244
243
  td->fieldDefs[i].enableFlags.bitE = false;
@@ -247,7 +246,7 @@ void dbdef::updateTableDef(short TableIndex, bool forPsqlDdf)
247
246
  if (!ret)
248
247
  {
249
248
  m_stat = STATUS_INVALID_FIELDLENGTH;
250
- return;
249
+ return m_stat;
251
250
  }
252
251
  // Note or Lvar type must be the last of fields.
253
252
  if ((type == ft_note) || (type == ft_lvar))
@@ -255,7 +254,7 @@ void dbdef::updateTableDef(short TableIndex, bool forPsqlDdf)
255
254
  if (i != td->fieldCount - 1)
256
255
  {
257
256
  m_stat = STATUS_LVAR_NOTE_NOT_LAST;
258
- return;
257
+ return m_stat;
259
258
  }
260
259
  }
261
260
 
@@ -265,7 +264,7 @@ void dbdef::updateTableDef(short TableIndex, bool forPsqlDdf)
265
264
  (type != ft_note) && (type != ft_lvar))
266
265
  {
267
266
  m_stat = STATUS_INVALID_VARIABLETABLE;
268
- return;
267
+ return m_stat;
269
268
  }
270
269
  if ((type == ft_myvarchar) || (type == ft_mywvarchar) ||
271
270
  (type == ft_myvarbinary) || (type == ft_mywvarbinary) ||
@@ -276,36 +275,44 @@ void dbdef::updateTableDef(short TableIndex, bool forPsqlDdf)
276
275
  }
277
276
 
278
277
  // Check invalid key type
279
- for (i = 0; i < td->keyCount; i++)
278
+ for (short i = 0; i < td->keyCount; i++)
280
279
  {
281
- for (j = 0; j < td->keyDefs[i].segmentCount; j++)
280
+ for (short j = 0; j < td->keyDefs[i].segmentCount; j++)
282
281
  {
283
- Fnum = td->keyDefs[i].segments[j].fieldNum;
284
- ret = isPassKey(td->fieldDefs[Fnum].type);
282
+ short fnum = td->keyDefs[i].segments[j].fieldNum;
283
+ short ret = isPassKey(td->fieldDefs[fnum].type);
285
284
  if (!ret)
286
285
  {
287
286
  m_stat = STATUS_INVALID_KEYTYPE;
288
- return;
287
+ return m_stat;
289
288
  }
290
289
  }
291
290
  }
292
291
 
293
292
  // Chack duplicate table name.
294
- for (i = 1; i < m_impl->tableCount; i++)
293
+ for (short i = 1; i < m_impl->tableCount; i++)
295
294
  {
296
295
  if ((tableDefs(i)) && (i != TableIndex))
297
296
  {
298
297
  if (strcmp(tableDefs(i)->tableNameA(), td->tableNameA()) == 0)
299
298
  {
300
299
  m_stat = STATUS_DUPPLICATE_KEYVALUE;
301
- return;
300
+ return m_stat;
302
301
  }
303
302
  }
304
303
  }
305
304
  setCodePage(td);
306
-
307
305
  setRecordLen(TableIndex);
308
- td = tableDefs(TableIndex);
306
+ return m_stat;
307
+ }
308
+
309
+ void dbdef::updateTableDef(short TableIndex, bool forPsqlDdf)
310
+ {
311
+ if ((m_stat = validateTableDef(TableIndex)) != 0)
312
+ return;
313
+
314
+ tabledef* td = tableDefs(TableIndex);
315
+
309
316
  if (m_impl->noWriteMode)
310
317
  {
311
318
  m_stat = STATUS_ACCESS_DENIED;
@@ -716,10 +723,9 @@ tabledef* dbdef::tableDefs(int index)
716
723
  }
717
724
  m_datalen =
718
725
  fixVariableLenBug(isUseTransactd(), (tabledef*)m_pdata, m_datalen);
719
-
720
- m_impl->tableDefs[index] = def =
721
- (tabledef*)malloc(getNewVersionSize((tabledef*)m_pdata));
722
-
726
+ size_t size = getNewVersionSize((tabledef*)m_pdata);
727
+ def = (tabledef*)malloc(size);
728
+ m_impl->tableDefs[index] = def;
723
729
  if (def == NULL)
724
730
  {
725
731
  m_stat = STATUS_CANT_ALLOC_MEMORY;
@@ -1709,7 +1715,11 @@ void dbdef::pushBackup(short TableIndex)
1709
1715
  }
1710
1716
 
1711
1717
  setFieldsCharsetIndex(tableDefs(TableIndex));
1712
- memcpy(m_impl->tableDefs[TABLE_NUM_TMP], tableDefs(TableIndex), blen);
1718
+ tabledef* td = m_impl->tableDefs[TABLE_NUM_TMP];
1719
+ memcpy(td, tableDefs(TableIndex), blen);
1720
+ td->fieldDefs = getFieldDef(td);
1721
+ td->keyDefs = getKeyDef(td);
1722
+
1713
1723
  }
1714
1724
 
1715
1725
  bool dbdef::compAsBackup(short TableIndex)
@@ -1745,10 +1755,10 @@ void dbdef::popBackup(short TableIndex)
1745
1755
  int len = totalDefLength(TABLE_NUM_TMP);
1746
1756
  m_impl->tableDefs[TableIndex] =
1747
1757
  (tabledef*)realloc(tableDefs(TableIndex), len);
1748
- memcpy(tableDefs(TableIndex), tableDefs(TABLE_NUM_TMP), len);
1749
- tableDefs(TableIndex)->fieldDefs = getFieldDef(tableDefs(TableIndex));
1750
- tableDefs(TableIndex)->keyDefs = getKeyDef(tableDefs(TableIndex));
1751
-
1758
+ tabledef* td = m_impl->tableDefs[TableIndex];
1759
+ memcpy(td, tableDefs(TABLE_NUM_TMP), len);
1760
+ td->fieldDefs = getFieldDef(td);
1761
+ td->keyDefs = getKeyDef(td);
1752
1762
  updateTableDef(TableIndex);
1753
1763
  }
1754
1764
 
@@ -99,7 +99,7 @@ public:
99
99
  int version() const;
100
100
 
101
101
  inline short_td stat() const { return m_stat; }
102
-
102
+ short validateTableDef(short TableIndex);
103
103
  void updateTableDef(short tableIndex, bool forPsqlDdf = true);
104
104
  fielddef* insertField(short tableIndex, short insertIndex);
105
105
  void deleteField(short tableIndex, short deleteIndex);
@@ -211,13 +211,13 @@ extern "C" PACKAGE_OSX short_td __STDCALL
211
211
  client_t->req().paramMask = P_MASK_NOKEYBUF;
212
212
  break;
213
213
  case TD_UNLOCK:
214
+ case TD_CLOSETABLE:
214
215
  client_t->req().paramMask = P_MASK_POSBLK | P_MASK_KEYNUM;
215
216
  break;
216
217
  case TD_UPDATE_PART:
217
218
  client_t->cleanup();
218
219
  return 0;
219
220
  case TD_REC_DELETE:
220
- case TD_CLOSETABLE:
221
221
  case TD_CLEAR_OWNERNAME:
222
222
  case TD_AUTOMEKE_SCHEMA:
223
223
  client_t->req().paramMask = P_MASK_POSBLK;
@@ -371,37 +371,7 @@ extern "C" PACKAGE_OSX short_td __STDCALL
371
371
  }
372
372
  catch (boost::system::system_error& e)
373
373
  {
374
- switch (e.code().value())
375
- {
376
- case 11004:
377
- case 11001:
378
- ret = ERROR_TD_HOSTNAME_NOT_FOUND;
379
- break;
380
- case 10060:
381
- case 10057: //blocking fire wall
382
- case 110: //connect: Connection timed out
383
- case 121: //timeout sema
384
- case 11: //EAGAIN
385
- ret = ERROR_TD_NET_TIMEOUT;
386
- break;
387
- case 32: //write:brokn pipe
388
- case 111: //connect: Connection refused
389
- case 10061:
390
- ret = ERROR_TD_CONNECTION_FAILURE;
391
- break;
392
- case 104: //write: Connection reset by peer
393
- case 10054:
394
- ret = ERROR_TD_NET_REMOTE_DISCONNECT;
395
- break;
396
- case 232:
397
- case 109:
398
- case 2:
399
- case 1:
400
- ret = ERROR_TD_INVALID_CLINETHOST;
401
- break;
402
- default:
403
- ret = ERROR_TD_NET_OTHER;
404
- }
374
+ ret = errorCode(e.code());
405
375
  OutputDebugString(e.what());
406
376
  char tmp[512];
407
377
  sprintf_s(tmp, 512, "%d %s", e.code().value(), e.what());
@@ -1614,7 +1614,6 @@ void* field::getFVbin(uint_td& size) const
1614
1614
  size = m_fd->len;
1615
1615
  return (void*)(p);
1616
1616
  }
1617
- return NULL;
1618
1617
  }
1619
1618
 
1620
1619
  double field::getFVDecimal() const
@@ -37,7 +37,6 @@ namespace client
37
37
  {
38
38
 
39
39
 
40
- #define BOOKMARK_SIZE 4
41
40
  #define DATASIZE_BYTE 2
42
41
 
43
42
 
@@ -504,12 +503,11 @@ public:
504
503
  }
505
504
  }
506
505
 
507
- int bookmarkSize(bool isTransactd) const
506
+ int bookmarkSize(bool isTransactd, ushort_td bmlen) const
508
507
  {
509
508
  if (isTransactd)
510
- return (itype & FILTER_CURRENT_TYPE_NOBOOKMARK) ? 0 : BOOKMARK_SIZE;
511
- assert(type[0]);
512
- return BOOKMARK_SIZE;
509
+ return (itype & FILTER_CURRENT_TYPE_NOBOOKMARK) ? 0 : bmlen;
510
+ return bmlen;
513
511
  }
514
512
 
515
513
  bool positionTypeNext(bool isTransactd) const
@@ -599,7 +597,7 @@ class filter
599
597
  struct
600
598
  {
601
599
  bool m_stopAtLimit : 1;
602
-
600
+ bool m_seekByBookmarks : 1;
603
601
  };
604
602
 
605
603
  struct bufSize
@@ -740,11 +738,20 @@ class filter
740
738
  {
741
739
  seek& l = m_seeks[index];
742
740
  uchar_td* to = dataBuf;
743
- for (int j = 0; j < joinKeySize; ++j)
741
+ if (m_seekByBookmarks)
744
742
  {
745
- const keyValuePtr& v = keyValues[i + j];
746
- fielddef& fd = fds[kd->segments[j].fieldNum];
747
- to = fd.keyCopy(to, (uchar_td*)v.ptr, v.len);
743
+ const keyValuePtr& v = keyValues[i];
744
+ memcpy(to, (uchar_td*)v.ptr, v.len);
745
+ to += v.len;
746
+ }
747
+ else
748
+ {
749
+ for (int j = 0; j < joinKeySize; ++j)
750
+ {
751
+ const keyValuePtr& v = keyValues[i + j];
752
+ fielddef& fd = fds[kd->segments[j].fieldNum];
753
+ to = fd.keyCopy(to, (uchar_td*)v.ptr, v.len);
754
+ }
748
755
  }
749
756
  if (!l.setParam(dataBuf, (ushort_td)(to - dataBuf)))
750
757
  return false;
@@ -758,25 +765,34 @@ class filter
758
765
  bool prebuiltSeeks( keydef* kd, size_t size, const queryBase* q, int& keySize, uchar_td** dataBuf)
759
766
  {
760
767
  // Check specify key size is smoller than kd->segmentCount or equal
761
- if (keySize == 0)
762
- keySize = kd->segmentCount;
763
- else if (kd->segmentCount < keySize)
764
- return false;
765
- if (size % keySize)
766
- return false;
767
-
768
- m_hasManyJoin = (kd->segmentCount != keySize) || kd->segments[0].flags.bit0;
769
- if (m_hasManyJoin)
770
- m_withBookmark = true;
771
- if (q && m_hasManyJoin &&
772
- !(q->getOptimize() & queryBase::joinHasOneOrHasMany))
773
- return false;
774
- m_seeks.resize(size / keySize);
775
768
  int maxKeylen = 0;
776
- for (int j = 0; j < keySize; ++j)
777
- maxKeylen +=
778
- m_tb->tableDef()->fieldDefs[kd->segments[j].fieldNum].len + 2;
769
+ if (m_seekByBookmarks)
770
+ {
771
+ maxKeylen = m_tb->bookmarkLen();
772
+ m_hasManyJoin = false;
773
+ keySize = 1;
774
+ m_seeks.resize(size);
775
+ }
776
+ else
777
+ {
778
+ if (keySize == 0)
779
+ keySize = kd->segmentCount;
780
+ else if (kd->segmentCount < keySize)
781
+ return false;
782
+ if (size % keySize)
783
+ return false;
779
784
 
785
+ m_hasManyJoin = (kd->segmentCount != keySize) || kd->segments[0].flags.bit0;
786
+ if (m_hasManyJoin)
787
+ m_withBookmark = true;
788
+ if (q && m_hasManyJoin &&
789
+ !(q->getOptimize() & queryBase::joinHasOneOrHasMany))
790
+ return false;
791
+ m_seeks.resize(size / keySize);
792
+ for (int j = 0; j < keySize; ++j)
793
+ maxKeylen +=
794
+ m_tb->tableDef()->fieldDefs[kd->segments[j].fieldNum].len + 2;
795
+ }
780
796
  // alloc databuffer
781
797
  *dataBuf = reallocSeeksDataBuffer(maxKeylen * m_seeks.size());
782
798
  m_hd.rejectCount = 0;
@@ -812,7 +828,7 @@ class filter
812
828
  m_withBookmark = q->isBookmarkAlso();
813
829
  m_cachedOptimize = q->getOptimize();
814
830
  m_stopAtLimit = q->isStopAtLimit();
815
-
831
+ m_seekByBookmarks = q->isSeekByBookmarks();
816
832
 
817
833
  if (q->isAll())
818
834
  addAllFields();
@@ -839,7 +855,7 @@ class filter
839
855
 
840
856
  int resultRowSize(bool ignoreFields) const
841
857
  {
842
- int recordLen = m_hd.bookmarkSize(m_isTransactd) + DATASIZE_BYTE;
858
+ int recordLen = bookmarkSize() + DATASIZE_BYTE;
843
859
  if (!ignoreFields)
844
860
  recordLen += bsize.retRowSize;
845
861
  return recordLen;
@@ -1152,8 +1168,12 @@ public:
1152
1168
  if (!m_withBookmark)
1153
1169
  type |= FILTER_CURRENT_TYPE_NOBOOKMARK;
1154
1170
  if (m_seeksMode)
1171
+ {
1172
+ incCurrent = false;
1155
1173
  type |= FILTER_TYPE_SEEKS;
1156
-
1174
+ if (m_seekByBookmarks)
1175
+ type |= FILTER_TYPE_SEEKS_BOOKMARKS;
1176
+ }
1157
1177
  }
1158
1178
  m_hd.setPositionType(incCurrent, m_isTransactd, type);
1159
1179
  }
@@ -1192,8 +1212,7 @@ public:
1192
1212
 
1193
1213
  ushort_td totalFieldLen() const
1194
1214
  {
1195
- return resultRowSize(false) - m_hd.bookmarkSize(m_isTransactd) -
1196
- DATASIZE_BYTE;
1215
+ return resultRowSize(false) - bookmarkSize() - DATASIZE_BYTE;
1197
1216
  }
1198
1217
 
1199
1218
  ushort_td totalSelectFieldLen() const
@@ -1240,7 +1259,12 @@ public:
1240
1259
 
1241
1260
  inline bool ignoreFields() const { return m_ignoreFields; }
1242
1261
 
1243
- inline int bookmarkSize() const { return m_hd.bookmarkSize(m_isTransactd); }
1262
+ inline int bookmarkSize() const
1263
+ {
1264
+ ushort_td bmlen = (m_seeksMode && m_hasManyJoin) ?
1265
+ 4 : m_tb->bookmarkLen();
1266
+ return m_hd.bookmarkSize(m_isTransactd, bmlen);
1267
+ }
1244
1268
 
1245
1269
  /* The Ignore fields option don't use with multi seek operation.
1246
1270
  because if a server are not found a record then a server return
@@ -1248,6 +1272,7 @@ public:
1248
1272
  */
1249
1273
  inline void setIgnoreFields(bool v) { m_ignoreFields = v; }
1250
1274
  inline bool isSeeksMode() const { return m_seeksMode; }
1275
+ inline bool isSeekByBookmarks() const { return m_seekByBookmarks; }
1251
1276
  inline table::eFindType direction() const { return m_direction; }
1252
1277
  inline bool setDirection(table::eFindType v)
1253
1278
  {
@@ -1304,6 +1329,8 @@ public:
1304
1329
  return setDirection(v ? table::findBackForword : table::findForword);
1305
1330
  }
1306
1331
 
1332
+ bool withBookmark() const { return m_withBookmark; }
1333
+
1307
1334
  static filter* create(table* tb)
1308
1335
  {
1309
1336
  return new filter(tb);
@@ -393,11 +393,8 @@ public:
393
393
  f->init(mdls.fieldDefs());
394
394
 
395
395
  if (f->resultKey() == (int)mdls.fieldDefs()->size())
396
- {
397
- groupFuncBase::numeric_type dummy = 0;
398
396
  mdls.appendField(f->resultName(), f->resultType(),
399
397
  f->resultLen());
400
- }
401
398
  }
402
399
 
403
400
  grouping_comp<recordsetImple> groupingComp(mdls, keyFields);
@@ -584,8 +581,8 @@ public:
584
581
 
585
582
  inline groupFuncBaseImple(const groupFuncBaseImple& r)
586
583
  : m_targetNames(r.m_targetNames), m_resultName(r.m_resultName),
587
- m_resultKey(r.m_resultKey), m_resultType(r.m_resultType),
588
- m_resultLen(r.m_resultLen),
584
+ m_resultKey(r.m_resultKey),
585
+ m_resultLen(r.m_resultLen), m_resultType(r.m_resultType),
589
586
  m_values(r.m_values), m_counts(r.m_counts)
590
587
  {
591
588
  copyStrings(r.m_strings);
@@ -320,6 +320,15 @@ bool writableRecord::read(bool KeysetAlrady)
320
320
  return true;
321
321
  }
322
322
 
323
+ bool writableRecord::read(bookmark_td& bm)
324
+ {
325
+ m_tb->seekByBookmark(bm);
326
+ if (m_tb->stat())
327
+ return false;
328
+ copyFromBuffer(m_tb);
329
+ return true;
330
+ }
331
+
323
332
  void writableRecord::insert()
324
333
  {
325
334
  copyToBuffer(m_tb);
@@ -171,6 +171,7 @@ class DLLLIB writableRecord : public memoryRecord
171
171
  public:
172
172
 
173
173
  bool read(bool KeysetAlrady = false);
174
+ bool read(bookmark_td& bm);
174
175
  void insert();
175
176
  void del(bool KeysetAlrady = false);
176
177
  void update();