transactd 3.5.0 → 3.6.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 (83) hide show
  1. checksums.yaml +4 -4
  2. data/bin/common/{tdclc_32_3_5.dll → tdclc_32_3_6.dll} +0 -0
  3. data/bin/common/tdclc_64_3_6.dll +0 -0
  4. data/build/swig/ruby/tdclrb_wrap.cpp +12524 -24430
  5. data/build/swig/tdcl.i +5 -0
  6. data/build/tdclc/tdclc.cbproj +1 -1
  7. data/build/tdclc/tdclc.rc +4 -4
  8. data/build/tdclcpp/tdclcpp.rc +4 -4
  9. data/build/tdclcpp/tdclcpp_bc.cbproj +1 -1
  10. data/build/tdclrb/tdclrb.rc +4 -4
  11. data/source/bzs/db/engine/mysql/database.cpp +210 -184
  12. data/source/bzs/db/engine/mysql/database.h +276 -105
  13. data/source/bzs/db/engine/mysql/mysqlInternal.h +37 -0
  14. data/source/bzs/db/engine/mysql/mysqlProtocol.cpp +1 -0
  15. data/source/bzs/db/protocol/hs/hsCommandExecuter.cpp +4 -4
  16. data/source/bzs/db/protocol/tdap/client/activeTable.h +1 -1
  17. data/source/bzs/db/protocol/tdap/client/activeTableImple.h +1 -0
  18. data/source/bzs/db/protocol/tdap/client/connMgr.cpp +1 -1
  19. data/source/bzs/db/protocol/tdap/client/database.cpp +7 -4
  20. data/source/bzs/db/protocol/tdap/client/database.h +6 -1
  21. data/source/bzs/db/protocol/tdap/client/databaseManager.h +2 -2
  22. data/source/bzs/db/protocol/tdap/client/dbDef.cpp +21 -9
  23. data/source/bzs/db/protocol/tdap/client/dbDef.h +1 -1
  24. data/source/bzs/db/protocol/tdap/client/dllmain.cpp +10 -2
  25. data/source/bzs/db/protocol/tdap/client/field.cpp +29 -5
  26. data/source/bzs/db/protocol/tdap/client/field.h +3 -1
  27. data/source/bzs/db/protocol/tdap/client/fieldNameAlias.cpp +5 -0
  28. data/source/bzs/db/protocol/tdap/client/fieldNameAlias.h +1 -0
  29. data/source/bzs/db/protocol/tdap/client/fields.h +9 -2
  30. data/source/bzs/db/protocol/tdap/client/groupQuery.cpp +8 -4
  31. data/source/bzs/db/protocol/tdap/client/memRecord.cpp +18 -5
  32. data/source/bzs/db/protocol/tdap/client/memRecord.h +2 -2
  33. data/source/bzs/db/protocol/tdap/client/nsTable.cpp +46 -13
  34. data/source/bzs/db/protocol/tdap/client/nsTable.h +5 -0
  35. data/source/bzs/db/protocol/tdap/client/recordset.cpp +5 -0
  36. data/source/bzs/db/protocol/tdap/client/recordset.h +1 -0
  37. data/source/bzs/db/protocol/tdap/client/recordsetImple.h +6 -2
  38. data/source/bzs/db/protocol/tdap/client/request.h +46 -38
  39. data/source/bzs/db/protocol/tdap/client/sqlBuilder.cpp +2 -3
  40. data/source/bzs/db/protocol/tdap/client/stringConverter.h +29 -13
  41. data/source/bzs/db/protocol/tdap/client/table.cpp +60 -10
  42. data/source/bzs/db/protocol/tdap/client/table.h +4 -1
  43. data/source/bzs/db/protocol/tdap/client/trdboostapi.h +18 -1
  44. data/source/bzs/db/protocol/tdap/client/trdormapi.h +10 -4
  45. data/source/bzs/db/protocol/tdap/fieldComp.h +1 -1
  46. data/source/bzs/db/protocol/tdap/mysql/characterset.h +1 -0
  47. data/source/bzs/db/protocol/tdap/mysql/databaseSchema.cpp +11 -4
  48. data/source/bzs/db/protocol/tdap/mysql/databaseSchema.h +2 -1
  49. data/source/bzs/db/protocol/tdap/mysql/recordsetReader.h +52 -94
  50. data/source/bzs/db/protocol/tdap/mysql/request.h +20 -13
  51. data/source/bzs/db/protocol/tdap/mysql/tdapCommandExecuter.cpp +92 -60
  52. data/source/bzs/db/protocol/tdap/mysql/tdapCommandExecuter.h +4 -4
  53. data/source/bzs/db/protocol/tdap/tdapRequest.h +11 -0
  54. data/source/bzs/db/protocol/tdap/tdapSchema.cpp +83 -34
  55. data/source/bzs/db/protocol/tdap/tdapSchema.h +5 -1
  56. data/source/bzs/db/protocol/tdap/tdapcapi.h +7 -3
  57. data/source/bzs/example/ormap_c.cpp +2 -2
  58. data/source/bzs/netsvc/server/serverPipe.cpp +35 -1
  59. data/source/bzs/test/tdclatl/test_v3.js +48 -1
  60. data/source/bzs/test/tdclphp/bench.php +89 -76
  61. data/source/bzs/test/tdclphp/transactd_Test.php +691 -687
  62. data/source/bzs/test/tdclphp/transactd_blob_Test.php +46 -43
  63. data/source/bzs/test/tdclphp/transactd_datetime_Test.php +46 -43
  64. data/source/bzs/test/tdclphp/transactd_kanjischema_Test.php +33 -33
  65. data/source/bzs/test/tdclphp/transactd_pool_Test.php +29 -25
  66. data/source/bzs/test/tdclphp/transactd_v3_Test.php +653 -183
  67. data/source/bzs/test/tdclrb/transactd_datetime_spec.rb +40 -4
  68. data/source/bzs/test/tdclrb/transactd_fetch_spec.rb +785 -0
  69. data/source/bzs/test/tdclrb/transactd_pool_spec.rb +21 -1
  70. data/source/bzs/test/tdclrb/transactd_setget_spec.rb +450 -0
  71. data/source/bzs/test/tdclrb/transactd_spec.rb +14 -2
  72. data/source/bzs/test/tdclrb/transactd_v3_spec.rb +1192 -11
  73. data/source/bzs/test/trdclengn/testField.h +522 -1
  74. data/source/bzs/test/trdclengn/test_tdclcpp_v3.cpp +37 -1
  75. data/source/bzs/test/trdclengn/test_trdclengn.cpp +62 -4
  76. data/source/global/tdclatl/RecordsetQuery.cpp +2 -1
  77. data/source/global/tdclatl/RecordsetQuery.h +1 -1
  78. data/source/global/tdclatl/Table.cpp +17 -0
  79. data/source/global/tdclatl/Table.h +3 -1
  80. data/source/global/tdclatl/tdclatl.idl +7 -2
  81. data/transactd.gemspec +1 -1
  82. metadata +7 -5
  83. data/bin/common/tdclc_64_3_5.dll +0 -0
