transactd 1.1.2 → 1.2.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 (73) hide show
  1. checksums.yaml +4 -4
  2. data/CMakeLists.txt +37 -4
  3. data/bin/common/tdclc_32_1_2.dll +0 -0
  4. data/bin/common/tdclc_64_1_2.dll +0 -0
  5. data/build/common/transactd_cl_common.cmake +0 -1
  6. data/build/common/transactd_common.cmake +26 -6
  7. data/build/swig/php/generate.cmake.in +58 -0
  8. data/build/swig/php/generate.cmd.in +41 -0
  9. data/build/swig/php/php.swg +155 -0
  10. data/build/swig/ruby/ruby.swg +38 -0
  11. data/build/swig/tdcl.i +133 -3
  12. data/build/tdclc/CMakeLists.txt +4 -1
  13. data/build/tdclc/tdclc_32.cbproj +1 -1
  14. data/build/tdclc/tdclc_64.cbproj +1 -1
  15. data/build/tdclcpp/CMakeLists.txt +1 -1
  16. data/build/tdclcpp/tdclcpp_bcb_32.cbproj +1 -4
  17. data/build/tdclcpp/tdclcpp_bcb_64.cbproj +0 -3
  18. data/build/tdclrb/CMakeLists.txt +1 -1
  19. data/build/tdclrb/GEM_VERSION +2 -2
  20. data/source/bzs/db/engine/mysql/IReadRecords.h +1 -1
  21. data/source/bzs/db/engine/mysql/bookmark.h +3 -3
  22. data/source/bzs/db/engine/mysql/database.cpp +95 -19
  23. data/source/bzs/db/engine/mysql/database.h +6 -6
  24. data/source/bzs/db/engine/mysql/mysqlInternal.h +43 -1
  25. data/source/bzs/db/engine/mysql/mysqlThd.cpp +10 -8
  26. data/source/bzs/db/protocol/hs/hsCommandExecuter.cpp +1 -1
  27. data/source/bzs/db/protocol/tdap/btrDate.h +2 -2
  28. data/source/bzs/db/protocol/tdap/client/dbDef.cpp +15 -8
  29. data/source/bzs/db/protocol/tdap/client/dbDef.h +2 -2
  30. data/source/bzs/db/protocol/tdap/client/dllmain.cpp +4 -0
  31. data/source/bzs/db/protocol/tdap/client/fieldDDF.cpp +0 -5
  32. data/source/bzs/db/protocol/tdap/client/fileDDF.cpp +0 -4
  33. data/source/bzs/db/protocol/tdap/client/filter.cpp +0 -484
  34. data/source/bzs/db/protocol/tdap/client/filter.h +696 -84
  35. data/source/bzs/db/protocol/tdap/client/nsTable.cpp +13 -3
  36. data/source/bzs/db/protocol/tdap/client/nsTable.h +12 -6
  37. data/source/bzs/db/protocol/tdap/client/sqlBuilder.cpp +2 -1
  38. data/source/bzs/db/protocol/tdap/client/stringConverter.h +1 -0
  39. data/source/bzs/db/protocol/tdap/client/table.cpp +519 -75
  40. data/source/bzs/db/protocol/tdap/client/table.h +49 -7
  41. data/source/bzs/db/protocol/tdap/client/trdboostapi.h +145 -124
  42. data/source/bzs/db/protocol/tdap/client/trdboostapiInternal.h +39 -0
  43. data/source/bzs/db/protocol/tdap/client/trdormapi.h +872 -0
  44. data/source/bzs/db/protocol/tdap/myDateTime.cpp +8 -8
  45. data/source/bzs/db/protocol/tdap/mysql/databaseSchema.cpp +7 -9
  46. data/source/bzs/db/protocol/tdap/mysql/recordsetReader.h +406 -195
  47. data/source/bzs/db/protocol/tdap/mysql/tdapCommandExecuter.cpp +64 -13
  48. data/source/bzs/db/protocol/tdap/mysql/tdapCommandExecuter.h +2 -1
  49. data/source/bzs/db/protocol/tdap/tdapSchema.cpp +35 -3
  50. data/source/bzs/db/protocol/tdap/tdapSchema.h +11 -3
  51. data/source/bzs/db/protocol/tdap/tdapcapi.h +63 -53
  52. data/source/bzs/env/crosscompile.h +8 -3
  53. data/source/bzs/example/connection_pool_c.cpp +1 -7
  54. data/source/bzs/example/useORM.cpp +585 -0
  55. data/source/bzs/rtl/exception.h +6 -0
  56. data/source/bzs/test/tdclatl/bench_tdclatl.js +12 -7
  57. data/source/bzs/test/tdclphp/transactd_Test.php +1845 -0
  58. data/source/bzs/test/tdclphp/transactd_blob_Test.php +325 -0
  59. data/source/bzs/test/tdclphp/transactd_datetime_Test.php +183 -0
  60. data/source/bzs/test/tdclphp/transactd_kanjischema_Test.php +212 -0
  61. data/source/bzs/test/tdclrb/transactd_blob_spec.rb +332 -0
  62. data/source/bzs/test/tdclrb/transactd_spec.rb +256 -1
  63. data/source/bzs/test/trdclengn/test_blob.cpp +327 -0
  64. data/source/bzs/test/trdclengn/test_trdclengn.cpp +485 -5
  65. data/source/global/tdclatl/QueryBase.cpp +231 -0
  66. data/source/global/tdclatl/QueryBase.h +96 -0
  67. data/source/global/tdclatl/Table.cpp +24 -0
  68. data/source/global/tdclatl/Table.h +2 -1
  69. data/source/global/tdclatl/resource.h +0 -0
  70. data/source/global/tdclatl/tdclatl.idl +88 -2
  71. metadata +16 -3
  72. data/bin/common/tdclc_32_1_1.dll +0 -0
  73. data/bin/common/tdclc_64_1_1.dll +0 -0
@@ -64,9 +64,6 @@ namespace client
64
64
  #define EXEC_CODEPAGE CP_UTF8
