add astyle formatting
This commit is contained in:
parent
57b8cdd31b
commit
7d1c56d0aa
|
@ -31,3 +31,6 @@ lib-test/
|
|||
*.exe
|
||||
*.out
|
||||
*.app
|
||||
|
||||
*.cpp.orig
|
||||
*.h.orig
|
9
Makefile
9
Makefile
|
@ -9,6 +9,9 @@ LIBCPP = $(shell find $(SRC) -name '*.cpp' -not -path "$(SRCPARSER)/*") $(S
|
|||
LIBOBJ = $(LIBCPP:%.cpp=%.o)
|
||||
TESTCPP = $(shell find test/lib/ -name '*.cpp')
|
||||
|
||||
ALLLIB = $(shell find $(SRC) -name '*.cpp' -not -path "$(SRCPARSER)/*") $(shell find $(SRC) -name '*.h' -not -path "$(SRCPARSER)/*")
|
||||
ALLTEST = $(shell find test/lib/ -name '*.cpp') $(shell find test/lib/ -name '*.h')
|
||||
|
||||
# compile & link flages
|
||||
CC = g++
|
||||
CFLAGS = -std=c++11 -Wall -fPIC
|
||||
|
@ -48,6 +51,10 @@ cleanall: clean cleanparser
|
|||
install:
|
||||
cp $(TARGET) $(INSTALL)/lib/$(TARGET)
|
||||
|
||||
format:
|
||||
astyle --options=astyle.options $(ALLLIB)
|
||||
astyle --options=astyle.options $(ALLTEST)
|
||||
|
||||
############
|
||||
### Test ###
|
||||
############
|
||||
|
@ -63,5 +70,3 @@ $(BIN)/sql_tests: library
|
|||
$(BIN)/sql_grammar_test: library
|
||||
@mkdir -p $(BIN)/
|
||||
$(CC) $(CTESTFLAGS) test/sql_grammar_test.cpp -o $(BIN)/sql_grammar_test -lsqlparser
|
||||
|
||||
|
||||
|
|
|
@ -0,0 +1,8 @@
|
|||
|
||||
# indentation
|
||||
--indent=spaces=4
|
||||
--indent-namespaces
|
||||
|
||||
--style=java
|
||||
--style=attach
|
||||
-A2
|
|
@ -8,39 +8,39 @@
|
|||
|
||||
namespace hsql {
|
||||
|
||||
SQLParser::SQLParser() {
|
||||
fprintf(stderr, "SQLParser only has static methods atm! Do not initialize!\n");
|
||||
}
|
||||
SQLParser::SQLParser() {
|
||||
fprintf(stderr, "SQLParser only has static methods atm! Do not initialize!\n");
|
||||
}
|
||||
|
||||
|
||||
SQLParserResult* SQLParser::parseSQLString(const char *text) {
|
||||
SQLParserResult* result = NULL;
|
||||
yyscan_t scanner;
|
||||
YY_BUFFER_STATE state;
|
||||
SQLParserResult* SQLParser::parseSQLString(const char *text) {
|
||||
SQLParserResult* result = NULL;
|
||||
yyscan_t scanner;
|
||||
YY_BUFFER_STATE state;
|
||||
|
||||
if (hsql_lex_init(&scanner)) {
|
||||
// couldn't initialize
|
||||
fprintf(stderr, "[Error] SQLParser: Error when initializing lexer!\n");
|
||||
return NULL;
|
||||
}
|
||||
if (hsql_lex_init(&scanner)) {
|
||||
// couldn't initialize
|
||||
fprintf(stderr, "[Error] SQLParser: Error when initializing lexer!\n");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
state = hsql__scan_string(text, scanner);
|
||||
state = hsql__scan_string(text, scanner);
|
||||
|
||||
if (hsql_parse(&result, scanner)) {
|
||||
// Returns an error stmt object
|
||||
return result;
|
||||
}
|
||||
if (hsql_parse(&result, scanner)) {
|
||||
// Returns an error stmt object
|
||||
return result;
|
||||
}
|
||||
|
||||
hsql__delete_buffer(state, scanner);
|
||||
hsql__delete_buffer(state, scanner);
|
||||
|
||||
hsql_lex_destroy(scanner);
|
||||
return result;
|
||||
}
|
||||
hsql_lex_destroy(scanner);
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
SQLParserResult* SQLParser::parseSQLString(const std::string& text) {
|
||||
return parseSQLString(text.c_str());
|
||||
}
|
||||
SQLParserResult* SQLParser::parseSQLString(const std::string& text) {
|
||||
return parseSQLString(text.c_str());
|
||||
}
|
||||
|
||||
|
||||
|
||||
} // namespace hsql
|
|
@ -5,19 +5,19 @@
|
|||
#include "sql/statements.h"
|
||||
|
||||
namespace hsql {
|
||||
/**
|
||||
* Main class for parsing SQL strings
|
||||
*/
|
||||
class SQLParser {
|
||||
public:
|
||||
static SQLParserResult* parseSQLString(const char* sql);
|
||||
static SQLParserResult* parseSQLString(const std::string& sql);
|
||||
/**
|
||||
* Main class for parsing SQL strings
|
||||
*/
|
||||
class SQLParser {
|
||||
public:
|
||||
static SQLParserResult* parseSQLString(const char* sql);
|
||||
static SQLParserResult* parseSQLString(const std::string& sql);
|
||||
|
||||
private:
|
||||
SQLParser();
|
||||
};
|
||||
|
||||
private:
|
||||
SQLParser();
|
||||
};
|
||||
|
||||
|
||||
} // namespace hsql
|
||||
|
||||
|
||||
|
|
|
@ -3,39 +3,39 @@
|
|||
|
||||
namespace hsql {
|
||||
|
||||
SQLParserResult::SQLParserResult() :
|
||||
isValid(true),
|
||||
errorMsg(NULL) {};
|
||||
SQLParserResult::SQLParserResult() :
|
||||
isValid(true),
|
||||
errorMsg(NULL) {};
|
||||
|
||||
|
||||
SQLParserResult::SQLParserResult(SQLStatement* stmt) :
|
||||
isValid(true),
|
||||
errorMsg(NULL) {
|
||||
addStatement(stmt);
|
||||
};
|
||||
SQLParserResult::SQLParserResult(SQLStatement* stmt) :
|
||||
isValid(true),
|
||||
errorMsg(NULL) {
|
||||
addStatement(stmt);
|
||||
};
|
||||
|
||||
|
||||
SQLParserResult::~SQLParserResult() {
|
||||
for (std::vector<SQLStatement*>::iterator it = statements.begin(); it != statements.end(); ++it) {
|
||||
delete *it;
|
||||
}
|
||||
SQLParserResult::~SQLParserResult() {
|
||||
for (std::vector<SQLStatement*>::iterator it = statements.begin(); it != statements.end(); ++it) {
|
||||
delete *it;
|
||||
}
|
||||
|
||||
delete errorMsg;
|
||||
}
|
||||
delete errorMsg;
|
||||
}
|
||||
|
||||
|
||||
void SQLParserResult::addStatement(SQLStatement* stmt) {
|
||||
statements.push_back(stmt);
|
||||
}
|
||||
void SQLParserResult::addStatement(SQLStatement* stmt) {
|
||||
statements.push_back(stmt);
|
||||
}
|
||||
|
||||
|
||||
SQLStatement* SQLParserResult::getStatement(int id) {
|
||||
return statements[id];
|
||||
}
|
||||
SQLStatement* SQLParserResult::getStatement(int id) {
|
||||
return statements[id];
|
||||
}
|
||||
|
||||
|
||||
size_t SQLParserResult::size() {
|
||||
return statements.size();
|
||||
}
|
||||
|
||||
size_t SQLParserResult::size() {
|
||||
return statements.size();
|
||||
}
|
||||
|
||||
} // namespace hsql
|
|
@ -4,31 +4,31 @@
|
|||
#include "sql/SQLStatement.h"
|
||||
|
||||
namespace hsql {
|
||||
/**
|
||||
* Represents the result of the SQLParser.
|
||||
* If parsing was successful it contains a list of SQLStatement.
|
||||
*/
|
||||
class SQLParserResult {
|
||||
public:
|
||||
/**
|
||||
* Represents the result of the SQLParser.
|
||||
* If parsing was successful it contains a list of SQLStatement.
|
||||
*/
|
||||
class SQLParserResult {
|
||||
public:
|
||||
|
||||
SQLParserResult();
|
||||
SQLParserResult(SQLStatement* stmt);
|
||||
virtual ~SQLParserResult();
|
||||
SQLParserResult();
|
||||
SQLParserResult(SQLStatement* stmt);
|
||||
virtual ~SQLParserResult();
|
||||
|
||||
void addStatement(SQLStatement* stmt);
|
||||
void addStatement(SQLStatement* stmt);
|
||||
|
||||
SQLStatement* getStatement(int id);
|
||||
SQLStatement* getStatement(int id);
|
||||
|
||||
size_t size();
|
||||
|
||||
// public properties
|
||||
std::vector<SQLStatement*> statements;
|
||||
bool isValid;
|
||||
size_t size();
|
||||
|
||||
const char* errorMsg;
|
||||
int errorLine;
|
||||
int errorColumn;
|
||||
};
|
||||
// public properties
|
||||
std::vector<SQLStatement*> statements;
|
||||
bool isValid;
|
||||
|
||||
const char* errorMsg;
|
||||
int errorLine;
|
||||
int errorColumn;
|
||||
};
|
||||
|
||||
} // namespace hsql
|
||||
|
||||
|
|
|
@ -5,62 +5,62 @@
|
|||
|
||||
namespace hsql {
|
||||
|
||||
/**
|
||||
* @struct ColumnDefinition
|
||||
* @brief Represents definition of a table column
|
||||
*/
|
||||
struct ColumnDefinition {
|
||||
enum DataType {
|
||||
TEXT,
|
||||
INT,
|
||||
DOUBLE
|
||||
};
|
||||
/**
|
||||
* @struct ColumnDefinition
|
||||
* @brief Represents definition of a table column
|
||||
*/
|
||||
struct ColumnDefinition {
|
||||
enum DataType {
|
||||
TEXT,
|
||||
INT,
|
||||
DOUBLE
|
||||
};
|
||||
|
||||
ColumnDefinition(char* name, DataType type) :
|
||||
name(name),
|
||||
type(type) {}
|
||||
ColumnDefinition(char* name, DataType type) :
|
||||
name(name),
|
||||
type(type) {}
|
||||
|
||||
virtual ~ColumnDefinition() {
|
||||
delete name;
|
||||
}
|
||||
virtual ~ColumnDefinition() {
|
||||
delete name;
|
||||
}
|
||||
|
||||
char* name;
|
||||
DataType type;
|
||||
};
|
||||
char* name;
|
||||
DataType type;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @struct CreateStatement
|
||||
* @brief Represents "CREATE TABLE students (name TEXT, student_number INTEGER, city TEXT, grade DOUBLE)"
|
||||
*/
|
||||
struct CreateStatement : SQLStatement {
|
||||
enum CreateType {
|
||||
kTable,
|
||||
kTableFromTbl, // Hyrise file format
|
||||
};
|
||||
/**
|
||||
* @struct CreateStatement
|
||||
* @brief Represents "CREATE TABLE students (name TEXT, student_number INTEGER, city TEXT, grade DOUBLE)"
|
||||
*/
|
||||
struct CreateStatement : SQLStatement {
|
||||
enum CreateType {
|
||||
kTable,
|
||||
kTableFromTbl, // Hyrise file format
|
||||
};
|
||||
|
||||
CreateStatement(CreateType type) :
|
||||
SQLStatement(kStmtCreate),
|
||||
type(type),
|
||||
if_not_exists(false),
|
||||
columns(NULL),
|
||||
file_path(NULL),
|
||||
table_name(NULL) {};
|
||||
CreateStatement(CreateType type) :
|
||||
SQLStatement(kStmtCreate),
|
||||
type(type),
|
||||
if_not_exists(false),
|
||||
columns(NULL),
|
||||
file_path(NULL),
|
||||
table_name(NULL) {};
|
||||
|
||||
virtual ~CreateStatement() {
|
||||
delete columns;
|
||||
delete file_path;
|
||||
delete table_name;
|
||||
}
|
||||
virtual ~CreateStatement() {
|
||||
delete columns;
|
||||
delete file_path;
|
||||
delete table_name;
|
||||
}
|
||||
|
||||
CreateType type;
|
||||
bool if_not_exists;
|
||||
CreateType type;
|
||||
bool if_not_exists;
|
||||
|
||||
std::vector<ColumnDefinition*>* columns;
|
||||
std::vector<ColumnDefinition*>* columns;
|
||||
|
||||
const char* file_path;
|
||||
const char* table_name;
|
||||
};
|
||||
const char* file_path;
|
||||
const char* table_name;
|
||||
};
|
||||
|
||||
|
||||
|
||||
|
|
|
@ -6,27 +6,27 @@
|
|||
namespace hsql {
|
||||
|
||||
|
||||
/**
|
||||
* @struct DeleteStatement
|
||||
* @brief Represents "DELETE FROM students WHERE grade > 3.0"
|
||||
*
|
||||
* If expr == NULL => delete all rows (truncate)
|
||||
*/
|
||||
struct DeleteStatement : SQLStatement {
|
||||
DeleteStatement() :
|
||||
SQLStatement(kStmtDelete),
|
||||
table_name(NULL),
|
||||
expr(NULL) {};
|
||||
/**
|
||||
* @struct DeleteStatement
|
||||
* @brief Represents "DELETE FROM students WHERE grade > 3.0"
|
||||
*
|
||||
* If expr == NULL => delete all rows (truncate)
|
||||
*/
|
||||
struct DeleteStatement : SQLStatement {
|
||||
DeleteStatement() :
|
||||
SQLStatement(kStmtDelete),
|
||||
table_name(NULL),
|
||||
expr(NULL) {};
|
||||
|
||||
virtual ~DeleteStatement() {
|
||||
delete table_name;
|
||||
delete expr;
|
||||
}
|
||||
virtual ~DeleteStatement() {
|
||||
delete table_name;
|
||||
delete expr;
|
||||
}
|
||||
|
||||
|
||||
char* table_name;
|
||||
Expr* expr;
|
||||
};
|
||||
char* table_name;
|
||||
Expr* expr;
|
||||
};
|
||||
|
||||
|
||||
|
||||
|
|
|
@ -6,33 +6,33 @@
|
|||
namespace hsql {
|
||||
|
||||
|
||||
/**
|
||||
* @struct DropStatement
|
||||
* @brief Represents "DROP TABLE"
|
||||
*/
|
||||
struct DropStatement : SQLStatement {
|
||||
enum EntityType {
|
||||
kTable,
|
||||
kSchema,
|
||||
kIndex,
|
||||
kView,
|
||||
kPreparedStatement
|
||||
};
|
||||
/**
|
||||
* @struct DropStatement
|
||||
* @brief Represents "DROP TABLE"
|
||||
*/
|
||||
struct DropStatement : SQLStatement {
|
||||
enum EntityType {
|
||||
kTable,
|
||||
kSchema,
|
||||
kIndex,
|
||||
kView,
|
||||
kPreparedStatement
|
||||
};
|
||||
|
||||
|
||||
DropStatement(EntityType type) :
|
||||
SQLStatement(kStmtDrop),
|
||||
type(type),
|
||||
name(NULL) {}
|
||||
DropStatement(EntityType type) :
|
||||
SQLStatement(kStmtDrop),
|
||||
type(type),
|
||||
name(NULL) {}
|
||||
|
||||
virtual ~DropStatement() {
|
||||
delete name;
|
||||
}
|
||||
virtual ~DropStatement() {
|
||||
delete name;
|
||||
}
|
||||
|
||||
|
||||
EntityType type;
|
||||
const char* name;
|
||||
};
|
||||
EntityType type;
|
||||
const char* name;
|
||||
};
|
||||
|
||||
|
||||
|
||||
|
|
|
@ -6,24 +6,24 @@
|
|||
namespace hsql {
|
||||
|
||||
|
||||
/**
|
||||
* @struct ExecuteStatement
|
||||
* @brief Represents "EXECUTE ins_prep(100, "test", 2.3);"
|
||||
*/
|
||||
struct ExecuteStatement : SQLStatement {
|
||||
ExecuteStatement() :
|
||||
SQLStatement(kStmtExecute),
|
||||
name(NULL),
|
||||
parameters(NULL) {}
|
||||
|
||||
virtual ~ExecuteStatement() {
|
||||
delete name;
|
||||
delete parameters;
|
||||
}
|
||||
/**
|
||||
* @struct ExecuteStatement
|
||||
* @brief Represents "EXECUTE ins_prep(100, "test", 2.3);"
|
||||
*/
|
||||
struct ExecuteStatement : SQLStatement {
|
||||
ExecuteStatement() :
|
||||
SQLStatement(kStmtExecute),
|
||||
name(NULL),
|
||||
parameters(NULL) {}
|
||||
|
||||
const char* name;
|
||||
std::vector<Expr*>* parameters;
|
||||
};
|
||||
virtual ~ExecuteStatement() {
|
||||
delete name;
|
||||
delete parameters;
|
||||
}
|
||||
|
||||
const char* name;
|
||||
std::vector<Expr*>* parameters;
|
||||
};
|
||||
|
||||
|
||||
|
||||
|
|
148
src/sql/Expr.cpp
148
src/sql/Expr.cpp
|
@ -5,98 +5,98 @@
|
|||
|
||||
namespace hsql {
|
||||
|
||||
char* substr(const char* source, int from, int to) {
|
||||
int len = to-from;
|
||||
char* copy = new char[len+1];
|
||||
strncpy(copy, source+from, len);
|
||||
copy[len] = '\0';
|
||||
return copy;
|
||||
}
|
||||
char* substr(const char* source, int from, int to) {
|
||||
int len = to-from;
|
||||
char* copy = new char[len+1];
|
||||
strncpy(copy, source+from, len);
|
||||
copy[len] = '\0';
|
||||
return copy;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
Expr* Expr::makeOpUnary(OperatorType op, Expr* expr) {
|
||||
Expr* e = new Expr(kExprOperator);
|
||||
e->op_type = op;
|
||||
e->expr = expr;
|
||||
e->expr2 = NULL;
|
||||
return e;
|
||||
}
|
||||
Expr* Expr::makeOpUnary(OperatorType op, Expr* expr) {
|
||||
Expr* e = new Expr(kExprOperator);
|
||||
e->op_type = op;
|
||||
e->expr = expr;
|
||||
e->expr2 = NULL;
|
||||
return e;
|
||||
}
|
||||
|
||||
|
||||
|
||||
Expr* Expr::makeOpBinary(Expr* expr1, OperatorType op, Expr* expr2) {
|
||||
Expr* e = new Expr(kExprOperator);
|
||||
e->op_type = op;
|
||||
e->op_char = 0;
|
||||
e->expr = expr1;
|
||||
e->expr2 = expr2;
|
||||
return e;
|
||||
}
|
||||
Expr* Expr::makeOpBinary(Expr* expr1, OperatorType op, Expr* expr2) {
|
||||
Expr* e = new Expr(kExprOperator);
|
||||
e->op_type = op;
|
||||
e->op_char = 0;
|
||||
e->expr = expr1;
|
||||
e->expr2 = expr2;
|
||||
return e;
|
||||
}
|
||||
|
||||
Expr* Expr::makeOpBinary(Expr* expr1, char op, Expr* expr2) {
|
||||
Expr* e = new Expr(kExprOperator);
|
||||
e->op_type = SIMPLE_OP;
|
||||
e->op_char = op;
|
||||
e->expr = expr1;
|
||||
e->expr2 = expr2;
|
||||
return e;
|
||||
}
|
||||
Expr* Expr::makeOpBinary(Expr* expr1, char op, Expr* expr2) {
|
||||
Expr* e = new Expr(kExprOperator);
|
||||
e->op_type = SIMPLE_OP;
|
||||
e->op_char = op;
|
||||
e->expr = expr1;
|
||||
e->expr2 = expr2;
|
||||
return e;
|
||||
}
|
||||
|
||||
|
||||
|
||||
Expr* Expr::makeLiteral(int64_t val) {
|
||||
Expr* e = new Expr(kExprLiteralInt);
|
||||
e->ival = val;
|
||||
return e;
|
||||
}
|
||||
Expr* Expr::makeLiteral(int64_t val) {
|
||||
Expr* e = new Expr(kExprLiteralInt);
|
||||
e->ival = val;
|
||||
return e;
|
||||
}
|
||||
|
||||
Expr* Expr::makeLiteral(double value) {
|
||||
Expr* e = new Expr(kExprLiteralFloat);
|
||||
e->fval = value;
|
||||
return e;
|
||||
}
|
||||
Expr* Expr::makeLiteral(double value) {
|
||||
Expr* e = new Expr(kExprLiteralFloat);
|
||||
e->fval = value;
|
||||
return e;
|
||||
}
|
||||
|
||||
Expr* Expr::makeLiteral(char* string) {
|
||||
Expr* e = new Expr(kExprLiteralString);
|
||||
e->name = string;
|
||||
return e;
|
||||
}
|
||||
Expr* Expr::makeLiteral(char* string) {
|
||||
Expr* e = new Expr(kExprLiteralString);
|
||||
e->name = string;
|
||||
return e;
|
||||
}
|
||||
|
||||
|
||||
Expr* Expr::makeColumnRef(char* name) {
|
||||
Expr* e = new Expr(kExprColumnRef);
|
||||
e->name = name;
|
||||
return e;
|
||||
}
|
||||
Expr* Expr::makeColumnRef(char* name) {
|
||||
Expr* e = new Expr(kExprColumnRef);
|
||||
e->name = name;
|
||||
return e;
|
||||
}
|
||||
|
||||
Expr* Expr::makeColumnRef(char* table, char* name) {
|
||||
Expr* e = new Expr(kExprColumnRef);
|
||||
e->name = name;
|
||||
e->table = table;
|
||||
return e;
|
||||
}
|
||||
Expr* Expr::makeColumnRef(char* table, char* name) {
|
||||
Expr* e = new Expr(kExprColumnRef);
|
||||
e->name = name;
|
||||
e->table = table;
|
||||
return e;
|
||||
}
|
||||
|
||||
Expr* Expr::makeFunctionRef(char* func_name, Expr* expr, bool distinct) {
|
||||
Expr* e = new Expr(kExprFunctionRef);
|
||||
e->name = func_name;
|
||||
e->expr = expr;
|
||||
e->distinct = distinct;
|
||||
return e;
|
||||
}
|
||||
Expr* Expr::makeFunctionRef(char* func_name, Expr* expr, bool distinct) {
|
||||
Expr* e = new Expr(kExprFunctionRef);
|
||||
e->name = func_name;
|
||||
e->expr = expr;
|
||||
e->distinct = distinct;
|
||||
return e;
|
||||
}
|
||||
|
||||
Expr* Expr::makePlaceholder(int id) {
|
||||
Expr* e = new Expr(kExprPlaceholder);
|
||||
e->ival = id;
|
||||
return e;
|
||||
}
|
||||
Expr* Expr::makePlaceholder(int id) {
|
||||
Expr* e = new Expr(kExprPlaceholder);
|
||||
e->ival = id;
|
||||
return e;
|
||||
}
|
||||
|
||||
Expr::~Expr() {
|
||||
delete expr;
|
||||
delete expr2;
|
||||
delete name;
|
||||
delete table;
|
||||
}
|
||||
Expr::~Expr() {
|
||||
delete expr;
|
||||
delete expr2;
|
||||
delete name;
|
||||
delete table;
|
||||
}
|
||||
|
||||
} // namespace hsql
|
192
src/sql/Expr.h
192
src/sql/Expr.h
|
@ -7,115 +7,127 @@
|
|||
namespace hsql {
|
||||
|
||||
// Helper function
|
||||
char* substr(const char* source, int from, int to);
|
||||
char* substr(const char* source, int from, int to);
|
||||
|
||||
|
||||
|
||||
typedef enum {
|
||||
kExprLiteralFloat,
|
||||
kExprLiteralString,
|
||||
kExprLiteralInt,
|
||||
kExprStar,
|
||||
kExprPlaceholder,
|
||||
kExprColumnRef,
|
||||
kExprFunctionRef,
|
||||
kExprOperator
|
||||
} ExprType;
|
||||
typedef enum {
|
||||
kExprLiteralFloat,
|
||||
kExprLiteralString,
|
||||
kExprLiteralInt,
|
||||
kExprStar,
|
||||
kExprPlaceholder,
|
||||
kExprColumnRef,
|
||||
kExprFunctionRef,
|
||||
kExprOperator
|
||||
} ExprType;
|
||||
|
||||
|
||||
typedef struct Expr Expr;
|
||||
typedef struct Expr Expr;
|
||||
|
||||
/**
|
||||
* Represents SQL expressions (i.e. literals, operators, column_refs)
|
||||
*
|
||||
* TODO: When destructing a placeholder expression, we might need to alter the placeholder_list
|
||||
*/
|
||||
struct Expr {
|
||||
/**
|
||||
* Operator types. These are important for expressions of type kExprOperator
|
||||
* Trivial types are those that can be described by a single character e.g:
|
||||
* + - * / < > = %
|
||||
* Non-trivial are:
|
||||
* <> <= >= LIKE ISNULL NOT
|
||||
*/
|
||||
typedef enum {
|
||||
SIMPLE_OP,
|
||||
// Binary
|
||||
NOT_EQUALS,
|
||||
LESS_EQ,
|
||||
GREATER_EQ,
|
||||
LIKE,
|
||||
NOT_LIKE,
|
||||
AND,
|
||||
OR,
|
||||
// Unary
|
||||
NOT,
|
||||
UMINUS,
|
||||
ISNULL
|
||||
} OperatorType;
|
||||
/**
|
||||
* Represents SQL expressions (i.e. literals, operators, column_refs)
|
||||
*
|
||||
* TODO: When destructing a placeholder expression, we might need to alter the placeholder_list
|
||||
*/
|
||||
struct Expr {
|
||||
/**
|
||||
* Operator types. These are important for expressions of type kExprOperator
|
||||
* Trivial types are those that can be described by a single character e.g:
|
||||
* + - * / < > = %
|
||||
* Non-trivial are:
|
||||
* <> <= >= LIKE ISNULL NOT
|
||||
*/
|
||||
typedef enum {
|
||||
SIMPLE_OP,
|
||||
// Binary
|
||||
NOT_EQUALS,
|
||||
LESS_EQ,
|
||||
GREATER_EQ,
|
||||
LIKE,
|
||||
NOT_LIKE,
|
||||
AND,
|
||||
OR,
|
||||
// Unary
|
||||
NOT,
|
||||
UMINUS,
|
||||
ISNULL
|
||||
} OperatorType;
|
||||
|
||||
|
||||
|
||||
Expr(ExprType type) :
|
||||
type(type),
|
||||
expr(NULL),
|
||||
expr2(NULL),
|
||||
name(NULL),
|
||||
table(NULL),
|
||||
alias(NULL) {};
|
||||
Expr(ExprType type) :
|
||||
type(type),
|
||||
expr(NULL),
|
||||
expr2(NULL),
|
||||
name(NULL),
|
||||
table(NULL),
|
||||
alias(NULL) {};
|
||||
|
||||
// Interesting side-effect:
|
||||
// Making the destructor virtual used to cause segmentation faults
|
||||
~Expr();
|
||||
|
||||
ExprType type;
|
||||
// Interesting side-effect:
|
||||
// Making the destructor virtual used to cause segmentation faults
|
||||
~Expr();
|
||||
|
||||
Expr* expr;
|
||||
Expr* expr2;
|
||||
char* name;
|
||||
char* table;
|
||||
char* alias;
|
||||
float fval;
|
||||
int64_t ival;
|
||||
int64_t ival2;
|
||||
ExprType type;
|
||||
|
||||
OperatorType op_type;
|
||||
char op_char;
|
||||
bool distinct;
|
||||
Expr* expr;
|
||||
Expr* expr2;
|
||||
char* name;
|
||||
char* table;
|
||||
char* alias;
|
||||
float fval;
|
||||
int64_t ival;
|
||||
int64_t ival2;
|
||||
|
||||
OperatorType op_type;
|
||||
char op_char;
|
||||
bool distinct;
|
||||
|
||||
|
||||
/**
|
||||
* Convenience accessor methods
|
||||
*/
|
||||
inline bool isType(ExprType e_type) { return e_type == type; }
|
||||
inline bool isLiteral() { return isType(kExprLiteralInt) || isType(kExprLiteralFloat) || isType(kExprLiteralString) || isType(kExprPlaceholder); }
|
||||
inline bool hasAlias() { return alias != NULL; }
|
||||
inline bool hasTable() { return table != NULL; }
|
||||
inline char* getName() {
|
||||
if (alias != NULL) return alias;
|
||||
else return name;
|
||||
}
|
||||
inline bool isSimpleOp() { return op_type == SIMPLE_OP; }
|
||||
inline bool isSimpleOp(char op) { return isSimpleOp() && op_char == op; }
|
||||
/**
|
||||
* Convenience accessor methods
|
||||
*/
|
||||
inline bool isType(ExprType e_type) {
|
||||
return e_type == type;
|
||||
}
|
||||
inline bool isLiteral() {
|
||||
return isType(kExprLiteralInt) || isType(kExprLiteralFloat) || isType(kExprLiteralString) || isType(kExprPlaceholder);
|
||||
}
|
||||
inline bool hasAlias() {
|
||||
return alias != NULL;
|
||||
}
|
||||
inline bool hasTable() {
|
||||
return table != NULL;
|
||||
}
|
||||
inline char* getName() {
|
||||
if (alias != NULL) return alias;
|
||||
else return name;
|
||||
}
|
||||
inline bool isSimpleOp() {
|
||||
return op_type == SIMPLE_OP;
|
||||
}
|
||||
inline bool isSimpleOp(char op) {
|
||||
return isSimpleOp() && op_char == op;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Static expression constructors
|
||||
*/
|
||||
static Expr* makeOpUnary(OperatorType op, Expr* expr);
|
||||
static Expr* makeOpBinary(Expr* expr1, char op, Expr* expr2);
|
||||
static Expr* makeOpBinary(Expr* expr1, OperatorType op, Expr* expr2);
|
||||
/**
|
||||
* Static expression constructors
|
||||
*/
|
||||
static Expr* makeOpUnary(OperatorType op, Expr* expr);
|
||||
static Expr* makeOpBinary(Expr* expr1, char op, Expr* expr2);
|
||||
static Expr* makeOpBinary(Expr* expr1, OperatorType op, Expr* expr2);
|
||||
|
||||
static Expr* makeLiteral(int64_t val);
|
||||
static Expr* makeLiteral(double val);
|
||||
static Expr* makeLiteral(char* val);
|
||||
static Expr* makeLiteral(int64_t val);
|
||||
static Expr* makeLiteral(double val);
|
||||
static Expr* makeLiteral(char* val);
|
||||
|
||||
static Expr* makeColumnRef(char* name);
|
||||
static Expr* makeColumnRef(char* table, char* name);
|
||||
static Expr* makeFunctionRef(char* func_name, Expr* expr, bool distinct);
|
||||
static Expr* makeColumnRef(char* name);
|
||||
static Expr* makeColumnRef(char* table, char* name);
|
||||
static Expr* makeFunctionRef(char* func_name, Expr* expr, bool distinct);
|
||||
|
||||
static Expr* makePlaceholder(int id);
|
||||
};
|
||||
static Expr* makePlaceholder(int id);
|
||||
};
|
||||
|
||||
// Zero initializes an Expr object and assigns it to a space in the heap
|
||||
// For Hyrise we still had to put in the explicit NULL constructor
|
||||
|
|
|
@ -8,33 +8,33 @@ namespace hsql {
|
|||
|
||||
|
||||
|
||||
/**
|
||||
* @struct ImportStatement
|
||||
* @brief Represents "IMPORT"
|
||||
*/
|
||||
struct ImportStatement : SQLStatement {
|
||||
enum ImportType {
|
||||
kImportCSV,
|
||||
kImportTbl, // Hyrise file format
|
||||
};
|
||||
/**
|
||||
* @struct ImportStatement
|
||||
* @brief Represents "IMPORT"
|
||||
*/
|
||||
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() {
|
||||
delete file_path;
|
||||
delete table_name;
|
||||
}
|
||||
ImportStatement(ImportType type) :
|
||||
SQLStatement(kStmtImport),
|
||||
type(type),
|
||||
file_path(NULL),
|
||||
table_name(NULL) {};
|
||||
|
||||
virtual ~ImportStatement() {
|
||||
delete file_path;
|
||||
delete table_name;
|
||||
}
|
||||
|
||||
|
||||
ImportType type;
|
||||
const char* file_path;
|
||||
const char* table_name;
|
||||
};
|
||||
ImportType type;
|
||||
const char* file_path;
|
||||
const char* table_name;
|
||||
};
|
||||
|
||||
|
||||
|
||||
|
|
|
@ -7,37 +7,37 @@
|
|||
namespace hsql {
|
||||
|
||||
|
||||
/**
|
||||
* @struct InsertStatement
|
||||
* @brief Represents "INSERT INTO students VALUES ('Max', 1112233, 'Musterhausen', 2.3)"
|
||||
*/
|
||||
struct InsertStatement : SQLStatement {
|
||||
enum InsertType {
|
||||
kInsertValues,
|
||||
kInsertSelect
|
||||
};
|
||||
/**
|
||||
* @struct InsertStatement
|
||||
* @brief Represents "INSERT INTO students VALUES ('Max', 1112233, 'Musterhausen', 2.3)"
|
||||
*/
|
||||
struct InsertStatement : SQLStatement {
|
||||
enum InsertType {
|
||||
kInsertValues,
|
||||
kInsertSelect
|
||||
};
|
||||
|
||||
InsertStatement(InsertType type) :
|
||||
SQLStatement(kStmtInsert),
|
||||
type(type),
|
||||
table_name(NULL),
|
||||
columns(NULL),
|
||||
values(NULL),
|
||||
select(NULL) {}
|
||||
|
||||
virtual ~InsertStatement() {
|
||||
delete table_name;
|
||||
delete columns;
|
||||
delete values;
|
||||
delete select;
|
||||
}
|
||||
InsertStatement(InsertType type) :
|
||||
SQLStatement(kStmtInsert),
|
||||
type(type),
|
||||
table_name(NULL),
|
||||
columns(NULL),
|
||||
values(NULL),
|
||||
select(NULL) {}
|
||||
|
||||
InsertType type;
|
||||
const char* table_name;
|
||||
std::vector<char*>* columns;
|
||||
std::vector<Expr*>* values;
|
||||
SelectStatement* select;
|
||||
};
|
||||
virtual ~InsertStatement() {
|
||||
delete table_name;
|
||||
delete columns;
|
||||
delete values;
|
||||
delete select;
|
||||
}
|
||||
|
||||
InsertType type;
|
||||
const char* table_name;
|
||||
std::vector<char*>* columns;
|
||||
std::vector<Expr*>* values;
|
||||
SelectStatement* select;
|
||||
};
|
||||
|
||||
|
||||
|
||||
|
|
|
@ -9,43 +9,43 @@
|
|||
namespace hsql {
|
||||
|
||||
|
||||
/**
|
||||
* @struct PrepareStatement
|
||||
* @brief Represents "PREPARE ins_prep: SELECT * FROM t1 WHERE c1 = ? AND c2 = ?"
|
||||
*/
|
||||
struct PrepareStatement : SQLStatement {
|
||||
PrepareStatement() :
|
||||
SQLStatement(kStmtPrepare),
|
||||
name(NULL),
|
||||
query(NULL) {}
|
||||
|
||||
virtual ~PrepareStatement() {
|
||||
delete query;
|
||||
delete name;
|
||||
}
|
||||
/**
|
||||
* @struct PrepareStatement
|
||||
* @brief Represents "PREPARE ins_prep: SELECT * FROM t1 WHERE c1 = ? AND c2 = ?"
|
||||
*/
|
||||
struct PrepareStatement : SQLStatement {
|
||||
PrepareStatement() :
|
||||
SQLStatement(kStmtPrepare),
|
||||
name(NULL),
|
||||
query(NULL) {}
|
||||
|
||||
/**
|
||||
* @param vector of placeholders that the parser found
|
||||
*
|
||||
* When setting the placeholders we need to make sure that they are in the correct order.
|
||||
* To ensure that, during parsing we store the character position use that to sort the list here.
|
||||
*/
|
||||
void setPlaceholders(std::vector<void*> ph) {
|
||||
for (void* e : ph) {
|
||||
if (e != NULL)
|
||||
placeholders.push_back((Expr*) e);
|
||||
}
|
||||
// Sort by col-id
|
||||
std::sort(placeholders.begin(), placeholders.end(), [](Expr* i, Expr* j) -> bool { return (i->ival < j->ival); });
|
||||
virtual ~PrepareStatement() {
|
||||
delete query;
|
||||
delete name;
|
||||
}
|
||||
|
||||
// Set the placeholder id on the Expr. This replaces the previously stored column id
|
||||
for (uint i = 0; i < placeholders.size(); ++i) placeholders[i]->ival = i;
|
||||
}
|
||||
/**
|
||||
* @param vector of placeholders that the parser found
|
||||
*
|
||||
* When setting the placeholders we need to make sure that they are in the correct order.
|
||||
* To ensure that, during parsing we store the character position use that to sort the list here.
|
||||
*/
|
||||
void setPlaceholders(std::vector<void*> ph) {
|
||||
for (void* e : ph) {
|
||||
if (e != NULL)
|
||||
placeholders.push_back((Expr*) e);
|
||||
}
|
||||
// Sort by col-id
|
||||
std::sort(placeholders.begin(), placeholders.end(), [](Expr* i, Expr* j) -> bool { return (i->ival < j->ival); });
|
||||
|
||||
const char* name;
|
||||
SQLParserResult* query;
|
||||
std::vector<Expr*> placeholders;
|
||||
};
|
||||
// Set the placeholder id on the Expr. This replaces the previously stored column id
|
||||
for (uint i = 0; i < placeholders.size(); ++i) placeholders[i]->ival = i;
|
||||
}
|
||||
|
||||
const char* name;
|
||||
SQLParserResult* query;
|
||||
std::vector<Expr*> placeholders;
|
||||
};
|
||||
|
||||
|
||||
|
||||
|
|
|
@ -6,37 +6,39 @@
|
|||
|
||||
namespace hsql {
|
||||
|
||||
typedef enum {
|
||||
kStmtError, // unused
|
||||
kStmtSelect,
|
||||
kStmtImport,
|
||||
kStmtInsert,
|
||||
kStmtUpdate,
|
||||
kStmtDelete,
|
||||
kStmtCreate,
|
||||
kStmtDrop,
|
||||
kStmtPrepare,
|
||||
kStmtExecute,
|
||||
kStmtExport,
|
||||
kStmtRename,
|
||||
kStmtAlter
|
||||
} StatementType;
|
||||
typedef enum {
|
||||
kStmtError, // unused
|
||||
kStmtSelect,
|
||||
kStmtImport,
|
||||
kStmtInsert,
|
||||
kStmtUpdate,
|
||||
kStmtDelete,
|
||||
kStmtCreate,
|
||||
kStmtDrop,
|
||||
kStmtPrepare,
|
||||
kStmtExecute,
|
||||
kStmtExport,
|
||||
kStmtRename,
|
||||
kStmtAlter
|
||||
} StatementType;
|
||||
|
||||
|
||||
/**
|
||||
* Base struct for every SQL statement
|
||||
*/
|
||||
struct SQLStatement {
|
||||
SQLStatement(StatementType type) :
|
||||
_type(type) {};
|
||||
/**
|
||||
* Base struct for every SQL statement
|
||||
*/
|
||||
struct SQLStatement {
|
||||
SQLStatement(StatementType type) :
|
||||
_type(type) {};
|
||||
|
||||
virtual ~SQLStatement() {}
|
||||
virtual ~SQLStatement() {}
|
||||
|
||||
virtual StatementType type() { return _type; }
|
||||
virtual StatementType type() {
|
||||
return _type;
|
||||
}
|
||||
|
||||
private:
|
||||
StatementType _type;
|
||||
};
|
||||
private:
|
||||
StatementType _type;
|
||||
};
|
||||
|
||||
} // namespace hsql
|
||||
|
||||
|
|
|
@ -9,98 +9,98 @@ namespace hsql {
|
|||
|
||||
|
||||
|
||||
/**
|
||||
* @struct OrderDescription
|
||||
* @brief Description of the order by clause within a select statement
|
||||
*
|
||||
* TODO: hold multiple expressions to be sorted by
|
||||
*/
|
||||
typedef enum {
|
||||
kOrderAsc,
|
||||
kOrderDesc
|
||||
} OrderType;
|
||||
/**
|
||||
* @struct OrderDescription
|
||||
* @brief Description of the order by clause within a select statement
|
||||
*
|
||||
* TODO: hold multiple expressions to be sorted by
|
||||
*/
|
||||
typedef enum {
|
||||
kOrderAsc,
|
||||
kOrderDesc
|
||||
} OrderType;
|
||||
|
||||
struct OrderDescription {
|
||||
OrderDescription(OrderType type, Expr* expr) :
|
||||
type(type),
|
||||
expr(expr) {}
|
||||
|
||||
virtual ~OrderDescription() {
|
||||
delete expr;
|
||||
}
|
||||
struct OrderDescription {
|
||||
OrderDescription(OrderType type, Expr* expr) :
|
||||
type(type),
|
||||
expr(expr) {}
|
||||
|
||||
OrderType type;
|
||||
Expr* expr;
|
||||
};
|
||||
virtual ~OrderDescription() {
|
||||
delete expr;
|
||||
}
|
||||
|
||||
/**
|
||||
* @struct LimitDescription
|
||||
* @brief Description of the limit clause within a select statement
|
||||
*/
|
||||
const int64_t kNoLimit = -1;
|
||||
const int64_t kNoOffset = -1;
|
||||
struct LimitDescription {
|
||||
LimitDescription(int64_t limit, int64_t offset) :
|
||||
limit(limit),
|
||||
offset(offset) {}
|
||||
OrderType type;
|
||||
Expr* expr;
|
||||
};
|
||||
|
||||
int64_t limit;
|
||||
int64_t offset;
|
||||
};
|
||||
/**
|
||||
* @struct LimitDescription
|
||||
* @brief Description of the limit clause within a select statement
|
||||
*/
|
||||
const int64_t kNoLimit = -1;
|
||||
const int64_t kNoOffset = -1;
|
||||
struct LimitDescription {
|
||||
LimitDescription(int64_t limit, int64_t offset) :
|
||||
limit(limit),
|
||||
offset(offset) {}
|
||||
|
||||
/**
|
||||
* @struct GroupByDescription
|
||||
*/
|
||||
struct GroupByDescription {
|
||||
GroupByDescription() :
|
||||
columns(NULL),
|
||||
having(NULL) {}
|
||||
int64_t limit;
|
||||
int64_t offset;
|
||||
};
|
||||
|
||||
~GroupByDescription() {
|
||||
delete columns;
|
||||
delete having;
|
||||
}
|
||||
/**
|
||||
* @struct GroupByDescription
|
||||
*/
|
||||
struct GroupByDescription {
|
||||
GroupByDescription() :
|
||||
columns(NULL),
|
||||
having(NULL) {}
|
||||
|
||||
std::vector<Expr*>* columns;
|
||||
Expr* having;
|
||||
};
|
||||
~GroupByDescription() {
|
||||
delete columns;
|
||||
delete having;
|
||||
}
|
||||
|
||||
/**
|
||||
* @struct SelectStatement
|
||||
* @brief Representation of a full select statement.
|
||||
*
|
||||
* TODO: add union_order and union_limit
|
||||
*/
|
||||
struct SelectStatement : SQLStatement {
|
||||
SelectStatement() :
|
||||
SQLStatement(kStmtSelect),
|
||||
from_table(NULL),
|
||||
select_list(NULL),
|
||||
where_clause(NULL),
|
||||
group_by(NULL),
|
||||
union_select(NULL),
|
||||
order(NULL),
|
||||
limit(NULL) {};
|
||||
std::vector<Expr*>* columns;
|
||||
Expr* having;
|
||||
};
|
||||
|
||||
virtual ~SelectStatement() {
|
||||
delete from_table;
|
||||
delete select_list;
|
||||
delete where_clause;
|
||||
delete group_by;
|
||||
delete order;
|
||||
delete limit;
|
||||
}
|
||||
/**
|
||||
* @struct SelectStatement
|
||||
* @brief Representation of a full select statement.
|
||||
*
|
||||
* TODO: add union_order and union_limit
|
||||
*/
|
||||
struct SelectStatement : SQLStatement {
|
||||
SelectStatement() :
|
||||
SQLStatement(kStmtSelect),
|
||||
from_table(NULL),
|
||||
select_list(NULL),
|
||||
where_clause(NULL),
|
||||
group_by(NULL),
|
||||
union_select(NULL),
|
||||
order(NULL),
|
||||
limit(NULL) {};
|
||||
|
||||
TableRef* from_table;
|
||||
bool select_distinct;
|
||||
std::vector<Expr*>* select_list;
|
||||
Expr* where_clause;
|
||||
GroupByDescription* group_by;
|
||||
virtual ~SelectStatement() {
|
||||
delete from_table;
|
||||
delete select_list;
|
||||
delete where_clause;
|
||||
delete group_by;
|
||||
delete order;
|
||||
delete limit;
|
||||
}
|
||||
|
||||
SelectStatement* union_select;
|
||||
OrderDescription* order;
|
||||
LimitDescription* limit;
|
||||
};
|
||||
TableRef* from_table;
|
||||
bool select_distinct;
|
||||
std::vector<Expr*>* select_list;
|
||||
Expr* where_clause;
|
||||
GroupByDescription* group_by;
|
||||
|
||||
SelectStatement* union_select;
|
||||
OrderDescription* order;
|
||||
LimitDescription* limit;
|
||||
};
|
||||
|
||||
|
||||
} // namespace hsql
|
||||
|
|
150
src/sql/Table.h
150
src/sql/Table.h
|
@ -7,97 +7,99 @@
|
|||
|
||||
namespace hsql {
|
||||
|
||||
struct SelectStatement;
|
||||
struct JoinDefinition;
|
||||
struct TableRef;
|
||||
struct SelectStatement;
|
||||
struct JoinDefinition;
|
||||
struct TableRef;
|
||||
|
||||
|
||||
/**
|
||||
* @enum TableRefType
|
||||
* Types table references
|
||||
*/
|
||||
typedef enum {
|
||||
kTableName,
|
||||
kTableSelect,
|
||||
kTableJoin,
|
||||
kTableCrossProduct
|
||||
} TableRefType;
|
||||
/**
|
||||
* @enum TableRefType
|
||||
* Types table references
|
||||
*/
|
||||
typedef enum {
|
||||
kTableName,
|
||||
kTableSelect,
|
||||
kTableJoin,
|
||||
kTableCrossProduct
|
||||
} TableRefType;
|
||||
|
||||
|
||||
/**
|
||||
* @struct TableRef
|
||||
* @brief Holds reference to tables. Can be either table names or a select statement.
|
||||
*/
|
||||
struct TableRef {
|
||||
TableRef(TableRefType type) :
|
||||
type(type),
|
||||
schema(NULL),
|
||||
name(NULL),
|
||||
alias(NULL),
|
||||
select(NULL),
|
||||
list(NULL),
|
||||
join(NULL) {}
|
||||
|
||||
virtual ~TableRef();
|
||||
/**
|
||||
* @struct TableRef
|
||||
* @brief Holds reference to tables. Can be either table names or a select statement.
|
||||
*/
|
||||
struct TableRef {
|
||||
TableRef(TableRefType type) :
|
||||
type(type),
|
||||
schema(NULL),
|
||||
name(NULL),
|
||||
alias(NULL),
|
||||
select(NULL),
|
||||
list(NULL),
|
||||
join(NULL) {}
|
||||
|
||||
TableRefType type;
|
||||
virtual ~TableRef();
|
||||
|
||||
char* schema;
|
||||
char* name;
|
||||
char* alias;
|
||||
TableRefType type;
|
||||
|
||||
SelectStatement* select;
|
||||
std::vector<TableRef*>* list;
|
||||
JoinDefinition* join;
|
||||
char* schema;
|
||||
char* name;
|
||||
char* alias;
|
||||
|
||||
SelectStatement* select;
|
||||
std::vector<TableRef*>* list;
|
||||
JoinDefinition* join;
|
||||
|
||||
|
||||
/**
|
||||
* Convenience accessor methods
|
||||
*/
|
||||
inline bool hasSchema() { return schema != NULL; }
|
||||
/**
|
||||
* Convenience accessor methods
|
||||
*/
|
||||
inline bool hasSchema() {
|
||||
return schema != NULL;
|
||||
}
|
||||
|
||||
inline char* getName() {
|
||||
if (alias != NULL) return alias;
|
||||
else return name;
|
||||
}
|
||||
};
|
||||
inline char* getName() {
|
||||
if (alias != NULL) return alias;
|
||||
else return name;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @enum JoinType
|
||||
* Types of joins
|
||||
*/
|
||||
typedef enum {
|
||||
kJoinInner,
|
||||
kJoinOuter,
|
||||
kJoinLeft,
|
||||
kJoinRight,
|
||||
} JoinType;
|
||||
/**
|
||||
* @enum JoinType
|
||||
* Types of joins
|
||||
*/
|
||||
typedef enum {
|
||||
kJoinInner,
|
||||
kJoinOuter,
|
||||
kJoinLeft,
|
||||
kJoinRight,
|
||||
} JoinType;
|
||||
|
||||
|
||||
/**
|
||||
* @struct JoinDefinition
|
||||
* @brief Definition of a join table
|
||||
*/
|
||||
struct JoinDefinition {
|
||||
JoinDefinition() :
|
||||
left(NULL),
|
||||
right(NULL),
|
||||
condition(NULL),
|
||||
type(kJoinInner) {}
|
||||
/**
|
||||
* @struct JoinDefinition
|
||||
* @brief Definition of a join table
|
||||
*/
|
||||
struct JoinDefinition {
|
||||
JoinDefinition() :
|
||||
left(NULL),
|
||||
right(NULL),
|
||||
condition(NULL),
|
||||
type(kJoinInner) {}
|
||||
|
||||
virtual ~JoinDefinition() {
|
||||
delete left;
|
||||
delete right;
|
||||
delete condition;
|
||||
}
|
||||
virtual ~JoinDefinition() {
|
||||
delete left;
|
||||
delete right;
|
||||
delete condition;
|
||||
}
|
||||
|
||||
TableRef* left;
|
||||
TableRef* right;
|
||||
Expr* condition;
|
||||
TableRef* left;
|
||||
TableRef* right;
|
||||
Expr* condition;
|
||||
|
||||
JoinType type;
|
||||
};
|
||||
JoinType type;
|
||||
};
|
||||
|
||||
|
||||
|
||||
|
|
|
@ -6,38 +6,38 @@
|
|||
namespace hsql {
|
||||
|
||||
|
||||
/**
|
||||
* @struct UpdateClause
|
||||
* @brief Represents "column = value" expressions
|
||||
*/
|
||||
struct UpdateClause {
|
||||
char* column;
|
||||
Expr* value;
|
||||
};
|
||||
/**
|
||||
* @struct UpdateClause
|
||||
* @brief Represents "column = value" expressions
|
||||
*/
|
||||
struct UpdateClause {
|
||||
char* column;
|
||||
Expr* value;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @struct UpdateStatement
|
||||
* @brief Represents "UPDATE"
|
||||
*/
|
||||
struct UpdateStatement : SQLStatement {
|
||||
UpdateStatement() :
|
||||
SQLStatement(kStmtUpdate),
|
||||
table(NULL),
|
||||
updates(NULL),
|
||||
where(NULL) {}
|
||||
|
||||
virtual ~UpdateStatement() {
|
||||
delete table;
|
||||
delete updates;
|
||||
delete where;
|
||||
}
|
||||
/**
|
||||
* @struct UpdateStatement
|
||||
* @brief Represents "UPDATE"
|
||||
*/
|
||||
struct UpdateStatement : SQLStatement {
|
||||
UpdateStatement() :
|
||||
SQLStatement(kStmtUpdate),
|
||||
table(NULL),
|
||||
updates(NULL),
|
||||
where(NULL) {}
|
||||
|
||||
// TODO: switch to char* instead of TableRef
|
||||
TableRef* table;
|
||||
std::vector<UpdateClause*>* updates;
|
||||
Expr* where;
|
||||
};
|
||||
virtual ~UpdateStatement() {
|
||||
delete table;
|
||||
delete updates;
|
||||
delete where;
|
||||
}
|
||||
|
||||
// TODO: switch to char* instead of TableRef
|
||||
TableRef* table;
|
||||
std::vector<UpdateClause*>* updates;
|
||||
Expr* where;
|
||||
};
|
||||
|
||||
|
||||
|
||||
|
|
|
@ -5,12 +5,12 @@
|
|||
namespace hsql {
|
||||
|
||||
|
||||
TableRef::~TableRef() {
|
||||
delete name;
|
||||
delete alias;
|
||||
delete select;
|
||||
delete list;
|
||||
}
|
||||
TableRef::~TableRef() {
|
||||
delete name;
|
||||
delete alias;
|
||||
delete select;
|
||||
delete list;
|
||||
}
|
||||
|
||||
|
||||
} // namespace hsql
|
|
@ -1,5 +1,5 @@
|
|||
#ifndef __STATEMENTS_H__
|
||||
#define __STATEMENTS_H__
|
||||
#define __STATEMENTS_H__
|
||||
|
||||
#include "SelectStatement.h"
|
||||
#include "ImportStatement.h"
|
||||
|
|
|
@ -5,159 +5,204 @@
|
|||
|
||||
namespace hsql {
|
||||
|
||||
void printOperatorExpression(Expr* expr, uint num_indent);
|
||||
void printOperatorExpression(Expr* expr, uint num_indent);
|
||||
|
||||
std::string indent(uint num_indent) { return std::string(num_indent, '\t'); }
|
||||
void inprint(int64_t val, uint num_indent) { printf("%s%ld \n", indent(num_indent).c_str(), val); }
|
||||
void inprint(float val, uint num_indent) { printf("%s%f\n", indent(num_indent).c_str(), val); }
|
||||
void inprint(const char* val, uint num_indent) { printf("%s%s\n", indent(num_indent).c_str(), val); }
|
||||
void inprint(const char* val, const char* val2, uint num_indent) { printf("%s%s->%s\n", indent(num_indent).c_str(), val, val2); }
|
||||
void inprintC(char val, uint num_indent) { printf("%s%c\n", indent(num_indent).c_str(), val); }
|
||||
void inprintU(uint64_t val, uint num_indent) { printf("%s%lu\n", indent(num_indent).c_str(), val); }
|
||||
std::string indent(uint num_indent) {
|
||||
return std::string(num_indent, '\t');
|
||||
}
|
||||
void inprint(int64_t val, uint num_indent) {
|
||||
printf("%s%ld \n", indent(num_indent).c_str(), val);
|
||||
}
|
||||
void inprint(float val, uint num_indent) {
|
||||
printf("%s%f\n", indent(num_indent).c_str(), val);
|
||||
}
|
||||
void inprint(const char* val, uint num_indent) {
|
||||
printf("%s%s\n", indent(num_indent).c_str(), val);
|
||||
}
|
||||
void inprint(const char* val, const char* val2, uint num_indent) {
|
||||
printf("%s%s->%s\n", indent(num_indent).c_str(), val, val2);
|
||||
}
|
||||
void inprintC(char val, uint num_indent) {
|
||||
printf("%s%c\n", indent(num_indent).c_str(), val);
|
||||
}
|
||||
void inprintU(uint64_t val, uint num_indent) {
|
||||
printf("%s%lu\n", indent(num_indent).c_str(), val);
|
||||
}
|
||||
|
||||
void printTableRefInfo(TableRef* table, uint num_indent) {
|
||||
switch (table->type) {
|
||||
case kTableName:
|
||||
inprint(table->name, num_indent);
|
||||
break;
|
||||
case kTableSelect:
|
||||
printSelectStatementInfo(table->select, num_indent);
|
||||
break;
|
||||
case kTableJoin:
|
||||
inprint("Join Table", num_indent);
|
||||
inprint("Left", num_indent+1);
|
||||
printTableRefInfo(table->join->left, num_indent+2);
|
||||
inprint("Right", num_indent+1);
|
||||
printTableRefInfo(table->join->right, num_indent+2);
|
||||
inprint("Join Condition", num_indent+1);
|
||||
printExpression(table->join->condition, num_indent+2);
|
||||
break;
|
||||
case kTableCrossProduct:
|
||||
for (TableRef* tbl : *table->list) printTableRefInfo(tbl, num_indent);
|
||||
break;
|
||||
}
|
||||
if (table->alias != NULL) {
|
||||
inprint("Alias", num_indent+1);
|
||||
inprint(table->alias, num_indent+2);
|
||||
}
|
||||
}
|
||||
void printTableRefInfo(TableRef* table, uint num_indent) {
|
||||
switch (table->type) {
|
||||
case kTableName:
|
||||
inprint(table->name, num_indent);
|
||||
break;
|
||||
case kTableSelect:
|
||||
printSelectStatementInfo(table->select, num_indent);
|
||||
break;
|
||||
case kTableJoin:
|
||||
inprint("Join Table", num_indent);
|
||||
inprint("Left", num_indent+1);
|
||||
printTableRefInfo(table->join->left, num_indent+2);
|
||||
inprint("Right", num_indent+1);
|
||||
printTableRefInfo(table->join->right, num_indent+2);
|
||||
inprint("Join Condition", num_indent+1);
|
||||
printExpression(table->join->condition, num_indent+2);
|
||||
break;
|
||||
case kTableCrossProduct:
|
||||
for (TableRef* tbl : *table->list) printTableRefInfo(tbl, num_indent);
|
||||
break;
|
||||
}
|
||||
if (table->alias != NULL) {
|
||||
inprint("Alias", num_indent+1);
|
||||
inprint(table->alias, num_indent+2);
|
||||
}
|
||||
}
|
||||
|
||||
void printOperatorExpression(Expr* expr, uint num_indent) {
|
||||
if (expr == NULL) { inprint("null", num_indent); return; }
|
||||
void printOperatorExpression(Expr* expr, uint num_indent) {
|
||||
if (expr == NULL) {
|
||||
inprint("null", num_indent);
|
||||
return;
|
||||
}
|
||||
|
||||
switch (expr->op_type) {
|
||||
case Expr::SIMPLE_OP: inprintC(expr->op_char, num_indent); break;
|
||||
case Expr::AND: inprint("AND", num_indent); break;
|
||||
case Expr::OR: inprint("OR", num_indent); break;
|
||||
case Expr::NOT: inprint("NOT", num_indent); break;
|
||||
default: inprintU(expr->op_type, num_indent); break;
|
||||
}
|
||||
printExpression(expr->expr, num_indent+1);
|
||||
if (expr->expr2 != NULL) printExpression(expr->expr2, num_indent+1);
|
||||
}
|
||||
switch (expr->op_type) {
|
||||
case Expr::SIMPLE_OP:
|
||||
inprintC(expr->op_char, num_indent);
|
||||
break;
|
||||
case Expr::AND:
|
||||
inprint("AND", num_indent);
|
||||
break;
|
||||
case Expr::OR:
|
||||
inprint("OR", num_indent);
|
||||
break;
|
||||
case Expr::NOT:
|
||||
inprint("NOT", num_indent);
|
||||
break;
|
||||
default:
|
||||
inprintU(expr->op_type, num_indent);
|
||||
break;
|
||||
}
|
||||
printExpression(expr->expr, num_indent+1);
|
||||
if (expr->expr2 != NULL) printExpression(expr->expr2, num_indent+1);
|
||||
}
|
||||
|
||||
void printExpression(Expr* expr, uint num_indent) {
|
||||
switch (expr->type) {
|
||||
case kExprStar: inprint("*", num_indent); break;
|
||||
case kExprColumnRef: inprint(expr->name, num_indent); break;
|
||||
// case kExprTableColumnRef: inprint(expr->table, expr->name, num_indent); break;
|
||||
case kExprLiteralFloat: inprint(expr->fval, num_indent); break;
|
||||
case kExprLiteralInt: inprint(expr->ival, num_indent); break;
|
||||
case kExprLiteralString: inprint(expr->name, num_indent); break;
|
||||
case kExprFunctionRef: inprint(expr->name, num_indent); inprint(expr->expr->name, num_indent+1); break;
|
||||
case kExprOperator: printOperatorExpression(expr, num_indent); break;
|
||||
default: fprintf(stderr, "Unrecognized expression type %d\n", expr->type); return;
|
||||
}
|
||||
if (expr->alias != NULL) {
|
||||
inprint("Alias", num_indent+1); inprint(expr->alias, num_indent+2);
|
||||
}
|
||||
}
|
||||
void printExpression(Expr* expr, uint num_indent) {
|
||||
switch (expr->type) {
|
||||
case kExprStar:
|
||||
inprint("*", num_indent);
|
||||
break;
|
||||
case kExprColumnRef:
|
||||
inprint(expr->name, num_indent);
|
||||
break;
|
||||
// case kExprTableColumnRef: inprint(expr->table, expr->name, num_indent); break;
|
||||
case kExprLiteralFloat:
|
||||
inprint(expr->fval, num_indent);
|
||||
break;
|
||||
case kExprLiteralInt:
|
||||
inprint(expr->ival, num_indent);
|
||||
break;
|
||||
case kExprLiteralString:
|
||||
inprint(expr->name, num_indent);
|
||||
break;
|
||||
case kExprFunctionRef:
|
||||
inprint(expr->name, num_indent);
|
||||
inprint(expr->expr->name, num_indent+1);
|
||||
break;
|
||||
case kExprOperator:
|
||||
printOperatorExpression(expr, num_indent);
|
||||
break;
|
||||
default:
|
||||
fprintf(stderr, "Unrecognized expression type %d\n", expr->type);
|
||||
return;
|
||||
}
|
||||
if (expr->alias != NULL) {
|
||||
inprint("Alias", num_indent+1);
|
||||
inprint(expr->alias, num_indent+2);
|
||||
}
|
||||
}
|
||||
|
||||
void printSelectStatementInfo(SelectStatement* stmt, uint num_indent) {
|
||||
inprint("SelectStatement", num_indent);
|
||||
inprint("Fields:", num_indent+1);
|
||||
for (Expr* expr : *stmt->select_list) printExpression(expr, num_indent+2);
|
||||
void printSelectStatementInfo(SelectStatement* stmt, uint num_indent) {
|
||||
inprint("SelectStatement", num_indent);
|
||||
inprint("Fields:", num_indent+1);
|
||||
for (Expr* expr : *stmt->select_list) printExpression(expr, num_indent+2);
|
||||
|
||||
inprint("Sources:", num_indent+1);
|
||||
printTableRefInfo(stmt->from_table, num_indent+2);
|
||||
inprint("Sources:", num_indent+1);
|
||||
printTableRefInfo(stmt->from_table, num_indent+2);
|
||||
|
||||
if (stmt->where_clause != NULL) {
|
||||
inprint("Search Conditions:", num_indent+1);
|
||||
printExpression(stmt->where_clause, num_indent+2);
|
||||
}
|
||||
if (stmt->where_clause != NULL) {
|
||||
inprint("Search Conditions:", num_indent+1);
|
||||
printExpression(stmt->where_clause, num_indent+2);
|
||||
}
|
||||
|
||||
|
||||
if (stmt->union_select != NULL) {
|
||||
inprint("Union:", num_indent+1);
|
||||
printSelectStatementInfo(stmt->union_select, num_indent+2);
|
||||
}
|
||||
if (stmt->union_select != NULL) {
|
||||
inprint("Union:", num_indent+1);
|
||||
printSelectStatementInfo(stmt->union_select, num_indent+2);
|
||||
}
|
||||
|
||||
if (stmt->order != NULL) {
|
||||
inprint("OrderBy:", num_indent+1);
|
||||
printExpression(stmt->order->expr, num_indent+2);
|
||||
if (stmt->order->type == kOrderAsc) inprint("ascending", num_indent+2);
|
||||
else inprint("descending", num_indent+2);
|
||||
}
|
||||
if (stmt->order != NULL) {
|
||||
inprint("OrderBy:", num_indent+1);
|
||||
printExpression(stmt->order->expr, num_indent+2);
|
||||
if (stmt->order->type == kOrderAsc) inprint("ascending", num_indent+2);
|
||||
else inprint("descending", num_indent+2);
|
||||
}
|
||||
|
||||
if (stmt->limit != NULL) {
|
||||
inprint("Limit:", num_indent+1);
|
||||
inprint(stmt->limit->limit, num_indent+2);
|
||||
}
|
||||
}
|
||||
if (stmt->limit != NULL) {
|
||||
inprint("Limit:", num_indent+1);
|
||||
inprint(stmt->limit->limit, num_indent+2);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
void printImportStatementInfo(ImportStatement* stmt, uint num_indent) {
|
||||
inprint("ImportStatment", num_indent);
|
||||
inprint(stmt->file_path, num_indent+1);
|
||||
inprint(stmt->table_name, num_indent+1);
|
||||
}
|
||||
void printImportStatementInfo(ImportStatement* stmt, uint num_indent) {
|
||||
inprint("ImportStatment", num_indent);
|
||||
inprint(stmt->file_path, num_indent+1);
|
||||
inprint(stmt->table_name, num_indent+1);
|
||||
}
|
||||
|
||||
void printCreateStatementInfo(CreateStatement* stmt, uint num_indent) {
|
||||
inprint("CreateStatment", num_indent);
|
||||
inprint(stmt->table_name, num_indent+1);
|
||||
inprint(stmt->file_path, num_indent+1);
|
||||
}
|
||||
void printCreateStatementInfo(CreateStatement* stmt, uint num_indent) {
|
||||
inprint("CreateStatment", num_indent);
|
||||
inprint(stmt->table_name, num_indent+1);
|
||||
inprint(stmt->file_path, num_indent+1);
|
||||
}
|
||||
|
||||
void printInsertStatementInfo(InsertStatement* stmt, uint num_indent) {
|
||||
inprint("InsertStatment", num_indent);
|
||||
inprint(stmt->table_name, num_indent+1);
|
||||
if (stmt->columns != NULL) {
|
||||
inprint("Columns", num_indent+1);
|
||||
for (char* col_name : *stmt->columns) {
|
||||
inprint(col_name, num_indent+2);
|
||||
}
|
||||
}
|
||||
switch (stmt->type) {
|
||||
case InsertStatement::kInsertValues:
|
||||
inprint("Values", num_indent+1);
|
||||
for (Expr* expr : *stmt->values) {
|
||||
printExpression(expr, num_indent+2);
|
||||
}
|
||||
break;
|
||||
case InsertStatement::kInsertSelect:
|
||||
printSelectStatementInfo(stmt->select, num_indent+1);
|
||||
break;
|
||||
}
|
||||
}
|
||||
void printInsertStatementInfo(InsertStatement* stmt, uint num_indent) {
|
||||
inprint("InsertStatment", num_indent);
|
||||
inprint(stmt->table_name, num_indent+1);
|
||||
if (stmt->columns != NULL) {
|
||||
inprint("Columns", num_indent+1);
|
||||
for (char* col_name : *stmt->columns) {
|
||||
inprint(col_name, num_indent+2);
|
||||
}
|
||||
}
|
||||
switch (stmt->type) {
|
||||
case InsertStatement::kInsertValues:
|
||||
inprint("Values", num_indent+1);
|
||||
for (Expr* expr : *stmt->values) {
|
||||
printExpression(expr, num_indent+2);
|
||||
}
|
||||
break;
|
||||
case InsertStatement::kInsertSelect:
|
||||
printSelectStatementInfo(stmt->select, num_indent+1);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void printStatementInfo(SQLStatement* stmt) {
|
||||
switch (stmt->type()) {
|
||||
case kStmtSelect:
|
||||
printSelectStatementInfo((SelectStatement*) stmt, 0);
|
||||
break;
|
||||
case kStmtInsert:
|
||||
printInsertStatementInfo((InsertStatement*) stmt, 0);
|
||||
break;
|
||||
case kStmtCreate:
|
||||
printCreateStatementInfo((CreateStatement*) stmt, 0);
|
||||
break;
|
||||
case kStmtImport:
|
||||
printImportStatementInfo((ImportStatement*) stmt, 0);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
void printStatementInfo(SQLStatement* stmt) {
|
||||
switch (stmt->type()) {
|
||||
case kStmtSelect:
|
||||
printSelectStatementInfo((SelectStatement*) stmt, 0);
|
||||
break;
|
||||
case kStmtInsert:
|
||||
printInsertStatementInfo((InsertStatement*) stmt, 0);
|
||||
break;
|
||||
case kStmtCreate:
|
||||
printCreateStatementInfo((CreateStatement*) stmt, 0);
|
||||
break;
|
||||
case kStmtImport:
|
||||
printImportStatementInfo((ImportStatement*) stmt, 0);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace hsql
|
|
@ -5,12 +5,12 @@
|
|||
|
||||
namespace hsql {
|
||||
|
||||
void printStatementInfo(SQLStatement* stmt);
|
||||
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);
|
||||
void printStatementInfo(SQLStatement* stmt);
|
||||
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
|
||||
|
||||
|
|
|
@ -7,40 +7,40 @@
|
|||
using namespace hsql;
|
||||
|
||||
TEST(SelectTest) {
|
||||
TEST_PARSE_SINGLE_SQL("SELECT * FROM students;", kStmtSelect, SelectStatement, stmt);
|
||||
TEST_PARSE_SINGLE_SQL("SELECT * FROM students;", kStmtSelect, SelectStatement, stmt);
|
||||
|
||||
ASSERT_NULL(stmt->where_clause);
|
||||
ASSERT_NULL(stmt->group_by);
|
||||
ASSERT_NULL(stmt->where_clause);
|
||||
ASSERT_NULL(stmt->group_by);
|
||||
}
|
||||
|
||||
|
||||
TEST(SelectHavingTest) {
|
||||
TEST_PARSE_SINGLE_SQL("SELECT city, AVG(grade) AS avg_grade FROM students GROUP BY city HAVING AVG(grade) < 2.0", kStmtSelect, SelectStatement, stmt);
|
||||
ASSERT_FALSE(stmt->select_distinct);
|
||||
TEST_PARSE_SINGLE_SQL("SELECT city, AVG(grade) AS avg_grade FROM students GROUP BY city HAVING AVG(grade) < 2.0", kStmtSelect, SelectStatement, stmt);
|
||||
ASSERT_FALSE(stmt->select_distinct);
|
||||
|
||||
GroupByDescription* group = stmt->group_by;
|
||||
ASSERT_NOTNULL(group);
|
||||
ASSERT_EQ(group->columns->size(), 1);
|
||||
ASSERT(group->having->isSimpleOp('<'));
|
||||
ASSERT(group->having->expr->isType(kExprFunctionRef));
|
||||
ASSERT(group->having->expr2->isType(kExprLiteralFloat));
|
||||
GroupByDescription* group = stmt->group_by;
|
||||
ASSERT_NOTNULL(group);
|
||||
ASSERT_EQ(group->columns->size(), 1);
|
||||
ASSERT(group->having->isSimpleOp('<'));
|
||||
ASSERT(group->having->expr->isType(kExprFunctionRef));
|
||||
ASSERT(group->having->expr2->isType(kExprLiteralFloat));
|
||||
}
|
||||
|
||||
|
||||
TEST(SelectDistinctTest) {
|
||||
TEST_PARSE_SINGLE_SQL("SELECT DISTINCT grade, city FROM students;", kStmtSelect, SelectStatement, stmt);
|
||||
TEST_PARSE_SINGLE_SQL("SELECT DISTINCT grade, city FROM students;", kStmtSelect, SelectStatement, stmt);
|
||||
|
||||
ASSERT(stmt->select_distinct);
|
||||
ASSERT_NULL(stmt->where_clause);
|
||||
ASSERT(stmt->select_distinct);
|
||||
ASSERT_NULL(stmt->where_clause);
|
||||
}
|
||||
|
||||
TEST(SelectGroupDistinctTest) {
|
||||
TEST_PARSE_SINGLE_SQL("SELECT city, COUNT(name), COUNT(DISTINCT grade) FROM students GROUP BY city;", kStmtSelect, SelectStatement, stmt);
|
||||
TEST_PARSE_SINGLE_SQL("SELECT city, COUNT(name), COUNT(DISTINCT grade) FROM students GROUP BY city;", kStmtSelect, SelectStatement, stmt);
|
||||
|
||||
ASSERT_FALSE(stmt->select_distinct);
|
||||
ASSERT_EQ(stmt->select_list->size(), 3);
|
||||
ASSERT(!stmt->select_list->at(1)->distinct);
|
||||
ASSERT(stmt->select_list->at(2)->distinct);
|
||||
ASSERT_FALSE(stmt->select_distinct);
|
||||
ASSERT_EQ(stmt->select_list->size(), 3);
|
||||
ASSERT(!stmt->select_list->at(1)->distinct);
|
||||
ASSERT(stmt->select_list->at(2)->distinct);
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -3,53 +3,53 @@
|
|||
|
||||
|
||||
class TestsManager {
|
||||
// Note: static initialization fiasco
|
||||
// http://www.parashift.com/c++-faq-lite/static-init-order.html
|
||||
// http://www.parashift.com/c++-faq-lite/static-init-order-on-first-use.html
|
||||
// Note: static initialization fiasco
|
||||
// http://www.parashift.com/c++-faq-lite/static-init-order.html
|
||||
// http://www.parashift.com/c++-faq-lite/static-init-order-on-first-use.html
|
||||
public:
|
||||
static std::vector<std::string>& test_names() {
|
||||
static std::vector<std::string>* test_names = new std::vector<std::string>;
|
||||
return *test_names;
|
||||
}
|
||||
static std::vector<std::string>& test_names() {
|
||||
static std::vector<std::string>* test_names = new std::vector<std::string>;
|
||||
return *test_names;
|
||||
}
|
||||
|
||||
static std::vector<void (*)(void)>& tests() {
|
||||
static std::vector<void (*)(void)>* tests = new std::vector<void (*)(void)>;
|
||||
return *tests;
|
||||
}
|
||||
static std::vector<void (*)(void)>& tests() {
|
||||
static std::vector<void (*)(void)>* tests = new std::vector<void (*)(void)>;
|
||||
return *tests;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
|
||||
int AddTest(void (*foo)(void), std::string name) {
|
||||
TestsManager::tests().push_back(foo);
|
||||
TestsManager::test_names().push_back(name);
|
||||
return 0;
|
||||
TestsManager::tests().push_back(foo);
|
||||
TestsManager::test_names().push_back(name);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
|
||||
void RunTests() {
|
||||
size_t num_failed = 0;
|
||||
for (size_t i = 0; i < TestsManager::tests().size(); ++i) {
|
||||
printf("\033[0;32m{ running}\033[0m %s\n", TestsManager::test_names()[i].c_str());
|
||||
size_t num_failed = 0;
|
||||
for (size_t i = 0; i < TestsManager::tests().size(); ++i) {
|
||||
printf("\033[0;32m{ running}\033[0m %s\n", TestsManager::test_names()[i].c_str());
|
||||
|
||||
try {
|
||||
// Run test
|
||||
(*TestsManager::tests()[i])();
|
||||
printf("\033[0;32m{ ok}\033[0m %s\n", TestsManager::test_names()[i].c_str());
|
||||
try {
|
||||
// Run test
|
||||
(*TestsManager::tests()[i])();
|
||||
printf("\033[0;32m{ ok}\033[0m %s\n", TestsManager::test_names()[i].c_str());
|
||||
|
||||
} catch (AssertionFailedException& e) {
|
||||
printf("\033[1;31m{ failed} %s\n", TestsManager::test_names()[i].c_str());
|
||||
printf("\tAssertion failed: %s\n\033[0m", e.what());
|
||||
num_failed++;
|
||||
}
|
||||
} catch (AssertionFailedException& e) {
|
||||
printf("\033[1;31m{ failed} %s\n", TestsManager::test_names()[i].c_str());
|
||||
printf("\tAssertion failed: %s\n\033[0m", e.what());
|
||||
num_failed++;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
int main() {
|
||||
RunTests();
|
||||
return 0;
|
||||
RunTests();
|
||||
return 0;
|
||||
}
|
|
@ -13,7 +13,7 @@
|
|||
|
||||
|
||||
#define ASSERT(cond) if (!(cond)) throw AssertionFailedException(#cond);
|
||||
|
||||
|
||||
#define ASSERT_TRUE(cond) ASSERT(cond);
|
||||
#define ASSERT_FALSE(cond) if (cond) throw AssertionFailedException(#cond);
|
||||
|
||||
|
@ -27,21 +27,21 @@
|
|||
std::cout << "Actual values: " << a << " != " << b << std::endl; \
|
||||
} \
|
||||
ASSERT(a == b);
|
||||
|
||||
|
||||
|
||||
|
||||
class AssertionFailedException: public std::exception {
|
||||
public:
|
||||
AssertionFailedException(std::string msg) :
|
||||
std::exception(),
|
||||
_msg(msg) {};
|
||||
AssertionFailedException(std::string msg) :
|
||||
std::exception(),
|
||||
_msg(msg) {};
|
||||
|
||||
virtual const char* what() const throw() {
|
||||
return _msg.c_str();
|
||||
}
|
||||
virtual const char* what() const throw() {
|
||||
return _msg.c_str();
|
||||
}
|
||||
|
||||
protected:
|
||||
std::string _msg;
|
||||
std::string _msg;
|
||||
};
|
||||
|
||||
|
||||
|
|
Loading…
Reference in New Issue