@@ -73,7 +73,7 @@ public:
73
73
  int index = findTable(name);
74
74
  if (index != -1)
75
75
  return m_tables[index];
76
- table_ptr t = openTable(m_db, name);
76
+ table_ptr t = openTable(m_db, name, TD_OPEN_NORMAL);
77
77
  if (t)
78
78
  m_tables.push_back(t);
79
79
  return t;
@@ -190,7 +190,7 @@ public:
190
190
  int index = findTable(name);
191
191
  if (index != -1)
192
192
  return m_tables[index];
193
- table_ptr t = openTable(m_db, name);
193
+ table_ptr t = openTable(m_db, name, TD_OPEN_NORMAL);
194
194
  if (t)
195
195
  m_tables.push_back(t);
196
196
  return t;
@@ -105,7 +105,7 @@ struct dbdimple
105
105
  }
106
106
  };
107
107
 
108
- dbdef::dbdef(nsdatabase* pbe, short defType) : nstable(pbe)
108
+ dbdef::dbdef(nsdatabase* pbe, short defType, short mode) : nstable(pbe)
109
109
  {
110
110
  m_dimpl = new dbdimple();
111
111
  m_dimpl->deftype = defType;
@@ -113,6 +113,7 @@ dbdef::dbdef(nsdatabase* pbe, short defType) : nstable(pbe)
113
113
  m_keybuflen = 128;
114
114
  m_keybuf = &m_dimpl->keybuf[0];
115
115
  setShared();
116
+ setMode((char_td)mode);
116
117
  }
117
118
 
118
119
  dbdef::~dbdef()
