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
@@ -25,6 +25,9 @@
25
25
  #include <bzs/db/engine/mysql/fieldAccess.h>
26
26
  #include <boost/shared_ptr.hpp>
27
27
 
28
+ #ifndef MAX_KEY_SEGMENT
29
+ #define MAX_KEY_SEGMENT 8
30
+ #endif
28
31
  namespace bzs
29
32
  {
30
33
  namespace db
@@ -145,7 +148,7 @@ inline int compareInt24(const char* l, const char* r)
145
148
  }
146
149
 
147
150
  template <class T>
148
- int compare(const char* l, const char* r)
151
+ inline int compare(const char* l, const char* r)
149
152
  {
150
153
  if (*((T*)l) < *((T*)r))
151
154
  return -1;
@@ -155,7 +158,7 @@ int compare(const char* l, const char* r)
155
158
  }
156
159
 
157
160
  template <class T>
158
- int compare(T l, T r)
161
+ inline int compare(T l, T r)
159
162
  {
160
163
  if (l < r)
161
164
  return -1;
@@ -165,7 +168,7 @@ int compare(T l, T r)
165
168
  }
166
169
 
167
170
  template <class T>
168
- int compareVartype(const char* l, const char* r, bool bin, char logType)
171
+ inline int compareVartype(const char* l, const char* r, bool bin, char logType)
169
172
  {
170
173
  int llen = (*(T*)l);
171
174
  int rlen = (*(T*)r);
@@ -183,7 +186,7 @@ int compareVartype(const char* l, const char* r, bool bin, char logType)
183
186
  }
184
187
 
185
188
  template <class T>
186
- int compareWvartype(const char* l, const char* r, bool bin, char logType)
189
+ inline int compareWvartype(const char* l, const char* r, bool bin, char logType)
187
190
  {
188
191
  int llen = (*(T*)l) / sizeof(char16_t);
189
192
  int rlen = (*(T*)r) / sizeof(char16_t);
@@ -220,32 +223,17 @@ inline int compareBlobType(const char* l, const char* r, bool bin, char logType,
220
223
  return (tmp==0 && (llen < rlen))? -1:tmp;
221
224
  }
222
225
 
223
- #define MAX_ISINDEX_CACHE 8
224
226
  #define REC_MACTH 0
225
227
  #define REC_NOMACTH 1
226
228
  #define REC_NOMACTH_NOMORE 2
227
229
 
230
+ //#define COMP_USE_SWITCHCASE
231
+ #ifndef COMP_USE_SWITCHCASE
232
+ #define COMP_USE_FUNCTION_POINTER
233
+ #endif
228
234
 
229
-
230
-
231
- struct extRequest;
232
- class fieldInfoCache
233
- {
234
- char m_sizeBytes[1000];
235
- bool m_isIndex[MAX_ISINDEX_CACHE];
236
- mutable int m_index;
237
-
238
- public:
239
- inline fieldInfoCache();
240
- inline ~fieldInfoCache();
241
- inline short cache(extRequest& req, position& position, const KEY* key);
242
- inline int getPos()const;
243
- inline bool isIndex()const;
244
- inline void reset()const;
245
-
246
- };
247
-
248
-
235
+ struct logicalField;
236
+ typedef int (logicalField::*compFunc)(const char* l, const char* r, int sizeByte) const;
249
237
  struct logicalField
250
238
  {
251
239
 
@@ -260,13 +248,14 @@ public:
260
248
  unsigned short offset;
261
249
  unsigned char ptr[2]; //variable
262
250
  };
263
-
251
+
264
252
  logicalField* next() const
265
253
  {
266
- return (logType & 64)?(logicalField*)(ptr + 2):(logicalField*)(ptr + len/*std::max((unsigned short)2,len)*/);
254
+ return (logType & 64)?(logicalField*)(ptr + 2):(logicalField*)(ptr + len);
267
255
  }
268
256
 
269
- private:
257
+ public:
258
+ #ifdef COMP_USE_SWITCHCASE
270
259
  int comp(const char* record, int sizeByte) const
271
260
  {
272
261
  const char* r = (const char*) ptr;
@@ -300,6 +289,7 @@ private:
300
289
  return strncmp(l, r, len);
301
290
  case ft_logical:
302
291
  case ft_uinteger:
292
+ case ft_autoIncUnsigned:
303
293
  case ft_date:
304
294
  case ft_time:
305
295
  case ft_timestamp:
@@ -350,48 +340,146 @@ private:
350
340
  }
351
341
  return 0;
352
342
  };