65
65
  #endif
66
66
 
67
- #define BOOKMARK_ALLOC_SIZE 40960
68
- #define BOOKMARK_SIZE 4
69
- #define DATASIZE_BYTE 2
70
67
 
71
68
  class CFiledNameIndex
72
69
  {
@@ -162,6 +159,7 @@ class recordCache
162
159
  char* m_ptr;
163
160
  char* m_tmpPtr;
164
161
  blobHeader* m_hd;
162
+ short_td m_seekMultiStat;
165
163
 
166
164
  public:
167
165
  inline recordCache(table* tb) : m_tb(tb) {reset();}
@@ -199,18 +197,34 @@ public:
199
197
  m_ptr += DATASIZE_BYTE;
200
198
  m_bookmark = *((bookmark_td*)(m_ptr));
201
199
  m_ptr += BOOKMARK_SIZE;
202
-
203
- if (m_hd)
200
+ }
201
+ if (m_hd)
202
+ {
203
+ //blob pointer is allready point to next row
204
+ while (m_row - m_hd->curRow)
204
205
  {
205
- m_hd->nextField = (blobField*)m_hd->nextField->next();
206
+ for(int j=0;j<m_hd->fieldCount;++j)
207
+ m_hd->nextField = (blobField*)m_hd->nextField->next();
206
208
  ++m_hd->curRow;
207
209
  }
208
210
  }
211
+
209
212
  m_tb->m_impl->strBufs.clear();
213
+
214
+ if ((m_len==0) && m_pFilter->isSeeksMode() && m_pFilter->fieldCount())
215
+ {
216
+ /*seek error*/
217
+ m_seekMultiStat = m_bookmark;
218
+ m_bookmark = 0;
219
+ memset(m_tmpPtr, 0, m_tb->tableDef()->maxRecordLen);
220
+ return m_tmpPtr;
221
+ }else
222
+ m_seekMultiStat = 0;
223
+
210
224
  if (m_pFilter->fieldSelected())
211
225
  {
212
226
  int offset = 0;
213
- memset(m_tmpPtr, 0, m_len);
227
+ memset(m_tmpPtr, 0, m_tb->tableDef()->maxRecordLen);
214
228
  for (int i = 0; i < m_pFilter->fieldCount(); i++)
215
229
  {
216
230
  memcpy((char*)m_tmpPtr + m_pFilter->fieldOffset(i), m_ptr + offset,
@@ -222,6 +236,7 @@ public:
222
236
  }
223
237
  else if (m_tb->valiableFormatType())
224
238
  {
239
+ memset(m_tmpPtr, 0, m_tb->tableDef()->maxRecordLen);
225
240
  memcpy(m_tmpPtr, m_ptr, m_len);
226
241
  m_unpackLen = m_tb->unPack((char*)m_tmpPtr, m_len);
227
242
  m_tb->setBlobFieldPointer(m_tmpPtr, m_hd);
@@ -252,6 +267,7 @@ public:
252
267
  inline int rowCount() const {return m_rowCount;}
253
268
  inline bool isEndOfRow(unsigned int row) const {return (m_rowCount && (row == m_rowCount));}
254
269
  inline bool withinCache(unsigned int row) const {return (row < m_rowCount);}
270
+ inline short_td seekMultiStat(){return m_seekMultiStat;}
255
271
  };
256
272
 
257
273
  // ---------------------------------------------------------------------------
@@ -286,6 +302,7 @@ inline __int64 getValue64(const fielddef& fd, const uchar_td* ptr)
286
302
  case 8: ret = *((__int64*)(ptr + fd.pos));
287
303
  break;
288
304
  }
305
+ case ft_autoIncUnsigned:
289
306
  case ft_uinteger:
290
307
  case ft_logical:
291
308
  case ft_bit:
@@ -332,10 +349,11 @@ inline void setValue(const fielddef& fd, uchar_td* ptr, __int64 value)
332
349
  break;
333
350
  case 4: *((int*)(ptr + fd.pos)) = (int)value;
334
351
  break;
335
- case 8: *((__int64*)(ptr + fd.pos)) = (int)value;
352
+ case 8: *((__int64*)(ptr + fd.pos)) = value;
336
353
  break;
337
354
  }
338
355
  }
356
+ case ft_autoIncUnsigned:
339
357
  case ft_uinteger:
340
358
  case ft_logical:
341
359
  case ft_bit:
@@ -346,7 +364,8 @@ inline void setValue(const fielddef& fd, uchar_td* ptr, __int64 value)
346
364
  case ft_mytime:
347
365
  case ft_mydate:
348
366
  case ft_mydatetime:
349
- case ft_mytimestamp: memcpy(ptr + fd.pos, &value, fd.len);
367
+ case ft_mytimestamp:
368
+ memcpy(ptr + fd.pos, &value, fd.len);
350
369
  break;
351
370
  }
352
371
  }
@@ -431,57 +450,51 @@ inline short calcNextReadRecordCount(ushort_td curCount, int eTime)
431
450
  else
432
451
  ret = (ushort_td)(curCount * ((float)100 / (float)eTime));
433
452
 
434
- if (ret > 10000)
435
- return 10000;
453
+ if (ret > 9500)
454
+ return 9500;
436
455
  if (ret == 0)
437
456
  return 1;
438
457
  return ret;
439
458
  }
440
459
 