@@ -745,6 +746,7 @@ tabledef* dbdef::initReadAfter(short tableIndex, const tabledef* data, uint_td d
745
746
  td->setFielddefsPtr();
746
747
  td->setKeydefsPtr();
747
748
  td->autoIncExSpace = ((database*)nsdb())->defaultAutoIncSpace();
749
+ td->convertToUtf8Schema();
748
750
  //Fix:Bug of maxRecordLen is mistake value saved, recalculate maxRecordLen.
749
751
  td->calcReclordlen();
750
752
  td->optionFlags.bitC = (td->fieldDefs[td->fieldCount -1].type == ft_myfixedbinary);
@@ -1014,12 +1016,14 @@ short dbdef::findKeynumByFieldNum(short tableIndex, short index)
1014
1016
  short dbdef::tableNumByName(const _TCHAR* tableName)
1015
1017
  {
1016
1018
  char buf[74];
1019
+ const char* p = NULL;
1017
1020
  for (short i = 1; i <= m_dimpl->tableCount; i++)
1018
1021
  {
1019
1022
  tabledef* td = tableDefs(i);
1020
1023
  if (td)
1021
1024
  {
1022
- const char* p = td->toChar(buf, tableName, 74);
1025
+ if (!p)
1026
+ p = td->toChar(buf, tableName, 74);
1023
1027
  if (strcmp(td->tableNameA(), p) == 0)
1024
1028
  return i;
1025
1029
  }
@@ -1277,6 +1281,9 @@ bool dbdef::isPassKey(uchar_td FieldType)
1277
1281
  void dbdef::autoMakeSchema(bool nouseNullkey)
1278
1282
  {
1279
1283
  m_keynum = (int)nouseNullkey;
1284
+ if (database::compatibleMode() & database::CMP_MODE_BINFD_DEFAULT_STR)
1285
+ m_keynum += 2; // binary field defaut string
1286
+
1280
1287
  tdap(TD_AUTOMEKE_SCHEMA);
1281
1288
  }
1282
1289
 
@@ -1591,12 +1598,15 @@ void dbdef::openDdf(const _TCHAR* dir, short Mode, const _TCHAR* OwnerName)
1591
1598
  insertKey(tbid, tableDefs(tbid)->keyCount);
1592
1599
 
1593
1600
  KeyDef = &(tableDefs(tbid)->keyDefs[id->keyid]);
1594
- if (KeyDef->segmentCount < id->segmentnum + 1)
1595
- KeyDef->segmentCount =
1596
- (uchar_td)(id->segmentnum + 1);
1597
- KeyDef->segments[id->segmentnum].fieldNum =
1598
- (uchar_td)FieldIndex;
1599
- KeyDef->segments[id->segmentnum].flags.all = id->flag;
1601
+ if (id->segmentnum < 8)
1602
+ {
1603
+ if (KeyDef->segmentCount < id->segmentnum + 1)
1604
+ KeyDef->segmentCount =
1605
+ (uchar_td)(id->segmentnum + 1);
1606
+ KeyDef->segments[id->segmentnum].fieldNum =
1607
+ (uchar_td)FieldIndex;
1608
+ KeyDef->segments[id->segmentnum].flags.all = id->flag;
1609
+ }
1600
1610
  id->seekNext();
1601
1611
  }
1602
1612
  }
@@ -1813,7 +1823,10 @@ void dbdef::synchronizeSeverSchema(short tableIndex)
1813
1823
  m_pdata = m_dimpl->bdf;
1814
1824
  m_buflen = m_datalen = m_dimpl->bdfLen;
1815
1825
  m_dimpl->bdf->id = tableIndex;
1826
+ m_keynum = SC_SUBOP_TABLEDEF;
1816
1827
  tdap((ushort_td)TD_GET_SCHEMA);
1828
+ m_keybuf = tmp;
1829
+ m_keynum = 0;
1817
1830
  if (m_stat == STATUS_SUCCESS)
1818
1831
  {
1819
1832
  if (m_datalen == 0)
@@ -1831,7 +1844,6 @@ void dbdef::synchronizeSeverSchema(short tableIndex)
1831
1844
  delete tdold;
1832
1845
  }
1833
1846
  }
1834
- m_keybuf = tmp;
1835
1847
  }
1836
1848
 
1837
1849
  } // namespace client
@@ -74,7 +74,7 @@ class DLLLIB dbdef : private nstable
74
74
  void tableDefCopy(tabledef* dest, const tabledef* src, size_t size);
75
75
 
76
76
  ~dbdef();