353
- bool matchThis(const char* record, int sizeByte) const
354
- {
355
-
356
- int v = comp(record, sizeByte);
357
- switch(logType & 0xF) //16 or more are disregarded.
358
- {
359
- case 1:return (v==0); //==
360
- case 2:return (v>0); //>
361
- case 3:return (v<0); //<
362
- case 4:return (v!=0); //!=
363
- case 5:return (v>=0); //>=
364
- case 6:return (v<=0); //<=
365
- }
366
- return false;
343
+ #else //COMP_USE_FUNCTION_POINTER
344
+
345
+ template <class T>
346
+ int compNumber(const char* l, const char* r, int sizeByte) const
347
+ {
348
+ return compare<T>(l , r);
367
349
  }
368
- public:
369
- int checkNomore(bool matchResult, bool typeNext, const fieldInfoCache& sb)const
370
- {
371
- if (matchResult)
372
- return REC_MACTH;
373
- else if(sb.isIndex())
350
+
351
+ int compNumber24(const char* l, const char* r, int sizeByte) const
352
+ {
353
+ return compareInt24(l , r);
354
+ }
355
+
356
+ int compNumberU24(const char* l, const char* r, int sizeByte) const
357
+ {
358
+ return compareUint24(l , r);
359
+ }
360
+
361
+ int compMem(const char* l, const char* r, int sizeByte) const
362
+ {
363
+ return memcmp(l , r, len);
364
+ }
365
+
366
+ int compString(const char* l, const char* r, int sizeByte) const
367
+ {
368
+ return strncmp(l , r, len);
369
+ }
370
+
371
+ int compiString(const char* l, const char* r, int sizeByte) const
372
+ {
373
+ return _strnicmp(l , r, len);
374
+ }
375
+
376
+ int compWString(const char* l, const char* r, int sizeByte) const
377
+ {
378
+ return wcsncmp16((char16_t*)l , (char16_t*)r, len);
379
+ }
380
+
381
+ int compiWString(const char* l, const char* r, int sizeByte) const
382
+ {
383
+ return wcsnicmp16((char16_t*)l , (char16_t*)r, len);
384
+ }
385
+
386
+ template <class T>
387
+ int compVarString(const char* l, const char* r, int sizeByte) const
388
+ {
389
+ return compareVartype<T>(l, r, type==ft_myvarbinary, logType);
390
+ }
391
+
392
+ template <class T>
393
+ int compWVarString(const char* l, const char* r, int sizeByte) const
394
+ {
395
+ return compareWvartype<T>(l, r, type==ft_mywvarbinary, logType);
396
+ }
397
+
398
+ int compBlob(const char* l, const char* r, int sizeByte) const
399
+ {
400
+ return compareBlobType(l, r, type==ft_myblob, logType, sizeByte);
401
+ }
402
+
403
+ compFunc logicalField::getCompFunc(int sizeByte)
404
+ {
405
+ switch(type)
374
406
  {
375
- char log = logType & 0xF;
376
- if (log == 1)//==
377
- return REC_NOMACTH_NOMORE;
378
- else if (typeNext && (log == 3 || log==6))
379
- return REC_NOMACTH_NOMORE;
380
- else if (!typeNext && (log == 2 || log==5))
381
- return REC_NOMACTH_NOMORE;
407
+ case ft_integer:
408
+ case ft_autoinc:
409
+ case ft_currency:
410
+ {
411
+ switch(len)
412
+ {
413
+ case 1:return &logicalField::compNumber<char>;
414
+ case 2:return &logicalField::compNumber<short>;
415
+ case 3:return &logicalField::compNumber24;
416
+ case 4:return &logicalField::compNumber<int>;
417
+ case 8:return &logicalField::compNumber<__int64>;
418
+ }
382
419
  }
383
- return REC_NOMACTH;
384
- }
385
- int match(const char* record, bool typeNext, const fieldInfoCache& sb) const
386
- {
387
- bool ret = matchThis(record, sb.getPos());
388
- if (opr == 0) //this is last
389
- return checkNomore(ret, typeNext, sb);
390
- if (!ret)
391
- return (opr == 1)?checkNomore(ret, typeNext, sb):next()->match(record, typeNext, sb);
392
- else
393
- return (opr == 1)?next()->match(record, typeNext, sb):checkNomore(ret, typeNext, sb);
420
+ case ft_mychar:
421
+ case ft_string:
422
+ if (logType & CMPLOGICAL_CASEINSENSITIVE)
423
+ return &logicalField::compiString;
424
+ return &logicalField::compMem;
425
+ case ft_zstring:
426
+ case ft_note:
427
+ if (logType & CMPLOGICAL_CASEINSENSITIVE)
428
+ return &logicalField::compiString;
429
+ return &logicalField::compString;
430
+ case ft_logical:
431
+ case ft_uinteger:
432
+ case ft_autoIncUnsigned:
433
+ case ft_date:
434
+ case ft_time:
435
+ case ft_timestamp:
436
+ case ft_mydate:
437
+ {
438
+ switch(len)
439
+ {
440
+ case 1:return &logicalField::compNumber<unsigned char>;
441
+ case 2:return &logicalField::compNumber<unsigned short>;
442
+ case 3:return &logicalField::compNumberU24;
443
+ case 4:return &logicalField::compNumber<unsigned int>;
444
+ case 8:return &logicalField::compNumber<unsigned __int64>;
445
+ }
446
+ }
447
+ case ft_mytime:
448
+ case ft_mydatetime:
449
+ case ft_mytimestamp:
450
+ return &logicalField::compMem;
451
+ case ft_float:
452
+ switch(len)
453
+ {
454
+ case 4:return &logicalField::compNumber<float>;
455
+ case 8:return &logicalField::compNumber<double>;
456
+ }
457
+ case ft_mywchar:
458
+ case ft_wstring:
459
+ case ft_wzstring:
460
+ if (logType & CMPLOGICAL_CASEINSENSITIVE)
461
+ return &logicalField::compiWString;
462
+ if ((type==ft_wstring)||(type==ft_mywchar))
463
+ return &logicalField::compMem;
464
+ return &logicalField::compWString;
465
+ case ft_lstring:
466
+ case ft_myvarchar:
467
+ case ft_myvarbinary:
468
+ if (sizeByte==1)
469
+ return &logicalField::compVarString<unsigned char>;
470
+ return &logicalField::compVarString<unsigned short>;
471
+ case ft_mywvarchar:
472
+ case ft_mywvarbinary:
473
+ if (sizeByte==1)
474
+ return &logicalField::compWVarString<unsigned char>;
475
+ return &logicalField::compWVarString<unsigned short>;
476
+ case ft_mytext:
477
+ case ft_myblob:
478
+ return &logicalField::compBlob;
479
+ }
480
+ return NULL;
394
481
  }
482
+ #endif
395
483
  extResultDef* resultDef() const
396
484
  {
397
485
  if (opr == 0)
@@ -407,12 +495,7 @@ struct extRequest
407
495
  unsigned short rejectCount;
408
496
  unsigned short logicalCount;
409
497
  logicalField field;
410
- int match(const char* record, bool typeNext, const fieldInfoCache& sb)const
411
- {
412
- if (logicalCount)
413
- return field.match(record, typeNext, sb);
414
- return REC_MACTH;
415
- }
498
+
416
499
  extResultDef* resultDef()const
417
500
  {
418
501
  if (logicalCount)
@@ -425,6 +508,185 @@ struct extRequest
425
508
  #pragma option -a
426
509
  pragma_pop
427
510
 
511
+ bool isMatch1(int v){return (v==0);}
512
+ bool isMatch2(int v){return (v>0);}
513
+ bool isMatch3(int v){return (v<0);}
514
+ bool isMatch4(int v){return (v!=0);}
515
+ bool isMatch5(int v){return (v>=0);}
516
+ bool isMatch6(int v){return (v<=0);}
517
+
518
+ class fields;
519
+ class fieldAdapter
520
+ {
521
+ logicalField* m_fd;
522
+ fieldAdapter* m_next;
523
+ bool (*m_isMatchFunc)(int);
524
+ #ifdef COMP_USE_FUNCTION_POINTER
525
+ compFunc m_compFunc;
526
+ #endif
527
+ unsigned char m_keySeg;
528
+ mutable bool m_judge;
529
+ char m_judgeType;
530
+ char m_sizeBytes;
531
+ mutable bool m_matched;
532
+ public:
533
+ friend class fields;
534
+ fieldAdapter(): m_keySeg(0xff),m_judge(false)
535
+ ,m_judgeType(0),m_sizeBytes(0),m_matched(false){}
536
+
537
+ int init(logicalField* fd, position& position, const KEY* key, bool forword)
538
+ {
539
+ m_fd = fd;
540
+ int num = position.getFieldNumByPos(fd->pos);
541
+ if (num == -1)
542
+ return STATUS_INVALID_FIELD_OFFSET;
543
+ m_sizeBytes = (char)position.fieldSizeByte(num);
544
+ #ifdef COMP_USE_FUNCTION_POINTER
545
+ m_compFunc = fd->getCompFunc(m_sizeBytes);
546
+ #endif
547
+ if (fd->opr == 2)
548
+ {
549
+ m_judgeType = 0;
550
+ return 0;
551
+ }
552
+ int segmentIndex = 0;
553
+ int segments = std::min<uint>(MAX_KEY_SEGMENT, key->user_defined_key_parts);
554
+ while (segmentIndex < segments)
555
+ {
556
+ if (key->key_part[segmentIndex].field->field_index == num)
557
+ {
558
+ eCompType comp = (eCompType)(fd->logType);
559
+ bool gt = (comp == greater)||(comp == greaterEq);
560
+ bool le = (comp == less)||(comp == lessEq);
561
+ bool valid = !(forword ? gt:le);
562
+ if (valid)
563
+ {
564
+ m_keySeg = (unsigned char)segmentIndex+1;
565
+ m_judgeType = (comp == equal) ? 2:1;
566
+ }
567
+ break;
568
+ }
569
+ ++segmentIndex;
570
+ }
571
+ return 0;
572
+ }
573
+
574
+ inline int checkNomore(bool typeNext, eCompType log)const
575
+ {
576
+ if (m_judge)
577
+ {
578
+ if ((log == equal) && m_matched)//==
579
+ return REC_NOMACTH_NOMORE;
580
+ else if (typeNext && (log == less || log==lessEq))
581
+ return REC_NOMACTH_NOMORE;
582
+ else if (!typeNext && (log == greater || log==greaterEq))
583
+ return REC_NOMACTH_NOMORE;
584
+ }
585
+ return REC_NOMACTH;
586
+ }
587
+
588
+ int match(const char* record, bool typeNext) const
589
+ {
590
+ #ifdef COMP_USE_SWITCHCASE
591
+ int v = m_fd->comp(record, m_sizeBytes);
592
+ #else //COMP_USE_FUNCTION_POINTER
593
+ const char* r = (const char*) m_fd->ptr;
594
+ if (m_fd->logType & CMPLOGICAL_FIELD)
595
+ r = record + m_fd->offset;
596
+ const char* l = record + m_fd->pos;
597
+ int v = (m_fd->*m_compFunc)(l, r , m_sizeBytes);
598
+ #endif
599
+ bool ret = m_isMatchFunc(v);
600
+ if (ret && m_judgeType)
601
+ {
602
+ m_matched = true;
603
+ // check is this logic range of max ?
604
+ // if max then set judge node to next logic
605
+ if ((m_fd->opr != 0) && m_judge && (v == 0) && m_next->m_judgeType)
606
+ m_next->m_judge = true;
607
+ }
608
+ bool end = (m_fd->opr == 0)||(!ret && (m_fd->opr == 1))||(ret && (m_fd->opr == 2));
609
+ if (!end)return m_next->match(record, typeNext);
610
+ return ret ? REC_MACTH : checkNomore(typeNext, (eCompType)(m_fd->logType & 0xF));
611
+ }
612
+
613
+ bool operator<(const fieldAdapter& r)
614
+ {
615
+ if (m_judgeType != r.m_judgeType)
616
+ return m_judgeType > r.m_judgeType;
617
+ return m_keySeg < r.m_keySeg;
618
+ }
619
+ };
620
+
621
+ class fields
622
+ {
623
+ fieldAdapter* m_fields;
624
+
625
+ public:
626
+ fields():m_fields(NULL){};
627
+
628
+ ~fields()
629
+ {
630
+ delete [] m_fields;
631
+ }
632
+
633
+ void init(extRequest& req, position& position, const KEY* key, bool forword)
634
+ {
635
+ if (req.logicalCount==0) return ;
636
+
637
+ logicalField* fd = &req.field;
638
+ delete [] m_fields;
639
+ m_fields = new fieldAdapter[req.logicalCount];
640
+ int lastIndex = req.logicalCount;
641
+ for (int i=0;i<req.logicalCount;++i)
642
+ {
643
+ fieldAdapter& fda = m_fields[i];
644
+ fda.init(fd, position, key, forword);
645
+ eCompType log = (eCompType)(fd->logType & 0xF);
646
+ switch(log)
647
+ {
648
+ case 1:fda.m_isMatchFunc = isMatch1;break;
649
+ case 2:fda.m_isMatchFunc = isMatch2;break;
650
+ case 3:fda.m_isMatchFunc = isMatch3;break;
651
+ case 4:fda.m_isMatchFunc = isMatch4;break;
652
+ case 5:fda.m_isMatchFunc = isMatch5;break;
653
+ case 6:fda.m_isMatchFunc = isMatch6;break;
654
+ }
655
+
656
+ fd = fd->next();
657
+ if (fda.m_fd->opr == 2)
658
+ lastIndex = i;
659
+ }
660
+ fieldAdapter* begin = &m_fields[0], *cur = &m_fields[0], *end = &m_fields[lastIndex];
661
+ char tmpOpr = (lastIndex != req.logicalCount) ? end->m_fd->opr: 0;
662
+ std::sort(begin, end);
663
+ bool flag = true;
664
+ while (cur != end)
665
+ {
666
+ cur->m_fd->opr = 1;//and
667
+ if (flag && cur->m_judgeType == 2)
668
+ cur->m_judge = true;
669
+ else
670
+ flag = false;
671
+ ++cur;
672
+ }
673
+
674
+ //if first logic is first segmnet then first logic can judge.
675
+ if ((begin->m_keySeg == 1) && begin->m_judgeType)
676
+ begin->m_judge = true;
677
+
678
+ if (lastIndex == req.logicalCount) --end;
679
+ end->m_fd->opr = tmpOpr;
680
+ for (int i=0;i<req.logicalCount-1;++i)
681
+ m_fields[i].m_next = &m_fields[i+1];
682
+ }
683
+
684
+ int match(const char* record, bool typeNext) const
685
+ {
686
+ return m_fields[0].match(record, typeNext);
687
+ }
688
+ };
689
+
428
690
  class resultWriter
429
691
  {
430
692
  char* m_buf;
@@ -437,8 +699,7 @@ class resultWriter
437
699
  short writeFirst( position* pos, unsigned int bookmark)
438
700
  {
439
701
  m_rowsPos = m_resultLen;
440
-
441
- memset(m_buf + m_resultLen, 0x00, sizeof(unsigned short));
702
+ *((unsigned short*)(m_buf + m_resultLen)) = 0;
442
703
  m_resultLen += sizeof(unsigned short);
443
704
  return doWrite(pos, bookmark);
444
705
  }
@@ -448,50 +709,56 @@ class resultWriter
448
709
  // write rowCount
449
710
  unsigned short* rows = (unsigned short*) (m_buf + m_rowsPos);
450
711
  ++(*rows);
712
+
451
713
  //write recLength space;
452
714
  unsigned short recLen = 0;
453
715
  unsigned short recLenPos = m_resultLen;
454
- memcpy(m_buf + m_resultLen, (const char*)&recLen, sizeof(unsigned short));
716
+ *((unsigned short*)(m_buf + m_resultLen)) = recLen;
455
717
  m_resultLen += sizeof(unsigned short);
718
+
456
719
  //write bookmark
457
- memcpy(m_buf + m_resultLen, (const char*)&bookmark, sizeof(unsigned int));
720
+ *((unsigned int*)(m_buf + m_resultLen)) = bookmark;
458
721
  m_resultLen += sizeof(unsigned int);
459
722
 
460
- if ((m_def->fieldCount == 1) && (m_def->field[0].len >= pos->recordLenCl()))
461
- { //write whole row
462
- int len = pos->recordLenCl();
463
- if (m_maxLen + RETBUF_EXT_RESERVE_SIZE >= m_resultLen + len)
464
- {
465
- int maxlen = m_maxLen + RETBUF_EXT_RESERVE_SIZE - m_resultLen;
466
- len = pos->recordPackCopy(m_buf + m_resultLen, maxlen);
467
- if (len == 0)
723
+ //if pos ==NULL , that is not found record in a TD_KEY_SEEK_MULTI operation
724
+ // and bookmark has error code also STATUS_NOT_FOUND_TI
725
+ // in the client, fieldCount > 0 buf recLen=0 then this pattern
726
+ if (pos)
727
+ {
728
+ if ((m_def->fieldCount == 1) && (m_def->field[0].len >= pos->recordLenCl()))
729
+ { //write whole row
730
+ int len = pos->recordLenCl();
731
+ if (m_maxLen + RETBUF_EXT_RESERVE_SIZE >= m_resultLen + len)
732
+ {
733
+ int maxlen = m_maxLen + RETBUF_EXT_RESERVE_SIZE - m_resultLen;
734
+ len = pos->recordPackCopy(m_buf + m_resultLen, maxlen);
735
+ if (len == 0)
736
+ return STATUS_BUFFERTOOSMALL;
737
+ m_resultLen += len;
738
+ recLen += len;
739
+ }else
468
740
  return STATUS_BUFFERTOOSMALL;
469
- m_resultLen += len;
470
- recLen += len;
471
741
  }else
472
- return STATUS_BUFFERTOOSMALL;
473
- }else
474
- {
475
- //write each fields by field num.
476
- for (int i=0;i<m_def->fieldCount;i++)
477
742
  {
478
- resultField& fd = m_def->field[i];
479
- if (m_maxLen+RETBUF_EXT_RESERVE_SIZE>= m_resultLen + fd.len)
743
+ //write each fields by field num.
744
+ for (int i=0;i<m_def->fieldCount;i++)
480
745
  {
481
- //memcpy(m_buf + m_resultLen, pos->record() + fd.pos, fd.len);
482
- memcpy(m_buf + m_resultLen, pos->fieldPtr(&fd), fd.len);
483
- m_resultLen += fd.len;
484
- recLen += fd.len;
485
- if (pos->isBlobField(&fd))
486
- pos->addBlobBuffer(fd.fieldNum);
746
+ resultField& fd = m_def->field[i];
747
+ if (m_maxLen+RETBUF_EXT_RESERVE_SIZE>= m_resultLen + fd.len)
748
+ {
749
+ memcpy(m_buf + m_resultLen, pos->fieldPtr(&fd), fd.len);
750
+ m_resultLen += fd.len;
751
+ recLen += fd.len;
752
+ if (pos->isBlobField(&fd))
753
+ pos->addBlobBuffer(fd.fieldNum);
754
+ }
755
+ else
756
+ return STATUS_BUFFERTOOSMALL;
487
757
  }
488
- else
489
- return STATUS_BUFFERTOOSMALL;
490
758
  }
491
759
  }
492
760
  //write recLength;
493
- unsigned short* tmp = (unsigned short*) (m_buf + recLenPos);
494
- *tmp = recLen;
761
+ *((unsigned short*)(m_buf + recLenPos)) = recLen;
495
762
  return 0;
496
763
  }
497
764
  public:
@@ -516,77 +783,6 @@ public:
516
783
  const char* resultBuffer(){return m_buf;}
517
784
  };
518
785
 
519
- /* ---------------------------------------------------------------
520
- * Implement fieldInfoCache
521
- * ---------------------------------------------------------------*/
522
- inline fieldInfoCache::fieldInfoCache()
523
- {
524
- memset(m_isIndex, 0, sizeof(bool) * MAX_ISINDEX_CACHE);
525
- }
526
-
527
- inline fieldInfoCache::~fieldInfoCache()
528
- {
529
-
530
- }
531
-
532
- inline short fieldInfoCache::cache(extRequest& req, position& position, const KEY* key)
533
- {
534
-
535
- m_index = 0;
536
- logicalField* fd = &req.field;
537
- char* pos = m_sizeBytes;
538
- bool isCheckKeyseg = (key != NULL);
539
- unsigned short segmentIndex = 0;
540
- for (int i=0;i<req.logicalCount;i++)
541
- {
542
-
543
- int num = position.getFieldNumByPos(fd->pos);
544
- if (num == -1)
545
- return STATUS_INVALID_FIELD_OFFSET;
546
- *pos = (char)position.fieldSizeByte(num);
547
-
548
- /* Is target field current keynum segnmnt
549
- For optimize match() return NOMATCH_NOMORE
550
- */
551
- if (isCheckKeyseg && (i < MAX_ISINDEX_CACHE))
552
- {
553
- if (segmentIndex < key->user_defined_key_parts)
554
- {
555
- m_isIndex[i] = (key->key_part[segmentIndex].field->field_index == num);
556
- if (!m_isIndex[i] && (++segmentIndex < key->user_defined_key_parts))
557
- m_isIndex[i] = (key->key_part[segmentIndex].field->field_index == num);
558
- }
559
- isCheckKeyseg = m_isIndex[i];
560
- if (fd->opr == 2) isCheckKeyseg = false;
561
- }
562
-
563
- ++pos;
564
- fd = fd->next();
565
- }
566
- return 0;
567
- }
568
-
569
- /* get value and inc index.
570
- */
571
- inline int fieldInfoCache::getPos()const
572
- {
573
- return m_sizeBytes[m_index++];
574
- }
575
-
576
- /* It certainly calls after getPos() */
577
- inline bool fieldInfoCache::isIndex()const
578
- {
579
- return m_isIndex[m_index-1];
580
- }
581
-
582
- /* reset for next record */
583
- inline void fieldInfoCache::reset()const
584
- {
585
- m_index = 0;
586
-
587
- }
588
-
589
- /* ---------------------------------------------------------------*/
590
786
 
591
787
  class ReadRecordsHandler : public engine::mysql::IReadRecordsHandler
592
788
  {
@@ -594,20 +790,23 @@ class ReadRecordsHandler : public engine::mysql::IReadRecordsHandler
594
790
  extRequest* m_req;
595
791
  extResultDef* m_resultDef;
596
792
  position m_position;
597
- fieldInfoCache m_fieldInfoCache;
598
- public:
793
+ fields m_fields;
599
794
 
600
- short begin(engine::mysql::table* tb, extRequest* req, char* buf,size_t offset, unsigned short maxlen)
795
+ public:
796
+ short begin(engine::mysql::table* tb, extRequest* req, bool fieldCache
797
+ , char* buf,size_t offset, unsigned short maxlen, bool forword)
601
798
  {
602
799
  short ret = 0;
603
800
  m_position.setTable(tb);
604
801
  m_req = req;
605
- const KEY* key = NULL;
606
- if (tb->keyNum() >= 0)
607
- key = &tb->keyDef(tb->keyNum());
608
- m_fieldInfoCache.cache(*m_req, m_position, key);
609
-
610
802
  m_resultDef = m_req->resultDef();
803
+ if (fieldCache)
804
+ {
805
+ const KEY* key = NULL;
806
+ if (tb->keyNum() >= 0)
807
+ key = &tb->keyDef(tb->keyNum());
808
+ m_fields.init(*m_req, m_position, key, forword);
809
+ }
611
810
  if (m_resultDef->fieldCount > 1)
612
811
  ret = convResultPosToFieldNum();
613
812
 
@@ -647,25 +846,37 @@ public:
647
846
 
648
847
  int match(bool typeNext)const
649
848
  {
650
- m_fieldInfoCache.reset();
651
- return m_req->match(m_position.record(), typeNext, m_fieldInfoCache);
849
+ if (m_req->logicalCount)
850
+ return m_fields.match(m_position.record(), typeNext);
851
+ return REC_MACTH;
652
852
  }
653
853
 
654
- short write(const unsigned char* bmPtr, unsigned int bmlen)
854
+ short write(const unsigned char* bmPtr, unsigned int bmlen, short stat=0)
655
855
  {
656
856
  unsigned int bookmark = 0;
657
- switch(bmlen)
857
+ //if bmPtr ==NULL , that is not found record in a TD_KEY_SEEK_MULTI operation
858
+ // and set error code to bookmark also STATUS_NOT_FOUND_TI
859
+ if (bmPtr == NULL)
860
+ {
861
+ bookmark = stat;
862
+ return m_writer->write(NULL, bookmark);
863
+ }
864
+ else
658
865
  {
659
- case 4:
660
- bookmark = *((unsigned int*)bmPtr);break;
661
- case 2:
662
- bookmark = *((unsigned short*)bmPtr);break;
663
- case 3:
664
- bookmark = *((unsigned int*)bmPtr) & 0x0FFFFFF;break;
665
- case 1:
666
- bookmark = *((unsigned short*)bmPtr) & 0x0FF;break;
866
+ switch(bmlen)
867
+ {
868
+ case 4:
869
+ bookmark = *((unsigned int*)bmPtr);break;
870
+ case 2:
871
+ bookmark = *((unsigned short*)bmPtr);break;
872
+ case 3:
873
+ bookmark = *((unsigned int*)bmPtr) & 0x0FFFFFF;break;
874
+ case 1:
875
+ bookmark = *((unsigned short*)bmPtr) & 0x0FF;break;
876
+ }
877
+ return m_writer->write(&m_position, bookmark);
667
878
  }
668
- return m_writer->write(&m_position, bookmark);
879
+
669
880
  }
670
881
  unsigned short rejectCount(){return m_req->rejectCount;};
671
882
  unsigned short maxRows(){return m_resultDef->maxRows;};