transactd 3.6.1 → 3.7.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (30) hide show
  1. checksums.yaml +4 -4
  2. data/bin/common/{tdclc_32_3_6.dll → tdclc_32_3_7.dll} +0 -0
  3. data/bin/common/{tdclc_64_3_6.dll → tdclc_64_3_7.dll} +0 -0
  4. data/build/swig/ruby/tdclrb_wrap.cpp +125 -17
  5. data/build/tdclc/tdclc.cbproj +1 -1
  6. data/build/tdclc/tdclc.rc +4 -4
  7. data/build/tdclcpp/tdclcpp.rc +4 -4
  8. data/build/tdclcpp/tdclcpp_bc.cbproj +1 -1
  9. data/build/tdclrb/tdclrb.rc +4 -4
  10. data/source/bzs/db/protocol/tdap/client/field.cpp +24 -0
  11. data/source/bzs/db/protocol/tdap/client/field.h +2 -0
  12. data/source/bzs/db/protocol/tdap/client/groupQuery.cpp +243 -59
  13. data/source/bzs/db/protocol/tdap/client/groupQuery.h +8 -0
  14. data/source/bzs/db/protocol/tdap/client/memRecord.cpp +19 -6
  15. data/source/bzs/db/protocol/tdap/client/memRecord.h +10 -1
  16. data/source/bzs/db/protocol/tdap/client/recordset.cpp +17 -0
  17. data/source/bzs/db/protocol/tdap/client/recordset.h +3 -0
  18. data/source/bzs/db/protocol/tdap/client/recordsetImple.h +131 -30
  19. data/source/bzs/db/protocol/tdap/client/table.cpp +11 -2
  20. data/source/bzs/db/protocol/tdap/mysql/recordsetReader.h +1 -0
  21. data/source/bzs/db/protocol/tdap/tdapcapi.h +5 -5
  22. data/source/bzs/test/tdclatl/test_v3.js +22 -0
  23. data/source/bzs/test/tdclphp/transactd_v3_Test.php +35 -0
  24. data/source/bzs/test/tdclrb/transactd_v3_spec.rb +40 -0
  25. data/source/bzs/test/trdclengn/testField.h +320 -0
  26. data/source/bzs/test/trdclengn/test_tdclcpp_v3.cpp +9 -0
  27. data/source/global/tdclatl/Recordset.cpp +44 -2
  28. data/source/global/tdclatl/Recordset.h +6 -2
  29. data/source/global/tdclatl/tdclatl.idl +5 -1
  30. metadata +4 -4
@@ -65,7 +65,10 @@ class dumpRecordset
65
65
  {
66
66
  row& rec = rs[i];
67
67
  for (size_t col = 0; col < fds.size(); ++col)
68
- m_widths[col] = std::max(_tcslen(rec[(short)col].c_str()), m_widths[col]);
68
+ {
69
+ if (!rec[(short)col].isNull())
70
+ m_widths[col] = std::max(_tcslen(rec[(short)col].c_str()), m_widths[col]);
71
+ }
69
72
  }
70
73
  }
71
74
 
@@ -199,12 +202,6 @@ class recordsetImple
199
202
  /* for registerMemoryBlock temp data */
200
203
  size_t m_joinRows;
201
204
 
202
- /*
203
- for optimazing join.
204
- If the first reading is using by unique key , set that field count.
205
- */
206
- short m_uniqueReadMaxField;
207
-
208
205
  public:
209
206
  typedef std::vector<row_ptr>::iterator iterator;
210
207
  typedef row_ptr item_type;
@@ -226,7 +223,7 @@ private:
226
223
  am->setParams(ptr, size, 0, true);
227
224
  m_memblock.push_back(boost::shared_ptr<autoMemory>(am, boost::bind(&autoMemory::release, _1)));
228
225
  unsigned char* p = am->ptr;
229
- // copy fileds
226
+ // copy fields
230
227
  if (addtype & mra_nextrows)
231
228
  {
232
229
  if (addtype == mra_nextrows)
@@ -241,13 +238,6 @@ private:
241
238
  m_mra->setCurFirstField((int)m_fds->size());
242
239
  if (tb)
243
240
  m_fds->addSelectedFields(tb);
244
- if (tb && (addtype == mra_nojoin))
245
- {
246
- const keydef& kd = tb->tableDef()->keyDefs[(int)tb->keyNum()];
247
- m_uniqueReadMaxField = (kd.segments[0].flags.bit0 == false)
248
- ? (short)m_fds->size()
249
- : 0;
250
- }
251
241
  }