77
- dbdef(nsdatabase* pbe, short defType);
77
+ dbdef(nsdatabase* pbe, short defType, short mode);
78
78
  void create(const _TCHAR* uri);
79
79
  void autoMakeSchema(bool noUseNullkey);
80
80
  bool testTablePtr(tabledef* td);
@@ -213,11 +213,16 @@ extern "C" PACKAGE_OSX short_td __STDCALL
213
213
  case TD_UPDATE_PART:
214
214
  client_t->cleanup();
215
215
  return 0;
216
- case TD_REC_DELETE:
216
+
217
217
  case TD_CLEAR_OWNERNAME:
218
218
  case TD_AUTOMEKE_SCHEMA:
219
219
  client_t->req().paramMask = P_MASK_POSBLK | P_MASK_KEYNUM;
220
220
  break;
221
+ case TD_REC_DELETE:
222
+ client_t->req().paramMask = P_MASK_POSBLK | P_MASK_KEYNUM;
223
+ if (client_t->req().op > 100)
224
+ client_t->req().paramMask |= P_MASK_DATA | P_MASK_DATALEN;
225
+ break;
221
226
  case TD_END_TRANSACTION:
222
227
  case TD_BEGIN_TRANSACTION:
223
228
  case TD_ABORT_TRANSACTION:
@@ -250,7 +255,10 @@ extern "C" PACKAGE_OSX short_td __STDCALL
250
255
  case TD_KEY_LE_KO:
251
256
  case TD_REC_DELLETEATKEY:
252
257
  client_t->req().paramMask = P_MASK_KEYNAVI;
253
- if (op > 50)
258
+ // Send updateTimepstamp value when op = TD_REC_DELLETEATKEY + 100
259
+ if (op == TD_REC_DELLETEATKEY && client_t->req().op > 100)
260
+ client_t->req().paramMask |= P_MASK_DATA;
261
+ else if (op > 50)
254
262
  client_t->req().paramMask &= ~P_MASK_DATALEN;
255
263
  break;
256
264
  case TD_KEY_NEXT_MULTI:
@@ -314,6 +314,7 @@ public:
314
314
  //------------------------------------------------------------------------------
315
315
  // class fieldShare
316
316
  //------------------------------------------------------------------------------
317
+
317
318
  struct Imple
318
319
  {
319
320
  stringConverter* cv;
@@ -359,6 +360,11 @@ void fieldShare::blobClear()
359
360
  m_imple->blobs.clear();
360
361
  }
361
362
 
363
+ void fieldShare::blobResize(size_t size)
364
+ {
365
+ m_imple->blobs.resize(size);
366
+ }
367
+
362
368
  //------------------------------------------------------------------------------
363
369
  // class fielddefs
364
370
  //------------------------------------------------------------------------------
@@ -463,21 +469,27 @@ void fielddefs::push_back(const fielddef* p)
463
469
  ++m_imple->mysqlnullEnable;
464
470
  // reset update indicator
465
471
  pp->enableFlags.bitE = false;
472
+
473
+ // For activeTable need replacing name
466
474
  aliasing(pp);
467
475
  m_imple->map[pp->name()] = index;
468
476
  }
469
477
 
470
478
  void fielddefs::remove(int index)
471
479
  {
472
- m_imple->map.erase(m_imple->fields[index].name());
473
480
  m_imple->fields.erase(m_imple->fields.begin() + index);
474
481
  boost::unordered_map<std::_tstring, int>::iterator it =
475
482
  m_imple->map.begin();
476
483
  while (it != m_imple->map.end())
477
484
  {
478
- if ((*it).second > index)
479
- (*it).second--;
480
- ++it;
485
+ if ((*it).second == index)
486
+ it = m_imple->map.erase(it);
487
+ else
488
+ {
489
+ if ((*it).second > index)
490
+ (*it).second--;
491
+ ++it;
492
+ }
481
493
  }
482
494
  }
483
495
 
@@ -508,6 +520,14 @@ bool fielddefs::checkIndex(int index) const
508
520
  return (index >= 0 && index < (int)m_imple->fields.size());
509
521
  }
510
522
 
523
+ void fielddefs::addAliasName(int index, const _TCHAR* name)
524
+ {
525
+ assert(checkIndex(index));
526
+ //replace original name
527
+ m_imple->fields[index].setName(name);
528
+ m_imple->map[name] = index;
529
+ }
530
+
511
531
  int fielddefs::indexByName(const std::_tstring& name) const
