30 #include <mysqld_error.h>
33 #include "NdbQueryBuilder.hpp"
34 #include "NdbQueryOperation.hpp"
41 #define PRINT_ERROR(code,msg) \
42 std::cout << "Error in " << __FILE__ << ", line: " << __LINE__ \
43 << ", code: " << code \
44 << ", msg: " << msg << "." << std::endl
45 #define MYSQLERROR(mysql) { \
46 PRINT_ERROR(mysql_errno(&mysql),mysql_error(&mysql)); \
48 #define PRINT_APIERROR(error) { \
49 PRINT_ERROR((error).code,(error).message); }
50 #define APIERROR(error) { \
51 PRINT_APIERROR(error); \
77 char first_name[14+1];
92 const char* employeeDef =
93 "CREATE TABLE employees ("
94 " emp_no INT NOT NULL,"
95 " dept_no CHAR(4) NOT NULL,"
96 " birth_date DATE NOT NULL,"
97 " first_name VARCHAR(14) NOT NULL,"
98 " last_name VARCHAR(16) NOT NULL,"
99 " gender ENUM ('M','F') NOT NULL, "
100 " hire_date DATE NOT NULL,"
101 " PRIMARY KEY (emp_no))"
104 const char* departmentsDef =
105 "CREATE TABLE departments ("
106 " dept_no CHAR(4) NOT NULL,"
107 " dept_name VARCHAR(40) NOT NULL,"
108 " PRIMARY KEY (dept_no),"
109 " UNIQUE KEY (dept_name))"
112 const char* dept_managerDef =
113 "CREATE TABLE dept_manager ("
114 " dept_no CHAR(4) NOT NULL,"
115 " emp_no INT NOT NULL,"
116 " from_date DATE NOT NULL,"
117 " to_date DATE NOT NULL,"
118 " my_key INT NOT NULL,"
123 " UNIQUE KEY MYINDEXNAME (my_key),"
124 " PRIMARY KEY (emp_no,dept_no))"
129 const char* dept_empDef =
130 "CREATE TABLE dept_emp ("
131 " emp_no INT NOT NULL,"
132 " dept_no CHAR(4) NOT NULL,"
133 " from_date DATE NOT NULL,"
134 " to_date DATE NOT NULL,"
137 " FOREIGN KEY (emp_no) REFERENCES employees (emp_no) ON DELETE CASCADE,"
138 " FOREIGN KEY (dept_no) REFERENCES departments (dept_no) ON DELETE CASCADE,"
139 " PRIMARY KEY (emp_no,dept_no))"
142 const char* titlesDef =
143 "CREATE TABLE titles ("
144 " emp_no INT NOT NULL,"
145 " title VARCHAR(50) NOT NULL,"
146 " from_date DATE NOT NULL,"
149 " FOREIGN KEY (emp_no) REFERENCES employees (emp_no) ON DELETE CASCADE,"
150 " PRIMARY KEY (emp_no,title, from_date))"
153 const char* salariesDef =
154 "CREATE TABLE salaries ("
155 " emp_no INT NOT NULL,"
156 " salary INT NOT NULL,"
157 " from_date DATE NOT NULL,"
158 " to_date DATE NOT NULL,"
160 " FOREIGN KEY (emp_no) REFERENCES employees (emp_no) ON DELETE CASCADE,"
161 " PRIMARY KEY (emp_no, from_date))"
165 int createEmployeeDb(
MYSQL& mysql)
169 mysql_query(&mysql,
"DROP DATABASE employees");
170 printf(
"Dropped existing employees DB\n");
171 mysql_query(&mysql,
"CREATE DATABASE employees");
172 mysql_commit(&mysql);
173 printf(
"Created new employees DB\n");
175 if (mysql_query(&mysql,
"USE employees") != 0) MYSQLERROR(mysql);
176 mysql_commit(&mysql);
177 printf(
"USE employees DB\n");
179 if (mysql_query(&mysql, employeeDef) != 0) MYSQLERROR(mysql);
180 mysql_commit(&mysql);
181 printf(
"Created 'employee' table\n");
183 if (mysql_query(&mysql, departmentsDef) != 0) MYSQLERROR(mysql);
184 mysql_commit(&mysql);
185 printf(
"Created 'departments' table\n");
187 if (mysql_query(&mysql, dept_managerDef) != 0) MYSQLERROR(mysql);
188 mysql_commit(&mysql);
189 printf(
"Created 'dept_manager' table\n");
191 if (mysql_query(&mysql, dept_empDef) != 0) MYSQLERROR(mysql);
192 mysql_commit(&mysql);
193 printf(
"Created 'dept_emp' table\n");
195 if (mysql_query(&mysql, titlesDef) != 0) MYSQLERROR(mysql);
196 mysql_commit(&mysql);
197 printf(
"Created 'titles' table\n");
199 if (mysql_query(&mysql, salariesDef) != 0) MYSQLERROR(mysql);
200 mysql_commit(&mysql);
201 printf(
"Created 'salaries' table\n");
204 printf(
"Insert simple test data\n");
206 if (mysql_query(&mysql,
"Insert into dept_manager(dept_no,emp_no,my_key) values ('d005',110567,110567)") != 0) MYSQLERROR(mysql);
207 mysql_commit(&mysql);
208 if (mysql_query(&mysql,
"Insert into dept_manager(dept_no,emp_no,my_key) values ('c005',11057,11067)") != 0) MYSQLERROR(mysql);
209 mysql_commit(&mysql);
210 if (mysql_query(&mysql,
"Insert into dept_manager(dept_no,emp_no,my_key) values ('e005',210567,210567)") != 0) MYSQLERROR(mysql);
211 mysql_commit(&mysql);
213 if (mysql_query(&mysql,
"Insert into dept_manager(dept_no,emp_no,my_key) values ('f005',210568,210568)") != 0) MYSQLERROR(mysql);
214 mysql_commit(&mysql);
215 if (mysql_query(&mysql,
"Insert into dept_manager(dept_no,emp_no,my_key) values ('g005',210569,210569)") != 0) MYSQLERROR(mysql);
216 mysql_commit(&mysql);
217 if (mysql_query(&mysql,
"Insert into dept_manager(dept_no,emp_no,my_key) values ('h005',210560,210560)") != 0) MYSQLERROR(mysql);
218 mysql_commit(&mysql);
219 if (mysql_query(&mysql,
"Insert into dept_manager(dept_no,emp_no,my_key) values ('i005',210561,210561)") != 0) MYSQLERROR(mysql);
220 mysql_commit(&mysql);
222 if (mysql_query(&mysql,
"Insert into employees(emp_no,dept_no) values (110567,'d005')") != 0) MYSQLERROR(mysql);
223 mysql_commit(&mysql);
234 static void init_ndbrecord_info(
Ndb &myNdb)
237 manager = myDict->
getTable(
"dept_manager");
238 employee= myDict->
getTable(
"employees");
239 salary = myDict->
getTable(
"salaries");
241 if (!employee || !manager || !salary)
244 rowManagerRecord = manager->getDefaultRecord();
245 if (rowManagerRecord == NULL) APIERROR(myDict->
getNdbError());
247 rowEmployeeRecord = employee->getDefaultRecord();
248 if (rowEmployeeRecord == NULL) APIERROR(myDict->
getNdbError());
250 rowSalaryRecord = salary->getDefaultRecord();
251 if (rowSalaryRecord == NULL) APIERROR(myDict->
getNdbError());
255 if (myPIndex == NULL)
258 indexSalaryRecord = myPIndex->getDefaultRecord();
259 if (indexSalaryRecord == NULL) APIERROR(myDict->
getNdbError());
272 int testQueryBuilder(
Ndb &myNdb)
279 const char* dept_no =
"d005";
280 Uint32 emp_no = 110567;
285 printf(
"\n -- Building query --\n");
288 manager = myDict->
getTable(
"dept_manager");
289 employee= myDict->
getTable(
"employees");
290 salary = myDict->
getTable(
"salaries");
292 if (!employee || !manager || !salary)
306 manager_dept_no = manager->
getColumn(
"dept_no");
307 if (manager_dept_no == NULL) APIERROR(myDict->
getNdbError());
308 manager_emp_no = manager->
getColumn(
"emp_no");
309 if (manager_emp_no == NULL) APIERROR(myDict->
getNdbError());
310 manager_from_date = manager->
getColumn(
"from_date");
311 if (manager_from_date == NULL) APIERROR(myDict->
getNdbError());
312 manager_to_date = manager->
getColumn(
"to_date");
313 if (manager_to_date == NULL) APIERROR(myDict->
getNdbError());
316 {manager_emp_no, offsetof(
ManagerRow, emp_no), 0,0},
319 {manager_to_date, offsetof(
ManagerRow, to_date), 0,0}
323 myDict->createRecord(manager, mngSpec, 2,
sizeof(mngSpec[0]));
324 if (rowManagerRecord == NULL) APIERROR(myDict->
getNdbError());
341 printf(
"Compare with old API interface\n");
345 if (myTransaction == NULL) APIERROR(myNdb.
getNdbError());
349 if (myPIndex == NULL)
353 myTransaction->
scanIndex(myPIndex->getDefaultRecord(),
366 bound.low_key=(
char*)&low;
367 bound.low_key_count=2;
368 bound.low_inclusive=
true;
369 bound.high_key=(
char*)&high;
370 bound.high_key_count=2;
371 bound.high_inclusive=
false;
374 if (ixScan->setBound(myPIndex->getDefaultRecord(), bound))
387 { qb->constValue(
"d005"),
388 qb->constValue(110567),
392 if (readManager == NULL) APIERROR(qb->
getNdbError());
412 qb->paramValue(
"emp"),
417 if (readManager == NULL) APIERROR(qb->
getNdbError());
459 { qb->constValue(
"d005"),
460 qb->constValue(110567),
465 qb->paramValue(
"emp"),
471 if (readManager == NULL) APIERROR(qb->
getNdbError());
478 { qb->linkedValue(readManager,
"emp_no"),
482 if (readEmployee == NULL) APIERROR(qb->
getNdbError());
496 if (myTransaction == NULL) APIERROR(myNdb.
getNdbError());
498 myQuery = myTransaction->
createQuery(q4,paramList);
505 for (Uint32
i=0;
i<myQuery->getNoOfOperations(); ++
i)
516 memset (&managerRow, 0,
sizeof(managerRow));
517 memset (&employeeRow, 0,
sizeof(employeeRow));
519 if (rowManagerRecord == NULL) APIERROR(myDict->
getNdbError());
522 if (rowEmployeeRecord == NULL) APIERROR(myDict->
getNdbError());
524 assert(myQuery->getNoOfOperations()==2);
533 printf(
"Start execute\n");
535 myQuery->getNdbError().code)
537 APIERROR(myQuery->getNdbError());
539 printf(
"Done executed\n");
543 res = myQuery->nextResult();
544 if (res == NdbQuery::NextResult_error)
545 APIERROR(myQuery->getNdbError());
548 printf(
"manager emp_no: %d\n", key[0][1]->u_32_value());
549 printf(
"employee emp_no: %d\n", key[1][0]->u_32_value());
550 assert(!key[0][1]->isNULL() && key[0][1]->u_32_value()==emp_no);
551 assert(!key[1][0]->isNULL() && key[1][0]->u_32_value()==emp_no);
554 printf(
"manager emp_no: %d\n", managerRow.emp_no);
555 printf(
"employee emp_no: %d\n", employeeRow.emp_no);
556 assert(managerRow.emp_no==emp_no);
557 assert(employeeRow.emp_no==emp_no);
583 if (readEmployee == NULL) APIERROR(qb->
getNdbError());
590 qb->linkedValue(readEmployee,
"emp_no"),
598 if (readManager == NULL) APIERROR(qb->
getNdbError());
600 q4_1 = qb->prepare();
615 if (myTransaction == NULL) APIERROR(myNdb.
getNdbError());
617 myQuery = myTransaction->
createQuery(q4_1,paramList_q4);
624 for (Uint32
i=0;
i<myQuery->getNoOfOperations(); ++
i)
634 memset (&managerRow, 0,
sizeof(managerRow));
635 memset (&employeeRow, 0,
sizeof(employeeRow));
637 if (rowEmployeeRecord == NULL) APIERROR(myDict->
getNdbError());
640 if (rowManagerRecord == NULL) APIERROR(myDict->
getNdbError());
642 assert(myQuery->getNoOfOperations()==2);
651 printf(
"Start execute\n");
653 myQuery->getNdbError().code)
655 APIERROR(myQuery->getNdbError());
657 printf(
"Done executed\n");
661 res = myQuery->nextResult();
662 if (res == NdbQuery::NextResult_error)
663 APIERROR(myQuery->getNdbError());
666 printf(
"employee emp_no: %d\n", value_q4[0][0]->u_32_value());
667 printf(
"manager emp_no: %d\n", value_q4[1][1]->u_32_value());
668 assert(!value_q4[0][0]->isNULL() && value_q4[0][0]->u_32_value()==emp_no);
669 assert(!value_q4[1][1]->isNULL() && value_q4[1][1]->u_32_value()==emp_no);
672 printf(
"employee emp_no: %d\n", employeeRow.emp_no);
673 printf(
"manager emp_no: %d\n", managerRow.emp_no);
674 assert(managerRow.emp_no==emp_no);
675 assert(employeeRow.emp_no==emp_no);
698 if (myPIndex == NULL)
710 if (readManager == NULL) APIERROR(qb->
getNdbError());
717 if (myTransaction == NULL) APIERROR(myNdb.
getNdbError());
720 myQuery = myTransaction->
createQuery(q5,paramList_q5);
734 memset (&managerRow, 0,
sizeof(managerRow));
736 if (rowManagerRecord == NULL) APIERROR(myDict->
getNdbError());
745 printf(
"Start execute\n");
747 myQuery->getNdbError().code)
749 APIERROR(myQuery->getNdbError());
751 printf(
"Done executed\n");
755 res = myQuery->nextResult();
756 if (res == NdbQuery::NextResult_error)
757 APIERROR(myQuery->getNdbError());
760 printf(
"employee emp_no: %d\n", value_q5[1]->u_32_value());
761 assert(!value_q5[1]->isNULL() && value_q5[1]->u_32_value()==emp_no);
763 printf(
"employee emp_no: %d\n", managerRow.emp_no);
764 assert(managerRow.emp_no==emp_no);
776 printf(
"q6: Table scan + linked lookup\n");
803 if (scanManager == NULL) APIERROR(qb->
getNdbError());
810 { qb->linkedValue(scanManager,
"emp_no"),
814 if (readEmployee == NULL) APIERROR(qb->
getNdbError());
821 if (myTransaction == NULL) APIERROR(myNdb.
getNdbError());
830 for (Uint32
i=0;
i<myQuery->getNoOfOperations(); ++
i)
842 if (rowManagerRecord == NULL) APIERROR(myDict->
getNdbError());
844 assert(myQuery->getNoOfOperations()==2);
851 if (rowEmployeeRecord == NULL) APIERROR(myDict->
getNdbError());
860 printf(
"Start execute\n");
862 myQuery->getNdbError().code)
864 APIERROR(myQuery->getNdbError());
869 memset (&managerRow, 0,
sizeof(managerRow));
870 memset (&employeeRow, 0,
sizeof(employeeRow));
876 if (res == NdbQuery::NextResult_error) {
877 PRINT_APIERROR(myQuery->getNdbError());
879 }
else if (res!=NdbQuery::NextResult_gotRow) {
884 printf(
"manager emp_no: %d, NULL:%d\n",
885 value_q6[0][1]->u_32_value(), myQuery->getQueryOperation(0
U)->isRowNULL());
886 printf(
"employee emp_no: %d, NULL:%d\n",
887 value_q6[1][0]->u_32_value(), myQuery->getQueryOperation(1
U)->isRowNULL());
890 printf(
"manager emp_no: %d, NULL:%d\n",
891 managerRow.emp_no, myQuery->getQueryOperation(0
U)->isRowNULL());
892 printf(
"employee emp_no: %d, NULL:%d\n",
893 employeeRow.emp_no, myQuery->getQueryOperation(1
U)->isRowNULL());
897 printf(
"EOF, %d rows\n", cnt);
907 printf(
"Ordered index scan + lookup\n");
915 if (myPIndex == NULL)
922 qb->constValue(
"d005"),
927 qb->constValue(110567),
928 qb->constValue(
"d005"),
936 if (scanManager == NULL) APIERROR(qb->
getNdbError());
943 { qb->linkedValue(scanManager,
"emp_no"),
947 if (readEmployee == NULL) APIERROR(qb->
getNdbError());
949 q6_1 = qb->prepare();
954 if (myTransaction == NULL) APIERROR(myNdb.
getNdbError());
957 myQuery = myTransaction->
createQuery(q6_1, paramList_q6_1);
964 for (Uint32
i=0;
i<myQuery->getNoOfOperations(); ++
i)
977 if (rowManagerRecord == NULL) APIERROR(myDict->
getNdbError());
979 assert(myQuery->getNoOfOperations()==2);
983 if (err) APIERROR(myQuery->getNdbError());
986 if (rowEmployeeRecord == NULL) APIERROR(myDict->
getNdbError());
991 if (err) APIERROR(myQuery->getNdbError());
995 printf(
"Start execute\n");
997 myQuery->getNdbError().code)
999 APIERROR(myQuery->getNdbError());
1001 printf(
"Done executed\n");
1005 memset (&managerRow, 0,
sizeof(managerRow));
1006 memset (&employeeRow, 0,
sizeof(employeeRow));
1012 if (res == NdbQuery::NextResult_error) {
1013 PRINT_APIERROR(myQuery->getNdbError());
1015 }
else if (res!=NdbQuery::NextResult_gotRow) {
1020 printf(
"manager emp_no: %d, NULL:%d\n",
1021 value_q6_1[0][1]->u_32_value(), myQuery->getQueryOperation(0
U)->isRowNULL());
1022 printf(
"employee emp_no: %d, NULL:%d\n",
1023 value_q6_1[1][0]->u_32_value(), myQuery->getQueryOperation(1
U)->isRowNULL());
1026 printf(
"manager emp_no: %d, NULL:%d\n",
1027 managerRow.emp_no, myQuery->getQueryOperation(0
U)->isRowNULL());
1028 printf(
"employee emp_no: %d, NULL:%d\n",
1029 employeeRow.emp_no, myQuery->getQueryOperation(1)->isRowNULL());
1034 printf(
"EOF, %d rows\n", cnt);
1048 main(
int argc,
const char** argv){
1050 std::cout <<
"Usage: " << argv[0]
1051 <<
" <mysql IP address> <mysql port> <cluster connect string>"
1055 const char*
const host=argv[1];
1056 const int port = atoi(argv[2]);
1057 const char*
const connectString = argv[3];
1063 if(!mysql_init(&mysql)){
1064 std::cout <<
"mysql_init() failed:" << std::endl;
1066 if(!mysql_real_connect(&mysql, host,
"root",
"",
"",
1068 std::cout <<
"mysql_real_connect() failed:" << std::endl;
1072 if (!createEmployeeDb(mysql))
1073 { std::cout <<
"Create of employee DB failed" << std::endl;
1076 mysql_close(&mysql);
1083 if (cluster_connection.connect(4, 5, 1))
1085 std::cout <<
"Unable to connect to cluster within 30 secs." << std::endl;
1089 if (cluster_connection.wait_until_ready(30,0) < 0)
1091 std::cout <<
"Cluster was not ready within 30 secs.\n";
1094 Ndb myNdb(&cluster_connection,
"employees");
1095 if (myNdb.
init(1024) == -1) {
1099 std::cout <<
"Connected to Cluster\n";
1106 bool has_tables =
true;
1109 if (myDict->
getTable(
"departments") == 0)
1110 { std::cout <<
"Table 'departments' not found" << std::endl;
1113 if (myDict->
getTable(
"employees") == 0)
1114 { std::cout <<
"Table 'employees' not found" << std::endl;
1117 if (myDict->
getTable(
"dept_emp") == 0)
1118 { std::cout <<
"Table 'dept_emp' not found" << std::endl;
1121 if (myDict->
getTable(
"dept_manager") == 0)
1122 { std::cout <<
"Table 'dept_manager' not found" << std::endl;
1125 if (myDict->
getTable(
"salaries") == 0)
1126 { std::cout <<
"Table 'salaries' not found" << std::endl;
1129 if (myDict->
getTable(
"titles") == 0)
1130 { std::cout <<
"Table 'titles' not found" << std::endl;
1134 { std::cout <<
"Table(s) was missing from the 'employees' DB" << std::endl;
1137 std::cout <<
"All tables in 'employees' DB was found" << std::endl;
1140 testQueryBuilder(myNdb);