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
@@ -244,22 +244,24 @@ unsigned char* database::getUserSha1Passwd(const char* host, const char* user,
244
244
  tb = useTable(tb2->id(), SQLCOM_SELECT, NULL);
245
245
  if (tb)
246
246
  {
247
- tb->setKeyNum((char)0);
248
- std::vector<std::string> keyValues;
249
- keyValues.push_back(host);
250
- keyValues.push_back(user);
251
- tb->setKeyValues(keyValues, -1, NULL);
252
- tb->seekKey(HA_READ_KEY_EXACT, tb->keymap());
253
- if (tb->stat() == 0)
254
- {
255
- int size;
256
- const char* p = tb->valStr(MYSQL_USER_FIELD_PASSWORD, size);
257
- if (strlen(p))
258
- {
259
- get_salt_from_password(buf, p);
260
- retPtr = buf;
261
- }
262
- }
247
+ if (tb->setKeyNum((char)0))
248
+ {
249
+ std::vector<std::string> keyValues;
250
+ keyValues.push_back(host);
251
+ keyValues.push_back(user);
252
+ tb->setKeyValues(keyValues, -1, NULL);
253
+ tb->seekKey(HA_READ_KEY_EXACT, tb->keymap());
254
+ if (tb->stat() == 0)
255
+ {
256
+ int size;
257
+ const char* p = tb->valStr(MYSQL_USER_FIELD_PASSWORD, size);
258
+ if (strlen(p))
259
+ {
260
+ get_salt_from_password(buf, p);
261
+ retPtr = buf;
262
+ }
263
+ }
264
+ }
263
265
  tb->unUse();
264
266
  }
265
267
  closeTable(tb2);
@@ -541,7 +543,7 @@ table* database::useTable(int index, enum_sql_command cmd, rowLockMode* lck)
541
543
  }
542
544
  if (tb->isExclusveMode())
543
545
  m_thd->variables.option_bits &= ~OPTION_TABLE_LOCK;
544
-
546
+ /* A orver head of init_table_handle_for_HANDLER is a small */
545
547
  tb->initForHANDLER();
546
548
  tb->setLocked(true);
547
549
  m_thd->in_lock_tables = 0;
@@ -1032,6 +1034,19 @@ unsigned short nisFieldNum(TABLE* tb)
1032
1034
  return 0;
1033
1035
  }
1034
1036
 
1037
+ /* class prepareHandler */
1038
+ void prepareHandler::setInnodbFetchExtraCols(unsigned long v)
1039
+ {
1040
+ if (m_innodb)
1041
+ {
1042
+ innodb_prebuit* prebuilt = *((innodb_prebuit**)((char*)(m_table->file) + sizeof(handler)+DSMRR_SIZE));
1043
+ if (prebuilt->magic_n == ROW_PREBUILT_ALLOCATED && prebuilt->hint_need_to_fetch_extra_cols <= ROW_RETRIEVE_ALL_COLS)
1044
+ prebuilt->hint_need_to_fetch_extra_cols = v;
1045
+ else
1046
+ THROW_BZS_ERROR_WITH_CODEMSG(STATUS_PROGRAM_ERROR, "Cast error for Innodb prebuilt.");
1047
+ }
1048
+ }
1049
+
1035
1050
  bool table::noKeybufResult = true;
1036
1051
 
