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
@@ -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;