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 -rf $(BUILD_DIR)
|
||||
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
|
||||
|
||||
TableRef* table;
|
||||
List<UpdateClause*> updates;
|
||||
List<UpdateClause*>* updates;
|
||||
Expr* where;
|
||||
};
|
||||
|
||||
|
|
|
@ -38,6 +38,15 @@ DeleteStatement::~DeleteStatement() {
|
|||
delete expr;
|
||||
}
|
||||
|
||||
/**
|
||||
* UpdateStatement.h
|
||||
*/
|
||||
UpdateStatement::~UpdateStatement() {
|
||||
delete table;
|
||||
delete updates;
|
||||
delete where;
|
||||
}
|
||||
|
||||
/**
|
||||
* SelectStatement.h
|
||||
*/
|
||||
|
|
|
@ -5,7 +5,6 @@
|
|||
|
||||
namespace hsql {
|
||||
|
||||
void printExpression(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(); }
|
||||
|
|
|
@ -11,6 +11,7 @@ void printSelectStatementInfo(SelectStatement* stmt, uint num_indent);
|
|||
void printImportStatementInfo(ImportStatement* stmt, uint num_indent);
|
||||
void printInsertStatementInfo(InsertStatement* stmt, uint num_indent);
|
||||
void printCreateStatementInfo(CreateStatement* stmt, uint num_indent);
|
||||
void printExpression(Expr* expr, uint num_indent);
|
||||
|
||||
} // namespace hsql
|
||||
|
||||
|
|
|
@ -84,6 +84,7 @@ typedef void* yyscan_t;
|
|||
hsql::CreateStatement* create_stmt;
|
||||
hsql::InsertStatement* insert_stmt;
|
||||
hsql::DeleteStatement* delete_stmt;
|
||||
hsql::UpdateStatement* update_stmt;
|
||||
|
||||
hsql::TableRef* table;
|
||||
hsql::Expr* expr;
|
||||
|
@ -91,12 +92,14 @@ typedef void* yyscan_t;
|
|||
hsql::OrderType order_type;
|
||||
hsql::LimitDescription* limit;
|
||||
hsql::ColumnDefinition* column_t;
|
||||
hsql::UpdateClause* update_t;
|
||||
|
||||
hsql::StatementList* stmt_list;
|
||||
hsql::List<char*>* slist;
|
||||
hsql::List<hsql::Expr*>* expr_list;
|
||||
hsql::List<hsql::TableRef*>* table_list;
|
||||
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 <insert_stmt> insert_statement
|
||||
%type <delete_stmt> delete_statement truncate_statement
|
||||
%type <update_stmt> update_statement
|
||||
%type <sval> table_name opt_alias alias file_path
|
||||
%type <bval> opt_not_exists
|
||||
%type <uval> import_file_type opt_join_type column_type
|
||||
%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> column_name literal int_literal num_literal string_literal
|
||||
%type <expr> comp_expr opt_where join_condition
|
||||
|
@ -151,6 +155,8 @@ typedef void* yyscan_t;
|
|||
%type <slist> ident_commalist opt_column_list
|
||||
%type <column_t> column_def
|
||||
%type <column_list_t> column_def_commalist
|
||||
%type <update_t> update_clause
|
||||
%type <update_list_t> update_clause_commalist
|
||||
|
||||
/******************************
|
||||
** Token Precedence and Associativity
|
||||
|
@ -198,6 +204,7 @@ statement:
|
|||
| insert_statement { $$ = $1; }
|
||||
| delete_statement { $$ = $1; }
|
||||
| truncate_statement { $$ = $1; }
|
||||
| update_statement { $$ = $1; }
|
||||
;
|
||||
|
||||
|
||||
|
@ -316,6 +323,34 @@ opt_column_list:
|
|||
| /* 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
|
||||
******************************/
|
||||
|
@ -539,7 +574,16 @@ table_ref_name:
|
|||
tbl->alias = $2;
|
||||
$$ = tbl;
|
||||
}
|
||||
;
|
||||
;
|
||||
|
||||
|
||||
table_ref_name_no_alias:
|
||||
table_name {
|
||||
$$ = new TableRef(kTableName);
|
||||
$$->name = $1;
|
||||
}
|
||||
;
|
||||
|
||||
|
||||
table_name:
|
||||
IDENTIFIER
|
||||
|
|
|
@ -86,9 +86,9 @@ int main(int argc, char *argv[]) {
|
|||
}
|
||||
|
||||
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 {
|
||||
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 "sqlhelper.h"
|
||||
#include "tests/test.h"
|
||||
|
||||
|
||||
|
||||
using namespace hsql;
|
||||
|
||||
|
||||
|
||||
TEST(SelectTest) {
|
||||
TEST(Select) {
|
||||
StatementList* stmt_list = SQLParser::parseSQLString("SELECT * FROM students;");
|
||||
ASSERT(stmt_list->isValid);
|
||||
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;");
|
||||
ASSERT(stmt_list->isValid);
|
||||
ASSERT_EQ(stmt_list->size(), 1);
|
||||
|
@ -35,7 +37,7 @@ TEST(DeleteTest) {
|
|||
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)");
|
||||
ASSERT(stmt_list->isValid);
|
||||
ASSERT_EQ(stmt_list->size(), 1);
|
||||
|
@ -51,3 +53,41 @@ TEST(CreateTable) {
|
|||
ASSERT_STREQ(stmt->columns->at(3)->name, "grade");
|
||||
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__
|
||||
#define __TEST_H__
|
||||
|
||||
|
||||
#include <iostream>
|
||||
|
||||
|
||||
#define TEST(name) \
|
||||
void name(); \
|
||||
namespace g_dummy { int _##name = AddTest(name, #name); } \
|
||||
void name()
|
||||
|
||||
|
||||
#define ASSERT(cond) if (!(cond)) throw AssertionFailedException(#cond);
|
||||
|
||||
#define ASSERT_TRUE(cond) ASSERT(cond);
|
||||
|
@ -17,9 +22,13 @@
|
|||
#define ASSERT_STREQ(a, b) \
|
||||
if (std::string(a).compare(std::string(b)) != 0) throw AssertionFailedException(#a " == " #b)
|
||||
#define ASSERT_EQ(a, b) \
|
||||
if (a != b) { \
|
||||
std::cout << "Actual values: " << a << " != " << b << std::endl; \
|
||||
} \
|
||||
ASSERT(a == b);
|
||||
|
||||
|
||||
|
||||
class AssertionFailedException: public std::exception {
|
||||
public:
|
||||
AssertionFailedException(std::string msg) :
|
||||
|
|
|
@ -24,3 +24,7 @@ INSERT INTO test_table SELECT * FROM students;
|
|||
DELETE FROM students WHERE grade > 3.0
|
||||
DELETE FROM 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