252
242
 
253
243
  *(am->endFieldIndex) = (short)m_fds->size();
@@ -262,8 +252,7 @@ private:
262
252
  if (jmap)
263
253
  {
264
254
  // At Join that if some base records reference to a joined
265
- // record
266
- // that the joined record pointer is shared by some
255
+ // record that the joined record pointer is shared by some
267
256
  // base records.
268
257
  for (int i = 0; i < (int)rows; ++i)
269
258
  {
@@ -322,6 +311,16 @@ private:
322
311
  return -1;
323
312
  }
324
313
 
314
+ inline size_t getIndexOfEndPtr(short* p, int memBlockIndex) const
315
+ {
316
+ const boost::shared_ptr<autoMemory>& am = m_memblock[memBlockIndex];
317
+ if ((p >= am->endFieldIndex) && (p < am->endFieldIndex + JOINLIMIT_PER_RECORD))
318
+ return p - am->endFieldIndex;
319
+
320
+ assert(0);
321
+ return -1;
322
+ }
323
+
325
324
  // Duplicate row for hasManyJoin
326
325
  void duplicateRow(int row, int count)
327
326
  {
@@ -336,18 +335,73 @@ private:
336
335
  }
337
336
  }
338
337
 
338
+ void assignJoinFields(const recordsetImple& r, std::vector<int>& indexes)
339
+ {
340
+ int fieldCount = (int)m_fds->size();
341
+ m_fds->append(r.m_fds.get());
342
+
343
+ // append memblock
344
+ std::vector<short*> endIndex;
345
+ for (size_t i = 0;i < r.m_memblock.size(); ++i)
346
+ {
347
+ m_memblock.push_back(r.m_memblock[i]);
348
+ short* ei = r.m_memblock[i]->appendEndFieldIndex(*r.m_memblock[i]->endFieldIndex + fieldCount);
349
+ endIndex.push_back(ei);
350
+ }
351
+
352
+ if (r.size() == 0) return;
353
+
354
+ //counting (row * memblock)
355
+ int rblockSize = (int)dynamic_cast<memoryRecord*>(r.m_recordset[0])->memBlockSize();
356
+ int amsize = (int)(rblockSize * indexes.size());
357
+
358
+ autoMemory* amar = autoMemory::create(amsize);
359
+ amsize = 0;
360
+ autoMemory* nullRecordAm = 0;
361
+ for (int i = 0; i < (int)m_recordset.size(); ++i)
362
+ {
363
+ memoryRecord* row = dynamic_cast<memoryRecord*>(m_recordset[i]);
364
+ for (int j = 0; j < (int)rblockSize; ++j)
365
+ {
366
+ autoMemory* mb = amar + amsize;
367
+ if (indexes[i] != -1)
368
+ {
369
+ memoryRecord* srow = dynamic_cast<memoryRecord*>(r.m_recordset[indexes[i]]);
370
+ assert(srow->memBlockSize() == rblockSize);
371
+ const autoMemory& smb = srow->memBlock(j);
372
+ int index = r.getMemBlockIndex(smb.ptr);
373
+ row->setRecordData(mb, smb.ptr, 0, endIndex[index], false);
374
+ }else
375
+ {
376
+ // Alloc data buffer for not found record.
377
+ if (nullRecordAm == NULL)
378
+ {
379
+ nullRecordAm = autoMemory::create();
380
+ nullRecordAm->addref();
381
+ short endIndex = (short)m_fds->size();
382
+ nullRecordAm->setParams(0, r.m_fds->totalFieldLen(), &endIndex, true);
383
+ m_memblock.push_back(boost::shared_ptr<autoMemory>(nullRecordAm, boost::bind(&autoMemory::release, _1)));
384
+ }
385
+ row->setRecordData(mb, nullRecordAm->ptr, 0, nullRecordAm->endFieldIndex, false);
386
+ // Specify fieldnum
387
+ row->setInvalidMemblockLast();
388
+ }
389
+ ++amsize;
390
+ }
391
+ }
392
+ }
393
+
339
394
  public:
