transactd 2.0.1 → 2.1.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 (146) hide show
  1. checksums.yaml +4 -4
  2. data/BUILD_UNIX-JA +6 -6
  3. data/README +16 -16
  4. data/README-JA +16 -16
  5. data/bin/common/tdclc_32_2_1.dll +0 -0
  6. data/bin/common/tdclc_64_2_1.dll +0 -0
  7. data/build/common/transactd_cl_common.cmake +0 -1
  8. data/build/common/transactd_common.cmake +28 -38
  9. data/build/swig/ruby/ruby.swg +36 -30
  10. data/build/swig/ruby/tdclrb_wrap.cpp +35016 -0
  11. data/build/swig/tdcl.i +217 -62
  12. data/build/tdclc/CMakeLists.txt +14 -26
  13. data/build/tdclc/libtdclcm.map +4 -0
  14. data/build/tdclc/tdclc.cbproj +1 -1
  15. data/build/tdclc/tdclc.rc +0 -0
  16. data/build/tdclcpp/CMakeLists.txt +7 -22
  17. data/build/tdclcpp/tdclcpp.rc +0 -0
  18. data/build/tdclcpp/tdclcpp_bc.cbproj +1 -1
  19. data/build/tdclrb/CMakeLists.txt +7 -49
  20. data/build/tdclrb/tdclrb.rc +62 -0
  21. data/source/bzs/db/blobBuffer.h +5 -0
  22. data/source/bzs/db/blobStructs.h +2 -0
  23. data/source/bzs/db/engine/mysql/IReadRecords.h +9 -0
  24. data/source/bzs/db/engine/mysql/database.cpp +391 -169
  25. data/source/bzs/db/engine/mysql/database.h +178 -40
  26. data/source/bzs/db/engine/mysql/dbManager.cpp +45 -3
  27. data/source/bzs/db/engine/mysql/dbManager.h +3 -39
  28. data/source/bzs/db/engine/mysql/errorMessage.cpp +11 -7
  29. data/source/bzs/db/engine/mysql/errorMessage.h +1 -1
  30. data/source/bzs/db/engine/mysql/mydebuglog.cpp +1 -2
  31. data/source/bzs/db/engine/mysql/mysqlInternal.h +8 -8
  32. data/source/bzs/db/engine/mysql/mysqlThd.cpp +11 -0
  33. data/source/bzs/db/protocol/hs/hsCommandExecuter.cpp +1 -1
  34. data/source/bzs/db/protocol/tdap/client/activeTable.cpp +41 -6
  35. data/source/bzs/db/protocol/tdap/client/activeTable.h +177 -8
  36. data/source/bzs/db/protocol/tdap/client/activeTableImple.h +141 -62
  37. data/source/bzs/db/protocol/tdap/client/client.cpp +39 -35
  38. data/source/bzs/db/protocol/tdap/client/client.h +52 -25
  39. data/source/bzs/db/protocol/tdap/client/connectionPool.cpp +17 -0
  40. data/source/bzs/db/protocol/tdap/client/connectionPool.h +1 -0
  41. data/source/bzs/db/protocol/tdap/client/database.cpp +5 -1
  42. data/source/bzs/db/protocol/tdap/client/database.h +1 -1
  43. data/source/bzs/db/protocol/tdap/client/databaseFactory.cpp +49 -12
  44. data/source/bzs/db/protocol/tdap/client/databaseManager.h +42 -5
  45. data/source/bzs/db/protocol/tdap/client/dbDef.cpp +4 -2
  46. data/source/bzs/db/protocol/tdap/client/dllmain.cpp +71 -41
  47. data/source/bzs/db/protocol/tdap/client/errorMessage_ja.cpp +49 -49
  48. data/source/bzs/db/protocol/tdap/client/field.cpp +22 -13
  49. data/source/bzs/db/protocol/tdap/client/field.h +7 -3
  50. data/source/bzs/db/protocol/tdap/client/fieldDDF.cpp +1 -1
  51. data/source/bzs/db/protocol/tdap/client/fieldNameAlias.cpp +0 -1
  52. data/source/bzs/db/protocol/tdap/client/fieldNameAlias.h +1 -0
  53. data/source/bzs/db/protocol/tdap/client/fields.h +111 -24
  54. data/source/bzs/db/protocol/tdap/client/fileDDF.cpp +1 -1
  55. data/source/bzs/db/protocol/tdap/client/filter.h +687 -310
  56. data/source/bzs/db/protocol/tdap/client/groupQuery.cpp +12 -4
  57. data/source/bzs/db/protocol/tdap/client/indexDDF.cpp +1 -1
  58. data/source/bzs/db/protocol/tdap/client/memRecord.cpp +190 -32
  59. data/source/bzs/db/protocol/tdap/client/memRecord.h +64 -22
  60. data/source/bzs/db/protocol/tdap/client/nsDatabase.cpp +4 -4
  61. data/source/bzs/db/protocol/tdap/client/nsDatabase.h +4 -2
  62. data/source/bzs/db/protocol/tdap/client/nsTable.cpp +6 -3
  63. data/source/bzs/db/protocol/tdap/client/nsTable.h +1 -1
  64. data/source/bzs/db/protocol/tdap/client/pooledDatabaseManager.h +19 -8
  65. data/source/bzs/db/protocol/tdap/client/recordsetImple.h +194 -87
  66. data/source/bzs/db/protocol/tdap/client/request.h +84 -26
  67. data/source/bzs/db/protocol/tdap/client/stringConverter.h +22 -12
  68. data/source/bzs/db/protocol/tdap/client/table.cpp +494 -286
  69. data/source/bzs/db/protocol/tdap/client/table.h +48 -5
  70. data/source/bzs/db/protocol/tdap/client/trdboostapi.h +133 -87
  71. data/source/bzs/db/protocol/tdap/client/trdboostapiInternal.h +22 -22
  72. data/source/bzs/db/protocol/tdap/client/trdormapi.h +43 -18
  73. data/source/bzs/db/protocol/tdap/client/trnsctcl.def +3 -3
  74. data/source/bzs/db/protocol/tdap/mysql/databaseSchema.cpp +1 -0
  75. data/source/bzs/db/protocol/tdap/mysql/recordsetReader.h +268 -74
  76. data/source/bzs/db/protocol/tdap/mysql/request.h +4 -4
  77. data/source/bzs/db/protocol/tdap/mysql/tdapCommandExecuter.cpp +179 -43
  78. data/source/bzs/db/protocol/tdap/mysql/tdapCommandExecuter.h +4 -4
  79. data/source/bzs/db/protocol/tdap/tdapRequest.h +15 -14
  80. data/source/bzs/db/protocol/tdap/tdapSchema.h +125 -90
  81. data/source/bzs/db/protocol/tdap/tdapcapi.h +46 -5
  82. data/source/bzs/db/transactd/appModule.h +1 -1
  83. data/source/bzs/db/transactd/connManager.cpp +2 -0
  84. data/source/bzs/db/transactd/transactd.cpp +1 -0
  85. data/source/bzs/env/compiler.h +10 -0
  86. data/source/bzs/env/mbcswchrLinux.cpp +42 -6
  87. data/source/bzs/env/mbcswchrLinux.h +40 -12
  88. data/source/bzs/example/queryData.cpp +33 -4
  89. data/source/bzs/netsvc/client/iconnection.h +107 -0
  90. data/source/bzs/netsvc/client/tcpClient.cpp +15 -1
  91. data/source/bzs/netsvc/client/tcpClient.h +96 -87
  92. data/source/bzs/netsvc/server/serverCpt.cpp +5 -6
  93. data/source/bzs/rtl/benchmark.cpp +2 -2
  94. data/source/bzs/rtl/stringBuffers.cpp +3 -3
  95. data/source/bzs/rtl/stringBuffers.h +2 -2
  96. data/source/bzs/test/tdclatl/bench_query_atl.js +92 -99
  97. data/source/bzs/test/tdclatl/test_query_atl.js +224 -115
  98. data/source/bzs/test/tdclphp/bench.php +126 -101
  99. data/source/bzs/test/tdclphp/transactd_Test.php +1122 -158
  100. data/source/bzs/test/tdclrb/bench_tdclcpp.rb +12 -14
  101. data/source/bzs/test/tdclrb/transactd_spec.rb +1127 -142
  102. data/source/bzs/test/transactdBench/query_bench.cpp +32 -15
  103. data/source/bzs/test/transactdBench/scaling_bench.cpp +32 -7
  104. data/source/bzs/test/transactdBench/transactdBench.cpp +1 -1
  105. data/source/bzs/test/transactdBench/workerBase.h +46 -0
  106. data/source/bzs/test/transactdBench/workerMySQLImple.h +15 -7
  107. data/source/bzs/test/transactdBench/workerTransactdImple.h +10 -18
  108. data/source/bzs/test/trdclengn/test_trdclengn.cpp +1487 -174
  109. data/source/global/ormsrcgen/main.cpp +2 -0
  110. data/source/global/tdclatl/Database.cpp +2 -2
  111. data/source/global/tdclatl/Database.h +1 -1
  112. data/source/global/tdclatl/FieldDefs.cpp +0 -3
  113. data/source/global/tdclatl/PooledDbManager.cpp +2 -2
  114. data/source/global/tdclatl/PooledDbManager.h +1 -1
  115. data/source/global/tdclatl/PreparedQuery.cpp +53 -0
  116. data/source/global/tdclatl/PreparedQuery.h +61 -0
  117. data/source/global/tdclatl/QueryBase.cpp +2 -1
  118. data/source/global/tdclatl/QueryBase.h +1 -1
  119. data/source/global/tdclatl/Record.cpp +3 -15
  120. data/source/global/tdclatl/Recordset.cpp +15 -10
  121. data/source/global/tdclatl/Recordset.h +3 -0
  122. data/source/global/tdclatl/Table.cpp +42 -7
  123. data/source/global/tdclatl/Table.h +3 -1
  124. data/source/global/tdclatl/activeTable.cpp +264 -76
  125. data/source/global/tdclatl/activeTable.h +12 -3
  126. data/source/global/tdclatl/tdclatl.idl +92 -10
  127. data/source/linux/charsetConvert.h +7 -7
  128. data/transactd.gemspec +14 -27
  129. metadata +18 -27
  130. data/bin/common/tdclc_32_2_0.dll +0 -0
  131. data/bin/common/tdclc_64_2_0.dll +0 -0
  132. data/build/swig/php/generate.cmake.in +0 -56
  133. data/build/swig/php/generate.cmd.in +0 -47
  134. data/build/swig/php/php.swg +0 -197
  135. data/build/swig/php/transactd.no_yield.php +0 -4494
  136. data/build/swig/php/transactd.no_yield.php.git.patch +0 -685
  137. data/build/swig/php/transactd.no_yield.php.patch +0 -685
  138. data/build/swig/php/transactd.yield.php +0 -4461
  139. data/build/swig/php/transactd.yield.php.git.patch +0 -652
  140. data/build/swig/php/transactd.yield.php.patch +0 -652
  141. data/build/swig/ruby/generate.cmake.in +0 -35
  142. data/build/swig/ruby/generate.cmd.in +0 -19
  143. data/build/tdclc/BUILDNUMBER.txt +0 -1
  144. data/build/tdclcpp/BUILDNUMBER.txt +0 -1
  145. data/build/tdclrb/BUILDNUMBER.txt +0 -1
  146. data/build/tdclrb/GEM_RELEASE_VERSION +0 -1
