From 39d0dbd9af6efd70fc4a2f2cff03e940f3e66399 Mon Sep 17 00:00:00 2001 From: Pedro Date: Wed, 8 Mar 2017 17:42:33 +0100 Subject: [PATCH 1/2] Implement CREATE VIEW and DROP VIEW --- src/parser/bison_parser.y | 11 +++++++++++ src/sql/CreateStatement.h | 8 +++++++- src/sql/statements.cpp | 12 +++++++++++- test/queries/tpc-h-11-15.sql | 11 +++++------ 4 files changed, 34 insertions(+), 8 deletions(-) diff --git a/src/parser/bison_parser.y b/src/parser/bison_parser.y index 2e32ca4..7593212 100644 --- a/src/parser/bison_parser.y +++ b/src/parser/bison_parser.y @@ -343,6 +343,13 @@ create_statement: $$->tableName = $4; $$->columns = $6; } + | CREATE VIEW opt_not_exists table_name opt_column_list AS select_statement { + $$ = new CreateStatement(CreateStatement::kView); + $$->ifNotExists = $3; + $$->tableName = $4; + $$->viewColumns = $5; + $$->select = $7; + } ; opt_not_exists: @@ -380,6 +387,10 @@ drop_statement: $$ = new DropStatement(DropStatement::kTable); $$->name = $3; } + | DROP VIEW table_name { + $$ = new DropStatement(DropStatement::kView); + $$->name = $3; + } | DEALLOCATE PREPARE IDENTIFIER { $$ = new DropStatement(DropStatement::kPreparedStatement); $$->name = $3; diff --git a/src/sql/CreateStatement.h b/src/sql/CreateStatement.h index 2034bc6..5b96d33 100644 --- a/src/sql/CreateStatement.h +++ b/src/sql/CreateStatement.h @@ -5,9 +5,12 @@ // Note: Implementations of constructors and destructors can be found in statements.cpp. namespace hsql { + struct SelectStatement; + // Represents definition of a table column struct ColumnDefinition { enum DataType { + UNKNOWN, TEXT, INT, DOUBLE @@ -26,7 +29,8 @@ namespace hsql { struct CreateStatement : SQLStatement { enum CreateType { kTable, - kTableFromTbl // Hyrise file format + kTableFromTbl, // Hyrise file format + kView }; CreateStatement(CreateType type); @@ -37,6 +41,8 @@ namespace hsql { char* filePath; // default: NULL char* tableName; // default: NULL std::vector* columns; // default: NULL + std::vector* viewColumns; + SelectStatement* select; }; } // namespace hsql diff --git a/src/sql/statements.cpp b/src/sql/statements.cpp index 8d9973b..69ffc84 100644 --- a/src/sql/statements.cpp +++ b/src/sql/statements.cpp @@ -29,11 +29,14 @@ namespace hsql { ifNotExists(false), filePath(NULL), tableName(NULL), - columns(NULL) {}; + columns(NULL), + viewColumns(NULL), + select(NULL) {}; CreateStatement::~CreateStatement() { free(filePath); free(tableName); + delete select; if (columns != NULL) { for (ColumnDefinition* def : *columns) { @@ -41,6 +44,13 @@ namespace hsql { } delete columns; } + + if (viewColumns != NULL) { + for (char* column : *viewColumns) { + free(column); + } + delete viewColumns; + } } // DeleteStatement diff --git a/test/queries/tpc-h-11-15.sql b/test/queries/tpc-h-11-15.sql index 9f5318d..69c755d 100644 --- a/test/queries/tpc-h-11-15.sql +++ b/test/queries/tpc-h-11-15.sql @@ -42,10 +42,10 @@ WHERE L_PARTKEY = P_PARTKEY AND L_SHIPDATE >= '1995-09-01' AND L_SHIPDATE < date -- TPC_H Query 15.1 - Create View for Top Supplier Query --- CREATE VIEW REVENUE0 (SUPPLIER_NO, TOTAL_REVENUE) AS --- SELECT L_SUPPKEY, SUM(L_EXTENDEDPRICE*(1-L_DISCOUNT)) FROM LINEITEM --- WHERE L_SHIPDATE >= '1996-01-01' AND L_SHIPDATE < dateadd(mm, 3, cast('1996-01-01' as datetime)) --- GROUP BY L_SUPPKEY; +CREATE VIEW REVENUE0 (SUPPLIER_NO, TOTAL_REVENUE) AS +SELECT L_SUPPKEY, SUM(L_EXTENDEDPRICE*(1-L_DISCOUNT)) FROM LINEITEM +WHERE L_SHIPDATE >= '1996-01-01' AND L_SHIPDATE < dateadd(mm, 3, cast('1996-01-01' as datetime)) +GROUP BY L_SUPPKEY; -- TPC_H Query 15.2 - Top Supplier @@ -55,5 +55,4 @@ WHERE S_SUPPKEY = SUPPLIER_NO AND TOTAL_REVENUE = (SELECT MAX(TOTAL_REVENUE) FRO ORDER BY S_SUPPKEY; -- TPC_H Query 15.3 - Drop View --- DROP VIEW REVENUE0; - +DROP VIEW REVENUE0; From 3e52bf1a665d628d9d190c8f7a7d3b5c0cfb6140 Mon Sep 17 00:00:00 2001 From: Pedro Date: Wed, 8 Mar 2017 19:28:25 +0100 Subject: [PATCH 2/2] Add test for grammar conflicts. Print summary at the end of tests --- src/parser/Makefile | 6 +++- test/test.sh | 70 +++++++++++++++++++++++++++++++++++++++------ 2 files changed, 66 insertions(+), 10 deletions(-) diff --git a/src/parser/Makefile b/src/parser/Makefile index a0102f4..10983c6 100644 --- a/src/parser/Makefile +++ b/src/parser/Makefile @@ -10,4 +10,8 @@ flex_lexer.cpp: flex_lexer.l flex flex_lexer.l clean: - rm -f bison_parser.cpp flex_lexer.cpp bison_parser.h flex_lexer.h *.output \ No newline at end of file + rm -f bison_parser.cpp flex_lexer.cpp bison_parser.h flex_lexer.h *.output + +# Tests if the parser builds correctly and doesn't contain conflicts. +test: + ! bison bison_parser.y -v 2>&1 | grep "conflict" >&2 diff --git a/test/test.sh b/test/test.sh index e7cae2a..73b3262 100755 --- a/test/test.sh +++ b/test/test.sh @@ -1,21 +1,73 @@ #!/bin/bash - # Has to be executed from the root of the repository. # Usually invoked by `make test`. export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:./ +# Colors +RED='\033[1;31m' +GREEN='\033[1;32m' +NC='\033[0m' +BOLD='\033[1;39m' + RET=0 +SQL_TEST_RET=0 +MEM_LEAK_RET=0 +CONFLICT_RET=0 +################################################# +# Running SQL parser tests. +printf "\n${GREEN}Running SQL parser tests...${NC}\n" bin/sql_tests -f "test/valid_queries.sql" -RET=$? +SQL_TEST_RET=$? -if [ $RET -eq 0 ]; then - # Running memory leak checks. - echo "" - echo "Running memory leak checks..." - valgrind --leak-check=full --error-exitcode=1 --log-fd=3 \ - ./bin/sql_tests -f "test/valid_queries.sql" 3>&1 >/dev/null 2>/dev/null - RET=$? +if [ $SQL_TEST_RET -eq 0 ]; then + printf "${GREEN}SQL parser tests succeeded!${NC}\n" +else + RET=1 + printf "${RED}SQL parser tests failed!${NC}\n" fi +################################################# +# Running memory leak checks. +printf "\n${GREEN}Running memory leak checks...${NC}\n" +valgrind --leak-check=full --error-exitcode=200 --log-fd=3 \ + ./bin/sql_tests -f "test/valid_queries.sql" 3>&1 >/dev/null 2>/dev/null + +if [ $MEM_LEAK_RET -ne 200 ]; then + printf "${GREEN}Memory leak check succeeded!${NC}\n" +else + MEM_LEAK_RET=1 + RET=1 + printf "${RED}Memory leak check failed!${NC}\n" +fi + +################################################# +# Checking if the grammar is conflict free. +printf "\n${GREEN}Checking for conflicts in the grammer...${NC}\n" +printf "${RED}" +make -C src/parser/ test >>/dev/null +CONFLICT_RET=$? + +if [ $CONFLICT_RET -eq 0 ]; then + printf "${GREEN}Conflict check succeeded!${NC}\n" +else + RET=1 + printf "${RED}Conflict check failed!${NC}\n" +fi + +# Print a summary of the test results. +printf " +---------------------------------- +${BOLD}Summary:\n" +if [ $SQL_TEST_RET -eq 0 ]; then printf "SQL Tests: ${GREEN}Success${BOLD}\n"; +else printf "SQL Tests: ${RED}Failure${BOLD}\n"; fi +if [ $MEM_LEAK_RET -eq 0 ]; then printf "Memory Leak Check: ${GREEN}Success${BOLD}\n"; +else printf "Memory Leak Check: ${RED}Failure${BOLD}\n"; fi +if [ $CONFLICT_RET -eq 0 ]; then printf "Grammar Conflict Check: ${GREEN}Success${BOLD}\n"; +else printf "Grammar Conflict Check: ${RED}Failure${BOLD}\n"; fi + +if [ $RET -eq 0 ]; then printf "${GREEN}All tests passed!${NC}\n"; +else printf "${RED}Some tests failed!${NC}\n"; fi +printf "${NC}----------------------------------\n" + exit $RET