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 BIN_DIR = ../bin
CC = g++ 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 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') TEST_SOURCES = $(shell find tests/ -name '*.cpp')
# release build is always using bison
build: clean build: clean
make -C parser/ make -C parser/
mkdir $(BUILD_DIR) mkdir $(BUILD_DIR)
cp lib/* $(BUILD_DIR) cp $(LIB_FILES) $(BUILD_DIR)
cp parser/*.h $(BUILD_DIR)
cp parser/*.cpp $(BUILD_DIR)
analysis: $(LIB_SOURCES) sql_analysis.cpp analysis: $(LIB_SOURCES) sql_analysis.cpp

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -16,7 +16,7 @@ int main(int argc, char *argv[]) {
char* sql = argv[n]; char* sql = argv[n];
printf("\nEvaluating Query \"%s\"\n", sql); printf("\nEvaluating Query \"%s\"\n", sql);
StatementList* stmt_list = SQLParser::parseSQLString(sql); SQLStatementList* stmt_list = SQLParser::parseSQLString(sql);
if (!stmt_list->isValid) { if (!stmt_list->isValid) {
fprintf(stderr, "Parsing of \"%s\" failed! Reason: %s\n", sql, stmt_list->parser_msg); 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; int i = 0;
for (Statement* stmt : stmt_list->vector()) { for (SQLStatement* stmt : stmt_list->vector()) {
printf("Statement %d:\n", i++); printf("Statement %d:\n", i++);
switch (stmt->type) { switch (stmt->type) {
case kStmtSelect: printSelectStatementInfo((SelectStatement*) stmt, 1); break; 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(); start = std::chrono::system_clock::now();
// Parsing // Parsing
StatementList* stmt_list = SQLParser::parseSQLString(sql.c_str()); SQLStatementList* stmt_list = SQLParser::parseSQLString(sql.c_str());
end = std::chrono::system_clock::now(); end = std::chrono::system_clock::now();
std::chrono::duration<double> elapsed_seconds = end-start; std::chrono::duration<double> elapsed_seconds = end-start;

View File

@ -9,10 +9,10 @@
using namespace hsql; using namespace hsql;
TEST(Delete) { 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(stmt_list->isValid);
ASSERT_EQ(stmt_list->size(), 1); 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); DeleteStatement* stmt = (DeleteStatement*) stmt_list->at(0);
ASSERT_STREQ(stmt->table_name, "students"); ASSERT_STREQ(stmt->table_name, "students");
@ -23,13 +23,13 @@ TEST(Delete) {
} }
TEST(Create) { 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(stmt_list->isValid);
ASSERT_EQ(stmt_list->size(), 1); 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); 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_STREQ(stmt->table_name, "students");
ASSERT_NOTNULL(stmt->columns); ASSERT_NOTNULL(stmt->columns);
ASSERT_EQ(stmt->columns->size(), 4); ASSERT_EQ(stmt->columns->size(), 4);
@ -45,10 +45,10 @@ TEST(Create) {
TEST(Update) { 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(stmt_list->isValid);
ASSERT_EQ(stmt_list->size(), 1); 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); UpdateStatement* stmt = (UpdateStatement*) stmt_list->at(0);
ASSERT_NOTNULL(stmt->table); ASSERT_NOTNULL(stmt->table);
@ -73,22 +73,23 @@ TEST(Update) {
TEST(Insert) { 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(stmt_list->isValid);
ASSERT_EQ(stmt_list->size(), 1); ASSERT_EQ(stmt_list->size(), 1);
ASSERT_EQ(stmt_list->at(0)->type, kStmtInsert); ASSERT_EQ(stmt_list->at(0)->type(), kStmtInsert);
// TODO // TODO
} }
TEST(DropTable) { TEST(DropTable) {
StatementList* stmt_list = SQLParser::parseSQLString("DROP TABLE students"); SQLStatementList* stmt_list = SQLParser::parseSQLString("DROP TABLE students");
ASSERT(stmt_list->isValid); ASSERT(stmt_list->isValid);
ASSERT_EQ(stmt_list->size(), 1); 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); DropStatement* stmt = (DropStatement*) stmt_list->at(0);
ASSERT_EQ(stmt->type, DropStatement::kTable);
ASSERT_NOTNULL(stmt->name); ASSERT_NOTNULL(stmt->name);
ASSERT_STREQ(stmt->name, "students"); ASSERT_STREQ(stmt->name, "students");
} }

View File

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