transactd 3.6.1 → 3.7.0
Sign up to get free protection for your applications and to get access to all the features.
- 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
|