add 10 tpch style queries and test for them
This commit is contained in:
parent
42049b4d56
commit
36adab70c5
2
Makefile
2
Makefile
|
@ -10,7 +10,7 @@ LIBOBJ = $(LIBCPP:%.cpp=%.o)
|
||||||
TESTCPP = $(shell find test/ -name '*.cpp')
|
TESTCPP = $(shell find test/ -name '*.cpp')
|
||||||
|
|
||||||
ALLLIB = $(shell find $(SRC) -name '*.cpp' -not -path "$(SRCPARSER)/*") $(shell find $(SRC) -name '*.h' -not -path "$(SRCPARSER)/*")
|
ALLLIB = $(shell find $(SRC) -name '*.cpp' -not -path "$(SRCPARSER)/*") $(shell find $(SRC) -name '*.h' -not -path "$(SRCPARSER)/*")
|
||||||
ALLTEST = $(shell find test/lib/ -name '*.cpp') $(shell find test/lib/ -name '*.h')
|
ALLTEST = $(shell find test/ -name '*.cpp') $(shell find test/ -name '*.h')
|
||||||
|
|
||||||
# compile & link flages
|
# compile & link flages
|
||||||
CFLAGS = -std=c++11 -Wall -fPIC -g
|
CFLAGS = -std=c++11 -Wall -fPIC -g
|
||||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -138,7 +138,7 @@ namespace hsql {
|
||||||
placeholders.push_back((Expr*) e);
|
placeholders.push_back((Expr*) e);
|
||||||
}
|
}
|
||||||
// Sort by col-id
|
// Sort by col-id
|
||||||
std::sort(placeholders.begin(), placeholders.end(), [](Expr* i, Expr* j) -> bool { return (i->ival < j->ival); });
|
std::sort(placeholders.begin(), placeholders.end(), [](Expr * i, Expr * j) -> bool { return (i->ival < j->ival); });
|
||||||
|
|
||||||
// Set the placeholder id on the Expr. This replaces the previously stored column id
|
// Set the placeholder id on the Expr. This replaces the previously stored column id
|
||||||
for (uintmax_t i = 0; i < placeholders.size(); ++i) placeholders[i]->ival = i;
|
for (uintmax_t i = 0; i < placeholders.size(); ++i) placeholders[i]->ival = i;
|
||||||
|
|
|
@ -0,0 +1,9 @@
|
||||||
|
-- http://www.sqlserver-dba.com/2011/09/this-is-a-followup-on-my-earlier-post-of-sql-server-test-data-generation-testing-tools-i-had-some-requests-for-my-set-up-pr.html
|
||||||
|
SELECT L_RETURNFLAG, L_LINESTATUS, SUM(L_QUANTITY) AS SUM_QTY,
|
||||||
|
SUM(L_EXTENDEDPRICE) AS SUM_BASE_PRICE, SUM(L_EXTENDEDPRICE*(1-L_DISCOUNT)) AS SUM_DISC_PRICE,
|
||||||
|
SUM(L_EXTENDEDPRICE*(1-L_DISCOUNT)*(1+L_TAX)) AS SUM_CHARGE, AVG(L_QUANTITY) AS AVG_QTY,
|
||||||
|
AVG(L_EXTENDEDPRICE) AS AVG_PRICE, AVG(L_DISCOUNT) AS AVG_DISC, COUNT(*) AS COUNT_ORDER
|
||||||
|
FROM LINEITEM
|
||||||
|
WHERE L_SHIPDATE <= dateadd(dd, -90, cast('1998-12-01' as datetime))
|
||||||
|
GROUP BY L_RETURNFLAG, L_LINESTATUS
|
||||||
|
ORDER BY L_RETURNFLAG,L_LINESTATUS
|
|
@ -0,0 +1,10 @@
|
||||||
|
-- http://www.sqlserver-dba.com/2011/09/this-is-a-followup-on-my-earlier-post-of-sql-server-test-data-generation-testing-tools-i-had-some-requests-for-my-set-up-pr.html
|
||||||
|
SELECT TOP 100 S_ACCTBAL, S_NAME, N_NAME, P_PARTKEY, P_MFGR, S_ADDRESS, S_PHONE, S_COMMENT
|
||||||
|
FROM PART, SUPPLIER, PARTSUPP, NATION, REGION
|
||||||
|
WHERE P_PARTKEY = PS_PARTKEY AND S_SUPPKEY = PS_SUPPKEY AND P_SIZE = 15 AND
|
||||||
|
P_TYPE LIKE '%%BRASS' AND S_NATIONKEY = N_NATIONKEY AND N_REGIONKEY = R_REGIONKEY AND
|
||||||
|
R_NAME = 'EUROPE' AND
|
||||||
|
PS_SUPPLYCOST = (SELECT MIN(PS_SUPPLYCOST) FROM PARTSUPP, SUPPLIER, NATION, REGION
|
||||||
|
WHERE P_PARTKEY = PS_PARTKEY AND S_SUPPKEY = PS_SUPPKEY
|
||||||
|
AND S_NATIONKEY = N_NATIONKEY AND N_REGIONKEY = R_REGIONKEY AND R_NAME = 'EUROPE')
|
||||||
|
ORDER BY S_ACCTBAL DESC, N_NAME, S_NAME, P_PARTKEY
|
|
@ -0,0 +1,7 @@
|
||||||
|
-- http://www.sqlserver-dba.com/2011/09/this-is-a-followup-on-my-earlier-post-of-sql-server-test-data-generation-testing-tools-i-had-some-requests-for-my-set-up-pr.html
|
||||||
|
SELECT TOP 10 L_ORDERKEY, SUM(L_EXTENDEDPRICE*(1-L_DISCOUNT)) AS REVENUE, O_ORDERDATE, O_SHIPPRIORITY
|
||||||
|
FROM CUSTOMER, ORDERS, LINEITEM
|
||||||
|
WHERE C_MKTSEGMENT = 'BUILDING' AND C_CUSTKEY = O_CUSTKEY AND L_ORDERKEY = O_ORDERKEY AND
|
||||||
|
O_ORDERDATE < '1995-03-15' AND L_SHIPDATE > '1995-03-15'
|
||||||
|
GROUP BY L_ORDERKEY, O_ORDERDATE, O_SHIPPRIORITY
|
||||||
|
ORDER BY REVENUE DESC, O_ORDERDATE;
|
|
@ -0,0 +1,6 @@
|
||||||
|
-- http://www.sqlserver-dba.com/2011/09/this-is-a-followup-on-my-earlier-post-of-sql-server-test-data-generation-testing-tools-i-had-some-requests-for-my-set-up-pr.html
|
||||||
|
SELECT O_ORDERPRIORITY, COUNT(*) AS ORDER_COUNT FROM ORDERS
|
||||||
|
WHERE O_ORDERDATE >= '1993-07-01' AND O_ORDERDATE < dateadd(mm,3, cast('1993-07-01' as datetime))
|
||||||
|
AND EXISTS (SELECT * FROM LINEITEM WHERE L_ORDERKEY = O_ORDERKEY AND L_COMMITDATE < L_RECEIPTDATE)
|
||||||
|
GROUP BY O_ORDERPRIORITY
|
||||||
|
ORDER BY O_ORDERPRIORITY
|
|
@ -0,0 +1,9 @@
|
||||||
|
-- http://www.sqlserver-dba.com/2011/09/this-is-a-followup-on-my-earlier-post-of-sql-server-test-data-generation-testing-tools-i-had-some-requests-for-my-set-up-pr.html
|
||||||
|
SELECT N_NAME, SUM(L_EXTENDEDPRICE*(1-L_DISCOUNT)) AS REVENUE
|
||||||
|
FROM CUSTOMER, ORDERS, LINEITEM, SUPPLIER, NATION, REGION
|
||||||
|
WHERE C_CUSTKEY = O_CUSTKEY AND L_ORDERKEY = O_ORDERKEY AND L_SUPPKEY = S_SUPPKEY
|
||||||
|
AND C_NATIONKEY = S_NATIONKEY AND S_NATIONKEY = N_NATIONKEY AND N_REGIONKEY = R_REGIONKEY
|
||||||
|
AND R_NAME = 'ASIA' AND O_ORDERDATE >= '1994-01-01'
|
||||||
|
AND O_ORDERDATE < DATEADD(YY, 1, cast('1994-01-01' as datetime))
|
||||||
|
GROUP BY N_NAME
|
||||||
|
ORDER BY REVENUE DESC
|
|
@ -0,0 +1,5 @@
|
||||||
|
-- http://www.sqlserver-dba.com/2011/09/this-is-a-followup-on-my-earlier-post-of-sql-server-test-data-generation-testing-tools-i-had-some-requests-for-my-set-up-pr.html
|
||||||
|
SELECT SUM(L_EXTENDEDPRICE*L_DISCOUNT) AS REVENUE
|
||||||
|
FROM LINEITEM
|
||||||
|
WHERE L_SHIPDATE >= '1994-01-01' AND L_SHIPDATE < dateadd(yy, 1, cast('1994-01-01' as datetime))
|
||||||
|
AND L_DISCOUNT BETWEEN .06 - 0.01 AND .06 + 0.01 AND L_QUANTITY < 24
|
|
@ -0,0 +1,11 @@
|
||||||
|
-- http://www.sqlserver-dba.com/2011/09/this-is-a-followup-on-my-earlier-post-of-sql-server-test-data-generation-testing-tools-i-had-some-requests-for-my-set-up-pr.html
|
||||||
|
SELECT SUPP_NATION, CUST_NATION, L_YEAR, SUM(VOLUME) AS REVENUE
|
||||||
|
FROM ( SELECT N1.N_NAME AS SUPP_NATION, N2.N_NAME AS CUST_NATION, datepart(yy, L_SHIPDATE) AS L_YEAR,
|
||||||
|
L_EXTENDEDPRICE*(1-L_DISCOUNT) AS VOLUME
|
||||||
|
FROM SUPPLIER, LINEITEM, ORDERS, CUSTOMER, NATION N1, NATION N2
|
||||||
|
WHERE S_SUPPKEY = L_SUPPKEY AND O_ORDERKEY = L_ORDERKEY AND C_CUSTKEY = O_CUSTKEY
|
||||||
|
AND S_NATIONKEY = N1.N_NATIONKEY AND C_NATIONKEY = N2.N_NATIONKEY AND ((N1.N_NAME = 'FRANCE' AND N2.N_NAME = 'GERMANY') OR
|
||||||
|
(N1.N_NAME = 'GERMANY' AND N2.N_NAME = 'FRANCE')) AND
|
||||||
|
L_SHIPDATE BETWEEN '1995-01-01' AND '1996-12-31' ) AS SHIPPING
|
||||||
|
GROUP BY SUPP_NATION, CUST_NATION, L_YEAR
|
||||||
|
ORDER BY SUPP_NATION, CUST_NATION, L_YEAR
|
|
@ -0,0 +1,10 @@
|
||||||
|
-- http://www.sqlserver-dba.com/2011/09/this-is-a-followup-on-my-earlier-post-of-sql-server-test-data-generation-testing-tools-i-had-some-requests-for-my-set-up-pr.html
|
||||||
|
SELECT O_YEAR, SUM(CASE WHEN NATION = 'BRAZIL' THEN VOLUME ELSE 0 END)/SUM(VOLUME) AS MKT_SHARE
|
||||||
|
FROM (SELECT datepart(yy,O_ORDERDATE) AS O_YEAR, L_EXTENDEDPRICE*(1-L_DISCOUNT) AS VOLUME, N2.N_NAME AS NATION
|
||||||
|
FROM PART, SUPPLIER, LINEITEM, ORDERS, CUSTOMER, NATION N1, NATION N2, REGION
|
||||||
|
WHERE P_PARTKEY = L_PARTKEY AND S_SUPPKEY = L_SUPPKEY AND L_ORDERKEY = O_ORDERKEY
|
||||||
|
AND O_CUSTKEY = C_CUSTKEY AND C_NATIONKEY = N1.N_NATIONKEY AND
|
||||||
|
N1.N_REGIONKEY = R_REGIONKEY AND R_NAME = 'AMERICA' AND S_NATIONKEY = N2.N_NATIONKEY
|
||||||
|
AND O_ORDERDATE BETWEEN '1995-01-01' AND '1996-12-31' AND P_TYPE= 'ECONOMY ANODIZED STEEL') AS ALL_NATIONS
|
||||||
|
GROUP BY O_YEAR
|
||||||
|
ORDER BY O_YEAR
|
|
@ -0,0 +1,10 @@
|
||||||
|
-- http://www.sqlserver-dba.com/2011/09/this-is-a-followup-on-my-earlier-post-of-sql-server-test-data-generation-testing-tools-i-had-some-requests-for-my-set-up-pr.html
|
||||||
|
SELECT NATION, O_YEAR, SUM(AMOUNT) AS SUM_PROFIT
|
||||||
|
FROM (SELECT N_NAME AS NATION, datepart(yy, O_ORDERDATE) AS O_YEAR,
|
||||||
|
L_EXTENDEDPRICE*(1-L_DISCOUNT)-PS_SUPPLYCOST*L_QUANTITY AS AMOUNT
|
||||||
|
FROM PART, SUPPLIER, LINEITEM, PARTSUPP, ORDERS, NATION
|
||||||
|
WHERE S_SUPPKEY = L_SUPPKEY AND PS_SUPPKEY= L_SUPPKEY AND PS_PARTKEY = L_PARTKEY AND
|
||||||
|
P_PARTKEY= L_PARTKEY AND O_ORDERKEY = L_ORDERKEY AND S_NATIONKEY = N_NATIONKEY AND
|
||||||
|
P_NAME LIKE '%%green%%') AS PROFIT
|
||||||
|
GROUP BY NATION, O_YEAR
|
||||||
|
ORDER BY NATION, O_YEAR DESC
|
|
@ -0,0 +1,9 @@
|
||||||
|
-- http://www.sqlserver-dba.com/2011/09/this-is-a-followup-on-my-earlier-post-of-sql-server-test-data-generation-testing-tools-i-had-some-requests-for-my-set-up-pr.html
|
||||||
|
SELECT TOP 20 C_CUSTKEY, C_NAME, SUM(L_EXTENDEDPRICE*(1-L_DISCOUNT)) AS REVENUE, C_ACCTBAL,
|
||||||
|
N_NAME, C_ADDRESS, C_PHONE, C_COMMENT
|
||||||
|
FROM CUSTOMER, ORDERS, LINEITEM, NATION
|
||||||
|
WHERE C_CUSTKEY = O_CUSTKEY AND L_ORDERKEY = O_ORDERKEY AND O_ORDERDATE>= '1993-10-01' AND
|
||||||
|
O_ORDERDATE < dateadd(mm, 3, cast('1993-10-01' as datetime)) AND
|
||||||
|
L_RETURNFLAG = 'R' AND C_NATIONKEY = N_NATIONKEY
|
||||||
|
GROUP BY C_CUSTKEY, C_NAME, C_ACCTBAL, C_PHONE, N_NAME, C_ADDRESS, C_COMMENT
|
||||||
|
ORDER BY REVENUE DESC
|
|
@ -13,96 +13,96 @@ using namespace hsql;
|
||||||
|
|
||||||
|
|
||||||
std::vector<std::string> readlines(std::string path) {
|
std::vector<std::string> readlines(std::string path) {
|
||||||
std::ifstream infile(path);
|
std::ifstream infile(path);
|
||||||
std::vector<std::string> lines;
|
std::vector<std::string> lines;
|
||||||
std::string line;
|
std::string line;
|
||||||
while (std::getline(infile, line)) {
|
while (std::getline(infile, line)) {
|
||||||
std::istringstream iss(line);
|
std::istringstream iss(line);
|
||||||
|
|
||||||
// Skip comments
|
// Skip comments
|
||||||
if (line[0] == '#' ||
|
if (line[0] == '#' ||
|
||||||
(line[0] == '-' && line[1] == '-')) {
|
(line[0] == '-' && line[1] == '-')) {
|
||||||
continue;
|
continue;
|
||||||
}
|
|
||||||
|
|
||||||
lines.push_back(line);
|
|
||||||
}
|
}
|
||||||
return lines;
|
|
||||||
|
lines.push_back(line);
|
||||||
|
}
|
||||||
|
return lines;
|
||||||
}
|
}
|
||||||
|
|
||||||
#define STREQ(a, b) (std::string(a).compare(std::string(b)) == 0)
|
#define STREQ(a, b) (std::string(a).compare(std::string(b)) == 0)
|
||||||
|
|
||||||
TEST(AutoGrammarTest) {
|
TEST(AutoGrammarTest) {
|
||||||
const std::vector<std::string>& args = mt::Runtime::args();
|
const std::vector<std::string>& args = mt::Runtime::args();
|
||||||
if (args.size() <= 1) {
|
if (args.size() <= 1) {
|
||||||
fprintf(stderr, "Usage: grammar_test [--false] [-f path] query, ...\n");
|
fprintf(stderr, "Usage: grammar_test [--false] [-f path] query, ...\n");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool globalExpectFalse = false;
|
bool globalExpectFalse = false;
|
||||||
bool useFile = false;
|
bool useFile = false;
|
||||||
std::string filePath = "";
|
std::string filePath = "";
|
||||||
|
|
||||||
// Parse command line arguments
|
// Parse command line arguments
|
||||||
uint i = 1;
|
uint i = 1;
|
||||||
for (; i < args.size(); ++i) {
|
for (; i < args.size(); ++i) {
|
||||||
if (STREQ(args[i], "--false")) globalExpectFalse = true;
|
if (STREQ(args[i], "--false")) globalExpectFalse = true;
|
||||||
else if (STREQ(args[i], "-f")) {
|
else if (STREQ(args[i], "-f")) {
|
||||||
useFile = true;
|
useFile = true;
|
||||||
filePath = args[++i];
|
filePath = args[++i];
|
||||||
} else {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
// Read list of queries for this rest
|
|
||||||
std::vector<std::string> queries;
|
|
||||||
if (useFile) {
|
|
||||||
queries = readlines(filePath);
|
|
||||||
} else {
|
} else {
|
||||||
for (; i < args.size(); ++i) queries.push_back(args[i]);
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// Read list of queries for this rest
|
||||||
|
std::vector<std::string> queries;
|
||||||
|
if (useFile) {
|
||||||
|
queries = readlines(filePath);
|
||||||
|
} else {
|
||||||
|
for (; i < args.size(); ++i) queries.push_back(args[i]);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// Execute queries
|
||||||
|
int numFailed = 0;
|
||||||
|
for (std::string sql : queries) {
|
||||||
|
bool expectFalse = globalExpectFalse;
|
||||||
|
if (sql.at(0) == '!') {
|
||||||
|
expectFalse = !expectFalse;
|
||||||
|
sql = sql.substr(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Measuring the parsing time
|
||||||
|
std::chrono::time_point<std::chrono::system_clock> start, end;
|
||||||
|
start = std::chrono::system_clock::now();
|
||||||
|
|
||||||
// Execute queries
|
// Parsing
|
||||||
int numFailed = 0;
|
SQLParserResult* result = SQLParser::parseSQLString(sql.c_str());
|
||||||
for (std::string sql : queries) {
|
|
||||||
bool expectFalse = globalExpectFalse;
|
|
||||||
if (sql.at(0) == '!') {
|
|
||||||
expectFalse = !expectFalse;
|
|
||||||
sql = sql.substr(1);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Measuring the parsing time
|
end = std::chrono::system_clock::now();
|
||||||
std::chrono::time_point<std::chrono::system_clock> start, end;
|
std::chrono::duration<double> elapsed_seconds = end - start;
|
||||||
start = std::chrono::system_clock::now();
|
double us = elapsed_seconds.count() * 1000 * 1000;
|
||||||
|
|
||||||
// Parsing
|
if (expectFalse == result->isValid()) {
|
||||||
SQLParserResult* result = SQLParser::parseSQLString(sql.c_str());
|
printf("\033[0;31m{ failed}\033[0m\n");
|
||||||
|
printf("\t\033[0;31m%s (L%d:%d)\n\033[0m", result->errorMsg(), result->errorLine(), result->errorColumn());
|
||||||
end = std::chrono::system_clock::now();
|
printf("\t%s\n", sql.c_str());
|
||||||
std::chrono::duration<double> elapsed_seconds = end-start;
|
numFailed++;
|
||||||
double us = elapsed_seconds.count() * 1000 * 1000;
|
|
||||||
|
|
||||||
if (expectFalse == result->isValid()) {
|
|
||||||
printf("\033[0;31m{ failed}\033[0m\n");
|
|
||||||
printf("\t\033[0;31m%s (L%d:%d)\n\033[0m", result->errorMsg(), result->errorLine(), result->errorColumn());
|
|
||||||
printf("\t%s\n", sql.c_str());
|
|
||||||
numFailed++;
|
|
||||||
} else {
|
|
||||||
// TODO: indicate whether expectFalse was set
|
|
||||||
printf("\033[0;32m{ ok} (%.1fus)\033[0m %s\n", us, sql.c_str());
|
|
||||||
}
|
|
||||||
|
|
||||||
delete result;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (numFailed == 0) {
|
|
||||||
printf("\033[0;32m{ ok} \033[0mAll %lu grammar tests completed successfully!\n", queries.size());
|
|
||||||
} else {
|
} else {
|
||||||
fprintf(stderr, "\033[0;31m{ failed} \033[0mSome grammar tests failed! %d out of %lu tests failed!\n", numFailed, queries.size());
|
// TODO: indicate whether expectFalse was set
|
||||||
|
printf("\033[0;32m{ ok} (%.1fus)\033[0m %s\n", us, sql.c_str());
|
||||||
}
|
}
|
||||||
ASSERT_EQ(numFailed, 0);
|
|
||||||
|
delete result;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (numFailed == 0) {
|
||||||
|
printf("\033[0;32m{ ok} \033[0mAll %lu grammar tests completed successfully!\n", queries.size());
|
||||||
|
} else {
|
||||||
|
fprintf(stderr, "\033[0;31m{ failed} \033[0mSome grammar tests failed! %d out of %lu tests failed!\n", numFailed, queries.size());
|
||||||
|
}
|
||||||
|
ASSERT_EQ(numFailed, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -11,160 +11,161 @@ using namespace hsql;
|
||||||
|
|
||||||
|
|
||||||
TEST(DeleteStatementTest) {
|
TEST(DeleteStatementTest) {
|
||||||
const SQLParserResult* result = SQLParser::parseSQLString("DELETE FROM students WHERE grade > 2.0;");
|
const SQLParserResult* result = SQLParser::parseSQLString("DELETE FROM students WHERE grade > 2.0;");
|
||||||
ASSERT(result->isValid());
|
ASSERT(result->isValid());
|
||||||
ASSERT_EQ(result->size(), 1);
|
ASSERT_EQ(result->size(), 1);
|
||||||
ASSERT(result->getStatement(0)->type() == kStmtDelete);
|
ASSERT(result->getStatement(0)->type() == kStmtDelete);
|
||||||
|
|
||||||
const DeleteStatement* stmt = (const DeleteStatement*) result->getStatement(0);
|
const DeleteStatement* stmt = (const DeleteStatement*) result->getStatement(0);
|
||||||
ASSERT_STREQ(stmt->tableName, "students");
|
ASSERT_STREQ(stmt->tableName, "students");
|
||||||
ASSERT_NOTNULL(stmt->expr);
|
ASSERT_NOTNULL(stmt->expr);
|
||||||
ASSERT(stmt->expr->isType(kExprOperator));
|
ASSERT(stmt->expr->isType(kExprOperator));
|
||||||
ASSERT_STREQ(stmt->expr->expr->name, "grade");
|
ASSERT_STREQ(stmt->expr->expr->name, "grade");
|
||||||
ASSERT_EQ(stmt->expr->expr2->fval, 2.0);
|
ASSERT_EQ(stmt->expr->expr2->fval, 2.0);
|
||||||
|
|
||||||
delete result;
|
delete result;
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST(CreateStatementTest) {
|
TEST(CreateStatementTest) {
|
||||||
const SQLParserResult* result = SQLParser::parseSQLString("CREATE TABLE students (name TEXT, student_number INT, city INTEGER, grade DOUBLE)");
|
const SQLParserResult* result = SQLParser::parseSQLString("CREATE TABLE students (name TEXT, student_number INT, city INTEGER, grade DOUBLE)");
|
||||||
ASSERT(result->isValid());
|
ASSERT(result->isValid());
|
||||||
ASSERT_EQ(result->size(), 1);
|
ASSERT_EQ(result->size(), 1);
|
||||||
ASSERT_EQ(result->getStatement(0)->type(), kStmtCreate);
|
ASSERT_EQ(result->getStatement(0)->type(), kStmtCreate);
|
||||||
|
|
||||||
const CreateStatement* stmt = (const CreateStatement*) result->getStatement(0);
|
const CreateStatement* stmt = (const CreateStatement*) result->getStatement(0);
|
||||||
ASSERT_EQ(stmt->type, CreateStatement::kTable);
|
ASSERT_EQ(stmt->type, CreateStatement::kTable);
|
||||||
ASSERT_STREQ(stmt->tableName, "students");
|
ASSERT_STREQ(stmt->tableName, "students");
|
||||||
ASSERT_NOTNULL(stmt->columns);
|
ASSERT_NOTNULL(stmt->columns);
|
||||||
ASSERT_EQ(stmt->columns->size(), 4);
|
ASSERT_EQ(stmt->columns->size(), 4);
|
||||||
ASSERT_STREQ(stmt->columns->at(0)->name, "name");
|
ASSERT_STREQ(stmt->columns->at(0)->name, "name");
|
||||||
ASSERT_STREQ(stmt->columns->at(1)->name, "student_number");
|
ASSERT_STREQ(stmt->columns->at(1)->name, "student_number");
|
||||||
ASSERT_STREQ(stmt->columns->at(2)->name, "city");
|
ASSERT_STREQ(stmt->columns->at(2)->name, "city");
|
||||||
ASSERT_STREQ(stmt->columns->at(3)->name, "grade");
|
ASSERT_STREQ(stmt->columns->at(3)->name, "grade");
|
||||||
ASSERT_EQ(stmt->columns->at(0)->type, ColumnDefinition::TEXT);
|
ASSERT_EQ(stmt->columns->at(0)->type, ColumnDefinition::TEXT);
|
||||||
ASSERT_EQ(stmt->columns->at(1)->type, ColumnDefinition::INT);
|
ASSERT_EQ(stmt->columns->at(1)->type, ColumnDefinition::INT);
|
||||||
ASSERT_EQ(stmt->columns->at(2)->type, ColumnDefinition::INT);
|
ASSERT_EQ(stmt->columns->at(2)->type, ColumnDefinition::INT);
|
||||||
ASSERT_EQ(stmt->columns->at(3)->type, ColumnDefinition::DOUBLE);
|
ASSERT_EQ(stmt->columns->at(3)->type, ColumnDefinition::DOUBLE);
|
||||||
|
|
||||||
delete result;
|
delete result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
TEST(UpdateStatementTest) {
|
TEST(UpdateStatementTest) {
|
||||||
const SQLParserResult* result = SQLParser::parseSQLString("UPDATE students SET grade = 5.0, name = 'test' WHERE name = 'Max Mustermann';");
|
const SQLParserResult* result = SQLParser::parseSQLString("UPDATE students SET grade = 5.0, name = 'test' WHERE name = 'Max Mustermann';");
|
||||||
ASSERT(result->isValid());
|
ASSERT(result->isValid());
|
||||||
ASSERT_EQ(result->size(), 1);
|
ASSERT_EQ(result->size(), 1);
|
||||||
ASSERT_EQ(result->getStatement(0)->type(), kStmtUpdate);
|
ASSERT_EQ(result->getStatement(0)->type(), kStmtUpdate);
|
||||||
|
|
||||||
const UpdateStatement* stmt = (const UpdateStatement*) result->getStatement(0);
|
const UpdateStatement* stmt = (const UpdateStatement*) result->getStatement(0);
|
||||||
ASSERT_NOTNULL(stmt->table);
|
ASSERT_NOTNULL(stmt->table);
|
||||||
ASSERT_STREQ(stmt->table->name, "students");
|
ASSERT_STREQ(stmt->table->name, "students");
|
||||||
|
|
||||||
ASSERT_NOTNULL(stmt->updates);
|
ASSERT_NOTNULL(stmt->updates);
|
||||||
ASSERT_EQ(stmt->updates->size(), 2);
|
ASSERT_EQ(stmt->updates->size(), 2);
|
||||||
ASSERT_STREQ(stmt->updates->at(0)->column, "grade");
|
ASSERT_STREQ(stmt->updates->at(0)->column, "grade");
|
||||||
ASSERT_STREQ(stmt->updates->at(1)->column, "name");
|
ASSERT_STREQ(stmt->updates->at(1)->column, "name");
|
||||||
ASSERT(stmt->updates->at(0)->value->isType(kExprLiteralFloat));
|
ASSERT(stmt->updates->at(0)->value->isType(kExprLiteralFloat));
|
||||||
ASSERT(stmt->updates->at(1)->value->isType(kExprLiteralString));
|
ASSERT(stmt->updates->at(1)->value->isType(kExprLiteralString));
|
||||||
ASSERT_EQ(stmt->updates->at(0)->value->fval, 5.0);
|
ASSERT_EQ(stmt->updates->at(0)->value->fval, 5.0);
|
||||||
ASSERT_STREQ(stmt->updates->at(1)->value->name, "test");
|
ASSERT_STREQ(stmt->updates->at(1)->value->name, "test");
|
||||||
|
|
||||||
ASSERT_NOTNULL(stmt->where);
|
ASSERT_NOTNULL(stmt->where);
|
||||||
ASSERT(stmt->where->isType(kExprOperator));
|
ASSERT(stmt->where->isType(kExprOperator));
|
||||||
ASSERT(stmt->where->isSimpleOp('='));
|
ASSERT(stmt->where->isSimpleOp('='));
|
||||||
ASSERT_STREQ(stmt->where->expr->name, "name");
|
ASSERT_STREQ(stmt->where->expr->name, "name");
|
||||||
ASSERT_STREQ(stmt->where->expr2->name, "Max Mustermann");\
|
ASSERT_STREQ(stmt->where->expr2->name, "Max Mustermann");
|
||||||
|
\
|
||||||
|
|
||||||
delete result;
|
delete result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
TEST(InsertStatementTest) {
|
TEST(InsertStatementTest) {
|
||||||
TEST_PARSE_SINGLE_SQL(
|
TEST_PARSE_SINGLE_SQL(
|
||||||
"INSERT INTO students VALUES ('Max Mustermann', 12345, 'Musterhausen', 2.0)",
|
"INSERT INTO students VALUES ('Max Mustermann', 12345, 'Musterhausen', 2.0)",
|
||||||
kStmtInsert,
|
kStmtInsert,
|
||||||
InsertStatement,
|
InsertStatement,
|
||||||
result,
|
result,
|
||||||
stmt);
|
stmt);
|
||||||
|
|
||||||
ASSERT_EQ(stmt->values->size(), 4);
|
ASSERT_EQ(stmt->values->size(), 4);
|
||||||
// TODO
|
// TODO
|
||||||
|
|
||||||
delete result;
|
delete result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
TEST(DropTableStatementTest) {
|
TEST(DropTableStatementTest) {
|
||||||
TEST_PARSE_SINGLE_SQL(
|
TEST_PARSE_SINGLE_SQL(
|
||||||
"DROP TABLE students",
|
"DROP TABLE students",
|
||||||
kStmtDrop,
|
kStmtDrop,
|
||||||
DropStatement,
|
DropStatement,
|
||||||
result,
|
result,
|
||||||
stmt);
|
stmt);
|
||||||
|
|
||||||
ASSERT_EQ(stmt->type, DropStatement::kTable);
|
ASSERT_EQ(stmt->type, DropStatement::kTable);
|
||||||
ASSERT_NOTNULL(stmt->name);
|
ASSERT_NOTNULL(stmt->name);
|
||||||
ASSERT_STREQ(stmt->name, "students");
|
ASSERT_STREQ(stmt->name, "students");
|
||||||
|
|
||||||
delete result;
|
delete result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
TEST(PrepareStatementTest) {
|
TEST(PrepareStatementTest) {
|
||||||
std::string query = "PREPARE test {"
|
std::string query = "PREPARE test {"
|
||||||
"INSERT INTO test VALUES(?);"
|
"INSERT INTO test VALUES(?);"
|
||||||
"SELECT ?, test FROM test WHERE c1 = ?;"
|
"SELECT ?, test FROM test WHERE c1 = ?;"
|
||||||
"};"
|
"};"
|
||||||
"PREPARE stmt: SELECT * FROM data WHERE c1 = ?;"
|
"PREPARE stmt: SELECT * FROM data WHERE c1 = ?;"
|
||||||
"DEALLOCATE PREPARE stmt;";
|
"DEALLOCATE PREPARE stmt;";
|
||||||
|
|
||||||
TEST_PARSE_SQL_QUERY(query, result, 3);
|
TEST_PARSE_SQL_QUERY(query, result, 3);
|
||||||
|
|
||||||
TEST_CAST_STMT(result, 0, kStmtPrepare, PrepareStatement, prep1);
|
TEST_CAST_STMT(result, 0, kStmtPrepare, PrepareStatement, prep1);
|
||||||
TEST_CAST_STMT(result, 1, kStmtPrepare, PrepareStatement, prep2);
|
TEST_CAST_STMT(result, 1, kStmtPrepare, PrepareStatement, prep2);
|
||||||
TEST_CAST_STMT(result, 2, kStmtDrop, DropStatement, drop);
|
TEST_CAST_STMT(result, 2, kStmtDrop, DropStatement, drop);
|
||||||
|
|
||||||
// Prepare Statement #1
|
// Prepare Statement #1
|
||||||
ASSERT_STREQ(prep1->name, "test");
|
ASSERT_STREQ(prep1->name, "test");
|
||||||
ASSERT_EQ(prep1->placeholders.size(), 3);
|
ASSERT_EQ(prep1->placeholders.size(), 3);
|
||||||
ASSERT_EQ(prep1->query->size(), 2);
|
ASSERT_EQ(prep1->query->size(), 2);
|
||||||
|
|
||||||
TEST_CAST_STMT(prep1->query, 0, kStmtInsert, InsertStatement, insert);
|
TEST_CAST_STMT(prep1->query, 0, kStmtInsert, InsertStatement, insert);
|
||||||
TEST_CAST_STMT(prep1->query, 1, kStmtSelect, SelectStatement, select);
|
TEST_CAST_STMT(prep1->query, 1, kStmtSelect, SelectStatement, select);
|
||||||
|
|
||||||
ASSERT(insert->values->at(0)->isType(kExprPlaceholder));
|
ASSERT(insert->values->at(0)->isType(kExprPlaceholder));
|
||||||
ASSERT(select->selectList->at(0)->isType(kExprPlaceholder));
|
ASSERT(select->selectList->at(0)->isType(kExprPlaceholder));
|
||||||
ASSERT(select->whereClause->expr2->isType(kExprPlaceholder));
|
ASSERT(select->whereClause->expr2->isType(kExprPlaceholder));
|
||||||
|
|
||||||
// Check IDs of placeholders
|
// Check IDs of placeholders
|
||||||
ASSERT_EQ(insert->values->at(0)->ival, 0);
|
ASSERT_EQ(insert->values->at(0)->ival, 0);
|
||||||
ASSERT_EQ(insert->values->at(0), prep1->placeholders[0]);
|
ASSERT_EQ(insert->values->at(0), prep1->placeholders[0]);
|
||||||
|
|
||||||
ASSERT_EQ(select->selectList->at(0)->ival, 1);
|
ASSERT_EQ(select->selectList->at(0)->ival, 1);
|
||||||
ASSERT_EQ(select->selectList->at(0), prep1->placeholders[1]);
|
ASSERT_EQ(select->selectList->at(0), prep1->placeholders[1]);
|
||||||
|
|
||||||
ASSERT_EQ(select->whereClause->expr2->ival, 2);
|
ASSERT_EQ(select->whereClause->expr2->ival, 2);
|
||||||
ASSERT_EQ(select->whereClause->expr2, prep1->placeholders[2]);
|
ASSERT_EQ(select->whereClause->expr2, prep1->placeholders[2]);
|
||||||
|
|
||||||
// Prepare Statement #2
|
// Prepare Statement #2
|
||||||
ASSERT_STREQ(prep2->name, "stmt");
|
ASSERT_STREQ(prep2->name, "stmt");
|
||||||
ASSERT_EQ(prep2->placeholders.size(), 1);
|
ASSERT_EQ(prep2->placeholders.size(), 1);
|
||||||
|
|
||||||
// Deallocate Statement
|
// Deallocate Statement
|
||||||
ASSERT_EQ(drop->type, DropStatement::kPreparedStatement);
|
ASSERT_EQ(drop->type, DropStatement::kPreparedStatement);
|
||||||
ASSERT_STREQ(drop->name, "stmt");
|
ASSERT_STREQ(drop->name, "stmt");
|
||||||
|
|
||||||
delete result;
|
delete result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
TEST(ExecuteStatementTest) {
|
TEST(ExecuteStatementTest) {
|
||||||
TEST_PARSE_SINGLE_SQL("EXECUTE test(1, 2);", kStmtExecute, ExecuteStatement, result, stmt);
|
TEST_PARSE_SINGLE_SQL("EXECUTE test(1, 2);", kStmtExecute, ExecuteStatement, result, stmt);
|
||||||
|
|
||||||
ASSERT_STREQ(stmt->name, "test");
|
ASSERT_STREQ(stmt->name, "test");
|
||||||
ASSERT_EQ(stmt->parameters->size(), 2);
|
ASSERT_EQ(stmt->parameters->size(), 2);
|
||||||
|
|
||||||
delete result;
|
delete result;
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_MAIN();
|
TEST_MAIN();
|
|
@ -0,0 +1,43 @@
|
||||||
|
#include "thirdparty/microtest/microtest.h"
|
||||||
|
#include "sql_asserts.h"
|
||||||
|
#include "SQLParser.h"
|
||||||
|
#include "sqlhelper.h"
|
||||||
|
|
||||||
|
#include <string>
|
||||||
|
#include <fstream>
|
||||||
|
#include <streambuf>
|
||||||
|
#include <iostream>
|
||||||
|
|
||||||
|
using namespace hsql;
|
||||||
|
|
||||||
|
TEST(TPCHQueryTests) {
|
||||||
|
std::vector<std::string> files = {
|
||||||
|
"test/queries/tpc-h-01.sql",
|
||||||
|
"test/queries/tpc-h-02.sql",
|
||||||
|
"test/queries/tpc-h-03.sql",
|
||||||
|
"test/queries/tpc-h-04.sql",
|
||||||
|
"test/queries/tpc-h-05.sql",
|
||||||
|
"test/queries/tpc-h-06.sql",
|
||||||
|
"test/queries/tpc-h-07.sql",
|
||||||
|
"test/queries/tpc-h-08.sql",
|
||||||
|
"test/queries/tpc-h-09.sql",
|
||||||
|
"test/queries/tpc-h-10.sql"
|
||||||
|
};
|
||||||
|
|
||||||
|
int testsFailed = 0;
|
||||||
|
for (const std::string& file_path : files) {
|
||||||
|
std::ifstream t(file_path.c_str());
|
||||||
|
std::string query((std::istreambuf_iterator<char>(t)),
|
||||||
|
std::istreambuf_iterator<char>());
|
||||||
|
|
||||||
|
SQLParserResult* result = SQLParser::parseSQLString(query.c_str());
|
||||||
|
if (!result->isValid()) {
|
||||||
|
mt::printFailed(file_path.c_str());
|
||||||
|
printf("%s %s (L%d:%d)%s\n", mt::red(), result->errorMsg(), result->errorLine(), result->errorColumn(), mt::def());
|
||||||
|
++testsFailed;
|
||||||
|
} else {
|
||||||
|
mt::printOk(file_path.c_str());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
ASSERT_EQ(testsFailed, 0);
|
||||||
|
}
|
Loading…
Reference in New Issue