transactd 3.6.1 → 3.7.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.
- checksums.yaml +4 -4
- data/bin/common/{tdclc_32_3_6.dll → tdclc_32_3_7.dll} +0 -0
- data/bin/common/{tdclc_64_3_6.dll → tdclc_64_3_7.dll} +0 -0
- data/build/swig/ruby/tdclrb_wrap.cpp +125 -17
- data/build/tdclc/tdclc.cbproj +1 -1
- data/build/tdclc/tdclc.rc +4 -4
- data/build/tdclcpp/tdclcpp.rc +4 -4
- data/build/tdclcpp/tdclcpp_bc.cbproj +1 -1
- data/build/tdclrb/tdclrb.rc +4 -4
- data/source/bzs/db/protocol/tdap/client/field.cpp +24 -0
- data/source/bzs/db/protocol/tdap/client/field.h +2 -0
- data/source/bzs/db/protocol/tdap/client/groupQuery.cpp +243 -59
- data/source/bzs/db/protocol/tdap/client/groupQuery.h +8 -0
- data/source/bzs/db/protocol/tdap/client/memRecord.cpp +19 -6
- data/source/bzs/db/protocol/tdap/client/memRecord.h +10 -1
- data/source/bzs/db/protocol/tdap/client/recordset.cpp +17 -0
- data/source/bzs/db/protocol/tdap/client/recordset.h +3 -0
- data/source/bzs/db/protocol/tdap/client/recordsetImple.h +131 -30
- data/source/bzs/db/protocol/tdap/client/table.cpp +11 -2
- data/source/bzs/db/protocol/tdap/mysql/recordsetReader.h +1 -0
- data/source/bzs/db/protocol/tdap/tdapcapi.h +5 -5
- data/source/bzs/test/tdclatl/test_v3.js +22 -0
- data/source/bzs/test/tdclphp/transactd_v3_Test.php +35 -0
- data/source/bzs/test/tdclrb/transactd_v3_spec.rb +40 -0
- data/source/bzs/test/trdclengn/testField.h +320 -0
- data/source/bzs/test/trdclengn/test_tdclcpp_v3.cpp +9 -0
- data/source/global/tdclatl/Recordset.cpp +44 -2
- data/source/global/tdclatl/Recordset.h +6 -2
- data/source/global/tdclatl/tdclatl.idl +5 -1
- 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
|
-
|
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
|
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)
|
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
|
-
|
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(
|
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 "
|
673
|
-
#define C_INTERFACE_VER_RELEASE "
|
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 "
|
737
|
-
#define CPP_INTERFACE_VER_RELEASE "
|
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
|
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
|