340
395
  inline recordsetImple()
341
396
  : m_fds(fielddefs::create(), boost::bind(&fielddefs::release, _1)),
342
- m_joinRows(0), m_uniqueReadMaxField(0)
397
+ m_joinRows(0)
343
398
  {
344
399
  m_mra.reset(new multiRecordAlocatorImple(this));
345
400
  }
346
401
 
347
402
  inline recordsetImple(const recordsetImple& r)
348
403
  : m_fds(r.m_fds),m_mra(r.m_mra), m_recordset(r.m_recordset),
349
- m_memblock(r.m_memblock), m_joinRows(r.m_joinRows),
350
- m_uniqueReadMaxField(r.m_uniqueReadMaxField)
404
+ m_memblock(r.m_memblock), m_joinRows(r.m_joinRows)
351
405
  {
352
406
  for (size_t i = 0; i < m_recordset.size(); ++i)
353
407
  m_recordset[i]->addref();
@@ -370,7 +424,6 @@ public:
370
424
  m_recordset = r.m_recordset;
371
425
  m_memblock = r.m_memblock;
372
426
  m_joinRows = r.m_joinRows;
373
- m_uniqueReadMaxField = r.m_uniqueReadMaxField;
374
427
  for (size_t i = 0; i < m_recordset.size(); ++i)
375
428
  m_recordset[i]->addref();
376
429
  }
@@ -384,7 +437,6 @@ public:
384
437
  {
385
438
  recordsetImple* p = new recordsetImple();
386
439
  p->m_joinRows = m_joinRows;
387
- p->m_uniqueReadMaxField = m_uniqueReadMaxField;
388
440
  p->m_fds.reset(m_fds->clone(), boost::bind(&fielddefs::release, _1));
389
441
 
390
442
  std::vector<size_t> offsets;
@@ -396,7 +448,7 @@ public:
396
448
  autoMemory* am = ama + i;
397
449
  am->addref();
398
450
  am->setParams(m_memblock[i]->ptr, m_memblock[i]->size, 0, true);
399
- *am->endFieldIndex = *m_memblock[i]->endFieldIndex;
451
+ am->assignEndFieldIndex(m_memblock[i]->endFieldIndex);
400
452
  p->m_memblock.push_back(boost::shared_ptr<autoMemory>(am, boost::bind(&autoMemory::release, _1)));
401
453
  offsets.push_back((am->ptr - m_memblock[i]->ptr));
402
454
  }
@@ -443,8 +495,10 @@ public:
443
495
  #pragma warn .8072
444
496
  autoMemory* a = amar + amindex;
445
497
  const boost::shared_ptr<autoMemory>& am = p->m_memblock[index];
446
- // isInvalidRecord will be reset.
447
498
  mr->setRecordData(a, ptr, mb.size, am->endFieldIndex, mb.owner);
499
+ // set endFieldIndex
500
+ size_t offset = getIndexOfEndPtr(mb.endFieldIndex, index);
501
+ a->endFieldIndex += offset;
448
502
  ++amindex;
449
503
  }
450
504
 
@@ -456,8 +510,6 @@ public:
456
510
  return p;
457
511
  }
458
512
 
459
- inline short uniqueReadMaxField() const { return m_uniqueReadMaxField; }
460
-
461
513
  inline void clearRecords()
462
514
  {
463
515
  if (m_recordset.size())
@@ -468,9 +520,8 @@ public:
468
520
  m_recordset[i]->release();
469
521
  }
470
522
  }
471
-
523
+
472
524
  m_recordset.clear();
473
- m_uniqueReadMaxField = 0;
474
525
  }
475
526
 
476
527
  inline const fielddefs* fieldDefs() const { return m_fds.get(); }
@@ -654,8 +705,6 @@ public:
654
705
 
655
706
  inline void appendField(const _TCHAR* name, int type, short len, uchar_td decimals=0)
