restructured and refactored statements

This commit is contained in:
Pedro 2014-12-03 17:43:02 +01:00
parent 4e9eebb2af
commit adcdc490dd
18 changed files with 100 additions and 100 deletions

View File

@ -4,20 +4,17 @@ BUILD_DIR = ../build/
BIN_DIR = ../bin
CC = g++
CFLAGS = -O3 -Ilib/ -I./ -Iparser/ -std=c++11 -pthread -Wall -g
CFLAGS = -O3 -I./ -Ilib/ -Ilib/statements/ -Iparser/ -std=c++11 -pthread -Wall -g
LIB_FILES = $(shell find lib/ -name '*.cpp') $(shell find lib/ -name '*.h') parser/bison_parser.cpp parser/flex_lexer.cpp parser/SQLParser.cpp
LIB_SOURCES = $(shell find lib/ -name '*.cpp') parser/bison_parser.cpp parser/flex_lexer.cpp parser/SQLParser.cpp
TEST_SOURCES = $(shell find tests/ -name '*.cpp')
# release build is always using bison
build: clean
make -C parser/
mkdir $(BUILD_DIR)
cp lib/* $(BUILD_DIR)
cp parser/*.h $(BUILD_DIR)
cp parser/*.cpp $(BUILD_DIR)
cp $(LIB_FILES) $(BUILD_DIR)
analysis: $(LIB_SOURCES) sql_analysis.cpp

View File

@ -5,10 +5,10 @@
namespace hsql {
/**
* Statement.h
* SQLStatement.h
*/
Statement::~Statement() { /* empty */ }
StatementList::~StatementList() {
SQLStatement::~SQLStatement() { /* empty */ }
SQLStatementList::~SQLStatementList() {
delete parser_msg;
}

View File

@ -128,7 +128,7 @@ void printInsertStatementInfo(InsertStatement* stmt, uint num_indent) {
inprint(col_name, num_indent+2);
}
}
switch (stmt->insert_type) {
switch (stmt->type) {
case InsertStatement::kInsertValues:
inprint("Values", num_indent+1);
for (Expr* expr : stmt->values->vector()) {

View File

@ -1,7 +1,7 @@
#ifndef __CREATE_STATEMENT_H__
#define __CREATE_STATEMENT_H__
#include "Statement.h"
#include "SQLStatement.h"
namespace hsql {
@ -31,14 +31,15 @@ struct ColumnDefinition {
* CREATE TABLE students (name TEXT, student_number INTEGER, city TEXT, grade DOUBLE)
* CREATE TABLE students FROM TBL FILE 'test/students.tbl'
*/
struct CreateStatement : Statement {
struct CreateStatement : SQLStatement {
enum CreateType {
kTable,
kTableFromTbl, // Hyrise file format
};
CreateStatement() :
Statement(kStmtCreate),
CreateStatement(CreateType type) :
SQLStatement(kStmtCreate),
type(type),
if_not_exists(false),
columns(NULL),
file_path(NULL),
@ -46,7 +47,7 @@ struct CreateStatement : Statement {
virtual ~CreateStatement(); // defined in destructors.cpp
CreateType create_type;
CreateType type;
bool if_not_exists;
List<ColumnDefinition*>* columns;

View File

@ -1,7 +1,7 @@
#ifndef __DELETE_STATEMENT_H__
#define __DELETE_STATEMENT_H__
#include "Statement.h"
#include "SQLStatement.h"
namespace hsql {
@ -13,9 +13,9 @@ namespace hsql {
*
* If expr == NULL => delete all rows (truncate)
*/
struct DeleteStatement : Statement {
struct DeleteStatement : SQLStatement {
DeleteStatement() :
Statement(kStmtDelete),
SQLStatement(kStmtDelete),
table_name(NULL),
expr(NULL) {};

View File

@ -1,12 +1,12 @@
#ifndef __DROP_STATEMENT_H__
#define __DROP_STATEMENT_H__
#include "Statement.h"
#include "SQLStatement.h"
namespace hsql {
struct DropStatement : Statement {
enum ObjectType {
struct DropStatement : SQLStatement {
enum EntityType {
kTable,
kSchema,
kIndex,
@ -14,17 +14,16 @@ struct DropStatement : Statement {
};
DropStatement(ObjectType type) :
Statement(kStmtDrop),
obj_type(type),
DropStatement(EntityType type) :
SQLStatement(kStmtDrop),
type(type),
name(NULL) {}
ObjectType obj_type;
EntityType type;
const char* name;
virtual ~DropStatement() {
delete name;
}

View File

@ -1,33 +1,34 @@
#ifndef __IMPORT_STATEMENT_H__
#define __IMPORT_STATEMENT_H__
#include "Statement.h"
#include "SQLStatement.h"
namespace hsql {
typedef enum {
kImportCSV,
kImportTbl, // Hyrise file format
} ImportFileType;
/**
* @struct ImportStatement
*/
struct ImportStatement : Statement {
ImportStatement() :
Statement(kStmtImport),
struct ImportStatement : SQLStatement {
enum ImportType {
kImportCSV,
kImportTbl, // Hyrise file format
};
ImportStatement(ImportType type) :
SQLStatement(kStmtImport),
type(type),
file_path(NULL),
table_name(NULL) {};
virtual ~ImportStatement(); // defined in destructors.cpp
ImportFileType file_type;
ImportType type;
const char* file_path;
const char* table_name;
};

View File

@ -1,7 +1,7 @@
#ifndef __INSERT_STATEMENT_H__
#define __INSERT_STATEMENT_H__
#include "Statement.h"
#include "SQLStatement.h"
#include "SelectStatement.h"
namespace hsql {
@ -12,14 +12,15 @@ namespace hsql {
* INSERT INTO students VALUES ('Max', 1112233, 'Musterhausen', 2.3)
* INSERT INTO employees SELECT * FROM stundents
*/
struct InsertStatement : Statement {
typedef enum {
struct InsertStatement : SQLStatement {
enum InsertType {
kInsertValues,
kInsertSelect
} Type;
};
InsertStatement() :
Statement(kStmtInsert),
InsertStatement(InsertType type) :
SQLStatement(kStmtInsert),
type(type),
table_name(NULL),
columns(NULL),
values(NULL),
@ -27,7 +28,7 @@ struct InsertStatement : Statement {
virtual ~InsertStatement(); // defined in destructors.cpp
Type insert_type;
InsertType type;
const char* table_name;
List<char*>* columns;
List<Expr*>* values;

View File

@ -1,5 +1,5 @@
/*
* Statement.h
* SQLStatement.h
* Definition of the structure used to build the syntax tree.
*/
#ifndef __STATEMENT_H__
@ -16,44 +16,49 @@ typedef enum {
kStmtImport,
kStmtInsert,
kStmtUpdate,
// Following types are planned but not supported yet
kStmtDelete,
kStmtCreate,
kStmtDrop,
// Following types are not supported yet
kStmtExport,
kStmtRename,
kStmtAlter
} StatementType;
struct Statement {
Statement(StatementType type) :
type(type) {};
struct SQLStatement {
SQLStatement(StatementType type) :
_type(type) {};
virtual ~Statement(); // defined in destructors.cpp
virtual ~SQLStatement(); // defined in destructors.cpp
StatementType type;
virtual StatementType type() { return _type; }
private:
StatementType _type;
};
class StatementList : public List<Statement*> {
class SQLStatementList : public List<SQLStatement*> {
public:
StatementList() :
List<Statement*>(),
SQLStatementList() :
List<SQLStatement*>(),
isValid(true),
parser_msg(NULL) {};
StatementList(Statement* stmt) :
List<Statement*>(stmt),
SQLStatementList(SQLStatement* stmt) :
List<SQLStatement*>(stmt),
isValid(true),
parser_msg(NULL) {};
virtual ~StatementList(); // defined in destructors.cpp
virtual ~SQLStatementList(); // defined in destructors.cpp
bool isValid;
const char* parser_msg;
};
// typedef List<Statement*> StatementList;
} // namespace hsql

View File

@ -1,7 +1,7 @@
#ifndef __SELECT_STATEMENT_H__
#define __SELECT_STATEMENT_H__
#include "Statement.h"
#include "SQLStatement.h"
#include "Expr.h"
#include "List.h"
#include "Table.h"
@ -50,9 +50,9 @@ struct LimitDescription {
* Representation of a full select statement.
* TODO: add union_order and union_limit
*/
struct SelectStatement : Statement {
struct SelectStatement : SQLStatement {
SelectStatement() :
Statement(kStmtSelect),
SQLStatement(kStmtSelect),
from_table(NULL),
select_list(NULL),
where_clause(NULL),

View File

@ -1,7 +1,7 @@
#ifndef __UPDATE_STATEMENT_H__
#define __UPDATE_STATEMENT_H__
#include "Statement.h"
#include "SQLStatement.h"
namespace hsql {
@ -10,9 +10,9 @@ struct UpdateClause {
Expr* value;
};
struct UpdateStatement : Statement {
struct UpdateStatement : SQLStatement {
UpdateStatement() :
Statement(kStmtUpdate),
SQLStatement(kStmtUpdate),
table(NULL),
updates(NULL),
where(NULL) {}

View File

@ -11,8 +11,8 @@ SQLParser::SQLParser() {
}
StatementList* SQLParser::parseSQLString(const char *text) {
StatementList* result;
SQLStatementList* SQLParser::parseSQLString(const char *text) {
SQLStatementList* result;
yyscan_t scanner;
YY_BUFFER_STATE state;

View File

@ -8,7 +8,7 @@ namespace hsql {
class SQLParser {
public:
static StatementList* parseSQLString(const char* sql);
static SQLStatementList* parseSQLString(const char* sql);
private:
SQLParser();

View File

@ -19,9 +19,9 @@
using namespace hsql;
int yyerror(StatementList** result, yyscan_t scanner, const char *msg) {
int yyerror(SQLStatementList** result, yyscan_t scanner, const char *msg) {
StatementList* list = new StatementList();
SQLStatementList* list = new SQLStatementList();
list->isValid = false;
list->parser_msg = strdup(msg);
*result = list;
@ -64,7 +64,7 @@ typedef void* yyscan_t;
%lex-param { yyscan_t scanner }
// Define additional parameters for yyparse
%parse-param { hsql::StatementList** result }
%parse-param { hsql::SQLStatementList** result }
%parse-param { yyscan_t scanner }
@ -78,7 +78,7 @@ typedef void* yyscan_t;
uint uval;
bool bval;
hsql::Statement* statement;
hsql::SQLStatement* statement;
hsql::SelectStatement* select_stmt;
hsql::ImportStatement* import_stmt;
hsql::CreateStatement* create_stmt;
@ -95,7 +95,7 @@ typedef void* yyscan_t;
hsql::ColumnDefinition* column_t;
hsql::UpdateClause* update_t;
hsql::StatementList* stmt_list;
hsql::SQLStatementList* stmt_list;
hsql::List<char*>* slist;
hsql::List<hsql::Expr*>* expr_list;
hsql::List<hsql::TableRef*>* table_list;
@ -195,7 +195,7 @@ input:
statement_list:
statement { $$ = new StatementList($1); }
statement { $$ = new SQLStatementList($1); }
| statement_list ';' statement { $1->push_back($3); $$ = $1; }
;
@ -217,15 +217,14 @@ statement:
******************************/
import_statement:
IMPORT FROM import_file_type FILE file_path INTO table_name {
$$ = new ImportStatement();
$$->file_type = (ImportFileType) $3;
$$ = new ImportStatement((ImportStatement::ImportType) $3);
$$->file_path = $5;
$$->table_name = $7;
}
;
import_file_type:
CSV { $$ = kImportCSV; }
CSV { $$ = ImportStatement::kImportCSV; }
;
file_path:
@ -240,15 +239,13 @@ file_path:
******************************/
create_statement:
CREATE TABLE opt_not_exists table_name FROM TBL FILE file_path {
$$ = new CreateStatement();
$$->create_type = CreateStatement::kTableFromTbl;
$$ = new CreateStatement(CreateStatement::kTableFromTbl);
$$->if_not_exists = $3;
$$->table_name = $4;
$$->file_path = $8;
}
| CREATE TABLE opt_not_exists table_name '(' column_def_commalist ')' {
$$ = new CreateStatement();
$$->create_type = CreateStatement::kTable;
$$ = new CreateStatement(CreateStatement::kTable);
$$->if_not_exists = $3;
$$->table_name = $4;
$$->columns = $6;
@ -317,15 +314,13 @@ truncate_statement:
******************************/
insert_statement:
INSERT INTO table_name opt_column_list VALUES '(' literal_list ')' {
$$ = new InsertStatement();
$$->insert_type = InsertStatement::kInsertValues;
$$ = new InsertStatement(InsertStatement::kInsertValues);
$$->table_name = $3;
$$->columns = $4;
$$->values = $7;
}
| INSERT INTO table_name opt_column_list select_no_paren {
$$ = new InsertStatement();
$$->insert_type = InsertStatement::kInsertSelect;
$$ = new InsertStatement(InsertStatement::kInsertSelect);
$$->table_name = $3;
$$->columns = $4;
$$->select = $5;

View File

@ -16,7 +16,7 @@ int main(int argc, char *argv[]) {
char* sql = argv[n];
printf("\nEvaluating Query \"%s\"\n", sql);
StatementList* stmt_list = SQLParser::parseSQLString(sql);
SQLStatementList* stmt_list = SQLParser::parseSQLString(sql);
if (!stmt_list->isValid) {
fprintf(stderr, "Parsing of \"%s\" failed! Reason: %s\n", sql, stmt_list->parser_msg);
@ -24,7 +24,7 @@ int main(int argc, char *argv[]) {
}
int i = 0;
for (Statement* stmt : stmt_list->vector()) {
for (SQLStatement* stmt : stmt_list->vector()) {
printf("Statement %d:\n", i++);
switch (stmt->type) {
case kStmtSelect: printSelectStatementInfo((SelectStatement*) stmt, 1); break;

View File

@ -68,7 +68,7 @@ int main(int argc, char *argv[]) {
start = std::chrono::system_clock::now();
// Parsing
StatementList* stmt_list = SQLParser::parseSQLString(sql.c_str());
SQLStatementList* stmt_list = SQLParser::parseSQLString(sql.c_str());
end = std::chrono::system_clock::now();
std::chrono::duration<double> elapsed_seconds = end-start;

View File

@ -9,10 +9,10 @@
using namespace hsql;
TEST(Delete) {
StatementList* stmt_list = SQLParser::parseSQLString("DELETE FROM students WHERE grade > 2.0;");
SQLStatementList* stmt_list = SQLParser::parseSQLString("DELETE FROM students WHERE grade > 2.0;");
ASSERT(stmt_list->isValid);
ASSERT_EQ(stmt_list->size(), 1);
ASSERT(stmt_list->at(0)->type == kStmtDelete);
ASSERT(stmt_list->at(0)->type() == kStmtDelete);
DeleteStatement* stmt = (DeleteStatement*) stmt_list->at(0);
ASSERT_STREQ(stmt->table_name, "students");
@ -23,13 +23,13 @@ TEST(Delete) {
}
TEST(Create) {
StatementList* stmt_list = SQLParser::parseSQLString("CREATE TABLE students (name TEXT, student_number INT, city INTEGER, grade DOUBLE)");
SQLStatementList* stmt_list = SQLParser::parseSQLString("CREATE TABLE students (name TEXT, student_number INT, city INTEGER, grade DOUBLE)");
ASSERT(stmt_list->isValid);
ASSERT_EQ(stmt_list->size(), 1);
ASSERT_EQ(stmt_list->at(0)->type, kStmtCreate);
ASSERT_EQ(stmt_list->at(0)->type(), kStmtCreate);
CreateStatement* stmt = (CreateStatement*) stmt_list->at(0);
ASSERT_EQ(stmt->create_type, CreateStatement::kTable);
ASSERT_EQ(stmt->type, CreateStatement::kTable);
ASSERT_STREQ(stmt->table_name, "students");
ASSERT_NOTNULL(stmt->columns);
ASSERT_EQ(stmt->columns->size(), 4);
@ -45,10 +45,10 @@ TEST(Create) {
TEST(Update) {
StatementList* stmt_list = SQLParser::parseSQLString("UPDATE students SET grade = 5.0, name = 'test' WHERE name = 'Max Mustermann';");
SQLStatementList* stmt_list = SQLParser::parseSQLString("UPDATE students SET grade = 5.0, name = 'test' WHERE name = 'Max Mustermann';");
ASSERT(stmt_list->isValid);
ASSERT_EQ(stmt_list->size(), 1);
ASSERT_EQ(stmt_list->at(0)->type, kStmtUpdate);
ASSERT_EQ(stmt_list->at(0)->type(), kStmtUpdate);
UpdateStatement* stmt = (UpdateStatement*) stmt_list->at(0);
ASSERT_NOTNULL(stmt->table);
@ -73,22 +73,23 @@ TEST(Update) {
TEST(Insert) {
StatementList* stmt_list = SQLParser::parseSQLString("INSERT INTO students VALUES ('Max Mustermann', 12345, 'Musterhausen', 2.0)");
SQLStatementList* stmt_list = SQLParser::parseSQLString("INSERT INTO students VALUES ('Max Mustermann', 12345, 'Musterhausen', 2.0)");
ASSERT(stmt_list->isValid);
ASSERT_EQ(stmt_list->size(), 1);
ASSERT_EQ(stmt_list->at(0)->type, kStmtInsert);
ASSERT_EQ(stmt_list->at(0)->type(), kStmtInsert);
// TODO
}
TEST(DropTable) {
StatementList* stmt_list = SQLParser::parseSQLString("DROP TABLE students");
SQLStatementList* stmt_list = SQLParser::parseSQLString("DROP TABLE students");
ASSERT(stmt_list->isValid);
ASSERT_EQ(stmt_list->size(), 1);
ASSERT_EQ(stmt_list->at(0)->type, kStmtDrop);
ASSERT_EQ(stmt_list->at(0)->type(), kStmtDrop);
DropStatement* stmt = (DropStatement*) stmt_list->at(0);
ASSERT_EQ(stmt->type, DropStatement::kTable);
ASSERT_NOTNULL(stmt->name);
ASSERT_STREQ(stmt->name, "students");
}

View File

@ -5,10 +5,10 @@
using namespace hsql;
TEST(Select) {
StatementList* stmt_list = SQLParser::parseSQLString("SELECT * FROM students;");
SQLStatementList* stmt_list = SQLParser::parseSQLString("SELECT * FROM students;");
ASSERT(stmt_list->isValid);
ASSERT_EQ(stmt_list->size(), 1);
ASSERT(stmt_list->at(0)->type == kStmtSelect);
ASSERT_EQ(stmt_list->at(0)->type(), kStmtSelect);
SelectStatement* stmt = (SelectStatement*) stmt_list->at(0);
ASSERT_NULL(stmt->where_clause);