441
- uint_td table::doRecordCount(bool estimate, bool fromCurrent)
460
+ uint_td table::doRecordCount(bool estimate, bool fromCurrent, eFindType direction)
442
461
  {
443
462
  uint_td result = 0;
444
463
 
445
464
  if (m_impl->filterPtr)
446
465
  {
466
+ short_td op = (direction == findForword) ? TD_KEY_NEXT_MULTI:TD_KEY_PREV_MULTI;
467
+
468
+ if (tableDef()->keyCount == 0)
469
+ op += TD_POS_NEXT_MULTI - TD_KEY_NEXT_MULTI;// KEY to POS
447
470
  short curStat = m_stat;
448
471
  m_impl->exBookMarking = true;
449
- ushort_td recCountOnce = 50;
472
+ ushort_td recCountOnce = 100;
450
473
 
451
474
  bookmark_td bm = bookmark();
452
- ushort_td tmpFieldCount = m_impl->filterPtr->fieldCount();
475
+
453
476
  ushort_td tmpRejectCount = m_impl->filterPtr->rejectCount();
454
477
  ushort_td tmpRecCount = m_impl->filterPtr->recordCount();
455
- _TCHAR* str = new _TCHAR[_tcslen(filterStr()) + 1];
456
- if (str)
457
- {
458
- _tcscpy(str, filterStr());
459
- m_impl->filterPtr->setFieldCount(0);
460
- m_stat = 0;
461
- m_impl->filterPtr->setFilter(str, tmpRejectCount, 10000);
462
- if (m_stat != 0)
463
- {
464
- // restore filter string
465
- m_impl->filterPtr->setFieldCount(tmpFieldCount);
466
- m_impl->filterPtr->setFilter(str, tmpRejectCount, tmpRecCount);
467
- delete[]str;
468
- str = NULL;
469
- }
470
- }
471
- else
472
- assert(0);
478
+
479
+ m_impl->filterPtr->setIgnoreFields(true);
473
480
  m_impl->maxBookMarkedCount = 0;
474
481
  if (fromCurrent)
475
482
  m_stat = curStat;
476
- else
483
+ else if (op == TD_KEY_NEXT_MULTI)
477
484
  seekFirst();
478
-
479
- *(m_impl->filterPtr->recordCountDirect()) = recCountOnce;
485
+ else if (op == TD_KEY_PREV_MULTI)
486
+ seekLast();
487
+ else if (op == TD_POS_NEXT_MULTI)
488
+ stepFirst();
489
+ else if (op == TD_POS_PREV_MULTI)
490
+ stepLast();
491
+
492
+ m_impl->filterPtr->setMaxRows(recCountOnce);
480
493
  if (m_stat == 0)
481
494
  {
482
495
  m_impl->filterPtr->setPosTypeNext(false);
483
496
  boost::timer t;
484
- btrvGetExtend(TD_KEY_NEXT_MULTI);
497
+ btrvGetExtend(op);
485
498
  int eTime = (int)(t.elapsed() * 1000);
486
499
  while ((m_stat == 0) || (m_stat == STATUS_LIMMIT_OF_REJECT) || (m_stat == STATUS_EOF)
487
500
  || (m_stat == STATUS_REACHED_FILTER_COND))
@@ -502,35 +515,34 @@ uint_td table::doRecordCount(bool estimate, bool fromCurrent)
502
515
  }
503
516
  }
504
517
  recCountOnce = calcNextReadRecordCount(recCountOnce, eTime);
505
-
506
- *(m_impl->filterPtr->recordCountDirect()) = recCountOnce;
518
+ m_impl->filterPtr->setMaxRows(recCountOnce);
507
519
  result += *((ushort_td*)m_impl->dataBak);
508
520
  setBookMarks(m_impl->maxBookMarkedCount + 1, (void*)((char*)m_impl->dataBak + 2),
509
521
  *((ushort_td*)m_impl->dataBak));
510
522
  m_impl->maxBookMarkedCount = result;
511
-
512
523
  onRecordCounting(result, Complete);
513
524
  if (Complete)
514
525
  break;
515
526
  t.restart();
516
527
  m_impl->filterPtr->setPosTypeNext(true);
517
- btrvGetExtend(TD_KEY_NEXT_MULTI);
528
+ btrvGetExtend(op);
518
529
  eTime = (int)(t.elapsed() * 1000);
519
530
  }
520
531
  }
532
+
521
533
  short tmpStat = m_stat;
522
- if (str)
523
- {
524
- setFilter(str, tmpRejectCount, tmpRecCount);
525
- delete[]str;
526
- }
534
+ m_impl->filterPtr->setIgnoreFields(false);
535
+ m_impl->filterPtr->setMaxRows(tmpRecCount);
536
+
527
537
  if (bm)
528
538
  seekByBookmark(bm);
529
539
  m_impl->exBookMarking = false;
530
540
  m_stat = tmpStat;
541
+ if (m_stat == STATUS_EOF)
542
+ m_stat = 0;
531
543
  }
532
544
  else
533
- return nstable::doRecordCount(estimate, fromCurrent);
545
+ return nstable::doRecordCount(estimate, fromCurrent, direction);
534
546
 
535
547
  return result;
536
548
  }
@@ -540,11 +552,26 @@ void table::btrvGetExtend(ushort_td op)
540
552
 
541
553
  if (op >= TD_KEY_GE_NEXT_MULTI)
542
554
  m_keylen = writeKeyData();
555
+
543
556
  m_pdata = m_impl->dataBak;
544
- m_impl->filterPtr->WriteBuffer();
557
+ if (!m_impl->filterPtr->writeBuffer())
558
+ {
559
+ m_stat = STATUS_WARKSPACE_TOO_SMALL;
560
+ return;
561
+ }
545
562
  m_datalen = m_impl->filterPtr->exDataBufLen();
563
+
564
+ //cacheing direction
565
+ if ((op == TD_KEY_LE_PREV_MULTI) || (op == TD_KEY_PREV_MULTI)|| (op == TD_POS_PREV_MULTI))
566
+ m_impl->filterPtr->setDirection(findBackForword);
567
+ else
568
+ m_impl->filterPtr->setDirection(findForword);
569
+
546
570
  tdap(op);
547
571
  short stat = m_stat;
572
+ if (!m_impl->filterPtr->isWriteComleted() && (stat == STATUS_REACHED_FILTER_COND))
573
+ stat = STATUS_LIMMIT_OF_REJECT;
574
+
548
575
  m_impl->rc->reset(m_impl->filterPtr, (char*)m_impl->dataBak, m_datalen, blobFieldUsed() ?
549
576
  getBlobHeader() : NULL);
550
577
 
