409 lines
12 KiB
C++

/*
Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved.
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; version 2 of the License.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA */
#include <stdio.h>
#include <time.h>
#include <mysqld_error.h>
#include <ndb_global.h>
#include <ndb_opts.h>
#include <NDBT.hpp>
#include <NdbApi.hpp>
#include <NdbSleep.h>
#include <HugoOperations.hpp>
#include <../../src/ndbapi/NdbApiSignal.hpp>
#include <kernel/signaldata/ScanTab.hpp>
#include <kernel/signaldata/QueryTree.hpp>
#include <kernel/AttributeHeader.hpp>
typedef uchar* gptr;
static int _scan = 0;
static const char* _dbname = "TEST_DB";
static struct my_option my_long_options[] =
{
NDB_STD_OPTS("spj_test"),
{ "database", 'd', "Name of database table is in",
(uchar**) &_dbname, (uchar**) &_dbname, 0,
GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0 },
{ "scan", 's', "Table scan followed by key lookup",
(uchar**) &_scan, (uchar**) &_scan, 0,
GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0 },
{ 0, 0, 0, 0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0}
};
class NdbScanFilterImpl
{
public:
static void set(NdbScanOperation* op, const Uint32 * src, Uint32 len) {
op->theTotalCurrAI_Len = 0;
op->attrInfoRemain = 0;
op->theFirstATTRINFO = 0;
op->insertATTRINFOData_NdbRecord((const char*)src, 4*len);
}
static void setIsLinkedFlag(NdbScanOperation* op){
ScanTabReq * req = (ScanTabReq*)(op->theSCAN_TABREQ->getDataPtrSend());
ScanTabReq::setViaSPJFlag(req->requestInfo, 1);
}
};
/**
* SQL:
drop table if exists t1;
create table t1 (a int primary key, b int not null) engine = ndb;
insert into t1 values (1,2), (2,3), (3,1);
*/
int main(int argc, char** argv)
{
NDB_INIT(argv[0]);
const char *load_default_groups[]= { "mysql_cluster",0 };
load_defaults("my",load_default_groups,&argc,&argv);
int ho_error;
#ifndef DBUG_OFF
opt_debug= "d:t:O,/tmp/ndb_desc.trace";
#endif
if ((ho_error=handle_options(&argc, &argv, my_long_options,
ndb_std_get_one_option)))
return NDBT_ProgramExit(NDBT_WRONGARGS);
Ndb_cluster_connection con(opt_ndb_connectstring);
if(con.connect(12, 5, 1) != 0)
{
ndbout << "Unable to connect to management server." << endl;
return NDBT_ProgramExit(NDBT_FAILED);
}
int res = con.wait_until_ready(30,30);
if (res != 0)
{
ndbout << "Cluster nodes not ready in 30 seconds." << endl;
return NDBT_ProgramExit(NDBT_FAILED);
}
Ndb MyNdb(&con, _dbname);
if(MyNdb.init() != 0){
ERR(MyNdb.getNdbError());
return NDBT_ProgramExit(NDBT_FAILED);
}
const NdbDictionary::Dictionary * dict= MyNdb.getDictionary();
const NdbDictionary::Table * pTab = dict->getTable(argv[0]);
if (pTab == 0)
{
ndbout_c("Failed to retreive table: \"%s\"", argv[0]);
exit(0);
}
else
{
ndbout_c("Retreived %s", argv[0]);
}
const NdbDictionary::Index * pIdx = dict->getIndex("PRIMARY", argv[0]);
if (pIdx == 0)
{
ndbout_c("Failed to retreive index PRIMARY for table: \"%s\"", argv[0]);
exit(0);
}
else
{
ndbout_c("Retreived index PRIMARY for table %s", argv[0]);
}
NdbTransaction * pTrans = MyNdb.startTransaction();
NdbScanOperation * pOp = pTrans->scanTable(pTab->getDefaultRecord(),
NdbOperation::LM_CommittedRead);
bool scanindexchild = false;
#if 0
/**
select STRAIGHT_JOIN *
from t1 join t1 as t2
where t2.a = t1.b and t1.b <= 100 and t2.b <= 3;
*
* - ScanFrag
* PI_ATTR_INTERPRET w/ values inlined
* - Lookup
* PI_ATTR_INTERPRET w/ values in subroutine section
*/
Uint32 request[] = {
// pos: 0
0x000d0002,
// ScanFragNode
0x00050002, // type/len
0x00000010, // bits
0x00000007, // table id
0x00000001, // table version
0x00010001, // #cnt linked / [ attr-list ]
// LookupNode
0x00070001, // type/len
0x00000003, // bits
0x00000007, // table id
0x00000001, // table version
0x00000001, // parent list
0x00000001, // key pattern: #parameters/#len
QueryPattern::col(0), // P_COL col = 0
// ScanFragParameters
0x000c0002, // type/len
0x00000009, // bits
0x10000018, // result data
0x00000005, // #len subroutine / #len interpreted program
0x00043017, // p0: BRANCH_ATTR_OP_COL | LE | OFFSET-JUMP
0x00010004, // p0: ATTRID / LEN of VALUE
0x00000064, // p1: VALUE (100)
0x00000012, // p2: EXIT_OK
0x03830013, // p3: EXIT_NOK
0x00000002, // len user projection
0xfff00002, // read all
0xffe90000, // read any value
// LookupParameters
0x000d0001, // type/len
0x00000009, // bits
0x1000001c, // result data
0x00020004, // #len subroutine / #len interpreted program
0x0003301a, // p0: BRANCH_ATTR_OP_COL2 | LE | OFFSET-JUMP
0x00010000, // p0: attrid: 1, param ref 0
0x00000012, // p1: EXIT_OK
0x03830013, // p2: EXIT_NOK
0x00000004, // param 0 header
0x00000003, // param 0 value (3)
0x00000002, // len user projection
0xfff00002, // read all
0xffe90000 // read any value
};
#elif 0
/**
* EXECUTE ?1 = 3
* select STRAIGHT_JOIN *
* from t1 join t1 as t2
* where t2.a = t1.b and t1.b <= 100 and t2.b <= ?1;
*
* - ScanFrag
* PI_ATTR_INTERPRET w/ values inlined
* - Lookup
* NI_ATTR_INTERPRET
* NI_ATTR_PARAMS & PI_ATTR_PARAMS
*/
Uint32 request[] = {
// pos: 0
0x000d0002,
// ScanFragNode
0x00050002, // type/len
0x00000010, // bits
0x00000007, // table id
0x00000001, // table version
0x00010001, // #cnt linked / [ attr-list ]
// LookupNode
0x000e0001, // type/len
DABits::NI_HAS_PARENT | DABits::NI_KEY_LINKED |
DABits::NI_ATTR_INTERPRET | DABits::NI_ATTR_PARAMS,
0x00000007, // table id
0x00000001, // table version
0x00000001, // parent list
0x00000001, // key pattern: #parameters/#len
QueryPattern::col(0), // P_COL col = 0
0x00010004, // attrinfo pattern: #len-pattern / #len interpreted program
0x0003301a, // p0: BRANCH_ATTR_OP_COL_2 | LE | OFFSET-JUMP
0x00010000, // p0: attrid: 1 / program param 0
0x00000012, // p1: EXIT_OK
0x03830013, // p2: EXIT_NOK
0x00000001, // attr-param pattern: #parameters
QueryPattern::paramHeader(0), // P_PARAM_WITH_HEADER col=0
// ScanFragParameters
0x000c0002, // type/len
0x00000009, // bits
0x10000018, // result data
0x00000005, // #len subroutine / #len interpreted program
0x00043017, // p0: BRANCH_ATTR_OP_COL | LE | OFFSET-JUMP
0x00010004, // p1: ATTRID / LEN of VALUE
0x00000064, // p2: VALUE (100)
0x00000012, // p3: EXIT_OK
0x03830013, // p4: EXIT_NOK
0x00000002, // len user projection
0xfff00002, // read all
0xffe90000, // read any value
// LookupParameters
0x00080001, // type/len
DABits::PI_ATTR_LIST | DABits::PI_ATTR_PARAMS, // bits
0x1000001c, // result data
0x00000004, // Param 0 header
0x00000003, // Param 0 value
0x00000002, // len user projection
0xfff00002, // read all
0xffe90000 // read any value
};
#elif 0
/**
*
* select STRAIGHT_JOIN *
* from t1 join t1 as t2
* where t2.a = t1.b and t1.b <= 100 and t2.b <= t1.b;
*
* - ScanFrag
* PI_ATTR_INTERPRET w/ values inlined
* - Lookup
* NI_ATTR_INTERPRET
* NI_ATTR_LINKED
*/
Uint32 request[] = {
// pos: 0
0x000d0002,
// ScanFragNode
0x00050002, // type/len
0x00000010, // bits
0x00000007, // table id
0x00000001, // table version
0x00010001, // #cnt linked / [ attr-list ]
// LookupNode
0x000e0001, // type/len
DABits::NI_HAS_PARENT | DABits::NI_KEY_LINKED |
DABits::NI_ATTR_INTERPRET | DABits::NI_ATTR_LINKED,
0x00000007, // table id
0x00000001, // table version
0x00000001, // parent list
0x00000001, // key pattern: #parameters/#len
QueryPattern::col(0), // P_COL col = 0
0x00010004, // attrinfo pattern: #len-pattern / #len interpreted program
0x0003301a, // p0: BRANCH_ATTR_OP_COL_2 | LE | OFFSET-JUMP
0x00010000, // p0: attrid: 1 / program param 0
0x00000012, // p1: EXIT_OK
0x03830013, // p2: EXIT_NOK
0x00000000, // attr-param pattern: #parameters
QueryPattern::attrInfo(0), // attr-param pattern: P_ATTRINFO col=0
// ScanFragParameters
0x000c0002, // type/len
0x00000009, // bits
0x10000018, // result data
0x00000005, // #len subroutine / #len interpreted program
0x00043017, // p0: BRANCH_ATTR_OP_COL | LE | OFFSET-JUMP
0x00010004, // p1: ATTRID / LEN of VALUE
0x00000064, // p2: VALUE (100)
0x00000012, // p3: EXIT_OK
0x03830013, // p4: EXIT_NOK
0x00000002, // len user projection
0xfff00002, // read all
0xffe90000, // read any value
// LookupParameters
0x00060001, // type/len
DABits::PI_ATTR_LIST, // bits
0x1000001c, // result data
0x00000002, // len user projection
0xfff00002, // read all
0xffe90000 // read any value
};
#else
/**
select STRAIGHT_JOIN *
from t1 join t1 as t2 on t2.a >= t1.b;
*/
scanindexchild = true;
Uint32 request[] = {
// pos: 0
0x000d0002,
// pos: 1 ScanFragNode
0x00050002, // len-type
DABits::NI_LINKED_ATTR, // bits
0x0000000c, // table id
0x00000001, // table version
0x00010001, // #cnt, linked attr
// pos: 6 ScanIndexNode
0x00090003, // type len
DABits::NI_HAS_PARENT | DABits::NI_KEY_LINKED, // bits
0x0000000b, // table id
0x00000001, // table version
0x00000001, // parent list
0x00000003, // key pattern (cnt/len)
QueryPattern::data(1), // P_DATA len = 1
0x00000002, // BoundLE
QueryPattern::attrInfo(0), // P_ATTRINFO col = 0
// pos: 15 ScanFragParameters
0x00080002, // type len
0x00000009, // bits
0x10000020, // result data
0x00000001, // param/len interpret program
0x00000012, // p1 = exit ok
0x00000002, // len user projection
0xfff00002, // up 1 - read all
0xffe90000, // up 2 - read any value
// pos: 23 ScanIndexParameters
0x000a0003, // type/len
0x00020009, // bits
0xffff0100, // batch size
0x10000024, // result data
0x00000001, // param/len interpret program
0x00000012, // p1 = exit ok
0x00000003, // len user projection
0xfff00002, // up 1 - read all
0xffe90000, // up 2 - read any value
0xfffb0000
};
#endif
Uint32 n0 = (request[1] >> 16);
Uint32 n1 = (request[1 + n0] >> 16);
request[0] = ((1 + n0 + n1) << 16) | 2;
request[1+2] = pTab->getObjectId();
request[1+3] = pTab->getObjectVersion();
if (scanindexchild == false)
{
request[1 + n0 + 2] = pTab->getObjectId();
request[1 + n0 + 3] = pTab->getObjectVersion();
}
else
{
request[1 + n0 + 2] = pIdx->getObjectId();
request[1 + n0 + 3] = pIdx->getObjectVersion();
}
NdbScanFilterImpl::setIsLinkedFlag(pOp);
NdbScanFilterImpl::set(pOp, request, NDB_ARRAY_SIZE(request));
pTrans->execute(NoCommit);
while (true) NdbSleep_SecSleep(1);
return NDBT_ProgramExit(NDBT_OK);
}