transactd 3.5.0 → 3.6.0

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