@@ -554,13 +581,11 @@ void table::btrvGetExtend(ushort_td op)
554
581
  if (m_impl->rc->rowCount() && (!m_impl->exBookMarking))
555
582
  {
556
583
  m_pdata = (void*)m_impl->rc->setRow(0);
557
- m_datalen = m_impl->rc->len();
584
+ m_datalen = tableDef()->maxRecordLen;//m_impl->rc->len();
558
585
 
559
- m_stat = STATUS_SUCCESS;
586
+ m_stat = m_impl->rc->seekMultiStat();
560
587
  }else if ((m_stat == STATUS_LIMMIT_OF_REJECT) && (m_impl->filterPtr->rejectCount()>=1))
561
588
  m_stat = STATUS_EOF;
562
-
563
-
564
589
  }
565
590
 
566
591
  void table::getRecords(ushort_td op)
@@ -586,24 +611,40 @@ bookmark_td table::bookmarkFindCurrent() const
586
611
 
587
612
  void table::find(eFindType type)
588
613
  {
614
+ ushort_td op;
615
+
616
+ if (m_impl->filterPtr->isSeeksMode())
617
+ {
618
+ m_impl->filterPtr->resetSeeksWrited();
619
+ op = TD_KEY_SEEK_MULTI;
620
+ }
621
+ else
622
+ op = (type == findForword) ? TD_KEY_GE_NEXT_MULTI:TD_KEY_LE_PREV_MULTI;
623
+
589
624
  if (nsdb()->isUseTransactd())
590
625
  {
591
626
  m_impl->rc->reset();
592
- ushort_td op = (type == findForword) ? TD_KEY_GE_NEXT_MULTI:TD_KEY_LE_PREV_MULTI;
593
627
  doFind(op, true/*notIncCurrent*/);
594
628
  }
595
629
  else
596
630
  {
631
+
632
+ if (op == TD_KEY_SEEK_MULTI)
633
+ {
634
+ //P.SQL not support TD_KEY_SEEK_MULTI
635
+ m_stat = STATUS_FILTERSTRING_ERROR;
636
+ return;
637
+ }
597
638
  if (type == findForword)
598
- seekGreater(true);
639
+ seekGreater(false);
599
640
  else
600
- seekLessThan(true);
641
+ seekLessThan(false);
601
642
  if (m_stat == 0)
602
643
  {
603
644
  if (type == findForword)
604
- findNext(true);
645
+ findNext(false);
605
646
  else
606
- findPrev(true);
647
+ findPrev(false);
607
648
  }
608
649
  }
609
650
 
@@ -617,6 +658,7 @@ void table::findFirst()
617
658
  {
618
659
  if (m_impl->filterPtr)
619
660
  {
661
+
620
662
  m_impl->exNext = 1;
621
663
  m_impl->filterPtr->setPosTypeNext(false);
622
664
  getRecords(TD_KEY_NEXT_MULTI);
@@ -631,6 +673,7 @@ void table::findLast()
631
673
  {
632
674
  if (m_impl->filterPtr)
633
675
  {
676
+
634
677
  m_impl->exNext = -1;
635
678
  m_impl->filterPtr->setPosTypeNext(false);
636
679
  getRecords(TD_KEY_PREV_MULTI);
@@ -638,6 +681,21 @@ void table::findLast()
638
681
  }
639
682
  }
640
683
 
684
+ bool table::checkFindDirection(ushort_td op)
685
+ {
686
+ bool ret ;
687
+ if ((op == TD_KEY_LE_PREV_MULTI) || (op == TD_KEY_PREV_MULTI))
688
+ ret = (m_impl->filterPtr->direction() == findBackForword);
689
+ else
690
+ ret = (m_impl->filterPtr->direction() == findForword);
691
+ if (!ret)
692
+ {
693
+ assert(0);
694
+ m_stat = 1;
695
+ }
696
+ return ret;
697
+ }
698
+
641
699
  void table::doFind( ushort_td op, bool notIncCurrent)
642
700
  {
643
701
  /*
@@ -650,12 +708,27 @@ void table::doFind( ushort_td op, bool notIncCurrent)
650
708
 
651
709
  if (m_impl->rc->withinCache(row) && (!m_impl->exBookMarking))
652
710
  { /* read from cache */
711
+
712
+ /*Is direction same */
713
+ if (!checkFindDirection(op))
714
+ return ;
715
+
653
716
  m_pdata = (void*)m_impl->rc->setRow(row);
654
- m_datalen = m_impl->rc->len();
717
+ m_stat = m_impl->rc->seekMultiStat();
718
+
719
+ /*set keyvalue for keyValueDescription*/
720
+ if (m_stat != 0)
721
+ setSeekValueField(row);
722
+
723
+ //m_datalen = m_impl->rc->len();
724
+ m_datalen = tableDef()->maxRecordLen;
655
725
  }
656
726
  else if (m_impl->rc->isEndOfRow(row))
657
727
  {
658
728
  /* whole row readed */
729
+ /*Is direction same */
730
+ if (!checkFindDirection(op))
731
+ return ;
659
732
  /* A special situation that if rejectCount() == 0 and status = STATUS_LIMMIT_OF_REJECT
660
733
  then it continues . */
661
734
  if ((m_impl->exSlideStat == 0)
@@ -685,7 +758,11 @@ void table::findNext(bool notIncCurrent)
685
758
  {
686
759
 
687
760
  if (m_impl->filterPtr)
688
- doFind(TD_KEY_NEXT_MULTI, notIncCurrent);
761
+ {
762
+ short op = m_impl->filterPtr->isSeeksMode() ? TD_KEY_SEEK_MULTI
763
+ : TD_KEY_NEXT_MULTI;
764
+ doFind(op, notIncCurrent);
765
+ }
689
766
  else if (notIncCurrent == true)
690
767
  seekNext();
691
768
  }
@@ -699,7 +776,7 @@ void table::findPrev(bool notIncCurrent)
699
776
 
700
777
  }
701
778
 
702
- void table::setFilter(const _TCHAR* str, ushort_td RejectCount, ushort_td CashCount)
779
+ void table::setQuery(const queryBase* query)
703
780
  {
704
781
 
705
782
  m_stat = 0;
@@ -708,7 +785,7 @@ void table::setFilter(const _TCHAR* str, ushort_td RejectCount, ushort_td CashCo
708
785
  m_impl->exBookMarking = false;
709
786
  m_impl->exSlideStat = 0;
710
787
  m_impl->exNext = 0;
711
- if (str[0] == 0x00)
788
+ if (query == NULL)
712
789
  {
713
790
  m_impl->maxBookMarkedCount = 0;
714
791
  delete m_impl->filterPtr;
@@ -725,7 +802,8 @@ void table::setFilter(const _TCHAR* str, ushort_td RejectCount, ushort_td CashCo
725
802
  return;
726
803
 
727
804
  }
728
- if (!m_impl->filterPtr->setFilter(str, RejectCount, CashCount))
805
+
806
+ if (!m_impl->filterPtr->setQuery(query))
729
807
  {
730
808
  m_stat = STATUS_FILTERSTRING_ERROR;
731
809
  delete m_impl->filterPtr;
@@ -734,9 +812,9 @@ void table::setFilter(const _TCHAR* str, ushort_td RejectCount, ushort_td CashCo
734
812
  }
735
813
  if (!m_impl->bookMarks)
736
814
  {
737
- m_impl->bookMarks = malloc(40960);
815
+ m_impl->bookMarks = malloc(BOOKMARK_ALLOC_SIZE);
738
816
  if (m_impl->bookMarks)
739
- m_impl->bookMarksMemSize = 40960;
817
+ m_impl->bookMarksMemSize = BOOKMARK_ALLOC_SIZE;
740
818
  else
741
819
  {
742
820
  m_stat = STATUS_FILTERSTRING_ERROR;
@@ -746,6 +824,19 @@ void table::setFilter(const _TCHAR* str, ushort_td RejectCount, ushort_td CashCo
746
824
  }
747
825
  }
748
826
 
827
+ void table::setFilter(const _TCHAR* str, ushort_td RejectCount, ushort_td CashCount)
828
+ {
829
+ if (!str || (str[0] == 0x00))
830
+ setQuery(NULL);
831
+ else
832
+ {
833
+ queryBase q;
834
+ q.queryString(str).reject(RejectCount).limit(CashCount);
835
+ setQuery(&q);
836
+ }
837
+
838
+ }
839
+
749
840
  const _TCHAR* table::filterStr()
750
841
  {
751
842
  if (m_impl->filterPtr)
@@ -756,8 +847,10 @@ const _TCHAR* table::filterStr()
756
847
 
757
848
  void table::clearBuffer()
758
849
  {
850
+ m_impl->rc->reset();
851
+ m_pdata = m_impl->dataBak;
759
852
  memset(m_pdata, 0x00, m_buflen);
760
- if (blobFieldUsed())
853
+ if ((bulkIns()==NULL) && blobFieldUsed())
761
854
  resetSendBlob();
762
855
 
763
856
  }
@@ -867,7 +960,8 @@ bool table::onUpdateCheck(eUpdateType type)
867
960
  void table::onUpdateAfter(int beforeResult)
868
961
  {
869
962
  if (blobFieldUsed())
870
- resetSendBlob();
963
+ addSendBlob(NULL);
964
+
871
965
  if (valiableFormatType() && m_impl->dataPacked)
872
966
  m_datalen = unPack((char*)m_pdata, m_datalen);
873
967
 
@@ -892,16 +986,23 @@ ushort_td table::doCommitBulkInsert(bool autoCommit)
892
986
  {
893
987
  ushort_td ret = nstable::doCommitBulkInsert(autoCommit);
894
988
  if (blobFieldUsed())
895
- resetSendBlob();
989
+ addSendBlob(NULL);
896
990
  return ret;
897
991
  }
898
992
 
993
+ void table::doAbortBulkInsert()
994
+ {
995
+ nstable::doAbortBulkInsert();
996
+ if (blobFieldUsed())
997
+ addSendBlob(NULL);
998
+ }
999
+
899
1000
  void table::onInsertAfter(int beforeResult)
900
1001
  {
901
1002
  if (valiableFormatType() && m_impl->dataPacked)
902
1003
  m_datalen = unPack((char*)m_pdata, m_datalen);
903
- if (blobFieldUsed())
904
- resetSendBlob();
1004
+ if ((bulkIns()==NULL) && blobFieldUsed())
1005
+ addSendBlob(NULL);
905
1006
  }
906
1007
 
907
1008
  void* table::attachBuffer(void* NewPtr, bool unpack, size_t size)
@@ -1119,9 +1220,11 @@ void table::resetSendBlob()
1119
1220
  void table::addSendBlob(const blob* blob)
1120
1221
  {
1121
1222
  short stat = m_stat;
1223
+ /*backup current data buffer*/
1122
1224
  const void *tmp = data();
1123
1225
  setData((void*)blob);
1124
1226
  tdap(TD_ADD_SENDBLOB);
1227
+ /*restore data buffer*/
1125
1228
  setData((void*)tmp);
1126
1229
  m_stat = stat;
1127
1230
  }
@@ -1130,9 +1233,11 @@ const blobHeader* table::getBlobHeader()
1130
1233
  {
1131
1234
  short stat = m_stat;
1132
1235
  const blobHeader* p;
1236
+ /*backup current data buffer*/
1133
1237
  const void *tmp = data();
1134
1238
  setData(&p);
1135
1239
  tdap(TD_GET_BLOB_BUF);
1240
+ /*restore data buffer*/
1136
1241
  setData((void*)tmp);
1137
1242
  std::swap(stat, m_stat);
1138
1243
 
@@ -1171,7 +1276,7 @@ void table::onReadAfter()
1171
1276
  {
1172
1277
  m_datalen = unPack((char*)m_pdata, m_datalen);
1173
1278
  if (m_datalen == 0)
1174
- m_stat = 22;
1279
+ m_stat = STATUS_BUFFERTOOSMALL;
1175
1280
  }
1176
1281
  if (blobFieldUsed())
1177
1282
  {
@@ -1276,6 +1381,7 @@ void table::setFVA(short index, const char* data)
1276
1381
  case ft_time: // time hh:nn:ss
1277
1382
  value = /*StrToBtrTime*/atobtrt((const char*)data).i;
1278
1383
  break;
1384
+ case ft_autoIncUnsigned:
1279
1385
  case ft_uinteger:
1280
1386
  case ft_integer:
1281
1387
  case ft_autoinc:
@@ -1375,6 +1481,7 @@ void table::setFVW(short index, const wchar_t* data)
1375
1481
  setFV(index, value);
1376
1482
  return;
1377
1483
 
1484
+ case ft_autoIncUnsigned:
1378
1485
  case ft_uinteger:
1379
1486
  case ft_integer:
1380
1487
  case ft_autoinc:
@@ -1485,6 +1592,7 @@ void table::setFV(short index, int data)
1485
1592
  case ft_integer:
1486
1593
  case ft_date:
1487
1594
  case ft_time:
1595
+ case ft_autoIncUnsigned:
1488
1596
  case ft_uinteger:
1489
1597
  case ft_logical:
1490
1598
  case ft_autoinc:
@@ -1593,6 +1701,7 @@ void table::setFV(short index, double data)
1593
1701
  case ft_integer:
1594
1702
  case ft_date:
1595
1703
  case ft_time:
1704
+ case ft_autoIncUnsigned:
1596
1705
  case ft_uinteger:
1597
1706
  case ft_logical:
1598
1707
  case ft_autoinc:
@@ -1684,6 +1793,7 @@ int table::getFVlng(short index)
1684
1793
  break;
1685
1794
  }
1686
1795
  break;
1796
+ case ft_autoIncUnsigned:
1687
1797
  case ft_uinteger:
1688
1798
  case ft_logical:
1689
1799
  case ft_bit:
@@ -1794,6 +1904,7 @@ double table::getFVdbl(short index)
1794
1904
  case ft_integer:
1795
1905
  case ft_date:
1796
1906
  case ft_time:
1907
+ case ft_autoIncUnsigned:
1797
1908
  case ft_uinteger:
1798
1909
  case ft_logical:
1799
1910
  case ft_autoinc:
@@ -1903,7 +2014,9 @@ const wchar_t* table::getFVWstr(short index)
1903
2014
  }
1904
2015
  break;
1905
2016
  }
1906
- case ft_uinteger: swprintf_s(p, 50, L"%u", getFVlng(index));
2017
+ case ft_autoIncUnsigned:
2018
+ case ft_uinteger:
2019
+ swprintf_s(p, 50, L"%lu", getFV64(index));
1907
2020
  break;
1908
2021
  case ft_date: return btrdtoa(getFVlng(index), p);
1909
2022
  case ft_time: return btrttoa(getFVlng(index), p);
@@ -2038,7 +2151,9 @@ const char* table::getFVAstr(short index)
2038
2151
  }
2039
2152
  case ft_date: return btrdtoa(getFVlng(index), p);
2040
2153
  case ft_time: return btrttoa(getFVlng(index), p);
2041
- case ft_uinteger: sprintf(p, "%u", getFVlng(index));
2154
+ case ft_autoIncUnsigned:
2155
+ case ft_uinteger:
2156
+ sprintf_s(p, 50, "%lu", getFV64(index));
2042
2157
  break;
2043
2158
 
2044
2159
  case ft_mydate:
@@ -2185,6 +2300,7 @@ __int64 table::getFV64(short index)
2185
2300
  case 8:
2186
2301
  switch (fd.type)
2187
2302
  {
2303
+ case ft_autoIncUnsigned:
2188
2304
  case ft_uinteger:
2189
2305
  case ft_integer:
2190
2306
  case ft_logical:
@@ -2229,6 +2345,7 @@ void table::setFV(short index, __int64 data)
2229
2345
  case 8:
2230
2346
  switch (fd.type)
2231
2347
  {
2348
+ case ft_autoIncUnsigned:
2232
2349
  case ft_uinteger:
2233
2350
  case ft_integer:
2234
2351
  case ft_logical:
@@ -2578,10 +2695,6 @@ unsigned int table::getRecordHash()
2578
2695
  return hash((const char*)fieldPtr(0), datalen());
2579
2696
  }
2580
2697
 
2581
-
2582
-
2583
-
2584
-
2585
2698
  int table::bookMarksCount() const
2586
2699
  {
2587
2700
  int ret;
@@ -2604,6 +2717,337 @@ short_td table::doBtrvErr(HWND hWnd, _TCHAR* retbuf)
2604
2717
  return nstable::tdapErr(hWnd, m_stat, m_tableDef->tableName(), retbuf);
2605
2718
  }
2606
2719
 
2720
+ /* For keyValueDescription */
2721
+ bool table::setSeekValueField(int row)
2722
+ {
2723
+ const std::vector<std::_tstring>& keyValues = m_impl->filterPtr->keyValuesCache();
2724
+ keydef* kd = &tableDef()->keyDefs[keyNum()];
2725
+ if (keyValues.size() % kd->segmentCount)
2726
+ return false;
2727
+ //Check uniqe key
2728
+ if (kd->segments[0].flags.bit0)
2729
+ return false;
2730
+
2731
+ size_t pos = kd->segmentCount * row;
2732
+ for (int j=0;j<kd->segmentCount;++j)
2733
+ setFV(kd->segments[j].fieldNum, keyValues[pos+j].c_str());
2734
+ return true;
2735
+ }
2736
+
2737
+ void table::keyValueDescription(_TCHAR* buf, int bufsize)
2738
+ {
2739
+
2740
+ std::_tstring s;
2741
+ if (stat() == STATUS_NOT_FOUND_TI)
2742
+ {
2743
+
2744
+ for (int i=0;i<tableDef()->keyDefs[keyNum()].segmentCount;i++)
2745
+ {
2746
+ short fnum = tableDef()->keyDefs[keyNum()].segments[i].fieldNum;
2747
+ s += std::_tstring(tableDef()->fieldDefs[fnum].name())
2748
+ + _T(" = ") + getFVstr(fnum) + _T("\n");
2749
+ }
2750
+ }
2751
+ else if (stat() == STATUS_DUPPLICATE_KEYVALUE)
2752
+ {
2753
+ _TCHAR tmp[50];
2754
+ for (int j=0;j<tableDef()->keyCount;j++)
2755
+ {
2756
+ _stprintf_s(tmp, 50, _T("[key%d]\n"), j);
2757
+ s += tmp;
2758
+ for (int i=0;i<tableDef()->keyDefs[j].segmentCount;i++)
2759
+ {
2760
+ short fnum = tableDef()->keyDefs[j].segments[i].fieldNum;
2761
+ s += std::_tstring(tableDef()->fieldDefs[fnum].name())
2762
+ + _T(" = ") + getFVstr(fnum) + _T("\n");
2763
+ }
2764
+ }
2765
+
2766
+ }
2767
+
2768
+ _stprintf_s(buf, bufsize, _T("table:%s\nstat:%d\n%s")
2769
+ ,tableDef()->tableName()
2770
+ ,stat()
2771
+ ,s.c_str());
2772
+ }
2773
+
2774
+
2775
+ //-------------------------------------------------------------------
2776
+ // class queryBase
2777
+ //-------------------------------------------------------------------
2778
+ typedef boost::escaped_list_separator<_TCHAR> esc_sep;
2779
+ typedef boost::tokenizer<esc_sep
2780
+ ,std::_tstring::const_iterator
2781
+ ,std::_tstring> tokenizer;
2782
+
2783
+ void analyzeQuery(const _TCHAR* str
2784
+ , std::vector<std::_tstring>& selects
2785
+ , std::vector<std::_tstring>& where
2786
+ , std::vector<std::_tstring>& keyValues
2787
+ ,bool& nofilter)
2788
+ {
2789
+ esc_sep sep(_T('&'), _T(' '), _T('\''));
2790
+ std::_tstring s = str;
2791
+ tokenizer tokens(s, sep);
2792
+
2793
+ tokenizer::iterator it = tokens.begin();
2794
+ if (it == tokens.end()) return;
2795
+ if (*it == _T("*"))
2796
+ {
2797
+ nofilter = true;
2798
+ return;
2799
+ }
2800
+ s = *it;
2801
+ boost::algorithm::to_lower(s);
2802
+ if (s == _T("select"))
2803
+ {
2804
+ tokenizer::iterator itTmp = it;
2805
+ s = *(++it);
2806
+ if (getFilterLogicTypeCode(s.c_str())==255)
2807
+ {
2808
+ esc_sep sep(_T('&'), _T(','), _T('\''));
2809
+ tokenizer fields(s, sep);
2810
+ tokenizer::iterator itf = fields.begin();
2811
+ while (itf != fields.end())
2812
+ selects.push_back(*(itf++));
2813
+ ++it;
2814
+ }else
2815
+ it = itTmp; // field name is select
2816
+ }
2817
+ if (it == tokens.end())
2818
+ return;
2819
+ s = *it;
2820
+ boost::algorithm::to_lower(s);
2821
+ bool enableWhere = true;
2822
+ if (s == _T("in"))
2823
+ {
2824
+ tokenizer::iterator itTmp = it;
2825
+ s = *(++it);
2826
+ if (getFilterLogicTypeCode(s.c_str())==255)
2827
+ {
2828
+ enableWhere = false;
2829
+ esc_sep sep(_T('&'), _T(','), _T('\''));
2830
+ tokenizer values(s, sep);
2831
+ tokenizer::iterator itf = values.begin();
2832
+ while (itf != values.end())
2833
+ keyValues.push_back(*(itf++));
2834
+ }else
2835
+ it = itTmp; // field name is in
2836
+ }
2837
+ if (enableWhere)
2838
+ {
2839
+ while (it != tokens.end())
2840
+ where.push_back(*(it++));
2841
+ }
2842
+
2843
+ }
2844
+
2845
+
2846
+ struct impl
2847
+ {
2848
+ impl():
2849
+ m_reject(1),m_limit(0),m_direction(table::findForword)
2850
+ ,m_nofilter(false),m_optimize(false){}
2851
+
2852
+ int m_reject;
2853
+ int m_limit;
2854
+ table::eFindType m_direction;
2855
+ bool m_nofilter;
2856
+ bool m_optimize;
2857
+ mutable std::_tstring m_str;
2858
+ std::vector<std::_tstring> m_selects;
2859
+ std::vector<std::_tstring> m_wheres;
2860
+ std::vector<std::_tstring> m_keyValues;
2861
+ };
2862
+
2863
+ queryBase::queryBase():m_impl(new impl){}
2864
+
2865
+ queryBase::~queryBase()
2866
+ {
2867
+ delete m_impl;
2868
+ }
2869
+
2870
+ void queryBase::reset()
2871
+ {
2872
+ delete m_impl;
2873
+ m_impl = new impl;
2874
+ }
2875
+
2876
+ void queryBase::clearSelectFields()
2877
+ {
2878
+ m_impl->m_selects.clear();
2879
+ }
2880
+
2881
+ void queryBase::addField(const _TCHAR* name)
2882
+ {
2883
+ m_impl->m_selects.push_back(name);
2884
+ m_impl->m_nofilter = false;
2885
+ }
2886
+
2887
+ void queryBase::addLogic(const _TCHAR* name, const _TCHAR* logic, const _TCHAR* value)
2888
+ {
2889
+ m_impl->m_keyValues.clear();
2890
+ m_impl->m_wheres.clear();
2891
+ m_impl->m_wheres.push_back(name);
2892
+ m_impl->m_wheres.push_back(logic);
2893
+ m_impl->m_wheres.push_back(value);
2894
+ m_impl->m_nofilter = false;
2895
+
2896
+ }
2897
+
2898
+ void queryBase::addLogic(const _TCHAR* combine, const _TCHAR* name
2899
+ , const _TCHAR* logic, const _TCHAR* value)
2900
+ {
2901
+ m_impl->m_wheres.push_back(combine);
2902
+ m_impl->m_wheres.push_back(name);
2903
+ m_impl->m_wheres.push_back(logic);
2904
+ m_impl->m_wheres.push_back(value);
2905
+ m_impl->m_nofilter = false;
2906
+
2907
+ }
2908
+
2909
+ void queryBase::addSeekKeyValue(const _TCHAR* value, bool reset)
2910
+ {
2911
+ if (reset)
2912
+ {
2913
+ m_impl->m_wheres.clear();
2914
+ m_impl->m_keyValues.clear();
2915
+ }
2916
+ m_impl->m_keyValues.push_back(value);
2917
+ //m_impl->m_reject = 1;
2918
+ m_impl->m_nofilter = false;
2919
+
2920
+ }
2921
+
2922
+ void queryBase::clearSeekKeyValues()
2923
+ {
2924
+ m_impl->m_keyValues.clear();
2925
+ }
2926
+
2927
+ queryBase& queryBase::queryString(const _TCHAR* str)
2928
+ {
2929
+ m_impl->m_selects.clear();
2930
+ m_impl->m_wheres.clear();
2931
+ m_impl->m_keyValues.clear();
2932
+ m_impl->m_nofilter = false;
2933
+ if (str && str[0])
2934
+ analyzeQuery(str, m_impl->m_selects, m_impl->m_wheres, m_impl->m_keyValues
2935
+ ,m_impl->m_nofilter);
2936
+ return *this;
2937
+ }
2938
+
2939
+ queryBase& queryBase::reject(int v)
2940
+ {
2941
+ m_impl->m_reject = v;
2942
+ return *this;
2943
+ }
2944
+
2945
+ queryBase& queryBase::limit(int v)
2946
+ {
2947
+ m_impl->m_limit = v;
2948
+ return *this;
2949
+ }
2950
+
2951
+ queryBase& queryBase::direction(table::eFindType v)
2952
+ {
2953
+ m_impl->m_direction = v;
2954
+ return *this;
2955
+ }
2956
+
2957
+ queryBase& queryBase::all()
2958
+ {
2959
+ reset();
2960
+ m_impl->m_nofilter = true;
2961
+ return *this;
2962
+ }
2963
+
2964
+ queryBase& queryBase::optimize(bool v)
2965
+ {
2966
+ m_impl->m_optimize = v;
2967
+ return *this;
2968
+ }
2969
+
2970
+ bool queryBase::isOptimize()const
2971
+ {
2972
+ return m_impl->m_optimize;
2973
+ }
2974
+
2975
+ table::eFindType queryBase::getDirection() const {return m_impl->m_direction;}
2976
+
2977
+ std::_tstring escape_value(std::_tstring s)
2978
+ {
2979
+ std::_tstring::iterator it = s.begin();
2980
+ for (int i=(int)s.size()-1;i>=0;--i)
2981
+ {
2982
+ if (s[i] == _T('&'))
2983
+ s.insert(s.begin()+i, _T('&'));
2984
+ else if (s[i] == _T('\''))
2985
+ s.insert(s.begin()+i, _T('&'));
2986
+ }
2987
+ return s;
2988
+ }
2989
+
2990
+ const _TCHAR* queryBase::toString() const
2991
+ {
2992
+ m_impl->m_str.clear();
2993
+ if (m_impl->m_nofilter)
2994
+ return _T("*");
2995
+
2996
+ std::_tstring& s = m_impl->m_str;
2997
+ std::vector<std::_tstring>& selects = m_impl->m_selects;
2998
+ std::vector<std::_tstring>& wheres = m_impl->m_wheres;
2999
+ std::vector<std::_tstring>& keyValues = m_impl->m_keyValues;
3000
+ if (selects.size())
3001
+ {
3002
+ s = _T("select ");
3003
+ for (int i= 0;i < (int)selects.size();++i)
3004
+ s += selects[i] + _T(",");
3005
+
3006
+ if (s.size())
3007
+ s.replace(s.size()-1,1, _T(" "));
3008
+ }
3009
+
3010
+ for (size_t i= 0;i < wheres.size();i+=4)
3011
+ {
3012
+ s += wheres[i] + _T(" ") + wheres[i+1] + _T(" '")
3013
+ + escape_value(wheres[i+2]) + _T("' ");
3014
+ if (i+3 < wheres.size())
3015
+ s += wheres[i+3] + _T(" ");
3016
+ }
3017
+
3018
+ if (keyValues.size())
3019
+ {
3020
+ s += _T("in ");
3021
+ for (size_t i= 0;i < keyValues.size();++i)
3022
+ s += _T("'") + escape_value(keyValues[i]) + _T("',");
3023
+ }
3024
+ if (s.size())
3025
+ s.erase(s.end() -1);
3026
+
3027
+
3028
+ return s.c_str();
3029
+ }
3030
+
3031
+ int queryBase::getReject()const{return m_impl->m_reject;}
3032
+
3033
+ int queryBase::getLimit()const{return m_impl->m_limit;}
3034
+
3035
+ bool queryBase::isAll()const{return m_impl->m_nofilter;};
3036
+
3037
+ const std::vector<std::_tstring>& queryBase::getSelects() const {return m_impl->m_selects;}
3038
+ const std::vector<std::_tstring>& queryBase::getWheres() const {return m_impl->m_wheres;}
3039
+ const std::vector<std::_tstring>& queryBase::getSeekKeyValues() const{return m_impl->m_keyValues;}
3040
+
3041
+ void queryBase::release()
3042
+ {
3043
+ delete this;
3044
+ }
3045
+
3046
+ queryBase* queryBase::create()
3047
+ {
3048
+ return new queryBase();
3049
+
3050
+ }
2607
3051
 
2608
3052
 
2609
3053
  }// namespace client