656
707
  {
657
- assert(m_fds->size());
658
-
659
708
  fielddef fd;
660
709
  memset(&fd, 0, sizeof(fielddef));
661
710
  fd.len = len;
@@ -664,6 +713,13 @@ public:
664
713
  fd.decimals = decimals;
665
714
  fd.setName(name);
666
715
  fd.setCharsetIndex((*m_fds)[0].charsetIndex());
716
+ appendField(fd);
717
+ }
718
+
719
+ inline void appendField(const fielddef& fd)
720
+ {
721
+ assert(m_fds->size());
722
+
667
723
  if (blobLenBytes(fd))
668
724
  THROW_BZS_ERROR_WITH_MSG(_T("Can not append Blob or Text field."));
669
725
  m_fds->push_back(&fd);
@@ -697,6 +753,51 @@ public:
697
753
  m_recordset.reserve(size);
698
754
  }
699
755
 
756
+ void nestedLoopJoin(const recordsetImple& r, recordsetQuery& q, bool inner)
757
+ {
758
+
759
+ std::vector<int> indexes;
760
+ size_t i = 0;
761
+ indexes.reserve(size() * 3);
762
+ q.init(m_fds.get(), r.m_fds.get());
763
+ while (i < size())
764
+ {
765
+ size_t j = 0;
766
+ size_t found = 0;
767
+ q.setJoinRow(m_recordset[i]);
768
+ while (j < r.size())
769
+ {
770
+ if (q.matchJoin(r.m_recordset[j]))
771
+ {
772
+ indexes.push_back((int)j);
773
+ ++found;
774
+ }
775
+ if(q.matchStatus() == JOIN_NO_MORERECORD)
776
+ break;
777
+ ++j;
778
+ }
779
+ if (found == 0)
780
+ {
781
+ if (inner)
782
+ erase(i);
783
+ else
784
+ {
785
+ indexes.push_back(-1);
786
+ ++i;
787
+ }
788
+ }
789
+ else if (found == 1)
790
+ ++i;
791
+ else
792
+ {
793
+ duplicateRow((int)i, (int)(found - 1));
794
+ i += found;
795
+ }
796
+ }
797
+ assert(m_recordset.size() == indexes.size());
798
+ assignJoinFields(r, indexes);
799
+ }
800
+
700
801
  #ifdef _DEBUG
701
802
  void dump()
702
803
  {
@@ -229,6 +229,13 @@ public:
229
229
  }
230
230
  }
231
231
 
232
+ inline int currentRow()
233
+ {
234
+ if (m_filter->hasManyJoin())
235
+ return *((int*)(m_ptr + DATASIZE_BYTE));
236
+ return m_row;
237
+ }
238
+
232
239
  inline char* moveCurrentData(char* ptr, unsigned short& len, int& sqnum)