512
532
  {
513
533
  if (m_imple->map.count(name) == 0)
@@ -544,16 +564,20 @@ size_t fielddefs::totalFieldLen() const
544
564
  return fd.pos + fd.len + fd.nullbytes();
545
565
  }
546
566
 
547
- void fielddefs::addAllFileds(const tabledef* def)
567
+ void fielddefs::addAllFields(const tabledef* def)
548
568
  {
549
569
  m_imple->fields.clear();
550
570
  m_imple->mysqlnullEnable = 0;
571
+ short blobCount = 0;
551
572
  for (int i = 0; i < def->fieldCount; ++i)
552
573
  {
553
574
  const fielddef* fd = &def->fieldDefs[i];
554
575
  push_back(fd);
555
576
  m_imple->fields[m_imple->fields.size() - 1].setPadCharDefaultSettings();
577
+ if (fd->isBlob())
578
+ ++blobCount;
556
579
  }
580
+ blobResize(blobCount);
557
581
  }
558
582
 
559
583
  void fielddefs::addSelectedFields(const table* tb)
@@ -66,6 +66,7 @@ protected:
66
66
  bzs::rtl::stringBuffer* strBufs() const;
67
67
  void blobPushBack(char* p);
68
68
  void blobClear();
69
+ void blobResize(size_t size);
69
70
  };
70
71
 
71
72
  /** @endcond */
@@ -100,13 +101,14 @@ class DLLLIB fielddefs : public fieldShare
100
101
  public:
101
102
  void clear();
102
103
  fielddefs* clone() const;
104
+ void addAliasName(int index, const _TCHAR* name);
103
105
  int indexByName(const std::_tstring& name) const;
104
106
  const fielddef& operator[](int index) const;
105
107
  const fielddef& operator[](const _TCHAR* name) const;
106
108
  const fielddef& operator[](const std::_tstring& name) const;
107
109
  bool checkIndex(int index) const;
108
110
  size_t size() const;
109
- void addAllFileds(const tabledef* def);
111
+ void addAllFields(const tabledef* def);
110
112
  void addSelectedFields(const class table* tb);
111
113
  void release();
112
114
  static fielddefs* create();
@@ -115,6 +115,11 @@ void fdNmaeAlias::reverseAliasNamesQuery(queryBase& q) const
115
115
  }
116
116
  }
117
117
 
118
+ size_t fdNmaeAlias::size() const
119
+ {
120
+ return m_imple->map.size();
121
+ }
122
+
118
123
  } // namespace client
119
124
  } // namespace tdap
120
125
  } // namespace protocol
@@ -45,6 +45,7 @@ public:
45
45
  const _TCHAR* resolv(const _TCHAR* dst) const;
46
46
  void clear();
47
47
  void reverseAliasNamesQuery(queryBase& q) const;
48
+ size_t size() const;
48
49
 
49
50
  };
50
51
 
@@ -126,6 +126,8 @@ class fieldsBase : public refarymem
126
126
  friend class recordsetImple; // setRecordData setFielddefs
127
127
  friend class recordsetQuery; // setRecordData
128
128
  friend class groupQueryImple; // setInvalidMemblock
129
+ friend class recordCache; // setInvalidMemblock
130
+ friend class table; // setInvalidMemblock
129
131
 
130
132
  virtual unsigned char* ptr(int index) const = 0;
131
133
  virtual unsigned char* nullPtr(int index) const = 0;
@@ -169,8 +171,13 @@ protected:
169
171
 
170
172
  inline void setInvalidMemblock(short index)
171
173
  {
172
- int num = memoryBlockIndex(index);
173
- m_InvalidFlags |= ((2L << num) | 1L);
174
+ if (index == -1)
175
+ m_InvalidFlags = 0;
176
+ else
177
+ {
178
+ int num = memoryBlockIndex(index);
179
+ m_InvalidFlags |= ((2L << num) | 1L);
180
+ }
174
181
  }
175
182
 
176
183
  /** @endcond */
