diff --git a/src/Makefile b/src/Makefile index ea1f3e0..bb92777 100644 --- a/src/Makefile +++ b/src/Makefile @@ -4,7 +4,7 @@ PARSER = bison -LIB_FILES = $(PARSER)/$(PARSER)_parser.cpp $(PARSER)/flex_lexer.cpp $(PARSER)/SQLParser.cpp lib/Statement.cpp lib/Expr.cpp +LIB_FILES = $(PARSER)/$(PARSER)_parser.cpp $(PARSER)/flex_lexer.cpp $(PARSER)/SQLParser.cpp lib/Statement.cpp lib/Expr.cpp lib/sqlhelper.cpp TESTS_MAIN = sql_tests.cpp TESTS_BIN = bin/tests diff --git a/src/bison/bison_parser.y b/src/bison/bison_parser.y index 53eca1c..0453279 100644 --- a/src/bison/bison_parser.y +++ b/src/bison/bison_parser.y @@ -71,6 +71,7 @@ typedef void* yyscan_t; List* slist; List* explist; + List* tbllist; } @@ -92,11 +93,11 @@ typedef void* yyscan_t; %type statement %type select_statement %type table_name -%type from_clause table_exp +%type
from_clause table_ref table_ref_atomic %type expr column_name scalar_exp literal %type comparison_predicate predicate search_condition where_clause -%type table_ref_commalist %type expr_list group_clause select_list +%type table_ref_commalist @@ -146,7 +147,7 @@ select_list: from_clause: - FROM table_exp { $$ = $2; } + FROM table_ref { $$ = $2; } ; @@ -162,21 +163,6 @@ group_clause: ; -// TODO: comma_list with mixed table names and select statements -table_exp: - table_ref_commalist { - TableRef* t = new TableRef(eTableName); - t->table_names = $1; - $$ = t; - } - | '(' select_statement ')' { - TableRef* t = new TableRef(eTableSelect); - t->stmt = $2; - $$ = t; - } - ; - - // TODO: multiple predicates search_condition: predicate @@ -214,10 +200,6 @@ column_name: NAME { $$ = makeColumnRef($1); } ; -table_name: - NAME - | NAME '.' NAME - ; literal: STRING { $$ = makeStringLiteral($1); } @@ -231,20 +213,47 @@ opt_semicolon: ; -/****************************** - ** Lists - ******************************/ expr_list: expr { $$ = new List($1); } | expr_list ',' expr { $1->push_back($3); $$ = $1; } ; -// TODO: add table_ref to include names and select queries -table_ref_commalist: - table_name { $$ = new List($1); } - | table_ref_commalist ',' table_name { $1->push_back($3); $$ = $1; } + +/****************************** + ** Table + ******************************/ +table_ref: + table_ref_atomic + | table_ref_atomic ',' table_ref_commalist { + $3->push_back($1); + auto tbl = new TableRef(eTableCrossProduct); + tbl->list = $3; + $$ = tbl; + } ; +table_ref_atomic: + table_name { + auto tbl = new TableRef(eTableName); + tbl->name = $1; + $$ = tbl; + } + | '(' select_statement ')' { + auto tbl = new TableRef(eTableSelect); + tbl->stmt = $2; + $$ = tbl; + } + ; + +table_ref_commalist: + table_ref_atomic { $$ = new List($1); } + | table_ref_commalist ',' table_ref_atomic { $1->push_back($3); $$ = $1; } + ; + +table_name: + NAME + | NAME '.' NAME + ; %% diff --git a/src/build_and_run_tests.sh b/src/build_and_run_tests.sh index 2ea2e9a..936ab3c 100644 --- a/src/build_and_run_tests.sh +++ b/src/build_and_run_tests.sh @@ -4,5 +4,5 @@ make clean make tests ./bin/tests -# make execution -# ./bin/sql_execution "SELECT col1, col2 FROM table GROUP BY col1;" \ No newline at end of file +make execution +./bin/sql_execution "SELECT col1, col2 FROM table, (SELECT * FROM a, table, (SELECT * FROM (SELECT * FROM foo))) GROUP BY col1;" \ No newline at end of file diff --git a/src/lib/Table.h b/src/lib/Table.h index 2bbd0a9..68c4951 100644 --- a/src/lib/Table.h +++ b/src/lib/Table.h @@ -9,16 +9,20 @@ class SelectStatement; */ typedef enum { eTableName, - eTableSelect + eTableSelect, + eTableCrossProduct } ETableRefType; +typedef struct TableRef TableRef; struct TableRef { TableRef(ETableRefType type) : type(type) {} ETableRefType type; + + char* name; SelectStatement* stmt; - List* table_names; + List* list; }; diff --git a/src/lib/sqlhelper.cpp b/src/lib/sqlhelper.cpp new file mode 100644 index 0000000..90ef43d --- /dev/null +++ b/src/lib/sqlhelper.cpp @@ -0,0 +1,40 @@ + +#include "sqlhelper.h" +#include +#include + +const char* indent(uint num_indent) { return std::string(num_indent, ' ').c_str(); } +void inprint(int val, uint num_indent) { printf("%s%d\n", indent(num_indent), val); } +void inprint(float val, uint num_indent) { printf("%s%f\n", indent(num_indent), val); } +void inprint(const char* val, uint num_indent) { printf("%s%s\n", indent(num_indent), val); } + +void printTableRefInfo(TableRef* table, uint num_indent) { + switch (table->type) { + case eTableName: + inprint(table->name, num_indent); + break; + case eTableSelect: + printSelectStatementInfo(table->stmt, num_indent); + break; + case eTableCrossProduct: + for (TableRef* tbl : table->list->_vector) printTableRefInfo(tbl, num_indent); + break; + } +} + +void printSelectStatementInfo(SelectStatement* stmt, uint num_indent) { + inprint("SelectStatement", num_indent); + inprint("Fields:", num_indent+1); + for (Expr* expr : stmt->select_list->_vector) { + switch (expr->type) { + case eExprStar: inprint("*", num_indent+2); break; + case eExprColumnRef: inprint(expr->name, num_indent+2); break; + case eExprLiteralFloat: inprint(expr->float_literal, num_indent+2); break; + case eExprLiteralString: inprint(expr->name, num_indent+2); break; + case eExprFunctionRef: /* todo */ break; + case eExprPredicate: /* todo */ break; + } + } + inprint("Sources:", num_indent+1); + printTableRefInfo(stmt->from_table, num_indent+2); +} diff --git a/src/lib/sqlhelper.h b/src/lib/sqlhelper.h new file mode 100644 index 0000000..35919bb --- /dev/null +++ b/src/lib/sqlhelper.h @@ -0,0 +1,11 @@ + +#ifndef __SQLHELPER_H__ +#define __SQLHELPER_H__ + + +#include "Statement.h" + +void printSelectStatementInfo(SelectStatement* stmt, uint num_indent); + + +#endif \ No newline at end of file diff --git a/src/sql_execution.cpp b/src/sql_execution.cpp index b390a63..439f822 100644 --- a/src/sql_execution.cpp +++ b/src/sql_execution.cpp @@ -1,11 +1,8 @@ -#include "SQLParser.h" #include #include - -typedef int* Table; -Table executeSelect(SelectStatement* stmt); - +#include "lib/sqlhelper.h" +#include "SQLParser.h" int main(int argc, char *argv[]) { if (argc <= 1) { @@ -13,8 +10,6 @@ int main(int argc, char *argv[]) { return -1; } - // Statement *stmt = NULL; - for (int n = 1; n < argc; ++n) { char* sql = argv[n]; @@ -27,71 +22,11 @@ int main(int argc, char *argv[]) { } if (stmt->type == eSelect) { - executeSelect((SelectStatement*)stmt); + printSelectStatementInfo((SelectStatement*) stmt, 0); } else { fprintf(stderr, "Only Supporting Select Statements!\n"); } } return 0; -} - - -// Dummy Database -int NUM_COLUMNS = 4; -int NUM_ROWS = 100; -int TABLE[] = {40,59,8,7,74,28,7,10,15,17,2,20,15,82,41,20,25,72,89,67,74,0,70,31,67,75,74,30,0,45,82,6,9,35,73,83,13,46,39,45,28,34,11,41,20,30,72,78,51,36,32,71,16,70,39,88,59,25,0,68,73,54,0,4,7,35,19,4,6,23,30,25,51,31,52,14,65,95,95,85,94,90,65,35,51,64,68,44,80,7,78,23,99,30,17,72,8,22,40,47,15,30,9,51,77,9,67,94,15,69,49,21,51,99,91,36,5,91,69,55,36,36,74,63,1,87,24,67,51,52,21,10,60,37,6,43,53,4,25,35,19,4,61,61,16,83,9,69,32,46,36,74,96,47,90,27,48,48,79,95,55,64,48,40,42,77,33,18,36,80,23,24,1,75,2,63,9,23,17,99,82,56,9,92,17,94,76,35,28,86,61,58,38,61,16,4,69,61,51,33,53,23,6,48,81,62,46,51,61,34,97,100,53,7,41,61,45,15,46,91,85,29,73,75,39,24,99,38,0,32,68,23,76,25,62,40,58,67,85,33,18,51,70,45,27,62,30,89,85,53,87,91,61,37,33,69,2,2,9,24,23,55,45,76,0,59,72,12,75,5,10,52,59,32,34,24,86,72,97,2,5,4,0,70,6,98,29,22,11,69,74,90,19,12,68,7,55,22,70,83,20,72,88,61,46,38,98,4,15,63,14,42,16,94,100,33,58,65,53,56,26,94,63,80,88,22,49,20,57,81,89,30,82,83,62,87,21,91,36,98,78,53,24,69,60,31,24,71,9,95,94,30,42,35,97,56,51,14,31,0,73,80,11,83,77,9,51,93,37,16,41,99,24,93,100,12,23,59,61,36,70,69,100,4,14,73,47,81,54,44,12,34,14,55,95,19,79,95,77,69}; - -int getValue(int col, int row) { - return TABLE[row*NUM_COLUMNS+col]; -} -int getValue(std::string col_name, int row) { - if (col_name.compare("col1") == 0) return getValue(0, row); - if (col_name.compare("col2") == 0) return getValue(1, row); - if (col_name.compare("col3") == 0) return getValue(2, row); - if (col_name.compare("col4") == 0) return getValue(3, row); - return 0; -} - - - -Table executeGroupBySelect(SelectStatement* stmt, Table source) { - fprintf(stderr, "GROUP BY not yet implemented!\n"); - return NULL; -} - - -Table executeSelect(SelectStatement* stmt) { - - // Step 1: - // Determine source table - TableRef* from_table = stmt->from_table; - Table source; - - if (from_table->type == eTableSelect) { - // Nested Select Statements - source = executeSelect(from_table->stmt); - - } else if (from_table->type == eTableName) { - if (from_table->table_names->size() == 1) { - if (std::string(from_table->table_names->at(0)).compare("table") == 0) { - source = TABLE; - } else { - fprintf(stderr, "Couldn't find table!\n"); - return NULL; - } - } else { - // Cross product of table - fprintf(stderr, "We're not supporting cross product of tables atm.\n"); - return NULL; - } - } - - // Step 2 - // Check if group by - if (stmt->group_by != NULL) { - return executeGroupBySelect(stmt, source); - } - - return NULL; -} +} \ No newline at end of file