Merge pull request #23 from torpedro/statements-clean

Clean-Up and Reformatting of Code
This commit is contained in:
Pedro Flemming 2017-02-08 03:15:15 +01:00 committed by GitHub
commit 89a81848b4
31 changed files with 1358 additions and 1239 deletions

View File

@ -1,8 +1,10 @@
--style=google
# indentation # indentation
--indent=spaces=4 --indent=spaces=2
--indent-namespaces --indent-namespaces
--style=java --align-reference=type
--style=attach --align-pointer=type
-A2 --pad-oper

View File

@ -12,22 +12,22 @@ namespace hsql {
fprintf(stderr, "SQLParser only has static methods atm! Do not initialize!\n"); fprintf(stderr, "SQLParser only has static methods atm! Do not initialize!\n");
} }
SQLParserResult* SQLParser::parseSQLString(const char* text) {
SQLParserResult* SQLParser::parseSQLString(const char *text) {
SQLParserResult* result = NULL; SQLParserResult* result = NULL;
yyscan_t scanner; yyscan_t scanner;
YY_BUFFER_STATE state; YY_BUFFER_STATE state;
if (hsql_lex_init(&scanner)) { if (hsql_lex_init(&scanner)) {
// couldn't initialize // Couldn't initialize the lexer.
fprintf(stderr, "[Error] SQLParser: Error when initializing lexer!\n"); fprintf(stderr, "[Error] SQLParser: Error when initializing lexer!\n");
return NULL; return NULL;
} }
state = hsql__scan_string(text, scanner); state = hsql__scan_string(text, scanner);
// Parser and return early if it failed.
if (hsql_parse(&result, scanner)) { if (hsql_parse(&result, scanner)) {
// Returns an error stmt object // Returns an error stmt object.
return result; return result;
} }

View File

@ -5,15 +5,18 @@
#include "sql/statements.h" #include "sql/statements.h"
namespace hsql { namespace hsql {
/**
* Main class for parsing SQL strings // Static methods used to parse SQL strings.
*/
class SQLParser { class SQLParser {
public: public:
// Parses a given constant character SQL string.
static SQLParserResult* parseSQLString(const char* sql); static SQLParserResult* parseSQLString(const char* sql);
// Parses an SQL std::string.
static SQLParserResult* parseSQLString(const std::string& sql); static SQLParserResult* parseSQLString(const std::string& sql);
private: private:
// Static class can't be instatiated.
SQLParser(); SQLParser();
}; };

View File

@ -4,38 +4,63 @@
namespace hsql { namespace hsql {
SQLParserResult::SQLParserResult() : SQLParserResult::SQLParserResult() :
isValid(true), isValid_(true),
errorMsg(NULL) {}; errorMsg_(NULL) {};
SQLParserResult::SQLParserResult(SQLStatement* stmt) : SQLParserResult::SQLParserResult(SQLStatement* stmt) :
isValid(true), isValid_(true),
errorMsg(NULL) { errorMsg_(NULL) {
addStatement(stmt); addStatement(stmt);
}; };
SQLParserResult::~SQLParserResult() { SQLParserResult::~SQLParserResult() {
for (std::vector<SQLStatement*>::iterator it = statements.begin(); it != statements.end(); ++it) { for (SQLStatement* statement : statements_) {
delete *it; delete statement;
} }
delete errorMsg; delete errorMsg_;
} }
void SQLParserResult::addStatement(SQLStatement* stmt) { void SQLParserResult::addStatement(SQLStatement* stmt) {
statements.push_back(stmt); statements_.push_back(stmt);
} }
const SQLStatement* SQLParserResult::getStatement(int index) const {
SQLStatement* SQLParserResult::getStatement(int id) { return statements_[index];
return statements[id];
} }
SQLStatement* SQLParserResult::getMutableStatement(int index) {
return statements_[index];
}
size_t SQLParserResult::size() { size_t SQLParserResult::size() const {
return statements.size(); return statements_.size();
}
bool SQLParserResult::isValid() const {
return isValid_;
}
const char* SQLParserResult::errorMsg() const {
return errorMsg_;
}
int SQLParserResult::errorLine() const {
return errorLine_;
}
int SQLParserResult::errorColumn() const {
return errorColumn_;
}
void SQLParserResult::setIsValid(bool isValid) {
isValid_ = isValid;
}
void SQLParserResult::setErrorDetails(const char* errorMsg, int errorLine, int errorColumn) {
errorMsg_ = errorMsg;
errorLine_ = errorLine;
errorColumn_ = errorColumn;
} }
} // namespace hsql } // namespace hsql

View File

@ -4,30 +4,67 @@
#include "sql/SQLStatement.h" #include "sql/SQLStatement.h"
namespace hsql { namespace hsql {
/** // Represents the result of the SQLParser.
* Represents the result of the SQLParser. // If parsing was successful it contains a list of SQLStatement.
* If parsing was successful it contains a list of SQLStatement.
*/
class SQLParserResult { class SQLParserResult {
public: public:
// Initialize with empty statement list.
SQLParserResult(); SQLParserResult();
// Initialize with a single statement.
// Takes ownership of the statement.
SQLParserResult(SQLStatement* stmt); SQLParserResult(SQLStatement* stmt);
// Deletes all statements in the resul.
virtual ~SQLParserResult(); virtual ~SQLParserResult();
// Returns true if parsing was successful.
bool isValid() const;
// Returns the number of statements in the result.
size_t size() const;
// Returns the error message, if an error occurred.
const char* errorMsg() const;
// Returns the line number of the occurrance of the error in the query.
int errorLine() const;
// Returns the column number of the occurrance of the error in the query.
int errorColumn() const;
// Gets the SQL statement with the given index.
const SQLStatement* getStatement(int index) const;
// Gets the non const SQL statement with the given index.
SQLStatement* getMutableStatement(int index);
// Adds a statement to the result list of statements.
// Takes ownership of the statement.
void addStatement(SQLStatement* stmt); void addStatement(SQLStatement* stmt);
SQLStatement* getStatement(int id); // Set whether parsing was successful.
void setIsValid(bool isValid);
size_t size(); // Set the details of the error, if available.
void setErrorDetails(const char* errorMsg, int errorLine, int errorColumn);
// public properties
std::vector<SQLStatement*> statements;
bool isValid;
const char* errorMsg; private:
int errorLine; // List of statements within the result.
int errorColumn; std::vector<SQLStatement*> statements_;
// Flag indicating the parsing was successful.
bool isValid_;
// Error message, if an error occurred.
const char* errorMsg_;
// Line number of the occurrance of the error in the query.
int errorLine_;
// Column number of the occurrance of the error in the query.
int errorColumn_;
}; };
} // namespace hsql } // namespace hsql

File diff suppressed because it is too large Load Diff

View File

@ -48,7 +48,7 @@
extern int hsql_debug; extern int hsql_debug;
#endif #endif
/* "%code requires" blocks. */ /* "%code requires" blocks. */
#line 42 "bison_parser.y" /* yacc.c:1909 */ #line 40 "bison_parser.y" /* yacc.c:1909 */
// %code requires block // %code requires block
@ -209,7 +209,7 @@ extern int hsql_debug;
typedef union HSQL_STYPE HSQL_STYPE; typedef union HSQL_STYPE HSQL_STYPE;
union HSQL_STYPE union HSQL_STYPE
{ {
#line 101 "bison_parser.y" /* yacc.c:1909 */ #line 99 "bison_parser.y" /* yacc.c:1909 */
double fval; double fval;
int64_t ival; int64_t ival;

View File

@ -21,10 +21,8 @@ using namespace hsql;
int yyerror(YYLTYPE* llocp, SQLParserResult** result, yyscan_t scanner, const char *msg) { int yyerror(YYLTYPE* llocp, SQLParserResult** result, yyscan_t scanner, const char *msg) {
SQLParserResult* list = new SQLParserResult(); SQLParserResult* list = new SQLParserResult();
list->isValid = false; list->setIsValid(false);
list->errorMsg = strdup(msg); list->setErrorDetails(strdup(msg), llocp->first_line, llocp->first_column);
list->errorLine = llocp->first_line;
list->errorColumn = llocp->first_column;
*result = list; *result = list;
return 0; return 0;

View File

@ -3,10 +3,9 @@
#include "SQLStatement.h" #include "SQLStatement.h"
// Note: Implementations of constructors and destructors can be found in statements.cpp.
namespace hsql { namespace hsql {
/** // Represents definition of a table column
* Represents definition of a table column
*/
struct ColumnDefinition { struct ColumnDefinition {
enum DataType { enum DataType {
TEXT, TEXT,
@ -14,48 +13,30 @@ namespace hsql {
DOUBLE DOUBLE
}; };
ColumnDefinition(char* name, DataType type) : ColumnDefinition(char* name, DataType type);
name(name), virtual ~ColumnDefinition();
type(type) {}
virtual ~ColumnDefinition() {
delete name;
}
char* name; char* name;
DataType type; DataType type;
}; };
/**
* Represents SQL Create statements. // Represents SQL Create statements.
* Example: "CREATE TABLE students (name TEXT, student_number INTEGER, city TEXT, grade DOUBLE)" // Example: "CREATE TABLE students (name TEXT, student_number INTEGER, city TEXT, grade DOUBLE)"
*/
struct CreateStatement : SQLStatement { struct CreateStatement : SQLStatement {
enum CreateType { enum CreateType {
kTable, kTable,
kTableFromTbl // Hyrise file format kTableFromTbl // Hyrise file format
}; };
CreateStatement(CreateType type) : CreateStatement(CreateType type);
SQLStatement(kStmtCreate), virtual ~CreateStatement();
type(type),
ifNotExists(false),
filePath(NULL),
tableName(NULL),
columns(NULL) {};
virtual ~CreateStatement() {
delete columns;
delete filePath;
delete tableName;
}
CreateType type; CreateType type;
bool ifNotExists; // default: false
bool ifNotExists; const char* filePath; // default: NULL
const char* filePath; const char* tableName; // default: NULL
const char* tableName; std::vector<ColumnDefinition*>* columns; // default: NULL
std::vector<ColumnDefinition*>* columns;
}; };
} // namespace hsql } // namespace hsql

View File

@ -3,23 +3,14 @@
#include "SQLStatement.h" #include "SQLStatement.h"
// Note: Implementations of constructors and destructors can be found in statements.cpp.
namespace hsql { namespace hsql {
/** // Represents SQL Delete statements.
* Represents SQL Delete statements. // Example: "DELETE FROM students WHERE grade > 3.0"
* Example: "DELETE FROM students WHERE grade > 3.0" // Note: if (expr == NULL) => delete all rows (truncate)
*
* Note: if (expr == NULL) => delete all rows (truncate)
*/
struct DeleteStatement : SQLStatement { struct DeleteStatement : SQLStatement {
DeleteStatement() : DeleteStatement();
SQLStatement(kStmtDelete), virtual ~DeleteStatement();
tableName(NULL),
expr(NULL) {};
virtual ~DeleteStatement() {
delete tableName;
delete expr;
}
char* tableName; char* tableName;
Expr* expr; Expr* expr;

View File

@ -3,11 +3,10 @@
#include "SQLStatement.h" #include "SQLStatement.h"
// Note: Implementations of constructors and destructors can be found in statements.cpp.
namespace hsql { namespace hsql {
/** // Represents SQL Delete statements.
* Represents SQL Delete statements. // Example "DROP TABLE students;"
* Example "DROP TABLE students;"
*/
struct DropStatement : SQLStatement { struct DropStatement : SQLStatement {
enum EntityType { enum EntityType {
kTable, kTable,
@ -17,14 +16,8 @@ namespace hsql {
kPreparedStatement kPreparedStatement
}; };
DropStatement(EntityType type) : DropStatement(EntityType type);
SQLStatement(kStmtDrop), virtual ~DropStatement();
type(type),
name(NULL) {}
virtual ~DropStatement() {
delete name;
}
EntityType type; EntityType type;
const char* name; const char* name;

View File

@ -9,15 +9,8 @@ namespace hsql {
* Example: "EXECUTE ins_prep(100, "test", 2.3);" * Example: "EXECUTE ins_prep(100, "test", 2.3);"
*/ */
struct ExecuteStatement : SQLStatement { struct ExecuteStatement : SQLStatement {
ExecuteStatement() : ExecuteStatement();
SQLStatement(kStmtExecute), virtual ~ExecuteStatement();
name(NULL),
parameters(NULL) {}
virtual ~ExecuteStatement() {
delete name;
delete parameters;
}
const char* name; const char* name;
std::vector<Expr*>* parameters; std::vector<Expr*>* parameters;

View File

@ -5,31 +5,33 @@
namespace hsql { namespace hsql {
char* substr(const char* source, int from, int to) { Expr::Expr(ExprType type) :
int len = to-from; type(type),
char* copy = new char[len+1]; expr(NULL),
strncpy(copy, source+from, len); expr2(NULL),
copy[len] = '\0'; name(NULL),
return copy; table(NULL),
alias(NULL) {};
Expr::~Expr() {
delete expr;
delete expr2;
delete name;
delete table;
} }
Expr* Expr::makeOpUnary(OperatorType op, Expr* expr) { Expr* Expr::makeOpUnary(OperatorType op, Expr* expr) {
Expr* e = new Expr(kExprOperator); Expr* e = new Expr(kExprOperator);
e->op_type = op; e->opType = op;
e->expr = expr; e->expr = expr;
e->expr2 = NULL; e->expr2 = NULL;
return e; return e;
} }
Expr* Expr::makeOpBinary(Expr* expr1, OperatorType op, Expr* expr2) { Expr* Expr::makeOpBinary(Expr* expr1, OperatorType op, Expr* expr2) {
Expr* e = new Expr(kExprOperator); Expr* e = new Expr(kExprOperator);
e->op_type = op; e->opType = op;
e->op_char = 0; e->opChar = 0;
e->expr = expr1; e->expr = expr1;
e->expr2 = expr2; e->expr2 = expr2;
return e; return e;
@ -37,15 +39,13 @@ namespace hsql {
Expr* Expr::makeOpBinary(Expr* expr1, char op, Expr* expr2) { Expr* Expr::makeOpBinary(Expr* expr1, char op, Expr* expr2) {
Expr* e = new Expr(kExprOperator); Expr* e = new Expr(kExprOperator);
e->op_type = SIMPLE_OP; e->opType = SIMPLE_OP;
e->op_char = op; e->opChar = op;
e->expr = expr1; e->expr = expr1;
e->expr2 = expr2; e->expr2 = expr2;
return e; return e;
} }
Expr* Expr::makeLiteral(int64_t val) { Expr* Expr::makeLiteral(int64_t val) {
Expr* e = new Expr(kExprLiteralInt); Expr* e = new Expr(kExprLiteralInt);
e->ival = val; e->ival = val;
@ -92,11 +92,40 @@ namespace hsql {
return e; return e;
} }
Expr::~Expr() { bool Expr::isType(ExprType e_type) {
delete expr; return e_type == type;
delete expr2;
delete name;
delete table;
} }
bool Expr::isLiteral() {
return isType(kExprLiteralInt) || isType(kExprLiteralFloat) || isType(kExprLiteralString) || isType(kExprPlaceholder);
}
bool Expr::hasAlias() {
return alias != NULL;
}
bool Expr::hasTable() {
return table != NULL;
}
char* Expr::getName() {
if (alias != NULL) return alias;
else return name;
}
bool Expr::isSimpleOp() {
return opType == SIMPLE_OP;
}
bool Expr::isSimpleOp(char op) {
return isSimpleOp() && opChar == op;
}
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;
}
} // namespace hsql } // namespace hsql

View File

@ -6,12 +6,11 @@
namespace hsql { namespace hsql {
// Helper function // Helper function used by the lexer.
// TODO: move to more appropriate place.
char* substr(const char* source, int from, int to); char* substr(const char* source, int from, int to);
enum ExprType {
typedef enum {
kExprLiteralFloat, kExprLiteralFloat,
kExprLiteralString, kExprLiteralString,
kExprLiteralInt, kExprLiteralInt,
@ -20,27 +19,21 @@ namespace hsql {
kExprColumnRef, kExprColumnRef,
kExprFunctionRef, kExprFunctionRef,
kExprOperator kExprOperator
} ExprType; };
typedef struct Expr Expr; typedef struct Expr Expr;
/** // Represents SQL expressions (i.e. literals, operators, column_refs).
* Represents SQL expressions (i.e. literals, operators, column_refs) // TODO: When destructing a placeholder expression, we might need to alter the placeholder_list.
*
* TODO: When destructing a placeholder expression, we might need to alter the placeholder_list
*/
struct Expr { struct Expr {
/** // Operator types. These are important for expressions of type kExprOperator.
* Operator types. These are important for expressions of type kExprOperator // Trivial types are those that can be described by a single character e.g:
* Trivial types are those that can be described by a single character e.g: // + - * / < > = %
* + - * / < > = % // Non-trivial are: <> <= >= LIKE ISNULL NOT
* Non-trivial are: enum OperatorType {
* <> <= >= LIKE ISNULL NOT
*/
typedef enum {
SIMPLE_OP, SIMPLE_OP,
// Binary
// Binary operators.
NOT_EQUALS, NOT_EQUALS,
LESS_EQ, LESS_EQ,
GREATER_EQ, GREATER_EQ,
@ -48,24 +41,20 @@ namespace hsql {
NOT_LIKE, NOT_LIKE,
AND, AND,
OR, OR,
// Unary
// Unary operators.
NOT, NOT,
UMINUS, UMINUS,
ISNULL ISNULL
} OperatorType; };
Expr(ExprType type) : Expr(ExprType type);
type(type),
expr(NULL),
expr2(NULL),
name(NULL),
table(NULL),
alias(NULL) {};
// Interesting side-effect: // Interesting side-effect:
// Making the destructor virtual used to cause segmentation faults // Making the destructor virtual used to cause segmentation faults.
// TODO: inspect.
~Expr(); ~Expr();
ExprType type; ExprType type;
@ -79,51 +68,45 @@ namespace hsql {
int64_t ival; int64_t ival;
int64_t ival2; int64_t ival2;
OperatorType op_type; OperatorType opType;
char op_char; char opChar;
bool distinct; bool distinct;
// Convenience accessor methods.
/** bool isType(ExprType e_type);
* Convenience accessor methods
*/ bool isLiteral();
inline bool isType(ExprType e_type) {
return e_type == type; bool hasAlias();
}
inline bool isLiteral() { bool hasTable();
return isType(kExprLiteralInt) || isType(kExprLiteralFloat) || isType(kExprLiteralString) || isType(kExprPlaceholder);
} char* getName();
inline bool hasAlias() {
return alias != NULL; bool isSimpleOp();
}
inline bool hasTable() { bool isSimpleOp(char op);
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 constructors.
* Static expression constructors
*/
static Expr* makeOpUnary(OperatorType op, Expr* expr); static Expr* makeOpUnary(OperatorType op, Expr* expr);
static Expr* makeOpBinary(Expr* expr1, char op, Expr* expr2); static Expr* makeOpBinary(Expr* expr1, char op, Expr* expr2);
static Expr* makeOpBinary(Expr* expr1, OperatorType op, Expr* expr2); static Expr* makeOpBinary(Expr* expr1, OperatorType op, Expr* expr2);
static Expr* makeLiteral(int64_t val); static Expr* makeLiteral(int64_t val);
static Expr* makeLiteral(double val); static Expr* makeLiteral(double val);
static Expr* makeLiteral(char* val); static Expr* makeLiteral(char* val);
static Expr* makeColumnRef(char* name); static Expr* makeColumnRef(char* name);
static Expr* makeColumnRef(char* table, char* name); static Expr* makeColumnRef(char* table, char* name);
static Expr* makeFunctionRef(char* func_name, Expr* expr, bool distinct); static Expr* makeFunctionRef(char* func_name, Expr* expr, bool distinct);
static Expr* makePlaceholder(int id); static Expr* makePlaceholder(int id);

View File

@ -13,16 +13,8 @@ namespace hsql {
kImportTbl, // Hyrise file format kImportTbl, // Hyrise file format
}; };
ImportStatement(ImportType type) : ImportStatement(ImportType type);
SQLStatement(kStmtImport), virtual ~ImportStatement();
type(type),
filePath(NULL),
tableName(NULL) {};
virtual ~ImportStatement() {
delete filePath;
delete tableName;
}
ImportType type; ImportType type;
const char* filePath; const char* filePath;

View File

@ -15,20 +15,8 @@ namespace hsql {
kInsertSelect kInsertSelect
}; };
InsertStatement(InsertType type) : InsertStatement(InsertType type);
SQLStatement(kStmtInsert), virtual ~InsertStatement();
type(type),
tableName(NULL),
columns(NULL),
values(NULL),
select(NULL) {}
virtual ~InsertStatement() {
delete tableName;
delete columns;
delete values;
delete select;
}
InsertType type; InsertType type;
const char* tableName; const char* tableName;

View File

@ -12,15 +12,8 @@ namespace hsql {
* Example: "PREPARE ins_prep: SELECT * FROM t1 WHERE c1 = ? AND c2 = ?" * Example: "PREPARE ins_prep: SELECT * FROM t1 WHERE c1 = ? AND c2 = ?"
*/ */
struct PrepareStatement : SQLStatement { struct PrepareStatement : SQLStatement {
PrepareStatement() : PrepareStatement();
SQLStatement(kStmtPrepare), virtual ~PrepareStatement();
name(NULL),
query(NULL) {}
virtual ~PrepareStatement() {
delete query;
delete name;
}
/** /**
* When setting the placeholders we need to make sure that they are in the correct order. * When setting the placeholders we need to make sure that they are in the correct order.
@ -28,17 +21,7 @@ namespace hsql {
* *
* @param vector of placeholders that the parser found * @param vector of placeholders that the parser found
*/ */
void setPlaceholders(std::vector<void*> ph) { 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); });
// Set the placeholder id on the Expr. This replaces the previously stored column id
for (uintmax_t i = 0; i < placeholders.size(); ++i) placeholders[i]->ival = i;
}
const char* name; const char* name;
SQLParserResult* query; SQLParserResult* query;

View File

@ -5,7 +5,7 @@
#include <vector> #include <vector>
namespace hsql { namespace hsql {
typedef enum { enum StatementType {
kStmtError, // unused kStmtError, // unused
kStmtSelect, kStmtSelect,
kStmtImport, kStmtImport,
@ -19,23 +19,20 @@ namespace hsql {
kStmtExport, kStmtExport,
kStmtRename, kStmtRename,
kStmtAlter kStmtAlter
} StatementType; };
/** /**
* Base struct for every SQL statement * Base struct for every SQL statement
*/ */
struct SQLStatement { struct SQLStatement {
SQLStatement(StatementType type) : SQLStatement(StatementType type);
_type(type) {};
virtual ~SQLStatement() {} virtual ~SQLStatement();
virtual StatementType type() { virtual StatementType type() const;
return _type;
}
private: private:
StatementType _type; StatementType type_;
}; };
} // namespace hsql } // namespace hsql

View File

@ -6,23 +6,18 @@
#include "Table.h" #include "Table.h"
namespace hsql { namespace hsql {
typedef enum { enum OrderType {
kOrderAsc, kOrderAsc,
kOrderDesc kOrderDesc
} OrderType; };
/** /**
* Description of the order by clause within a select statement * Description of the order by clause within a select statement
* TODO: hold multiple expressions to be sorted by * TODO: hold multiple expressions to be sorted by
*/ */
struct OrderDescription { struct OrderDescription {
OrderDescription(OrderType type, Expr* expr) : OrderDescription(OrderType type, Expr* expr);
type(type), virtual ~OrderDescription();
expr(expr) {}
virtual ~OrderDescription() {
delete expr;
}
OrderType type; OrderType type;
Expr* expr; Expr* expr;
@ -35,9 +30,7 @@ namespace hsql {
* Description of the limit clause within a select statement * Description of the limit clause within a select statement
*/ */
struct LimitDescription { struct LimitDescription {
LimitDescription(int64_t limit, int64_t offset) : LimitDescription(int64_t limit, int64_t offset);
limit(limit),
offset(offset) {}
int64_t limit; int64_t limit;
int64_t offset; int64_t offset;
@ -47,14 +40,9 @@ namespace hsql {
* Description of the group-by clause within a select statement * Description of the group-by clause within a select statement
*/ */
struct GroupByDescription { struct GroupByDescription {
GroupByDescription() : GroupByDescription();
columns(NULL), // TODO: make virtual
having(NULL) {} ~GroupByDescription();
~GroupByDescription() {
delete columns;
delete having;
}
std::vector<Expr*>* columns; std::vector<Expr*>* columns;
Expr* having; Expr* having;
@ -65,25 +53,8 @@ namespace hsql {
* TODO: add union_order and union_limit * TODO: add union_order and union_limit
*/ */
struct SelectStatement : SQLStatement { struct SelectStatement : SQLStatement {
SelectStatement() : SelectStatement();
SQLStatement(kStmtSelect), virtual ~SelectStatement();
fromTable(NULL),
selectDistinct(false),
selectList(NULL),
whereClause(NULL),
groupBy(NULL),
unionSelect(NULL),
order(NULL),
limit(NULL) {};
virtual ~SelectStatement() {
delete fromTable;
delete selectList;
delete whereClause;
delete groupBy;
delete order;
delete limit;
}
TableRef* fromTable; TableRef* fromTable;
bool selectDistinct; bool selectDistinct;

View File

@ -11,33 +11,17 @@ namespace hsql {
struct JoinDefinition; struct JoinDefinition;
struct TableRef; struct TableRef;
// Possible table reference types.
/** enum TableRefType {
* @enum TableRefType
* Types table references
*/
typedef enum {
kTableName, kTableName,
kTableSelect, kTableSelect,
kTableJoin, kTableJoin,
kTableCrossProduct kTableCrossProduct
} TableRefType; };
// Holds reference to tables. Can be either table names or a select statement.
/**
* @struct TableRef
* @brief Holds reference to tables. Can be either table names or a select statement.
*/
struct TableRef { struct TableRef {
TableRef(TableRefType type) : TableRef(TableRefType type);
type(type),
schema(NULL),
name(NULL),
alias(NULL),
select(NULL),
list(NULL),
join(NULL) {}
virtual ~TableRef(); virtual ~TableRef();
TableRefType type; TableRefType type;
@ -50,49 +34,25 @@ namespace hsql {
std::vector<TableRef*>* list; std::vector<TableRef*>* list;
JoinDefinition* join; JoinDefinition* join;
// Returns true if a schema is set.
bool hasSchema();
/** // Returns the alias, if it is set. Otherwise the name.
* Convenience accessor methods char* getName();
*/
inline bool hasSchema() {
return schema != NULL;
}
inline char* getName() {
if (alias != NULL) return alias;
else return name;
}
}; };
// Possible types of joins.
/** enum JoinType {
* @enum JoinType
* Types of joins
*/
typedef enum {
kJoinInner, kJoinInner,
kJoinOuter, kJoinOuter,
kJoinLeft, kJoinLeft,
kJoinRight, kJoinRight,
} JoinType; };
// Definition of a join construct.
/**
* @struct JoinDefinition
* @brief Definition of a join table
*/
struct JoinDefinition { struct JoinDefinition {
JoinDefinition() : JoinDefinition();
left(NULL), virtual ~JoinDefinition();
right(NULL),
condition(NULL),
type(kJoinInner) {}
virtual ~JoinDefinition() {
delete left;
delete right;
delete condition;
}
TableRef* left; TableRef* left;
TableRef* right; TableRef* right;
@ -101,7 +61,5 @@ namespace hsql {
JoinType type; JoinType type;
}; };
} // namespace hsql } // namespace hsql
#endif #endif

View File

@ -16,17 +16,8 @@ namespace hsql {
* Represents SQL Update statements. * Represents SQL Update statements.
*/ */
struct UpdateStatement : SQLStatement { struct UpdateStatement : SQLStatement {
UpdateStatement() : UpdateStatement();
SQLStatement(kStmtUpdate), virtual ~UpdateStatement();
table(NULL),
updates(NULL),
where(NULL) {}
virtual ~UpdateStatement() {
delete table;
delete updates;
delete where;
}
// TODO: switch to char* instead of TableRef // TODO: switch to char* instead of TableRef
TableRef* table; TableRef* table;

View File

@ -1,16 +0,0 @@
#include "Table.h"
#include "SelectStatement.h"
namespace hsql {
TableRef::~TableRef() {
delete name;
delete alias;
delete select;
delete list;
}
} // namespace hsql

222
src/sql/statements.cpp Normal file
View File

@ -0,0 +1,222 @@
#include "statements.h"
namespace hsql {
// SQLStatement
SQLStatement::SQLStatement(StatementType type) :
type_(type) {};
SQLStatement::~SQLStatement() {}
StatementType SQLStatement::type() const {
return type_;
}
// ColumnDefinition
ColumnDefinition::ColumnDefinition(char* name, DataType type) :
name(name),
type(type) {};
ColumnDefinition::~ColumnDefinition() {
delete name;
}
// CreateStatemnet
CreateStatement::CreateStatement(CreateType type) :
SQLStatement(kStmtCreate),
type(type),
ifNotExists(false),
filePath(NULL),
tableName(NULL),
columns(NULL) {};
CreateStatement::~CreateStatement() {
delete columns;
delete filePath;
delete tableName;
}
// DeleteStatement
DeleteStatement::DeleteStatement() :
SQLStatement(kStmtDelete),
tableName(NULL),
expr(NULL) {};
DeleteStatement::~DeleteStatement() {
delete tableName;
delete expr;
}
// DropStatament
DropStatement::DropStatement(EntityType type) :
SQLStatement(kStmtDrop),
type(type),
name(NULL) {}
DropStatement::~DropStatement() {
delete name;
}
// ExecuteStatement
ExecuteStatement::ExecuteStatement() :
SQLStatement(kStmtExecute),
name(NULL),
parameters(NULL) {}
ExecuteStatement::~ExecuteStatement() {
delete name;
delete parameters;
}
// ImportStatement
ImportStatement::ImportStatement(ImportType type) :
SQLStatement(kStmtImport),
type(type),
filePath(NULL),
tableName(NULL) {};
ImportStatement::~ImportStatement() {
delete filePath;
delete tableName;
}
// InsertStatement
InsertStatement::InsertStatement(InsertType type) :
SQLStatement(kStmtInsert),
type(type),
tableName(NULL),
columns(NULL),
values(NULL),
select(NULL) {}
InsertStatement::~InsertStatement() {
delete tableName;
delete columns;
delete values;
delete select;
}
// PrepareStatement
PrepareStatement::PrepareStatement() :
SQLStatement(kStmtPrepare),
name(NULL),
query(NULL) {}
PrepareStatement::~PrepareStatement() {
delete query;
delete name;
}
void PrepareStatement::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); });
// Set the placeholder id on the Expr. This replaces the previously stored column id
for (uintmax_t i = 0; i < placeholders.size(); ++i) placeholders[i]->ival = i;
}
// SelectStatement.h
// OrderDescription
OrderDescription::OrderDescription(OrderType type, Expr* expr) :
type(type),
expr(expr) {}
OrderDescription::~OrderDescription() {
delete expr;
}
// LimitDescription
LimitDescription::LimitDescription(int64_t limit, int64_t offset) :
limit(limit),
offset(offset) {}
// GroypByDescription
GroupByDescription::GroupByDescription() :
columns(NULL),
having(NULL) {}
GroupByDescription::~GroupByDescription() {
delete columns;
delete having;
}
// SelectStatement
SelectStatement::SelectStatement() :
SQLStatement(kStmtSelect),
fromTable(NULL),
selectDistinct(false),
selectList(NULL),
whereClause(NULL),
groupBy(NULL),
unionSelect(NULL),
order(NULL),
limit(NULL) {};
SelectStatement::~SelectStatement() {
delete fromTable;
delete selectList;
delete whereClause;
delete groupBy;
delete order;
delete limit;
}
// UpdateStatement
UpdateStatement::UpdateStatement() :
SQLStatement(kStmtUpdate),
table(NULL),
updates(NULL),
where(NULL) {}
UpdateStatement::~UpdateStatement() {
delete table;
delete updates;
delete where;
}
// TableRef
TableRef::TableRef(TableRefType type) :
type(type),
schema(NULL),
name(NULL),
alias(NULL),
select(NULL),
list(NULL),
join(NULL) {}
TableRef::~TableRef() {
delete name;
delete alias;
delete select;
delete list;
}
bool TableRef::hasSchema() {
return schema != NULL;
}
char* TableRef::getName() {
if (alias != NULL) return alias;
else return name;
}
// JoinDefinition
JoinDefinition::JoinDefinition() :
left(NULL),
right(NULL),
condition(NULL),
type(kJoinInner) {}
JoinDefinition::~JoinDefinition() {
delete left;
delete right;
delete condition;
}
} // namespace hsql

View File

@ -39,20 +39,20 @@ namespace hsql {
break; break;
case kTableJoin: case kTableJoin:
inprint("Join Table", numIndent); inprint("Join Table", numIndent);
inprint("Left", numIndent+1); inprint("Left", numIndent + 1);
printTableRefInfo(table->join->left, numIndent+2); printTableRefInfo(table->join->left, numIndent + 2);
inprint("Right", numIndent+1); inprint("Right", numIndent + 1);
printTableRefInfo(table->join->right, numIndent+2); printTableRefInfo(table->join->right, numIndent + 2);
inprint("Join Condition", numIndent+1); inprint("Join Condition", numIndent + 1);
printExpression(table->join->condition, numIndent+2); printExpression(table->join->condition, numIndent + 2);
break; break;
case kTableCrossProduct: case kTableCrossProduct:
for (TableRef* tbl : *table->list) printTableRefInfo(tbl, numIndent); for (TableRef* tbl : *table->list) printTableRefInfo(tbl, numIndent);
break; break;
} }
if (table->alias != NULL) { if (table->alias != NULL) {
inprint("Alias", numIndent+1); inprint("Alias", numIndent + 1);
inprint(table->alias, numIndent+2); inprint(table->alias, numIndent + 2);
} }
} }
@ -62,9 +62,9 @@ namespace hsql {
return; return;
} }
switch (expr->op_type) { switch (expr->opType) {
case Expr::SIMPLE_OP: case Expr::SIMPLE_OP:
inprintC(expr->op_char, numIndent); inprintC(expr->opChar, numIndent);
break; break;
case Expr::AND: case Expr::AND:
inprint("AND", numIndent); inprint("AND", numIndent);
@ -76,11 +76,11 @@ namespace hsql {
inprint("NOT", numIndent); inprint("NOT", numIndent);
break; break;
default: default:
inprintU(expr->op_type, numIndent); inprintU(expr->opType, numIndent);
break; break;
} }
printExpression(expr->expr, numIndent+1); printExpression(expr->expr, numIndent + 1);
if (expr->expr2 != NULL) printExpression(expr->expr2, numIndent+1); if (expr->expr2 != NULL) printExpression(expr->expr2, numIndent + 1);
} }
void printExpression(Expr* expr, uintmax_t numIndent) { void printExpression(Expr* expr, uintmax_t numIndent) {
@ -103,7 +103,7 @@ namespace hsql {
break; break;
case kExprFunctionRef: case kExprFunctionRef:
inprint(expr->name, numIndent); inprint(expr->name, numIndent);
inprint(expr->expr->name, numIndent+1); inprint(expr->expr->name, numIndent + 1);
break; break;
case kExprOperator: case kExprOperator:
printOperatorExpression(expr, numIndent); printOperatorExpression(expr, numIndent);
@ -113,40 +113,40 @@ namespace hsql {
return; return;
} }
if (expr->alias != NULL) { if (expr->alias != NULL) {
inprint("Alias", numIndent+1); inprint("Alias", numIndent + 1);
inprint(expr->alias, numIndent+2); inprint(expr->alias, numIndent + 2);
} }
} }
void printSelectStatementInfo(SelectStatement* stmt, uintmax_t numIndent) { void printSelectStatementInfo(SelectStatement* stmt, uintmax_t numIndent) {
inprint("SelectStatement", numIndent); inprint("SelectStatement", numIndent);
inprint("Fields:", numIndent+1); inprint("Fields:", numIndent + 1);
for (Expr* expr : *stmt->selectList) printExpression(expr, numIndent+2); for (Expr* expr : *stmt->selectList) printExpression(expr, numIndent + 2);
inprint("Sources:", numIndent+1); inprint("Sources:", numIndent + 1);
printTableRefInfo(stmt->fromTable, numIndent+2); printTableRefInfo(stmt->fromTable, numIndent + 2);
if (stmt->whereClause != NULL) { if (stmt->whereClause != NULL) {
inprint("Search Conditions:", numIndent+1); inprint("Search Conditions:", numIndent + 1);
printExpression(stmt->whereClause, numIndent+2); printExpression(stmt->whereClause, numIndent + 2);
} }
if (stmt->unionSelect != NULL) { if (stmt->unionSelect != NULL) {
inprint("Union:", numIndent+1); inprint("Union:", numIndent + 1);
printSelectStatementInfo(stmt->unionSelect, numIndent+2); printSelectStatementInfo(stmt->unionSelect, numIndent + 2);
} }
if (stmt->order != NULL) { if (stmt->order != NULL) {
inprint("OrderBy:", numIndent+1); inprint("OrderBy:", numIndent + 1);
printExpression(stmt->order->expr, numIndent+2); printExpression(stmt->order->expr, numIndent + 2);
if (stmt->order->type == kOrderAsc) inprint("ascending", numIndent+2); if (stmt->order->type == kOrderAsc) inprint("ascending", numIndent + 2);
else inprint("descending", numIndent+2); else inprint("descending", numIndent + 2);
} }
if (stmt->limit != NULL) { if (stmt->limit != NULL) {
inprint("Limit:", numIndent+1); inprint("Limit:", numIndent + 1);
inprint(stmt->limit->limit, numIndent+2); inprint(stmt->limit->limit, numIndent + 2);
} }
} }
@ -154,34 +154,34 @@ namespace hsql {
void printImportStatementInfo(ImportStatement* stmt, uintmax_t numIndent) { void printImportStatementInfo(ImportStatement* stmt, uintmax_t numIndent) {
inprint("ImportStatment", numIndent); inprint("ImportStatment", numIndent);
inprint(stmt->filePath, numIndent+1); inprint(stmt->filePath, numIndent + 1);
inprint(stmt->tableName, numIndent+1); inprint(stmt->tableName, numIndent + 1);
} }
void printCreateStatementInfo(CreateStatement* stmt, uintmax_t numIndent) { void printCreateStatementInfo(CreateStatement* stmt, uintmax_t numIndent) {
inprint("CreateStatment", numIndent); inprint("CreateStatment", numIndent);
inprint(stmt->tableName, numIndent+1); inprint(stmt->tableName, numIndent + 1);
inprint(stmt->filePath, numIndent+1); inprint(stmt->filePath, numIndent + 1);
} }
void printInsertStatementInfo(InsertStatement* stmt, uintmax_t numIndent) { void printInsertStatementInfo(InsertStatement* stmt, uintmax_t numIndent) {
inprint("InsertStatment", numIndent); inprint("InsertStatment", numIndent);
inprint(stmt->tableName, numIndent+1); inprint(stmt->tableName, numIndent + 1);
if (stmt->columns != NULL) { if (stmt->columns != NULL) {
inprint("Columns", numIndent+1); inprint("Columns", numIndent + 1);
for (char* col_name : *stmt->columns) { for (char* col_name : *stmt->columns) {
inprint(col_name, numIndent+2); inprint(col_name, numIndent + 2);
} }
} }
switch (stmt->type) { switch (stmt->type) {
case InsertStatement::kInsertValues: case InsertStatement::kInsertValues:
inprint("Values", numIndent+1); inprint("Values", numIndent + 1);
for (Expr* expr : *stmt->values) { for (Expr* expr : *stmt->values) {
printExpression(expr, numIndent+2); printExpression(expr, numIndent + 2);
} }
break; break;
case InsertStatement::kInsertSelect: case InsertStatement::kInsertSelect:
printSelectStatementInfo(stmt->select, numIndent+1); printSelectStatementInfo(stmt->select, numIndent + 1);
break; break;
} }
} }

View File

@ -3,20 +3,20 @@
#define TEST_PARSE_SQL_QUERY(query, outputVar, numStatements) \ #define TEST_PARSE_SQL_QUERY(query, outputVar, numStatements) \
SQLParserResult* outputVar = SQLParser::parseSQLString(query); \ const SQLParserResult* outputVar = SQLParser::parseSQLString(query); \
ASSERT(outputVar->isValid); \ ASSERT(outputVar->isValid()); \
ASSERT_EQ(outputVar->size(), numStatements); ASSERT_EQ(outputVar->size(), numStatements);
#define TEST_PARSE_SINGLE_SQL(query, stmtType, stmtClass, outputVar) \ #define TEST_PARSE_SINGLE_SQL(query, stmtType, stmtClass, outputVar) \
TEST_PARSE_SQL_QUERY(query, stmt_list, 1); \ TEST_PARSE_SQL_QUERY(query, stmt_list, 1); \
ASSERT_EQ(stmt_list->getStatement(0)->type(), stmtType); \ ASSERT_EQ(stmt_list->getStatement(0)->type(), stmtType); \
stmtClass* outputVar = (stmtClass*) stmt_list->getStatement(0); const stmtClass* outputVar = (const stmtClass*) stmt_list->getStatement(0);
#define TEST_CAST_STMT(stmt_list, stmt_index, stmtType, stmtClass, outputVar) \ #define TEST_CAST_STMT(stmt_list, stmt_index, stmtType, stmtClass, outputVar) \
ASSERT_EQ(stmt_list->getStatement(stmt_index)->type(), stmtType); \ ASSERT_EQ(stmt_list->getStatement(stmt_index)->type(), stmtType); \
stmtClass* outputVar = (stmtClass*) stmt_list->getStatement(stmt_index); const stmtClass* outputVar = (const stmtClass*) stmt_list->getStatement(stmt_index);
#endif #endif

View File

@ -6,7 +6,7 @@ class TestsManager {
// Note: static initialization fiasco // 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.html
// http://www.parashift.com/c++-faq-lite/static-init-order-on-first-use.html // http://www.parashift.com/c++-faq-lite/static-init-order-on-first-use.html
public: public:
static std::vector<std::string>& testNames() { static std::vector<std::string>& testNames() {
static std::vector<std::string>* _testNames = new std::vector<std::string>; static std::vector<std::string>* _testNames = new std::vector<std::string>;
return *_testNames; return *_testNames;

View File

@ -31,7 +31,7 @@
class AssertionFailedException: public std::exception { class AssertionFailedException: public std::exception {
public: public:
AssertionFailedException(std::string msg) : AssertionFailedException(std::string msg) :
std::exception(), std::exception(),
_msg(msg) {}; _msg(msg) {};
@ -40,7 +40,7 @@ public:
return _msg.c_str(); return _msg.c_str();
} }
protected: protected:
std::string _msg; std::string _msg;
}; };

View File

@ -67,15 +67,15 @@ int main(int argc, char *argv[]) {
start = std::chrono::system_clock::now(); start = std::chrono::system_clock::now();
// Parsing // Parsing
SQLParserResult* stmt_list = SQLParser::parseSQLString(sql.c_str()); SQLParserResult* result = 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;
double us = elapsed_seconds.count() * 1000 * 1000; double us = elapsed_seconds.count() * 1000 * 1000;
if (expectFalse == stmt_list->isValid) { if (expectFalse == result->isValid()) {
printf("\033[0;31m{ failed}\033[0m\n"); printf("\033[0;31m{ failed}\033[0m\n");
printf("\t\033[0;31m%s (L%d:%d)\n\033[0m", stmt_list->errorMsg, stmt_list->errorLine, stmt_list->errorColumn); printf("\t\033[0;31m%s (L%d:%d)\n\033[0m", result->errorMsg(), result->errorLine(), result->errorColumn());
printf("\t%s\n", sql.c_str()); printf("\t%s\n", sql.c_str());
numFailed++; numFailed++;
} else { } else {

View File

@ -11,12 +11,12 @@ using namespace hsql;
TEST(DeleteStatementTest) { TEST(DeleteStatementTest) {
SQLParserResult* result = SQLParser::parseSQLString("DELETE FROM students WHERE grade > 2.0;"); const SQLParserResult* result = SQLParser::parseSQLString("DELETE FROM students WHERE grade > 2.0;");
ASSERT(result->isValid); ASSERT(result->isValid());
ASSERT_EQ(result->size(), 1); ASSERT_EQ(result->size(), 1);
ASSERT(result->getStatement(0)->type() == kStmtDelete); ASSERT(result->getStatement(0)->type() == kStmtDelete);
DeleteStatement* stmt = (DeleteStatement*) result->getStatement(0); const DeleteStatement* stmt = (const DeleteStatement*) result->getStatement(0);
ASSERT_STREQ(stmt->tableName, "students"); ASSERT_STREQ(stmt->tableName, "students");
ASSERT_NOTNULL(stmt->expr); ASSERT_NOTNULL(stmt->expr);
ASSERT(stmt->expr->isType(kExprOperator)); ASSERT(stmt->expr->isType(kExprOperator));
@ -25,12 +25,12 @@ TEST(DeleteStatementTest) {
} }
TEST(CreateStatementTest) { TEST(CreateStatementTest) {
SQLParserResult* result = SQLParser::parseSQLString("CREATE TABLE students (name TEXT, student_number INT, city INTEGER, grade DOUBLE)"); const SQLParserResult* result = SQLParser::parseSQLString("CREATE TABLE students (name TEXT, student_number INT, city INTEGER, grade DOUBLE)");
ASSERT(result->isValid); ASSERT(result->isValid());
ASSERT_EQ(result->size(), 1); ASSERT_EQ(result->size(), 1);
ASSERT_EQ(result->getStatement(0)->type(), kStmtCreate); ASSERT_EQ(result->getStatement(0)->type(), kStmtCreate);
CreateStatement* stmt = (CreateStatement*) result->getStatement(0); const CreateStatement* stmt = (const CreateStatement*) result->getStatement(0);
ASSERT_EQ(stmt->type, CreateStatement::kTable); ASSERT_EQ(stmt->type, CreateStatement::kTable);
ASSERT_STREQ(stmt->tableName, "students"); ASSERT_STREQ(stmt->tableName, "students");
ASSERT_NOTNULL(stmt->columns); ASSERT_NOTNULL(stmt->columns);
@ -47,12 +47,12 @@ TEST(CreateStatementTest) {
TEST(UpdateStatementTest) { TEST(UpdateStatementTest) {
SQLParserResult* result = SQLParser::parseSQLString("UPDATE students SET grade = 5.0, name = 'test' WHERE name = 'Max Mustermann';"); const SQLParserResult* result = SQLParser::parseSQLString("UPDATE students SET grade = 5.0, name = 'test' WHERE name = 'Max Mustermann';");
ASSERT(result->isValid); ASSERT(result->isValid());
ASSERT_EQ(result->size(), 1); ASSERT_EQ(result->size(), 1);
ASSERT_EQ(result->getStatement(0)->type(), kStmtUpdate); ASSERT_EQ(result->getStatement(0)->type(), kStmtUpdate);
UpdateStatement* stmt = (UpdateStatement*) result->getStatement(0); const UpdateStatement* stmt = (const UpdateStatement*) result->getStatement(0);
ASSERT_NOTNULL(stmt->table); ASSERT_NOTNULL(stmt->table);
ASSERT_STREQ(stmt->table->name, "students"); ASSERT_STREQ(stmt->table->name, "students");