@@ -503,11 +503,15 @@ public:
503
503
  {
504
504
  if (m_funcs[j]->isNull(i))
505
505
  (*cur).setInvalidMemblock(m_funcs[j]->resultKey());
506
- else if (m_funcs[j]->resultType() == ft_float)
507
- setValue(cur, m_funcs[j]->resultKey(), m_funcs[j]->numericResult(i));
508
506
  else
509
- memcpy((*cur)[m_funcs[j]->resultKey()].ptr() ,
510
- m_funcs[j]->stringResult(i), m_funcs[j]->resultLen());
507
+ {
508
+ (*cur).setInvalidMemblock(-1);
509
+ if (m_funcs[j]->resultType() == ft_float)
510
+ setValue(cur, m_funcs[j]->resultKey(), m_funcs[j]->numericResult(i));
511
+ else
512
+ memcpy((*cur)[m_funcs[j]->resultKey()].ptr() ,
513
+ m_funcs[j]->stringResult(i), m_funcs[j]->resultLen());
514
+ }
511
515
  }
512
516
  mdls.push_back(cur);
513
517
  }
@@ -146,13 +146,16 @@ memoryRecord::memoryRecord(const memoryRecord& r)
146
146
  {
147
147
  #ifdef JOIN_UNLIMIT
148
148
  m_memblock = r.m_memblock;
149
+ for (int i = 0; i < memBlockSize(); ++i)
150
+ m_memblock[i]->addref();
149
151
  #else
150
152
  m_memblockSize = r.m_memblockSize;
151
153
  for (int i = 0; i < m_memblockSize; ++i)
154
+ {
152
155
  m_memblock[i] = r.m_memblock[i];
153
- #endif
154
- for (int i = 0; i < memBlockSize(); ++i)
155
156
  m_memblock[i]->addref();
157
+ }
158
+ #endif
156
159
 
157
160
  }
158
161
 
@@ -166,10 +169,15 @@ memoryRecord& memoryRecord::operator=(const memoryRecord& r)
166
169
  {
167
170
  if (this != &r)
168
171
  {
169
- m_fns = r.m_fns;
172
+ for (int i = 0; i < memBlockSize(); ++i)
173
+ m_memblock[i]->release();
174
+ fieldsBase::operator=(r);
175
+ //m_fns = r.m_fns;
170
176
  m_blockIndexCache = r.m_blockIndexCache;
171
177
  #ifdef JOIN_UNLIMIT
172
178
  m_memblock = r.m_memblock;
179
+ #else
180
+ m_memblockSize = r.m_memblockSize;
173
181
  #endif
174
182
  for (int i = 0; i < memBlockSize(); ++i)
175
183
  {
@@ -178,7 +186,6 @@ memoryRecord& memoryRecord::operator=(const memoryRecord& r)
178
186
  #endif
179
187
  m_memblock[i]->addref();
180
188
  }
181
-
182
189
  }
183
190
  return *this;
184
191
  }
@@ -203,6 +210,8 @@ void memoryRecord::setRecordData(autoMemory* am, unsigned char* ptr,
203
210
  #ifdef JOIN_UNLIMIT
204
211
  m_memblock.push_back(am);
205
212
  #else
213
+ if (m_memblockSize == JOINLIMIT_PER_RECORD)
214
+ THROW_BZS_ERROR_WITH_MSG(_T("The number of Join limit has been exceeded."));
206
215
  m_memblock[m_memblockSize] = am;
207
216
  ++m_memblockSize;
208
217
  #endif
@@ -358,6 +367,7 @@ void writableRecord::del(bool KeysetAlrady, bool noSeek)
358
367
  if (m_tb->stat())
359
368
  nstable::throwError(_T("activeTable delete "), m_tb->stat());
360
369
  }
370
+ if (m_tb->updateConflictCheck()) copyToBuffer(m_tb);
361
371
  deleteRecord(m_tb);
362
372
  }
363
373
 
@@ -371,7 +381,7 @@ void writableRecord::update(bool KeysetAlrady, bool noSeek)
371
381
  if (m_tb->stat())
372
382
  nstable::throwError(_T("activeTable update "), m_tb->stat());
373
383
  }
374
- copyToBuffer(m_tb, true /*only changed*/);
384
+ copyToBuffer(m_tb, !m_tb->updateConflictCheck() /*only changed*/);
375
385
  updateRecord(m_tb);
376
386
  }
377
387
 
@@ -380,7 +390,10 @@ void writableRecord::save()
380
390
  copyToBuffer(m_tb);
381
391
  m_tb->seek();
382
392
  if (m_tb->stat() == STATUS_NOT_FOUND_TI)
393
+ {
383
394
  insertRecord(m_tb);
395
+ copyFromBuffer(m_tb);
396
+ }
384
397
  else