233
240
  {
234
241
  len = *((unsigned short*)ptr);
@@ -1011,8 +1018,8 @@ void table::doFind(ushort_td op, bool notIncCurrent)
1011
1018
  m_stat = m_impl->rc->seekMultiStat();
1012
1019
 
1013
1020
  /*If seek multi error, set keyvalue for keyValueDescription*/
1014
- if (m_stat != 0)
1015
- setSeekValueField(row);
1021
+ if (m_stat != 0 && m_impl->filterPtr->isSeeksMode())
1022
+ setSeekValueField(m_impl->rc->currentRow());
1016
1023
 
1017
1024
  // m_datalen = m_impl->rc->len();
1018
1025
  m_datalen = tableDef()->recordlen();
@@ -2110,6 +2117,8 @@ bool table::setSeekValueField(int row)
2110
2117
  keydef* kd = &tableDef()->keyDefs[(int)keyNum()];
2111
2118
  if (keyValues.size() % kd->segmentCount)
2112
2119
  return false;
2120
+ if (row >= keyValues.size())
2121
+ return false;
2113
2122
  // Check uniqe key
2114
2123
  if (kd->segments[0].flags.bit0)
2115
2124
  return false;
@@ -446,6 +446,7 @@ public:
446
446
  {
447
447
  m_matched = true;
448
448
  // check is this logic range of max ?
449
+ // (v == 0) it was max value of this node.
449
450
  // if max then set judge node to next logic
450
451
  if ((m_fd->opr != 0) && m_judge && (v == 0) && m_next->m_judgeType)
451
452
  m_next->m_judge = true;
@@ -669,8 +669,8 @@ struct handshale_t
669
669
  If you change this version then you need change The ($TargetName) project options too.
670
670
  */
671
671
  #define C_INTERFACE_VER_MAJOR "3"//##1 Build marker! Don't remove
672
- #define C_INTERFACE_VER_MINOR "6"//##2 Build marker! Don't remove
673
- #define C_INTERFACE_VER_RELEASE "1"//##3 Build marker! Don't remove
672
+ #define C_INTERFACE_VER_MINOR "7"//##2 Build marker! Don't remove
673
+ #define C_INTERFACE_VER_RELEASE "0"//##3 Build marker! Don't remove
674
674
 
675
675
  /* dnamic load library name.
676
676
  The default extention of Mac is ".boudle", Therefore ".so" is popular. */
@@ -733,8 +733,8 @@ struct handshale_t
733
733
  */
734
734
 
735
735
  #define CPP_INTERFACE_VER_MAJOR "3"//##4 Build marker! Don't remove
736
- #define CPP_INTERFACE_VER_MINOR "6"//##5 Build marker! Don't remove
737
- #define CPP_INTERFACE_VER_RELEASE "1"//##6 Build marker! Don't remove
736
+ #define CPP_INTERFACE_VER_MINOR "7"//##5 Build marker! Don't remove
737
+ #define CPP_INTERFACE_VER_RELEASE "0"//##6 Build marker! Don't remove
738
738
 
739
739
  /* use autolink tdclcpp */
740
740
  #if (__BCPLUSPLUS__ || _MSC_VER)
@@ -770,7 +770,7 @@ struct handshale_t
770
770
 
771
771
 
772
772
  #define TRANSACTD_VER_MAJOR 3//##7 Build marker! Don't remove
773
- #define TRANSACTD_VER_MINOR 6//##8 Build marker! Don't remove
773
+ #define TRANSACTD_VER_MINOR 7//##8 Build marker! Don't remove
774
774
  #define TRANSACTD_VER_RELEASE 0//##9 Build marker! Don't remove
775
775
 
776
776
  #endif // BZS_DB_PROTOCOL_TDAP_TDAPCAPI_H
@@ -331,6 +331,7 @@ var FMT_RIGHT = 2;
331
331
  var MAGNIFICATION = 100;
332
332
  var resultCode = 0;
333
333
  var q;
334
+ var gq;
334
335
 
335
336
  WScript.quit(main());
336
337
  /*--------------------------------------------------------------------------------*/
@@ -906,6 +907,25 @@ function tesAlias(db)
906
907
  tb.close();
907
908
  }
908
909
 
910
+ function testRecordsetJoin(atu, ate)
911
+ {
912
+ initQuery();
913
+ q.where("id" , ">=", 1).and("id", "<=", 10).select("id", "name");
914
+ rs = atu.index(0).keyValue(1).read(q);
915
+ checkEqual(rs.size, 10, "RecordsetJoin 1");
916
+ q.reset().where("id" , ">=", 1).and("id", "<=", 5);
917
+ rse = ate.index(0).keyValue(1).read(q);
918
+ checkEqual(rse.size, 5, "RecordsetJoin 2");
919
+ var rq = createRecordsetQuery();
920
+ var rs1 = rs.clone();
921
+ rq.when("id", "=", "id");
922
+ rs1.join(rse, rq);
923
+ checkEqual(rs1.size, 5, "RecordsetJoin 3");
924
+ rs.outerjoin(rse, rq);
925
+ checkEqual(rs.size, 10, "RecordsetJoin 4");
926
+ }
927
+
928
+
909
929
  /*--------------------------------------------------------------------------------*/
910
930
  function test(atu, ate, db)
911
931
  {
@@ -1218,6 +1238,8 @@ function test(atu, ate, db)
1218
1238
 
1219
1239
  //Alias
1220
1240
  tesAlias(db);
1241
+
1242
+ testRecordsetJoin(atu, ate);
1221
1243
  //WScript.Echo(" -- End Test -- ");
1222
1244
  }
1223
1245
  /*--------------------------------------------------------------------------------*/
@@ -24,6 +24,7 @@ use BizStation\Transactd\Transactd;
24
24
  use BizStation\Transactd\PooledDbManager;
25
25
  use BizStation\Transactd\ConnectParams;
26
26
  use BizStation\Transactd\Tabledef;
27
+ use BizStation\Transactd\Fielddef;
27
28
  use BizStation\Transactd\Database;
28
29
  use BizStation\Transactd\BtrVersions;
29
30
  use BizStation\Transactd\Nstable;
@@ -1429,4 +1430,38 @@ class TransactdTest extends PHPUnit_Framework_TestCase
1429
1430
  $this->assertEquals($tb->deleteByObject($usr, false/*inKey*/), false);
1430
1431
  $this->assertEquals($tb->deleteByObject($usr), true); //default value true
1431
1432
  }