@@ -56,7 +56,7 @@ public:
56
56
  {
57
57
  // The result contents is copied or sent allready.
58
58
 
59
- paramMask = nw->getParamMask(tb->blobFields() != 0);
59
+ paramMask = nw->getParamMask(tb->getBlobFieldCount() != 0);
60
60
  unsigned int allreadysent = nw->allreadySent();
61
61
  nw->writeHeadar(paramMask, result);
62
62
 
@@ -94,8 +94,8 @@ public:
94
94
 
95
95
  if (P_MASK_POSBLK & paramMask)
96
96
  {
97
- memcpy(p, (const char*)pbk, POSBLK_SIZE);
98
- p += POSBLK_SIZE;
97
+ memcpy(p, (const char*)pbk, TD_POSBLK_TRANSMIT_SIZE);
98
+ p += TD_POSBLK_TRANSMIT_SIZE;
99
99
  }
100
100
 
101
101
  if (P_MASK_DATALEN & paramMask)
@@ -140,7 +140,7 @@ public:
140
140
  if (P_MASK_POSBLK & paramMask)
141
141
  {
142
142
  pbk = (posblk*)p;
143
- p += POSBLK_SIZE;
143
+ p += TD_POSBLK_TRANSMIT_SIZE;
144
144
  }
145
145
  if (P_MASK_DATALEN & paramMask)
146
146
  {
@@ -24,6 +24,7 @@
24
24
  #include <bzs/db/engine/mysql/errorMessage.h>
25
25
  #include <bzs/db/engine/mysql/mydebuglog.h>
26
26
  #include <bzs/netsvc/server/IAppModule.h> //lookup for result value
27
+ #include <bzs/db/transactd/appModule.h>
27
28
  #include <bzs/rtl/stl_uty.h>
28
29
  #include <limits.h>
29
30
  #include <boost/algorithm/string.hpp>
@@ -52,6 +53,7 @@ namespace mysql
52
53
 
53
54
  static const char* TableNameTitle = "dbfile=";
54
55
  static const char* BdfNameTitle = ".bdf";
56
+ boost::mutex g_mutex_opentable;
55
57
 
56
58
  class smartReadRecordsHandler
57
59
  {
@@ -389,17 +391,36 @@ inline void dbExecuter::doOpenTable(request& req)
389
391
  std::string dbname = getDatabaseName(req);
390
392
  if (dbname != "")
391
393
  {
392
- database* db = getDatabase(dbname.c_str(), req.cid);
393
- m_tb = db->openTable(
394
- getTableName(req), req.keyNum,
395
- getOwnerName(req)); // if error occured that throw exception
396
- req.result = db->stat();
394
+ database* db;
395
+ {// Lock open table by another thread
396
+ boost::mutex::scoped_lock lck(g_mutex_opentable);
397
+ if (req.keyNum == TD_OPEN_EXCLUSIVE/* && isMetaDb(req)*/)
398
+ {
399
+ if (database::tableRef.count(dbname, getTableName(req)))
400
+ THROW_BZS_ERROR_WITH_CODEMSG(STATUS_CANNOT_LOCK_TABLE,
401
+ "lockTable error.");
402
+ }
403
+ db = getDatabase(dbname.c_str(), req.cid);
404
+ m_tb = db->openTable(
405
+ getTableName(req), req.keyNum,
406
+ getOwnerName(req)); // if error occured that throw exception
407
+ req.result = db->stat();
408
+ }
409
+
397
410
  if (m_tb)
398
411
  {
399
- req.pbk->handle = addHandle(getDatabaseID(req.cid), m_tb->id());
400
- m_tb = getTable(req.pbk->handle);
401
- m_tb->setBlobBuffer(m_blobBuffer);
402
- req.paramMask = P_MASK_POSBLK;
412
+ try
413
+ {
414
+ req.pbk->handle = addHandle(getDatabaseID(req.cid), m_tb->id());
415
+ m_tb = getTable(req.pbk->handle);
416
+ m_tb->setBlobBuffer(m_blobBuffer);
417
+ req.paramMask = P_MASK_POSBLK;
418
+ }
419
+ catch (bzs::rtl::exception& e)
420
+ {
421
+ m_tb->close();
422
+ throw e;
423
+ }
403
424
  }
404
425
  }
405
426
  else
@@ -423,10 +444,10 @@ inline void readAfter(request& req, table* tb, dbExecuter* dbm)
423
444
  req.result = dbm->errorCodeSht(tb->stat());
424
445
  }
425
446
 
426
- inline void dbExecuter::doSeekKey(request& req, int op)
447
+ inline void dbExecuter::doSeekKey(request& req, int op, engine::mysql::rowLockMode* lck)
427
448
  {
428
449
  bool read = true;
429
- m_tb = getTable(req.pbk->handle);
450
+ m_tb = getTable(req.pbk->handle, SQLCOM_SELECT, lck);
430
451
  if (m_tb->setKeyNum(m_tb->keyNumByMakeOrder(req.keyNum)))
431
452
  {
432
453
  m_tb->setKeyValuesPacked((const uchar*)req.keybuf, req.keylen);
@@ -443,17 +464,21 @@ inline void dbExecuter::doSeekKey(request& req, int op)
443
464
  flag = HA_READ_BEFORE_KEY;
444
465
  else if (op == TD_KEY_OR_BEFORE)
445
466
  flag = HA_READ_KEY_OR_PREV;
467
+ m_tb->setRowLock(lck);
446
468
  m_tb->seekKey(flag, m_tb->keymap());
469
+ if (lck->lock && m_tb->stat())
470
+ m_tb->setRowLockError();
447
471
  }
448
472
  }
449
473
  readAfter(req, m_tb, this);
450
474
  }
451
475
 
452
- inline void dbExecuter::doMoveFirst(request& req)
476
+ inline void dbExecuter::doMoveFirst(request& req, engine::mysql::rowLockMode* lck)
453
477
  {
454
- m_tb = getTable(req.pbk->handle);
478
+ m_tb = getTable(req.pbk->handle, SQLCOM_SELECT, lck);
455
479
  if (m_tb->setKeyNum(m_tb->keyNumByMakeOrder(req.keyNum)))
456
480
  {
481
+ m_tb->setRowLock(lck);
457
482
  if (m_tb->isNisKey(m_tb->keyNum()))
458
483
  {
459
484
  m_tb->clearKeybuf();
@@ -461,15 +486,18 @@ inline void dbExecuter::doMoveFirst(request& req)
461
486
  }
462
487
  else
463
488
  m_tb->getFirst();
489
+ if (lck->lock && m_tb->stat())
490
+ m_tb->setRowLockError();
464
491
  }
465
492
  readAfter(req, m_tb, this);
466
493
  }
467
494
 
468
- inline void dbExecuter::doMoveKey(request& req, int op)
495
+ inline void dbExecuter::doMoveKey(request& req, int op, engine::mysql::rowLockMode* lck)
469
496
  {
470
- m_tb = getTable(req.pbk->handle);
497
+ m_tb = getTable(req.pbk->handle, SQLCOM_SELECT, lck);
471
498
  if (m_tb->setKeyNum(m_tb->keyNumByMakeOrder(req.keyNum)))
472
499
  {
500
+ m_tb->setRowLock(lck);
473
501
  if (op == TD_KEY_FIRST)
474
502
  m_tb->getFirst();
475
503
  else if (op == TD_KEY_LAST)
@@ -478,6 +506,9 @@ inline void dbExecuter::doMoveKey(request& req, int op)
478
506
  m_tb->getNext();
479
507
  else if (op == TD_KEY_PREV)
480
508
  m_tb->getPrev();
509
+ if (lck->lock && m_tb->stat())
510
+ m_tb->setRowLockError();
511
+
481
512
  }
482
513
  readAfter(req, m_tb, this);
483
514
  }
@@ -498,13 +529,24 @@ inline int dbExecuter::doReadMultiWithSeek(request& req, int op,
498
529
 
499
530
  extRequest* ereq = (extRequest*)req.data;
500
531
  bool noBookmark = (ereq->itype & FILTER_CURRENT_TYPE_NOBOOKMARK) != 0;
501
-
532
+ bool execPrepared = (ereq->itype & FILTER_TYPE_SUPPLYVALUE) != 0;
502
533
  // smartReadRecordsHandler scope
503
534
  {
504
535
  smartReadRecordsHandler srrh(m_readHandler);
505
- req.result = m_readHandler->begin(m_tb, ereq, true, nw,
536
+
537
+ if (execPrepared)
538
+ {
539
+ if (m_tb->preparedStatements.size() < ereq->preparedId)
540
+ req.result = STATUS_INVALID_PREPAREID;
541
+ else
542
+ req.result = m_readHandler->beginPreparExecute(m_tb, ereq, true, nw,
543
+ noBookmark,
544
+ (prepared*)m_tb->preparedStatements[ereq->preparedId - 1]);
545
+ }
546
+ else
547
+ req.result = m_readHandler->begin(m_tb, ereq, true, nw,
506
548
  (op == TD_KEY_GE_NEXT_MULTI),
507
- noBookmark, false);
549
+ noBookmark);
508
550
  if (req.result != 0)
509
551
  return ret;
510
552
  if (m_tb->stat() == 0)
@@ -543,30 +585,32 @@ inline int dbExecuter::doReadMulti(request& req, int op,
543
585
  extRequest* ereq = (extRequest*)req.data;
544
586
  bool incCurrent = (ereq->itype & FILTER_CURRENT_TYPE_INC) != 0;
545
587
  bool noBookmark = (ereq->itype & FILTER_CURRENT_TYPE_NOBOOKMARK) != 0;
588
+ bool execPrepared = (ereq->itype & FILTER_TYPE_SUPPLYVALUE) != 0;
546
589
 
547
590
  bool forword = (op == TD_KEY_NEXT_MULTI) || (op == TD_POS_NEXT_MULTI);
548
591
  if (op == TD_KEY_SEEK_MULTI)
549
592
  {
550
593
  char keynum = m_tb->keyNumByMakeOrder(req.keyNum);
551
594
  if (!m_tb->setKeyNum(keynum))
552
- {
553
- if (m_tb)
554
- m_tb->unUse();
555
595
  return ret;
556
- }
557
596
  }
558
597
  // smartReadRecordsHandler scope
559
598
  {
560
599
  smartReadRecordsHandler srrh(m_readHandler);
561
- req.result = m_readHandler->begin(m_tb, ereq, (op != TD_KEY_SEEK_MULTI),
562
- nw, forword, noBookmark,
563
- (op == TD_KEY_SEEK_MULTI));
564
- if (req.result != 0)
600
+ if (execPrepared)
565
601
  {
566
- if (m_tb)
567
- m_tb->unUse();
568
- return ret;
602
+ if (m_tb->preparedStatements.size() < ereq->preparedId)
603
+ req.result = STATUS_INVALID_PREPAREID;
604
+ else
605
+ req.result = m_readHandler->beginPreparExecute(m_tb, ereq, (op != TD_KEY_SEEK_MULTI),
606
+ nw, noBookmark,
607
+ (prepared*)m_tb->preparedStatements[ereq->preparedId - 1]);
569
608
  }
609
+ else
610
+ req.result = m_readHandler->begin(m_tb, ereq, (op != TD_KEY_SEEK_MULTI),
611
+ nw, forword, noBookmark);
612
+ if (req.result != 0)
613
+ return ret;
570
614
  if (op == TD_KEY_SEEK_MULTI)
571
615
  req.result =
572
616
  errorCodeSht(seekEach((extRequestSeeks*)req.data, noBookmark));
@@ -642,6 +686,10 @@ inline short dbExecuter::seekEach(extRequestSeeks* ereq, bool noBookmark)
642
686
  else
643
687
  seg = 0;
644
688
 
689
+ // Duplicate records need a bookmark.
690
+ if (seg && noBookmark)
691
+ return STATUS_INVALID_BOOKMARK;
692
+
645
693
  for (int i = 0; i < ereq->logicalCount; ++i)
646
694
  {
647
695
  m_tb->setKeyValuesPacked(fd->ptr, fd->len);
@@ -649,13 +697,18 @@ inline short dbExecuter::seekEach(extRequestSeeks* ereq, bool noBookmark)
649
697
  if (m_tb->stat() == 0)
650
698
  {
651
699
  if (seg)
700
+ {
701
+ // If duplicate records , bookmark space is request row number.
652
702
  stat = m_readHandler->write((uchar*)&i, 4);
703
+ }
704
+ else if (noBookmark)
705
+ stat = m_readHandler->write((const unsigned char *)_T("dummy"), 0);
653
706
  else
654
707
  stat =
655
708
  m_readHandler->write(m_tb->position(), m_tb->posPtrLen());
656
709
  }
657
710
  else
658
- stat = m_readHandler->write(NULL, m_tb->posPtrLen());
711
+ stat = m_readHandler->write(NULL, 0);
659
712
  if (stat)
660
713
  break;
661
714
 
@@ -682,9 +735,10 @@ inline short dbExecuter::seekEach(extRequestSeeks* ereq, bool noBookmark)
682
735
  return stat;
683
736
  }
684
737
 
685
- inline void dbExecuter::doStepRead(request& req, int op)
738
+ inline void dbExecuter::doStepRead(request& req, int op, engine::mysql::rowLockMode* lck)
686
739
  {
687
- m_tb = getTable(req.pbk->handle);
740
+ m_tb = getTable(req.pbk->handle, SQLCOM_SELECT, lck);
741
+ m_tb->setRowLock(lck);
688
742
  if (op == TD_POS_FIRST)
689
743
  m_tb->stepFirst();
690
744
  else if (op == TD_POS_LAST)
@@ -693,6 +747,8 @@ inline void dbExecuter::doStepRead(request& req, int op)
693
747
  m_tb->stepNext();
694
748
  else if (op == TD_POS_PREV)
695
749
  m_tb->stepPrev();
750
+ if (lck->lock && m_tb->stat())
751
+ m_tb->setRowLockError();
696
752
  readAfter(req, m_tb, this);
697
753
  }
698
754
 
@@ -859,10 +915,20 @@ inline void dbExecuter::doStat(request& req)
859
915
  req.result = STATUS_BUFFERTOOSMALL;
860
916
  }
861
917
 
918
+ inline enum_tx_isolation getIsolationLevel(int op)
919
+ {
920
+ if (op > CONSISTENT_READ)
921
+ return (enum_tx_isolation)0;
922
+ else if (op > TRN_ISO_SERIALIZABLE)
923
+ return ISO_SERIALIZABLE;
924
+ else if(op > TRN_ISO_REPEATABLE_READ)
925
+ return ISO_REPEATABLE_READ;
926
+ return ISO_READ_COMMITTED;
927
+ }
928
+
862
929
  inline short getTrnsactionType(int op)
863
930
  {
864
- if (op > PARALLEL_TRN) // 1000
865
- op -= PARALLEL_TRN;
931
+ op = op % 1000;
866
932
  if (op > NOWAIT_WRITE) // 500
867
933
  op -= NOWAIT_WRITE;
868
934
  if (op >= 300)
@@ -870,6 +936,20 @@ inline short getTrnsactionType(int op)
870
936
  return TRN_RECORD_LOCK_SINGLE;
871
937
  }
872
938
 
939
+ inline rowLockMode* getRowLockMode(int op, rowLockMode* lck)
940
+ {
941
+ lck->lock = false;
942
+ lck->read = (op > ROW_LOCK_S);
943
+ if (op > 1000)
944
+ op = op % 1000;
945
+ if (op < NOWAIT_WRITE)
946
+ {
947
+ if (op >= LOCK_SINGLE_NOWAIT && op < LOCK_MULTI_NOWAIT)
948
+ lck->lock = true;
949
+ }
950
+ return lck;
951
+ }
952
+
873
953
  int dbExecuter::commandExec(request& req, netsvc::server::netWriter* nw)
874
954
  {
875
955
  DEBUG_PROFILE_START(1)
@@ -947,16 +1027,25 @@ int dbExecuter::commandExec(request& req, netsvc::server::netWriter* nw)
947
1027
  case TD_KEY_OR_AFTER:
948
1028
  case TD_KEY_BEFORE:
949
1029
  case TD_KEY_OR_BEFORE:
950
- doSeekKey(req, op);
1030
+ {
1031
+ rowLockMode lck;
1032
+ doSeekKey(req, op, getRowLockMode(opTrn, &lck));
951
1033
  break;
1034
+ }
952
1035
  case TD_KEY_FIRST:
953
- doMoveFirst(req);
1036
+ {
1037
+ rowLockMode lck;
1038
+ doMoveFirst(req, getRowLockMode(opTrn, &lck));
954
1039
  break;
1040
+ }
955
1041
  case TD_KEY_PREV:
956
1042
  case TD_KEY_LAST:
957
1043
  case TD_KEY_NEXT:
958
- doMoveKey(req, op);
1044
+ {
1045
+ rowLockMode lck;
1046
+ doMoveKey(req, op, getRowLockMode(opTrn, &lck));
959
1047
  break;
1048
+ }
960
1049
  case TD_REC_INSERT:
961
1050
  doInsert(req);
962
1051
  break;
@@ -974,7 +1063,8 @@ int dbExecuter::commandExec(request& req, netsvc::server::netWriter* nw)
974
1063
  break;
975
1064
  case TD_BEGIN_TRANSACTION:
976
1065
  transactionResult =
977
- getDatabaseCid(req.cid)->beginTrn(getTrnsactionType(opTrn));
1066
+ getDatabaseCid(req.cid)->beginTrn(getTrnsactionType(opTrn)
1067
+ ,getIsolationLevel(opTrn));
978
1068
  break;
979
1069
  case TD_END_TRANSACTION:
980
1070
  transactionResult = getDatabaseCid(req.cid)->commitTrn();
@@ -983,7 +1073,7 @@ int dbExecuter::commandExec(request& req, netsvc::server::netWriter* nw)
983
1073
  transactionResult = getDatabaseCid(req.cid)->abortTrn();
984
1074
  break;
985
1075
  case TD_BEGIN_SHAPSHOT:
986
- transactionResult = getDatabaseCid(req.cid)->beginSnapshot();
1076
+ transactionResult = getDatabaseCid(req.cid)->beginSnapshot(getIsolationLevel(opTrn));
987
1077
  break;
988
1078
  case TD_END_SNAPSHOT:
989
1079
  transactionResult = getDatabaseCid(req.cid)->endSnapshot();
@@ -995,8 +1085,11 @@ int dbExecuter::commandExec(request& req, netsvc::server::netWriter* nw)
995
1085
  case TD_POS_LAST:
996
1086
  case TD_POS_NEXT:
997
1087
  case TD_POS_PREV:
998
- doStepRead(req, op);
1088
+ {
1089
+ rowLockMode lck;
1090
+ doStepRead(req, op, getRowLockMode(opTrn, &lck));
999
1091
  break;
1092
+ }
1000
1093
  case TD_BOOKMARK:
1001
1094
  m_tb = getTable(req.pbk->handle);
1002
1095
  req.paramMask = P_MASK_MOVPOS;
@@ -1004,11 +1097,18 @@ int dbExecuter::commandExec(request& req, netsvc::server::netWriter* nw)
1004
1097
  req.resultLen = m_tb->posPtrLen();
1005
1098
  break;
1006
1099
  case TD_MOVE_BOOKMARK:
1007
- m_tb = getTable(req.pbk->handle);
1100
+ {
1101
+ rowLockMode lck;
1102
+ getRowLockMode(opTrn, &lck);
1103
+ m_tb = getTable(req.pbk->handle, lck.lock ? SQLCOM_UPDATE : SQLCOM_SELECT);
1104
+ m_tb->setRowLock(&lck);
1008
1105
  m_tb->movePos((uchar*)req.data,
1009
1106
  m_tb->keyNumByMakeOrder(req.keyNum));
1107
+ if (lck.lock && m_tb->stat())
1108
+ m_tb->setRowLockError();
1010
1109
  readAfter(req, m_tb, this);
1011
1110
  break;
1111
+ }
1012
1112
  case TD_GETDIRECTORY:
1013
1113
  {
1014
1114
  database* db = getDatabaseCid(req.cid);
@@ -1071,7 +1171,10 @@ int dbExecuter::commandExec(request& req, netsvc::server::netWriter* nw)
1071
1171
  case TD_KEY_LE_PREV_MULTI:
1072
1172
  nw->setClientBuffferSize(*(req.datalen));
1073
1173
  if (doReadMultiWithSeek(req, op, nw) == EXECUTE_RESULT_SUCCESS)
1174
+ {
1175
+ m_tb = NULL;
1074
1176
  return EXECUTE_RESULT_SUCCESS;
1177
+ }
1075
1178
  break;
1076
1179
  case TD_KEY_SEEK_MULTI:
1077
1180
  case TD_KEY_NEXT_MULTI:
@@ -1080,7 +1183,35 @@ int dbExecuter::commandExec(request& req, netsvc::server::netWriter* nw)
1080
1183
  case TD_POS_PREV_MULTI:
1081
1184
  nw->setClientBuffferSize(*(req.datalen));
1082
1185
  if (doReadMulti(req, op, nw) == EXECUTE_RESULT_SUCCESS)
1186
+ {
1187
+ m_tb = NULL;
1083
1188
  return EXECUTE_RESULT_SUCCESS;
1189
+ }
1190
+ break;
1191
+ case TD_FILTER_PREPARE:
1192
+ m_tb = getTable(req.pbk->handle);
1193
+ if (m_tb->setKeyNum(m_tb->keyNumByMakeOrder(req.keyNum)))
1194
+ {
1195
+ prepared* prp = new prepared();
1196
+ m_tb->preparedStatements.push_back(prp);
1197
+ extRequest* ereq = (extRequest*)req.data;
1198
+ req.result = m_readHandler->prepare(
1199
+ m_tb,
1200
+ ereq,
1201
+ ((ereq->itype & FILTER_TYPE_SEEKS) == 0),
1202
+ nw,
1203
+ ((ereq->itype & FILTER_TYPE_FORWORD) != 0),
1204
+ ((ereq->itype & FILTER_CURRENT_TYPE_NOBOOKMARK) != 0),
1205
+ prp);
1206
+ if (req.result != 0)
1207
+ m_tb->preparedStatements.pop_back();
1208
+ else
1209
+ {
1210
+ req.paramMask = P_MASK_DATA | P_MASK_DATALEN;
1211
+ *((unsigned short*)req.data) = (unsigned short)m_tb->preparedStatements.size();
1212
+ req.resultLen = 2;
1213
+ }
1214
+ }
1084
1215
  break;
1085
1216
  case TD_MOVE_PER:
1086
1217
  m_tb = getTable(req.pbk->handle);
@@ -1102,10 +1233,13 @@ int dbExecuter::commandExec(request& req, netsvc::server::netWriter* nw)
1102
1233
  case TD_INSERT_BULK:
1103
1234
  doInsertBulk(req);
1104
1235
  break;
1236
+ case TD_UNLOCK:
1237
+ m_tb = getTable(req.pbk->handle);
1238
+ req.result = m_tb->unlock() ? STATUS_NO_CURRENT : 0;
1239
+ break;
1105
1240
  }
1106
1241
  if (m_tb)
1107
1242
  m_tb->unUse();
1108
-
1109
1243
  DEBUG_WRITELOG2(op, req)
1110
1244
  size = req.serialize(m_tb, resultBuffer);
1111
1245
  short dymmy = 0;
@@ -1114,6 +1248,7 @@ int dbExecuter::commandExec(request& req, netsvc::server::netWriter* nw)
1114
1248
  size = req.serializeBlobBody(m_blobBuffer, resultBuffer, size,
1115
1249
  FILE_MAP_SIZE, optionalData, dymmy);
1116
1250
 
1251
+ m_tb = NULL;
1117
1252
  if (transactionResult)
1118
1253
  {
1119
1254
  if ((op == TD_BEGIN_TRANSACTION) || (op == TD_BEGIN_SHAPSHOT))
@@ -1136,7 +1271,7 @@ int dbExecuter::commandExec(request& req, netsvc::server::netWriter* nw)
1136
1271
  req.result = 20000;
1137
1272
  sql_print_error("%s", boost::diagnostic_information(e).c_str());
1138
1273
  }
1139
- printErrorMessage(code, getMsg(e));
1274
+ printWarningMessage(code, getMsg(e));
1140
1275
  }
1141
1276
 
1142
1277
  catch (...)
@@ -1158,6 +1293,7 @@ int dbExecuter::commandExec(request& req, netsvc::server::netWriter* nw)
1158
1293
  DEBUG_WRITELOG3(op, req, true);
1159
1294
  req.paramMask = 0;
1160
1295
  size = req.serialize(NULL, resultBuffer);
1296
+ m_tb = NULL;
1161
1297
  return EXECUTE_RESULT_SUCCESS;
1162
1298
  }
1163
1299