/* 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, version 2.0, as published by the Free Software Foundation. This program is also distributed with certain software (including but not limited to OpenSSL) that is licensed under separate terms, as designated in a particular file or component or in included license documentation. The authors of MySQL hereby grant you an additional permission to link the program and your derivative works with the separately licensed software that they have included with MySQL. 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, version 2.0, 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 St, Fifth Floor, Boston, MA 02110-1301 USA */ #include #include #include #include #include #include #include #include #include #include <../../src/ndbapi/NdbApiSignal.hpp> #include #include #include 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); }