1433
+
1434
+ public function testRecordsetJoin()
1435
+ {
1436
+ $db = new Database();
1437
+ $db->open(URI, Transactd::TYPE_SCHEMA_BDF, Transactd::TD_OPEN_NORMAL);
1438
+ $this->assertEquals($db->stat(), 0);
1439
+ $at = new ActiveTable($db, "user", Transactd::TD_OPEN_READONLY);
1440
+ $ate = new ActiveTable($db, "extention", Transactd::TD_OPEN_READONLY);
1441
+ $q = new Query;
1442
+ $q->where('id','>=', 1)->and_('id','<=',10);
1443
+ $rs = $at->index(0)->keyValue(1)->read($q);
1444
+ $this->assertEquals($rs->size(), 10);
1445
+ $q->reset()->where('id','>=', 1)->and_('id','<=',5);
1446
+ $rse = $ate->index(0)->keyValue(1)->read($q);
1447
+ $this->assertEquals($rse->size(), 5);
1448
+ $rs1 = clone($rs);
1449
+ $rq = new RecordsetQuery;
1450
+ $rq->when('id', '=', 'id');
1451
+ $rs1->join($rse, $rq);
1452
+ $this->assertEquals($rs1->size(), 5);
1453
+ $rs->outerJoin($rse, $rq);
1454
+ $this->assertEquals($rs->size(), 10);
1455
+
1456
+ // Recordset::appendField
1457
+ $n = $rs->fieldDefs()->size();
1458
+ $fd = new Fielddef;
1459
+ $fd->type = Transactd::ft_integer;
1460
+ $fd->len = 4;
1461
+ $fd->name = 'abc';
1462
+ $rs->appendField($fd);
1463
+ $this->assertEquals($n + 1, $rs->fieldDefs()->size());
1464
+ $rs->appendField($fd->name, $fd->type, $fd->len);
1465
+ $this->assertEquals($n + 2, $rs->fieldDefs()->size());
1466
+ }
1432
1467
  }
@@ -2114,4 +2114,44 @@ describe Transactd, 'V3Features' do
2114
2114
  tb.close
2115
2115
  db.close
2116
2116
  end
2117
+
2118
+ it 'recordset join' do
2119
+ db = Transactd::Database.new()
2120
+ db.open(URL, Transactd::TYPE_SCHEMA_BDF, Transactd::TD_OPEN_NORMAL)
2121
+ at = Transactd::ActiveTable.new(db, "user")
2122
+ ate = Transactd::ActiveTable.new(db, "extention")
2123
+
2124
+ q = Transactd::Query.new()
2125
+ q.where("id", ">=", 1).and_("id", "<=", 10)
2126
+ rs = at.index(0).keyValue(1).read(q)
2127
+ expect(rs.size).to eq 10
2128
+
2129
+ q.reset().where("id", ">=", 1).and_("id", "<=", 5)
2130
+ rse = ate.index(0).keyValue(1).read(q)
2131
+ expect(rse.size).to eq 5
2132
+
2133
+ rs1 = rs.clone();
2134
+ rq = Transactd::RecordsetQuery.new()
2135
+ rq.when('id', '=', 'id')
2136
+
2137
+ #Join
2138
+ rs1.join(rse, rq)
2139
+ expect(rs1.size).to eq 5
2140
+
2141
+ #outerJoin
2142
+ rs.outerJoin(rse, rq)
2143
+ expect(rs.size).to eq 10
2144
+
2145
+ #appendField
2146
+ n = rs.fieldDefs().size
2147
+ fd = Transactd::Fielddef.new()
2148
+ fd.name = 'abc'
2149
+ fd.len = 2
2150
+ fd.type = Transactd::Ft_integer
2151
+ rs.appendField(fd)
2152
+ expect(rs.fieldDefs().size).to eq n+1
2153
+ expect(rs.fieldDefs()[n].name).to eq 'abc'
2154
+ db.close
2155
+ end
2156
+
2117
2157
  end