385
398
  {
386
399
  copyToBuffer(m_tb);
@@ -59,7 +59,7 @@ public:
59
59
  #define ROW_MEM_BLOCK_RESERVE 4
60
60
 
61
61
  #ifndef JOINLIMIT_PER_RECORD
62
- #define JOINLIMIT_PER_RECORD 0
62
+ #define JOINLIMIT_PER_RECORD 14
63
63
  #endif
64
64
  #if (JOINLIMIT_PER_RECORD < 1)
65
65
  #define JOIN_UNLIMIT
@@ -141,7 +141,6 @@ protected:
141
141
  inline memoryRecord(fielddefs& fdinfo);
142
142
  memoryRecord(const memoryRecord& r);
143
143
  ~memoryRecord();
144
- memoryRecord& operator=(const memoryRecord& r);
145
144
  void copyToBuffer(table* tb, bool updateOnly = false) const;
146
145
  inline void copyFromBuffer(const table* tb)
147
146
  {
@@ -153,6 +152,7 @@ protected:
153
152
  /** @endcond */
154
153
  public:
155
154
  void clear(); // orverride
155
+ memoryRecord& operator=(const memoryRecord& r); // For SWIG
156
156
  static memoryRecord* create(fielddefs& fdinfo); // For SWIG
157
157
  };
158
158
 
@@ -51,7 +51,7 @@ struct nstimpl
51
51
  {
52
52
  nstimpl()
53
53
  : bulkIns(NULL), refCount(1), percentage(0), bookmarkLen(0), tableid(0), mode(0),
54
- shared(false), isOpen(false)
54
+ shared(false), isOpen(false), updateConflictCheck(false)
55
55
  {
56
56
  memset(posblk, 0 ,POS_BLOCK_SIZE);
57
57
  uri[0] = 0x00;
@@ -68,6 +68,7 @@ struct nstimpl
68
68
  char_td mode;
69
69
  bool shared;
70
70
  bool isOpen;
71
+ bool updateConflictCheck;
71
72
  };
72
73
 
73
74
  // -----------------------------------------------------------------
@@ -180,6 +181,11 @@ void nstable::setIsOpen(bool v)
180
181
  m_impl->isOpen = v;
181
182
  }
182
183
 
184
+ void nstable::setMode(char_td v)
185
+ {
186
+ m_impl->mode = v;
187
+ }
188
+
183
189
  bool nstable::isOpen() const
184
190
  {
185
191
  return m_impl->isOpen;
@@ -452,6 +458,17 @@ clean:
452
458
  m_pdata = data_bak;
453
459
  }
454
460
 
461
+ bool nstable::setUpdateConflictCheck(bool v)
462
+ {
463
+ m_impl->updateConflictCheck = v;
464
+ return getUpdateStampEnable();
465
+ }
466
+
467
+ bool nstable::updateConflictCheck() const
468
+ {
469
+ return m_impl->updateConflictCheck;
470
+ }
471
+
455
472
  void nstable::doUpdate(eUpdateType type)
456
473
  {
457
474
  int trnCount = nsdb()->enableTrn();
@@ -480,11 +497,11 @@ void nstable::doUpdate(eUpdateType type)
480
497
  else
481
498
  m_keylen = writeKeyData();
482
499
  m_datalen = getWriteImageLen();
483
-
484
- if (m_impl->nsdb->isUseTransactd() && (type == changeInKey))
485
- tdap(TD_REC_UPDATEATKEY);
486
- else
487
- tdap(TD_REC_UPDATE);
500
+ short op = (m_impl->nsdb->isUseTransactd() && (type == changeInKey)) ?
501
+ TD_REC_UPDATEATKEY : TD_REC_UPDATE;
502
+ if (m_impl->updateConflictCheck) op += 100;
503
+
504
+ tdap(op);
488
505
  m_keynum = keynum;
489
506
  onUpdateAfter(option);
490
507
  }
@@ -500,15 +517,26 @@ void nstable::doDel(bool inkey)
500
517
  return;
501
518
 
502
519
  m_datalen = m_buflen;
520
+ if (inkey && !isUniqeKey(m_keynum))
521
+ {
522
+ m_stat = STATUS_INVALID_KEYNUM;
523
+ return;
524
+ }
525
+ __int64 v = m_impl->updateConflictCheck ? getUpdateStampValue() : 0;
526
+ short op = v ? 100 : 0;
503
527
  if (m_impl->nsdb->isUseTransactd() && inkey)
504
528
  {
505
- if (!isUniqeKey(m_keynum))
529
+ m_keylen = writeKeyData();
530
+ void* data_bak = m_pdata;
531
+ if (v)
506
532
  {
507
- m_stat = STATUS_INVALID_KEYNUM;
508
- return;
533
+ m_datalen = sizeof(__int64);
534
+ m_pdata = &v;
509
535
  }
510
- m_keylen = writeKeyData();
511
- tdap(TD_REC_DELLETEATKEY);
536
+ op += TD_REC_DELLETEATKEY;
537
+ tdap(op);
538
+ m_pdata = data_bak;
539
+ m_datalen = m_buflen;
512
540
  }
513
541
  else
514
542
  {
@@ -516,10 +544,15 @@ void nstable::doDel(bool inkey)
516
544
  {
517
545
  m_keylen = writeKeyData();
518
546
  seek();
519
- if (m_stat)
547
+ if (m_stat) return;
548
+ if (v && v != getUpdateStampValue())
549
+ {
550
+ m_stat = STATUS_CHANGE_CONFLICT;
520
551
  return;
552
+ }
521
553
  }
522
- tdap(TD_REC_DELETE);
554
+ op += TD_REC_DELETE;
555
+ tdap(op);
523
556
  }
524
557
  }