1037
1052
  table::table(TABLE* myTable, database& db, const std::string& name, short mode,
@@ -1039,16 +1054,14 @@ table::table(TABLE* myTable, database& db, const std::string& name, short mode,
1039
1054
  : m_table(myTable), m_name(name), m_mode(mode), m_id(id), m_db(db),
1040
1055
  m_keybuf(new unsigned char[MAX_KEYLEN]),
1041
1056
  m_stat(0),
1042
- m_keyconv(m_table->key_info, m_table->s->keys), m_blobBuffer(NULL),
1057
+ m_keyconv(m_table->key_info, m_table->s->keys), m_blobBuffer(NULL),m_updateAtField(NULL),
1043
1058
  m_readCount(0), m_updCount(0), m_delCount(0), m_insCount(0), m_privilege(0xFFFF),
1044
- m_keyNum(-1), m_nonNcc(false), m_validCursor(true), m_cursor(false),
1059
+ m_nonNcc(false), m_validCursor(true), m_cursor(false),
1045
1060
  m_locked(false), m_changed(false), m_nounlock(false), m_bulkInserting(false),
1046
1061
  m_delayAutoCommit(false),m_forceConsistentRead(false), m_mysqlNull(mysqlnull),
1047
- m_timestampAlways(g_timestamp_always != 0)
1062
+ m_timestampAlways(g_timestamp_always != 0), m_prepare(myTable)
1048
1063
  {
1049
1064
 
1050
- m_table->read_set = &m_table->s->all_set;
1051
-
1052
1065
  m_recordFormatType = RF_VALIABLE_LEN;
1053
1066
  #ifdef USE_BTRV_VARIABLE_LEN
1054
1067
  m_lastVarLenBytes = 0;
@@ -1093,6 +1106,10 @@ table::table(TABLE* myTable, database& db, const std::string& name, short mode,
1093
1106
  fd->unireg_check == Field::TIMESTAMP_DNUN_FIELD ||
1094
1107
  fd->unireg_check == Field::TIMESTAMP_DN_FIELD)
1095
1108
  m_timeStampFields.push_back(fd);
1109
+ if (m_updateAtField == NULL &&
1110
+ (fd->unireg_check == Field::TIMESTAMP_UN_FIELD ||
1111
+ fd->unireg_check == Field::TIMESTAMP_DNUN_FIELD))
1112
+ m_updateAtField = fd;
1096
1113
  }
1097
1114
  m_nullBytesCl = (nullbits + 7) / 8;
1098
1115
 
@@ -1144,7 +1161,7 @@ void table::resetInternalTable(TABLE* table)
1144
1161
  else
1145
1162
  {
1146
1163
  m_table = table;
1147
- m_table->read_set = &m_table->s->all_set;
1164
+ m_prepare.init(table);
1148
1165
  m_locked = false;
1149
1166
  m_changed = false;
1150
1167
  m_validCursor = false;
@@ -1171,39 +1188,33 @@ void table::checkACL(enum_sql_command cmd)
1171
1188
  }
1172
1189
  }
1173
1190
 
1174
- bool table::setNonKey(bool scan)
1191
+ bool table::setNonKey(bool wholeRow, bool keyRead)
1175
1192
  {
1176
- if (m_keyNum != -2)
1177
- {
1178
- m_table->file->ha_index_or_rnd_end();
1179
- int ret = m_table->file->ha_rnd_init(scan);
1180
- if (ret)
1181
- THROW_BZS_ERROR_WITH_CODEMSG(ERROR_INDEX_RND_INIT,
1182
- "setNonKey rnd_init error.");
1183
- m_keyNum = -2;
1184
- }
1193
+ m_prepare.setKeyNum(-2);
1194
+ m_prepare.ready(wholeRow, keyRead);
1185
1195
  return true;
1186
1196
  }
1187
1197
 
1188
- bool table::setKeyNum(char num, bool sorted)
1198
+ bool table::setKeyNum(char num, bool wholeRow, bool keyRead)
1189
1199
  {
1190
- if (num < 0)
1200
+ if (!keynumCheck(num))
1191
1201
  {
1192
1202
  m_stat = STATUS_INVALID_KEYNUM;
1193
1203
  return false;
1194
1204
  }
1195
- if ((m_keyNum != num) ||
1196
- ((m_keyNum >= 0) && (m_table->file->inited == handler::NONE)))
1205
+ m_prepare.setKeyNum(num);
1206
+ m_prepare.ready(wholeRow, keyRead);
1207
+ return true;
1208
+ }
1209
+
1210
+ bool table::setKeyNumForMultiRead(char num)
1211
+ {
1212
+ if (num != -2 && !keynumCheck(num))
1197
1213
  {
1198
- m_table->file->ha_index_or_rnd_end();
1199
- if (!keynumCheck(num))
1200
- {
1201
- m_stat = STATUS_INVALID_KEYNUM;
1202
- return false;
1203
- }
1204
- m_keyNum = num;
1205
- m_table->file->ha_index_init(m_keyNum, sorted);
1214
+ m_stat = STATUS_INVALID_KEYNUM;
1215
+ return false;
1206
1216
  }
1217
+ m_prepare.setKeyNum(num);
1207
1218
  return true;
1208
1219
  }
1209
1220
 
@@ -1221,7 +1232,7 @@ void table::fillNull(uchar* ptr, int size)
1221
1232
 
1222
1233
  void table::setKeyValues(const uchar* ptr, int size)
1223
1234
  {
1224
- KEY& key = m_table->key_info[(int)m_keyNum];
1235
+ KEY& key = m_table->key_info[(int)keyNum()];
1225
1236
  memcpy(&m_keybuf[0], ptr, std::min(MAX_KEYLEN, size));
1226
1237
  int pos = 0;
1227
1238
  for (int j = 0; j < (int)key.user_defined_key_parts; j++)
@@ -1251,7 +1262,7 @@ void table::setKeyValues(const uchar* ptr, int size)
1251
1262
  */
1252
1263
  short table::setKeyValuesPacked(const uchar* ptr, int size)
1253
1264
  {
1254
- KEY& key = m_table->key_info[(int)m_keyNum];
1265
+ KEY& key = m_table->key_info[(int)keyNum()];
1255
1266
  int to = 0;
1256
1267
  const uchar* from = ptr;
1257
1268
  int ret = -1;
@@ -1308,10 +1319,10 @@ short table::setKeyValuesPacked(const uchar* ptr, int size)
1308
1319
  uint table::keyPackCopy(uchar* ptr)
1309
1320
  {
1310
1321
  // if nokey and getbookmark operation then keynum = -2
1311
- if (m_keyNum < 0)
1322
+ if (keyNum() < 0)
1312
1323
  return 0;
1313
1324
 
1314
- KEY& key = m_table->key_info[(int)m_keyNum];
1325
+ KEY& key = m_table->key_info[(int)keyNum()];
1315
1326
  if ((key.flags & HA_NULL_PART_KEY) || (key.flags & HA_VAR_LENGTH_KEY))
1316
1327
  {
1317
1328
  int from = 0;
@@ -1350,20 +1361,13 @@ void* table::record() const
1350
1361
  �@m_recordFormatType=RF_FIXED_PLUS_VALIABLE_LEN.
1351
1362
  ptr is excluding null flag sgement.
1352
1363
  */
1353
- void table::setRecord(void* ptr, unsigned short size, int offset)
1364
+ void table::setRecord(void* ptr, unsigned short size, int offset,
1365
+ bzs::db::protocol::tdap::autoIncPackInfo* ai)
1354
1366
  {
1355
1367
  m_cursor = false;
1356
1368
  unsigned char* p;
1357
- /*if (m_mysqlNull && m_table->s->null_fields)
1358
- {
1359
- p = m_table->record[0];
1360
- size = std::min(size, (unsigned short)recordLen());
1361
- }
1362
- else*/
1363
- {
1364
- p = (unsigned char*)record();
1365
- size = std::min(size, (unsigned short)recordLenCl());
1366
- }
1369
+ p = (unsigned char*)record();
1370
+ size = std::min(size, (unsigned short)recordLenCl());
1367
1371
  #ifdef USE_BTRV_VARIABLE_LEN
1368
1372
  if (offset + size <=
1369
1373
  (unsigned short)m_table->s->reclength + lastVarLenBytes())
@@ -1379,6 +1383,11 @@ void table::setRecord(void* ptr, unsigned short size, int offset)
1379
1383
  }
1380
1384
  else
1381
1385
  THROW_BZS_ERROR_WITH_CODEMSG(STATUS_INVALID_DATASIZE, "");
1386
+ if (ai && m_table->next_number_field)
1387
+ {
1388
+ ai->pos = (unsigned short)(m_table->next_number_field->ptr - m_table->field[0]->ptr);
1389
+ ai->len = m_table->next_number_field->pack_length();
1390
+ }
1382
1391
  }
1383
1392
 
1384
1393
  inline bool isNullValue(Field* fd)
@@ -1428,7 +1437,6 @@ inline bool isNullNis(KEY& key, bool all)
1428
1437
 
1429
1438
  void table::setBlobFieldPointer(const bzs::db::blobHeader* hd)
1430
1439
  {
1431
-
1432
1440
  if (hd)
1433
1441
  {
1434
1442
  assert(hd->curRow < hd->rows);
@@ -1450,7 +1458,8 @@ void table::setBlobFieldPointer(const bzs::db::blobHeader* hd)
1450
1458
  /** A packed data set to the record buffer.
1451
1459
  */
1452
1460
  void table::setRecordFromPacked(const uchar* packedPtr, uint size,
1453
- const bzs::db::blobHeader* hd)
1461
+ const bzs::db::blobHeader* hd,
1462
+ bzs::db::protocol::tdap::autoIncPackInfo* ai)
1454
1463
  {
1455
1464
  const uchar* p = packedPtr;
1456
1465
  bool nullable = (m_mysqlNull && m_table->s->null_fields);
@@ -1464,10 +1473,10 @@ void table::setRecordFromPacked(const uchar* packedPtr, uint size,
1464
1473
  (int)recordLenCl() - varlenStartPos);
1465
1474
  if (len > 0)
1466
1475
  {
1467
- setRecord(&len, varlenbyte, varlenStartPos);
1476
+ setRecord(&len, varlenbyte, varlenStartPos, ai);
1468
1477
  // if (len > 0)
1469
1478
  setRecord((void*)(p + varlenStartPos), len,
1470
- varlenStartPos + varlenbyte);
1479
+ varlenStartPos + varlenbyte, ai);
1471
1480
  }
1472
1481
  else if (len == 0)
1473
1482
  ;
@@ -1494,6 +1503,12 @@ void table::setRecordFromPacked(const uchar* packedPtr, uint size,
1494
1503
  for (uint i = 0; i < m_table->s->fields; ++i)
1495
1504
  {
1496
1505
  Field* fd = m_table->field[i];
1506
+ if (ai && (fd->flags & AUTO_INCREMENT_FLAG))
1507
+ {
1508
+ ai->pos = (unsigned short)(p - packedPtr);
1509
+ ai->len = fd->pack_length();
1510
+ }
1511
+
1497
1512
  bool isNull = false;
1498
1513
  if (fd->null_bit && nullable)
1499
1514
  {
@@ -1538,7 +1553,7 @@ void table::setRecordFromPacked(const uchar* packedPtr, uint size,
1538
1553
  setBlobFieldPointer(hd);
1539
1554
  }
1540
1555
  else
1541
- setRecord((void*)p, size);
1556
+ setRecord((void*)p, size, 0, ai);
1542
1557
  }
1543
1558
 
1544
1559
  /** A record image is packed, and is copied to the specified buffer, and length
@@ -1583,9 +1598,10 @@ uint table::recordPackCopy(char* buf, uint maxsize)
1583
1598
  {
1584
1599
  #endif
1585
1600
  int blobs = 0;
1601
+ if (m_nullBytesCl)
1602
+ memset(buf, 0, m_nullBytesCl);
1586
1603
  p = buf + m_nullBytesCl;
1587
1604
  unsigned char* null_ptr = (unsigned char*)buf;//m_table->record[0];
1588
- *null_ptr = 0x00;
1589
1605
  unsigned char null_bit = 1;
1590
1606
  for (uint i = 0; i < m_table->s->fields; i++)
1591
1607
  {
@@ -1596,11 +1612,7 @@ uint table::recordPackCopy(char* buf, uint maxsize)
1596
1612
  //copy null bit
1597
1613
  isNull = fd->is_null();
1598
1614
  if (isNull)
1599
- {
1600
- if (null_bit == 1)
1601
- *null_ptr = 0x00;
1602
1615
  *null_ptr |= null_bit;
1603
- }
1604
1616
  if (null_bit == (uchar)128)
1605
1617
  {
1606
1618
  ++null_ptr;
@@ -1695,21 +1707,16 @@ inline void table::unlockRow(bool noConsistent)
1695
1707
  void table::seekKey(enum ha_rkey_function find_flag, key_part_map keyMap)
1696
1708
  {
1697
1709
  m_nonNcc = false;
1698
- if (keynumCheck(m_keyNum))
1710
+ unlockRow(m_delayAutoCommit);
1711
+ m_stat = m_table->file->ha_index_read_map(
1712
+ m_table->record[0], &m_keybuf[0], keyMap /* keymap() */, find_flag);
1713
+ setCursorStaus();
1714
+ if (m_stat == 0)
1699
1715
  {
1700
- unlockRow(m_delayAutoCommit);
1701
- m_stat = m_table->file->ha_index_read_map(
1702
- m_table->record[0], &m_keybuf[0], keyMap /* keymap() */, find_flag);
1703
- setCursorStaus();
1704
- if (m_stat == 0)
1705
- {
1706
- if (find_flag != HA_READ_KEY_EXACT)
1707
- key_copy(&m_keybuf[0], m_table->record[0],
1708
- &m_table->key_info[(int)m_keyNum], KEYLEN_ALLCOPY);
1709
- }
1716
+ if (find_flag != HA_READ_KEY_EXACT)
1717
+ key_copy(&m_keybuf[0], m_table->record[0],
1718
+ &m_table->key_info[(int)keyNum()], KEYLEN_ALLCOPY);
1710
1719
  }
1711
- else
1712
- m_stat = STATUS_INVALID_KEYNUM;
1713
1720
  if ((m_stat == HA_ERR_KEY_NOT_FOUND) && (find_flag != HA_READ_KEY_EXACT))
1714
1721
  m_stat = HA_ERR_END_OF_FILE;
1715
1722
  }
@@ -1717,7 +1724,7 @@ void table::seekKey(enum ha_rkey_function find_flag, key_part_map keyMap)
1717
1724
  void table::moveKey(boost::function<int()> func)
1718
1725
  {
1719
1726
  m_nonNcc = false;
1720
- if (keynumCheck(m_keyNum))
1727
+ if (keynumCheck(keyNum()))
1721
1728
  {
1722
1729
  unlockRow(m_delayAutoCommit);
1723
1730
 
@@ -1725,7 +1732,7 @@ void table::moveKey(boost::function<int()> func)
1725
1732
  setCursorStaus();
1726
1733
  if (m_stat == 0)
1727
1734
  key_copy(&m_keybuf[0], m_table->record[0],
1728
- &m_table->key_info[(int)m_keyNum], KEYLEN_ALLCOPY);
1735
+ &m_table->key_info[(int)keyNum()], KEYLEN_ALLCOPY);
1729
1736
  }
1730
1737
  else
1731
1738
  m_stat = STATUS_INVALID_KEYNUM;
@@ -1736,20 +1743,15 @@ void table::moveKey(boost::function<int()> func)
1736
1743
  void table::getNextSame(key_part_map keyMap)
1737
1744
  {
1738
1745
  m_nonNcc = false;
1739
- if (keynumCheck(m_keyNum))
1746
+ unlockRow(false /*lock*/);
1747
+ m_stat = m_table->file->ha_index_next_same(
1748
+ m_table->record[0], &m_keybuf[0], keyMap /* keymap() */);
1749
+ setCursorStaus();
1750
+ if (m_stat == 0)
1740
1751
  {
1741
- unlockRow(false /*lock*/);
1742
- m_stat = m_table->file->ha_index_next_same(
1743
- m_table->record[0], &m_keybuf[0], keyMap /* keymap() */);
1744
- setCursorStaus();
1745
- if (m_stat == 0)
1746
- {
1747
- key_copy(&m_keybuf[0], m_table->record[0],
1748
- &m_table->key_info[(int)m_keyNum], KEYLEN_ALLCOPY);
1749
- }
1752
+ key_copy(&m_keybuf[0], m_table->record[0],
1753
+ &m_table->key_info[(int)keyNum()], KEYLEN_ALLCOPY);
1750
1754
  }
1751
- else
1752
- m_stat = STATUS_INVALID_KEYNUM;
1753
1755
  }
1754
1756
 
1755
1757
  void table::getLast()
@@ -1790,7 +1792,7 @@ void table::getNext()
1790
1792
  if (m_nonNcc)
1791
1793
  { // It moves to the position after updating.
1792
1794
  // Since it may be lost, ref is compared and the next is decided.
1793
- movePos(position(true), m_keyNum, true);
1795
+ movePos(position(true), keyNum(), true);
1794
1796
  if (m_stat)
1795
1797
  return;
1796
1798
  }
@@ -1807,7 +1809,7 @@ void table::getPrev()
1807
1809
  }
1808
1810
  if (m_nonNcc)
1809
1811
  {
1810
- movePos(position(true), m_keyNum, true);
1812
+ movePos(position(true), keyNum(), true);
1811
1813
  if (m_stat)
1812
1814
  return;
1813
1815
  }
@@ -1817,10 +1819,10 @@ void table::getPrev()
1817
1819
 
1818
1820
  bool table::keyCheckForPercent()
1819
1821
  {
1820
- if (m_keyNum == -1)
1821
- m_keyNum = m_table->s->primary_key;
1822
+ if (keyNum() == -1)
1823
+ setKeyNum(m_table->s->primary_key);
1822
1824
  // The value of the beginning of a key
1823
- KEY& key = m_table->key_info[(int)m_keyNum];
1825
+ KEY& key = m_table->key_info[(int)keyNum()];
1824
1826
  if (key.key_length > 128)
1825
1827
  return false;
1826
1828
  return true;
@@ -1828,7 +1830,7 @@ bool table::keyCheckForPercent()
1828
1830
 
1829
1831
  void table::preBuildPercent(uchar* first, uchar* last)
1830
1832
  {
1831
- KEY& key = m_table->key_info[(int)m_keyNum];
1833
+ KEY& key = m_table->key_info[(int)keyNum()];
1832
1834
  getFirst();
1833
1835
  if (m_stat == 0)
1834
1836
  {
@@ -1878,7 +1880,7 @@ void table::getByPercentage(unsigned short per)
1878
1880
  uchar* st = keybufFirst;
1879
1881
  uchar* en = keybufLast;
1880
1882
  uchar* cu = (uchar*)keybuf();
1881
- KEY& key = m_table->key_info[(int)m_keyNum];
1883
+ KEY& key = m_table->key_info[(int)keyNum()];
1882
1884
  uint keylen = key.key_length + 10;
1883
1885
  boost::shared_array<uchar> stbuf(new uchar[keylen]);
1884
1886
  boost::shared_array<uchar> lsbuf(new uchar[keylen]);
@@ -1966,7 +1968,7 @@ void table::getByPercentage(unsigned short per)
1966
1968
 
1967
1969
  int table::percentage(uchar* first, uchar* last, uchar* cur)
1968
1970
  {
1969
- KEY& key = m_table->key_info[(int)m_keyNum];
1971
+ KEY& key = m_table->key_info[(int)keyNum()];
1970
1972
  // 1 cur to last
1971
1973
  key_range minkey;
1972
1974
  minkey.key = cur;
@@ -1975,11 +1977,11 @@ int table::percentage(uchar* first, uchar* last, uchar* cur)
1975
1977
  minkey.flag = HA_READ_KEY_EXACT;
1976
1978
  key_range maxkey = minkey;
1977
1979
  maxkey.key = last;
1978
- ha_rows rows1 = m_table->file->records_in_range(m_keyNum, &minkey, &maxkey);
1980
+ ha_rows rows1 = m_table->file->records_in_range(keyNum(), &minkey, &maxkey);
1979
1981
 
1980
1982
  // 2 first to last
1981
1983
  maxkey.key = first;
1982
- ha_rows rows2 = m_table->file->records_in_range(m_keyNum, &maxkey, &minkey);
1984
+ ha_rows rows2 = m_table->file->records_in_range(keyNum(), &maxkey, &minkey);
1983
1985
 
1984
1986
  // 3 record count
1985
1987
  ha_rows total = recordCount(true);
@@ -2003,7 +2005,7 @@ void table::calcPercentage()
2003
2005
  m_percentResult = 0;
2004
2006
  // The present key value is copied.
2005
2007
  uchar keybufCur[MAX_KEYLEN] = { 0x00 };
2006
- key_copy(keybufCur, m_table->record[0], &m_table->key_info[(int)m_keyNum],
2008
+ key_copy(keybufCur, m_table->record[0], &m_table->key_info[(int)keyNum()],
2007
2009
  KEYLEN_ALLCOPY);
2008
2010
 
2009
2011
  uchar keybufFirst[MAX_KEYLEN] = { 0x00 };
@@ -2028,8 +2030,7 @@ void table::stepFirst()
2028
2030
  }
2029
2031
  else
2030
2032
  {
2031
- m_keyNum = -1;
2032
- if (setNonKey(true))
2033
+ if (setNonKey())
2033
2034
  {
2034
2035
  unlockRow(m_delayAutoCommit);
2035
2036
  m_stat = m_table->file->ha_rnd_next(m_table->record[0]);
@@ -2061,9 +2062,9 @@ void table::stepNext()
2061
2062
  }
2062
2063
  else
2063
2064
  {
2064
- if (m_keyNum != -2)
2065
+ if (keyNum() != -2)
2065
2066
  {
2066
- if (setNonKey(false))
2067
+ if (setNonKey())
2067
2068
  {
2068
2069
  unlockRow(false/*lock*/);
2069
2070
  m_stat = m_table->file->ha_rnd_pos(m_table->record[0],
@@ -2130,11 +2131,12 @@ void table::readRecords(IReadRecordsHandler* hdr, bool includeCurrent, int type,
2130
2131
  case READ_RECORD_STEPNEXT:
2131
2132
  m_stat = m_table->file->ha_rnd_next(m_table->record[0]);break;
2132
2133
  default: //READ_RECORD_STEPPREV
2133
- setCursorStaus();
2134
+ setCursorStaus(true);
2134
2135
  m_stat = STATUS_NOSUPPORT_OP;
2135
2136
  return;
2136
2137
  }
2137
- //setCursorStaus();
2138
+ if (m_stat == 0)
2139
+ ++m_readCount;
2138
2140
  }
2139
2141
  else
2140
2142
  read = true;
@@ -2159,7 +2161,7 @@ void table::readRecords(IReadRecordsHandler* hdr, bool includeCurrent, int type,
2159
2161
 
2160
2162
  if (ret == REC_NOMACTH_NOMORE)
2161
2163
  {
2162
- setCursorStaus();
2164
+ setCursorStaus(true);
2163
2165
  m_stat = STATUS_REACHED_FILTER_COND;
2164
2166
  return;
2165
2167
  }
@@ -2167,7 +2169,7 @@ void table::readRecords(IReadRecordsHandler* hdr, bool includeCurrent, int type,
2167
2169
  --reject;
2168
2170
  }
2169
2171
  }
2170
- setCursorStaus();
2172
+ setCursorStaus(true);
2171
2173
  m_stat = tmp_stat;
2172
2174
  if (reject == 0)
2173
2175
  m_stat = STATUS_LIMMIT_OF_REJECT;
@@ -2180,7 +2182,7 @@ void table::readRecords(IReadRecordsHandler* hdr, bool includeCurrent, int type,
2180
2182
  void table::seekPos(const uchar* rawPos)
2181
2183
  {
2182
2184
  seekKey(HA_READ_KEY_OR_NEXT, keymap());
2183
- if (m_keyNum == (int)m_table->s->primary_key)
2185
+ if (keyNum() == (int)m_table->s->primary_key)
2184
2186
  return;
2185
2187
  int cmp;
2186
2188
  while ((m_stat == 0) &&
@@ -2192,28 +2194,30 @@ void table::seekPos(const uchar* rawPos)
2192
2194
  }
2193
2195
  }
2194
2196
 
2195
- void table::movePos(const uchar* pos, char keyNum, bool sureRawValue)
2197
+ /* move by ref and change key */
2198
+ void table::movePos(const uchar* pos, char keynum, bool sureRawValue)
2196
2199
  {
2197
2200
  const uchar* rawPos = pos;
2198
2201
  if (!sureRawValue && (m_table->file->ref_length > REF_SIZE_MAX))
2199
2202
  rawPos = bms()->getRefByBm(*(unsigned int*)pos);
2200
2203
 
2201
- setNonKey();
2202
2204
  unlockRow(m_delayAutoCommit);
2205
+ setNonKey();
2206
+
2203
2207
  m_stat = m_table->file->ha_rnd_pos(m_table->record[0], (uchar*)rawPos);
2204
2208
  setCursorStaus();
2205
- if ((keyNum == -1) || (keyNum == -64) || (keyNum == -2))
2209
+ if ((keynum == -1) || (keynum == -64) || (keynum == -2))
2206
2210
  return;
2207
2211
  if (m_stat == 0)
2208
2212
  {
2209
- if (m_keyNum != keyNum)
2213
+ if (keyNum() != keynum)
2210
2214
  { // need key change
2211
2215
  key_copy(&m_keybuf[0], m_table->record[0],
2212
- &m_table->key_info[(int)keyNum], KEYLEN_ALLCOPY);
2216
+ &m_table->key_info[(int)keynum], KEYLEN_ALLCOPY);
2213
2217
  // It seek(s) until ref becomes the same, since it is a duplication
2214
2218
  // key.
2215
- setKeyNum(keyNum);
2216
- seekPos(rawPos);
2219
+ if (setKeyNum(keynum))
2220
+ seekPos(rawPos);
2217
2221
  }
2218
2222
  }
2219
2223
  }
@@ -2266,12 +2270,10 @@ ha_rows table::recordCount(bool estimate)
2266
2270
  }
2267
2271
 
2268
2272
  uint n = 0;
2269
- fieldBitmap fb(m_table);
2270
- char keynum = m_keyNum;
2271
- int inited = m_table->file->inited;
2272
- m_table->file->ha_index_or_rnd_end();
2273
- fb.setKeyRead(true);
2274
- if (setKeyNum((char)0, false /* sorted */))
2273
+ char keynum = keyNum();
2274
+
2275
+ /* force change keynumber */
2276
+ if (setKeyNum(primarykeyNum(), whole_row, key_read))
2275
2277
  {
2276
2278
  m_table->file->try_semi_consistent_read(true);
2277
2279
  m_stat = m_table->file->ha_index_first(m_table->record[0]);
@@ -2282,17 +2284,10 @@ ha_rows table::recordCount(bool estimate)
2282
2284
  ++m_readCount;
2283
2285
  m_stat = m_table->file->ha_index_next(m_table->record[0]);
2284
2286
  }
2285
- fb.setKeyRead(false);
2286
-
2287
- // restore index init
2288
- if ((inited == (int)handler::INDEX) && (m_keyNum != keynum))
2289
- setKeyNum(keynum);
2290
- else if (inited == (int)handler::RND)
2291
- setNonKey(true /* scan */);
2292
2287
  }
2293
2288
  else
2294
2289
  {
2295
- setNonKey(true /* scan */);
2290
+ setNonKey(whole_row, key_read);
2296
2291
  m_table->file->try_semi_consistent_read(true);
2297
2292
  m_stat = m_table->file->ha_rnd_next(m_table->record[0]);
2298
2293
  while (m_stat == 0)
@@ -2303,6 +2298,9 @@ ha_rows table::recordCount(bool estimate)
2303
2298
  m_stat = m_table->file->ha_rnd_next(m_table->record[0]);
2304
2299
  }
2305
2300
  }
2301
+ // restore keynumber
2302
+ m_prepare.setKeyNum(keynum);
2303
+
2306
2304
  return n;
2307
2305
  }
2308
2306
 
@@ -2370,7 +2368,7 @@ int table::setKeyNullFlags()
2370
2368
  if (key.flags & HA_NULL_PART_KEY)
2371
2369
  {
2372
2370
  bool nullKey = setNullIf(key, m_mysqlNull);
2373
- if (nullKey && (i == m_keyNum))
2371
+ if (nullKey && (i == keyNum()))
2374
2372
  ++setCount;
2375
2373
  }
2376
2374
  }
@@ -2450,7 +2448,7 @@ __int64 table::insert(bool ncc)
2450
2448
  m_nonNcc = !ncc;
2451
2449
  if (!ncc && !m_bulkInserting)
2452
2450
  key_copy(&m_keybuf[0], m_table->record[0],
2453
- &m_table->key_info[(int)m_keyNum], KEYLEN_ALLCOPY);
2451
+ &m_table->key_info[(int)keyNum()], KEYLEN_ALLCOPY);
2454
2452
 
2455
2453
  /* Do not change to m_changed = false */
2456
2454
  m_changed = true;
@@ -2459,71 +2457,83 @@ __int64 table::insert(bool ncc)
2459
2457
  return autoincValue;
2460
2458
  }
2461
2459
 
2462
- void table::beginUpdate(char keyNum)
2460
+ /**
2461
+ @return value of update_at
2462
+ */
2463
+ double table::beginUpdate(char keyNum, int confrictCheck)
2463
2464
  {
2464
2465
  m_stat = 0;
2465
- beginDel();
2466
+ double v = beginDel(confrictCheck);
2466
2467
  if (m_stat == 0)
2467
2468
  {
2468
2469
  if (keyNum >= 0)
2469
- setKeyNum(keyNum);
2470
+ setKeyNum(keyNum);
2470
2471
  store_record(m_table, record[1]);
2471
2472
  }
2473
+ return v;
2472
2474
  }
2473
- void table::beginDel()
2475
+
2476
+ double table::beginDel(int confrictCheck)
2474
2477
  {
2478
+ double v = 0;
2475
2479
  if ((m_mode == TD_OPEN_READONLY) || (m_table->reginfo.lock_type < TL_WRITE))
2476
2480
  {
2477
2481
  m_stat = STATUS_INVALID_LOCKTYPE;
2478
- return;
2482
+ return v;
2479
2483
  }
2480
-
2481
- if (m_db.m_inAutoTransaction == this)
2484
+ if (!m_cursor)
2482
2485
  {
2483
- // Confirmed that hold lock(X) by innodb_lock_monitor
2484
- indexInit();
2486
+ m_stat = STATUS_NO_CURRENT;
2487
+ return v;
2485
2488
  }
2486
2489
 
2487
- if (m_cursor)
2490
+ m_stat = 0;
2491
+ /* The current position is established in advance.
2492
+ If not in transaction then m_validCursor=false */
2493
+ if (m_validCursor == false || confrictCheck == 1)
2488
2494
  {
2489
- m_stat = 0;
2490
- /* The current position is established in advance.
2491
- If not in transaction then m_validCursor=false */
2492
- if (m_validCursor == false)
2495
+ store_record(m_table, record[1]);
2496
+ if (keyNum() >= 0)
2493
2497
  {
2494
- store_record(m_table, record[1]);
2495
- if (m_keyNum >= 0)
2496
- {
2497
- // seek until ref is same.
2498
- uchar rawPos[128];
2499
- memcpy(rawPos, position(true), m_table->file->ref_length);
2500
- seekPos(rawPos);
2501
- }
2502
- else
2503
- movePos(position(true), -1, true);
2498
+ // seek until ref is same.
2499
+ uchar rawPos[128];
2500
+ memcpy(rawPos, position(true), m_table->file->ref_length);
2501
+ seekPos(rawPos);
2502
+ }
2503
+ else
2504
+ movePos(position(true), -1, true);
2504
2505
 
2505
- // Has blob fields then ignore conflicts.
2506
- if ((m_stat == 0) && (m_table->s->blob_fields == 0) &&
2507
- cmp_record(m_table, record[1]))
2508
- m_stat = STATUS_CHANGE_CONFLICT;
2506
+ // Has blob fields then ignore conflicts.
2507
+ if ((m_stat == 0) && (m_table->s->blob_fields == 0) &&
2508
+ cmp_record(m_table, record[1]))
2509
+ m_stat = STATUS_CHANGE_CONFLICT;
2509
2510
 
2510
- setCursorStaus();
2511
- if (m_stat)
2512
- return;
2513
- }
2514
- }
2515
- else
2516
- m_stat = STATUS_NO_CURRENT;
2511
+ setCursorStaus();
2512
+ if (m_stat) return v;
2513
+ }
2514
+
2515
+ if (m_updateAtField && confrictCheck)
2516
+ v = m_updateAtField->val_real();
2517
+
2518
+ return v;
2517
2519
  }
2518
2520
 
2519
2521
  /** Update current record.
2520
2522
  * It is indispensable that there is a current record in advance
2521
2523
  * and beginUpdate() is called.
2522
2524
  */
2523
- void table::update(bool ncc)
2525
+ void table::update(bool ncc, double updateAtBefore)
2524
2526
  {
2525
2527
  if (m_stat == 0)
2526
2528
  {
2529
+ if (updateAtBefore != 0)
2530
+ {
2531
+ if(updateAtBefore != m_updateAtField->val_real())
2532
+ {
2533
+ m_stat = STATUS_CHANGE_CONFLICT;
2534
+ return;
2535
+ }
2536
+ }
2527
2537
  int nullFieldsOfCurrentKey = setKeyNullFlags();
2528
2538
  if (!m_mysqlNull) setFieldNullFlags();
2529
2539
  setTimeStamp(false /* update */);
@@ -2538,9 +2548,9 @@ void table::update(bool ncc)
2538
2548
  if (!ncc) // innodb default is ncc=-1.
2539
2549
  {
2540
2550
  // Only when the present key value is changed
2541
- if (m_keyNum >= 0)
2551
+ if (keyNum() >= 0)
2542
2552
  {
2543
- const KEY& key = m_table->key_info[(int)m_keyNum];
2553
+ const KEY& key = m_table->key_info[(int)keyNum()];
2544
2554
  key_copy(&m_keybuf[0], m_table->record[0], (KEY*)&key,
2545
2555
  KEYLEN_ALLCOPY);
2546
2556
 
@@ -2561,14 +2571,28 @@ void table::update(bool ncc)
2561
2571
  }
2562
2572
  }
2563
2573
 
2574
+ void table::setUpdateTimeValue(void* data)
2575
+ {
2576
+ if (m_updateAtField)
2577
+ memcpy(m_updateAtField->ptr, data, m_updateAtField->pack_length());
2578
+ }
2579
+
2564
2580
  /** del current record.
2565
2581
  * It is indispensable that there is a current record in advance
2566
2582
  * and beginDel() is called.
2567
2583
  */
2568
- void table::del()
2584
+ void table::del(double updateAtBefore)
2569
2585
  {
2570
2586
  if (m_stat == 0)
2571
2587
  {
2588
+ if (updateAtBefore != 0)
2589
+ {
2590
+ if(updateAtBefore != m_updateAtField->val_real())
2591
+ {
2592
+ m_stat = STATUS_CHANGE_CONFLICT;
2593
+ return;
2594
+ }
2595
+ }
2572
2596
  m_stat = m_table->file->ha_delete_row(m_table->record[0]);
2573
2597
  /* Do not change to m_changed = false */
2574
2598
  if (m_stat == 0)
@@ -2645,8 +2669,8 @@ void table::endBulkInsert()
2645
2669
  {
2646
2670
  if (m_bulkInserting)
2647
2671
  {
2648
- if (m_keyNum >= 0 && m_keyNum < (char)m_table->s->keys)
2649
- key_copy(&m_keybuf[0], m_table->record[0], &m_table->key_info[(int)m_keyNum],
2672
+ if (keyNum() >= 0 && keyNum() < (char)m_table->s->keys)
2673
+ key_copy(&m_keybuf[0], m_table->record[0], &m_table->key_info[(int)keyNum()],
2650
2674
  KEYLEN_ALLCOPY);
2651
2675
  m_bulkInserting = false;
2652
2676
  m_table->file->ha_release_auto_increment();
@@ -2680,7 +2704,7 @@ inline void setSegmentValue(const KEY_PART_INFO& segment, const std::string& v)
2680
2704
  void table::setKeyValues(const std::vector<std::string>& values, int keypart,
2681
2705
  const std::string* inValue)
2682
2706
  {
2683
- KEY& key = m_table->key_info[(int)m_keyNum];
2707
+ KEY& key = m_table->key_info[(int)keyNum()];
2684
2708
  for (int i = 0; i < (int)key.user_defined_key_parts; i++)
2685
2709
  if (i < (int)values.size())
2686
2710
  setSegmentValue(key.key_part[i], values[i]);
@@ -2713,9 +2737,11 @@ unsigned int table::writeDefaultImage(unsigned char* p, size_t size)
2713
2737
  return len + sizeof(unsigned short);
2714
2738
  }
2715
2739
 
2716
- unsigned int table::writeSchemaImage(unsigned char* p, size_t size)
2740
+ unsigned int table::writeSchemaImage(unsigned char* p, size_t size, bool bin_str)
2717
2741
  {
2718
- protocol::tdap::tabledef* td = schemaBuilder().getTabledef(this, 0, m_mysqlNull, p + 2, size - 2);
2742
+ unsigned char bin_char_index = bin_str ? 0 : CHARSET_BIN;
2743
+
2744
+ protocol::tdap::tabledef* td = schemaBuilder(bin_char_index).getTabledef(this, 0, m_mysqlNull, p + 2, size - 2);
2719
2745
  unsigned short len = 0;
2720
2746
  if (td)
2721
2747
  len = td->varSize + 4;