added update statement support
This commit is contained in:
parent
2f76183586
commit
03fe3a69e2
|
@ -36,3 +36,8 @@ clean:
|
||||||
rm -f *.o *~ $(BIN_DIR)/analysis $(TESTS_BIN) $(BIN_DIR)/grammar_test $(BIN_DIR)/tests
|
rm -f *.o *~ $(BIN_DIR)/analysis $(TESTS_BIN) $(BIN_DIR)/grammar_test $(BIN_DIR)/tests
|
||||||
rm -rf $(BUILD_DIR)
|
rm -rf $(BUILD_DIR)
|
||||||
make clean -C parser/
|
make clean -C parser/
|
||||||
|
|
||||||
|
|
||||||
|
test: tests grammar_test
|
||||||
|
@./$(BIN_DIR)/grammar_test -f ../test/valid_queries.sql
|
||||||
|
@./$(BIN_DIR)/tests
|
|
@ -20,7 +20,7 @@ struct UpdateStatement : Statement {
|
||||||
virtual ~UpdateStatement(); // defined in destructors.cpp
|
virtual ~UpdateStatement(); // defined in destructors.cpp
|
||||||
|
|
||||||
TableRef* table;
|
TableRef* table;
|
||||||
List<UpdateClause*> updates;
|
List<UpdateClause*>* updates;
|
||||||
Expr* where;
|
Expr* where;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -38,6 +38,15 @@ DeleteStatement::~DeleteStatement() {
|
||||||
delete expr;
|
delete expr;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* UpdateStatement.h
|
||||||
|
*/
|
||||||
|
UpdateStatement::~UpdateStatement() {
|
||||||
|
delete table;
|
||||||
|
delete updates;
|
||||||
|
delete where;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* SelectStatement.h
|
* SelectStatement.h
|
||||||
*/
|
*/
|
||||||
|
|
|
@ -5,7 +5,6 @@
|
||||||
|
|
||||||
namespace hsql {
|
namespace hsql {
|
||||||
|
|
||||||
void printExpression(Expr* expr, uint num_indent);
|
|
||||||
void printOperatorExpression(Expr* expr, uint num_indent);
|
void printOperatorExpression(Expr* expr, uint num_indent);
|
||||||
|
|
||||||
const char* indent(uint num_indent) { return std::string(num_indent, '\t').c_str(); }
|
const char* indent(uint num_indent) { return std::string(num_indent, '\t').c_str(); }
|
||||||
|
|
|
@ -11,6 +11,7 @@ void printSelectStatementInfo(SelectStatement* stmt, uint num_indent);
|
||||||
void printImportStatementInfo(ImportStatement* stmt, uint num_indent);
|
void printImportStatementInfo(ImportStatement* stmt, uint num_indent);
|
||||||
void printInsertStatementInfo(InsertStatement* stmt, uint num_indent);
|
void printInsertStatementInfo(InsertStatement* stmt, uint num_indent);
|
||||||
void printCreateStatementInfo(CreateStatement* stmt, uint num_indent);
|
void printCreateStatementInfo(CreateStatement* stmt, uint num_indent);
|
||||||
|
void printExpression(Expr* expr, uint num_indent);
|
||||||
|
|
||||||
} // namespace hsql
|
} // namespace hsql
|
||||||
|
|
||||||
|
|
|
@ -84,6 +84,7 @@ typedef void* yyscan_t;
|
||||||
hsql::CreateStatement* create_stmt;
|
hsql::CreateStatement* create_stmt;
|
||||||
hsql::InsertStatement* insert_stmt;
|
hsql::InsertStatement* insert_stmt;
|
||||||
hsql::DeleteStatement* delete_stmt;
|
hsql::DeleteStatement* delete_stmt;
|
||||||
|
hsql::UpdateStatement* update_stmt;
|
||||||
|
|
||||||
hsql::TableRef* table;
|
hsql::TableRef* table;
|
||||||
hsql::Expr* expr;
|
hsql::Expr* expr;
|
||||||
|
@ -91,12 +92,14 @@ typedef void* yyscan_t;
|
||||||
hsql::OrderType order_type;
|
hsql::OrderType order_type;
|
||||||
hsql::LimitDescription* limit;
|
hsql::LimitDescription* limit;
|
||||||
hsql::ColumnDefinition* column_t;
|
hsql::ColumnDefinition* column_t;
|
||||||
|
hsql::UpdateClause* update_t;
|
||||||
|
|
||||||
hsql::StatementList* stmt_list;
|
hsql::StatementList* 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;
|
||||||
hsql::List<hsql::ColumnDefinition*>* column_list_t;
|
hsql::List<hsql::ColumnDefinition*>* column_list_t;
|
||||||
|
hsql::List<hsql::UpdateClause*>* update_list_t;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -135,11 +138,12 @@ typedef void* yyscan_t;
|
||||||
%type <create_stmt> create_statement
|
%type <create_stmt> create_statement
|
||||||
%type <insert_stmt> insert_statement
|
%type <insert_stmt> insert_statement
|
||||||
%type <delete_stmt> delete_statement truncate_statement
|
%type <delete_stmt> delete_statement truncate_statement
|
||||||
|
%type <update_stmt> update_statement
|
||||||
%type <sval> table_name opt_alias alias file_path
|
%type <sval> table_name opt_alias alias file_path
|
||||||
%type <bval> opt_not_exists
|
%type <bval> opt_not_exists
|
||||||
%type <uval> import_file_type opt_join_type column_type
|
%type <uval> import_file_type opt_join_type column_type
|
||||||
%type <table> from_clause table_ref table_ref_atomic table_ref_name
|
%type <table> from_clause table_ref table_ref_atomic table_ref_name
|
||||||
%type <table> join_clause join_table
|
%type <table> join_clause join_table table_ref_name_no_alias
|
||||||
%type <expr> expr scalar_expr unary_expr binary_expr function_expr star_expr expr_alias
|
%type <expr> expr scalar_expr unary_expr binary_expr function_expr star_expr expr_alias
|
||||||
%type <expr> column_name literal int_literal num_literal string_literal
|
%type <expr> column_name literal int_literal num_literal string_literal
|
||||||
%type <expr> comp_expr opt_where join_condition
|
%type <expr> comp_expr opt_where join_condition
|
||||||
|
@ -151,6 +155,8 @@ typedef void* yyscan_t;
|
||||||
%type <slist> ident_commalist opt_column_list
|
%type <slist> ident_commalist opt_column_list
|
||||||
%type <column_t> column_def
|
%type <column_t> column_def
|
||||||
%type <column_list_t> column_def_commalist
|
%type <column_list_t> column_def_commalist
|
||||||
|
%type <update_t> update_clause
|
||||||
|
%type <update_list_t> update_clause_commalist
|
||||||
|
|
||||||
/******************************
|
/******************************
|
||||||
** Token Precedence and Associativity
|
** Token Precedence and Associativity
|
||||||
|
@ -198,6 +204,7 @@ statement:
|
||||||
| insert_statement { $$ = $1; }
|
| insert_statement { $$ = $1; }
|
||||||
| delete_statement { $$ = $1; }
|
| delete_statement { $$ = $1; }
|
||||||
| truncate_statement { $$ = $1; }
|
| truncate_statement { $$ = $1; }
|
||||||
|
| update_statement { $$ = $1; }
|
||||||
;
|
;
|
||||||
|
|
||||||
|
|
||||||
|
@ -316,6 +323,34 @@ opt_column_list:
|
||||||
| /* empty */ { $$ = NULL; }
|
| /* empty */ { $$ = NULL; }
|
||||||
;
|
;
|
||||||
|
|
||||||
|
|
||||||
|
/******************************
|
||||||
|
* Update Statement
|
||||||
|
* UPDATE students SET grade = 1.3, name='Felix Fürstenberg' WHERE name = 'Max Mustermann';
|
||||||
|
******************************/
|
||||||
|
|
||||||
|
update_statement:
|
||||||
|
UPDATE table_ref_name_no_alias SET update_clause_commalist opt_where {
|
||||||
|
$$ = new UpdateStatement();
|
||||||
|
$$->table = $2;
|
||||||
|
$$->updates = $4;
|
||||||
|
$$->where = $5;
|
||||||
|
}
|
||||||
|
;
|
||||||
|
|
||||||
|
update_clause_commalist:
|
||||||
|
update_clause { $$ = new List<UpdateClause*>($1); }
|
||||||
|
| update_clause_commalist ',' update_clause { $1->push_back($3); $$ = $1; }
|
||||||
|
;
|
||||||
|
|
||||||
|
update_clause:
|
||||||
|
IDENTIFIER '=' literal {
|
||||||
|
$$ = new UpdateClause();
|
||||||
|
$$->column = $1;
|
||||||
|
$$->value = $3;
|
||||||
|
}
|
||||||
|
;
|
||||||
|
|
||||||
/******************************
|
/******************************
|
||||||
* Select Statement
|
* Select Statement
|
||||||
******************************/
|
******************************/
|
||||||
|
@ -539,7 +574,16 @@ table_ref_name:
|
||||||
tbl->alias = $2;
|
tbl->alias = $2;
|
||||||
$$ = tbl;
|
$$ = tbl;
|
||||||
}
|
}
|
||||||
;
|
;
|
||||||
|
|
||||||
|
|
||||||
|
table_ref_name_no_alias:
|
||||||
|
table_name {
|
||||||
|
$$ = new TableRef(kTableName);
|
||||||
|
$$->name = $1;
|
||||||
|
}
|
||||||
|
;
|
||||||
|
|
||||||
|
|
||||||
table_name:
|
table_name:
|
||||||
IDENTIFIER
|
IDENTIFIER
|
||||||
|
|
|
@ -86,9 +86,9 @@ int main(int argc, char *argv[]) {
|
||||||
}
|
}
|
||||||
|
|
||||||
if (num_failed == 0) {
|
if (num_failed == 0) {
|
||||||
printf("All %lu grammar tests completed successfully!\n", queries.size());
|
printf("\033[0;32m{ ok} \033[0mAll %lu grammar tests completed successfully!\n", queries.size());
|
||||||
} else {
|
} else {
|
||||||
fprintf(stderr, "Some grammar tests failed! %d out of %lu tests failed!\n", num_failed, queries.size());
|
fprintf(stderr, "\033[0;31m{ failed} \033[0mSome grammar tests failed! %d out of %lu tests failed!\n", num_failed, queries.size());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -3,14 +3,16 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "SQLParser.h"
|
#include "SQLParser.h"
|
||||||
|
#include "sqlhelper.h"
|
||||||
#include "tests/test.h"
|
#include "tests/test.h"
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
using namespace hsql;
|
using namespace hsql;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
TEST(SelectTest) {
|
TEST(Select) {
|
||||||
StatementList* stmt_list = SQLParser::parseSQLString("SELECT * FROM students;");
|
StatementList* 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);
|
||||||
|
@ -21,7 +23,7 @@ TEST(SelectTest) {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
TEST(DeleteTest) {
|
TEST(Delete) {
|
||||||
StatementList* stmt_list = SQLParser::parseSQLString("DELETE FROM students WHERE grade > 2.0;");
|
StatementList* 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);
|
||||||
|
@ -35,7 +37,7 @@ TEST(DeleteTest) {
|
||||||
ASSERT_EQ(stmt->expr->expr2->fval, 2.0);
|
ASSERT_EQ(stmt->expr->expr2->fval, 2.0);
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST(CreateTable) {
|
TEST(Create) {
|
||||||
StatementList* stmt_list = SQLParser::parseSQLString("CREATE TABLE students (name TEXT, student_number INTEGER, city TEXT, grade DOUBLE)");
|
StatementList* stmt_list = SQLParser::parseSQLString("CREATE TABLE students (name TEXT, student_number INTEGER, city TEXT, grade DOUBLE)");
|
||||||
ASSERT(stmt_list->isValid);
|
ASSERT(stmt_list->isValid);
|
||||||
ASSERT_EQ(stmt_list->size(), 1);
|
ASSERT_EQ(stmt_list->size(), 1);
|
||||||
|
@ -50,4 +52,42 @@ TEST(CreateTable) {
|
||||||
ASSERT_EQ(stmt->columns->at(0)->type, ColumnDefinition::TEXT);
|
ASSERT_EQ(stmt->columns->at(0)->type, ColumnDefinition::TEXT);
|
||||||
ASSERT_STREQ(stmt->columns->at(3)->name, "grade");
|
ASSERT_STREQ(stmt->columns->at(3)->name, "grade");
|
||||||
ASSERT_EQ(stmt->columns->at(3)->type, ColumnDefinition::DOUBLE);
|
ASSERT_EQ(stmt->columns->at(3)->type, ColumnDefinition::DOUBLE);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
TEST(Update) {
|
||||||
|
StatementList* 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);
|
||||||
|
|
||||||
|
UpdateStatement* stmt = (UpdateStatement*) stmt_list->at(0);
|
||||||
|
ASSERT_NOTNULL(stmt->table);
|
||||||
|
ASSERT_STREQ(stmt->table->name, "students");
|
||||||
|
|
||||||
|
ASSERT_NOTNULL(stmt->updates);
|
||||||
|
ASSERT_EQ(stmt->updates->size(), 2);
|
||||||
|
ASSERT_STREQ(stmt->updates->at(0)->column, "grade");
|
||||||
|
ASSERT_STREQ(stmt->updates->at(1)->column, "name");
|
||||||
|
ASSERT(stmt->updates->at(0)->value->isType(kExprLiteralFloat));
|
||||||
|
ASSERT(stmt->updates->at(1)->value->isType(kExprLiteralString));
|
||||||
|
ASSERT_EQ(stmt->updates->at(0)->value->fval, 5.0);
|
||||||
|
ASSERT_STREQ(stmt->updates->at(1)->value->name, "test");
|
||||||
|
|
||||||
|
ASSERT_NOTNULL(stmt->where);
|
||||||
|
ASSERT(stmt->where->isType(kExprOperator));
|
||||||
|
ASSERT(stmt->where->isSimpleOp('='));
|
||||||
|
ASSERT_STREQ(stmt->where->expr->name, "name");
|
||||||
|
ASSERT_STREQ(stmt->where->expr2->name, "Max Mustermann");
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
TEST(Insert) {
|
||||||
|
StatementList* 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);
|
||||||
|
|
||||||
|
// TODO
|
||||||
}
|
}
|
|
@ -1,11 +1,16 @@
|
||||||
#ifndef __TEST_H__
|
#ifndef __TEST_H__
|
||||||
#define __TEST_H__
|
#define __TEST_H__
|
||||||
|
|
||||||
|
|
||||||
|
#include <iostream>
|
||||||
|
|
||||||
|
|
||||||
#define TEST(name) \
|
#define TEST(name) \
|
||||||
void name(); \
|
void name(); \
|
||||||
namespace g_dummy { int _##name = AddTest(name, #name); } \
|
namespace g_dummy { int _##name = AddTest(name, #name); } \
|
||||||
void name()
|
void name()
|
||||||
|
|
||||||
|
|
||||||
#define ASSERT(cond) if (!(cond)) throw AssertionFailedException(#cond);
|
#define ASSERT(cond) if (!(cond)) throw AssertionFailedException(#cond);
|
||||||
|
|
||||||
#define ASSERT_TRUE(cond) ASSERT(cond);
|
#define ASSERT_TRUE(cond) ASSERT(cond);
|
||||||
|
@ -17,7 +22,11 @@
|
||||||
#define ASSERT_STREQ(a, b) \
|
#define ASSERT_STREQ(a, b) \
|
||||||
if (std::string(a).compare(std::string(b)) != 0) throw AssertionFailedException(#a " == " #b)
|
if (std::string(a).compare(std::string(b)) != 0) throw AssertionFailedException(#a " == " #b)
|
||||||
#define ASSERT_EQ(a, b) \
|
#define ASSERT_EQ(a, b) \
|
||||||
|
if (a != b) { \
|
||||||
|
std::cout << "Actual values: " << a << " != " << b << std::endl; \
|
||||||
|
} \
|
||||||
ASSERT(a == b);
|
ASSERT(a == b);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
class AssertionFailedException: public std::exception {
|
class AssertionFailedException: public std::exception {
|
||||||
|
|
|
@ -23,4 +23,8 @@ INSERT INTO test_table SELECT * FROM students;
|
||||||
# DELETE
|
# DELETE
|
||||||
DELETE FROM students WHERE grade > 3.0
|
DELETE FROM students WHERE grade > 3.0
|
||||||
DELETE FROM students
|
DELETE FROM students
|
||||||
TRUNCATE students
|
TRUNCATE students
|
||||||
|
# UPDATE
|
||||||
|
UPDATE students SET grade = 1.3 WHERE name = 'Max Mustermann';
|
||||||
|
UPDATE students SET grade = 1.3, name='Felix Fürstenberg' WHERE name = 'Max Mustermann';
|
||||||
|
UPDATE students SET grade = 1.0;
|
Loading…
Reference in New Issue