525
558
 
@@ -99,6 +99,7 @@ protected:
99
99
  const _TCHAR* uri() const;
100
100
  const uchar_td* posblk() const;
101
101
  void setIsOpen(bool v);
102
+ void setMode(char_td v); //For dbdef in noschema mode.
102
103
 
103
104
  bulkInsert* bulkIns() const;
104
105
  virtual bool isUniqeKey(char_td keynum)
@@ -132,6 +133,8 @@ protected:
132
133
  virtual short_td doBtrvErr(HWND hWnd, _TCHAR* retbuf);
133
134
  virtual ushort_td doCommitBulkInsert(bool autoCommit);
134
135
  virtual void doAbortBulkInsert();
136
+ virtual __int64 getUpdateStampValue() const {return 0;}
137
+ virtual bool getUpdateStampEnable() const {return false;}
135
138
  inline void open(const _TCHAR* uri, char_td mode = 0,
136
139
  const _TCHAR* ownerName = NULL)
137
140
  {
@@ -229,6 +232,8 @@ public:
229
232
  void unlock();
230
233
  char_td mode() const;
231
234
  void setTimestampMode(int mode);
235
+ bool setUpdateConflictCheck(bool v);
236
+ bool updateConflictCheck() const;
232
237
  static _TCHAR* getFileName(const _TCHAR* uri, _TCHAR* retbuf);
233
238
  static short_td tdapErr(HWND hWnd, short_td status,
234
239
  const _TCHAR* tableName = NULL,
@@ -180,6 +180,11 @@ recordset& recordset::reverse()
180
180
  return *this;
181
181
  }
182
182
 
183
+ void recordset::reserve(size_t size)
184
+ {
185
+ m_imple->reserve(size);
186
+ }
187
+
183
188
  void recordset::appendField(const _TCHAR* name, int type, short len)
184
189
  {
185
190
  m_imple->appendField(name, type, len);
@@ -71,6 +71,7 @@ public:
71
71
  const _TCHAR* name7 = NULL, const _TCHAR* name8 = NULL);
72
72
  recordset& orderBy(const sortFields& orders);
73
73
  recordset& reverse();
74
+ void reserve(size_t size);
74
75
  void appendField(const _TCHAR* name, int type, short len);
75
76
  recordset& operator+=(const recordset& r);
76
77
  void release();
@@ -289,8 +289,7 @@ private:
289
289
  }
290
290
  else
291
291
  { // create new record
292
- size_t reserveSize = m_recordset.size() + rows;
293
- m_recordset.reserve(reserveSize);
292
+ m_recordset.reserve(m_recordset.size() + rows);
294
293
  memoryRecord* rec = memoryRecord::create(*m_fds, (int)rows);
295
294
  autoMemory* ama = autoMemory::create((int)rows);
296
295
  for (int i = 0; i < (int)rows; ++i)
@@ -693,6 +692,11 @@ public:
693
692
  m_fds->strBufs()->clear();
694
693
  }
695
694
 
695
+ inline void reserve(size_t size)
696
+ {
697
+ m_recordset.reserve(size);
698
+ }
699
+
696
700
  #ifdef _DEBUG
697
701
  void dump()
698
702
  {