query parser now returns a list of statements

This commit is contained in:
Pedro 2014-11-07 02:00:09 +01:00
parent 7c30786b53
commit c5d3a84395
13 changed files with 100 additions and 42 deletions

View File

@ -32,6 +32,8 @@ echo "\n\n"
# ./bin/analysis "-- test
# SELECT * FROM table WHERE a NOT LIKE '%s' -- inline comment
# --my comment"
# ./bin/analysis "SELECT * from table WHERE (b OR NOT a) AND a = 12.5 JOIN table2 ON a = b"
./bin/analysis "
IMPORT FROM TBL FILE 'students.tbl' INTO table;
SELECT * FROM table;"
echo "\n\n"

View File

@ -86,4 +86,8 @@ Expr* Expr::makeFunctionRef(char* func_name, Expr* expr) {
return e;
}
// Expr::~Expr() {
// }
} // namespace hsql

View File

@ -45,6 +45,7 @@ struct Expr {
Expr(ExprType type) : type(type) {};
// virtual ~Expr();
ExprType type;

View File

@ -19,7 +19,7 @@ typedef enum {
* @struct ImportStatement
*/
struct ImportStatement : Statement {
ImportStatement() : Statement(kStmtSelect) {};
ImportStatement() : Statement(kStmtImport) {};
ImportFileType file_type;
const char* file_path;

View File

@ -11,8 +11,6 @@ namespace hsql {
template <typename _T>
class List {
public:
std::vector<_T> _vector;
List() {}
List(_T first_value) {
@ -23,7 +21,15 @@ public:
inline _T at(int i) { return _vector[i]; }
inline _T &operator[](int i) { return _vector[i]; }
inline void push_back(_T value) { _vector.push_back(value); }
inline std::vector<_T> vector() { return _vector; };
private:
std::vector<_T> _vector;
};

View File

@ -5,9 +5,11 @@
#ifndef __STATEMENT_H__
#define __STATEMENT_H__
#include "List.h"
namespace hsql {
typedef enum {
kStmtError,
kStmtSelect,
@ -27,8 +29,19 @@ struct Statement {
Statement(StatementType type) : type(type) {};
StatementType type;
};
class StatementList : public List<Statement*> {
public:
StatementList() : List<Statement*>(), isValid(true) {};
StatementList(Statement* stmt) : List<Statement*>(stmt), isValid(true) {};
bool isValid;
const char* parser_msg;
};
// typedef List<Statement*> StatementList;
} // namespace hsql

View File

@ -34,7 +34,7 @@ void printTableRefInfo(TableRef* table, uint num_indent) {
printExpression(table->join_condition, num_indent+2);
break;
case kTableCrossProduct:
for (TableRef* tbl : table->list->_vector) printTableRefInfo(tbl, num_indent);
for (TableRef* tbl : table->list->vector()) printTableRefInfo(tbl, num_indent);
break;
}
if (table->alias != NULL) {
@ -74,7 +74,7 @@ void printExpression(Expr* expr, uint num_indent) {
void printSelectStatementInfo(SelectStatement* stmt, uint num_indent) {
inprint("SelectStatement", num_indent);
inprint("Fields:", num_indent+1);
for (Expr* expr : stmt->select_list->_vector) printExpression(expr, num_indent+2);
for (Expr* expr : stmt->select_list->vector()) printExpression(expr, num_indent+2);
inprint("Sources:", num_indent+1);
printTableRefInfo(stmt->from_table, num_indent+2);
@ -98,4 +98,12 @@ void printSelectStatementInfo(SelectStatement* stmt, uint num_indent) {
}
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);
}
} // namespace hsql

View File

@ -8,6 +8,7 @@
namespace hsql {
void printSelectStatementInfo(SelectStatement* stmt, uint num_indent);
void printImportStatementInfo(ImportStatement* stmt, uint num_indent);
} // namespace hsql

View File

@ -3,8 +3,6 @@
#include "flex_lexer.h"
#include <stdio.h>
// int yyparse(Statement **expression, yyscan_t scanner);
namespace hsql {
@ -13,8 +11,8 @@ SQLParser::SQLParser() {
}
Statement* SQLParser::parseSQLString(const char *text) {
Statement* stmt;
StatementList* SQLParser::parseSQLString(const char *text) {
StatementList* result;
yyscan_t scanner;
YY_BUFFER_STATE state;
@ -26,15 +24,15 @@ Statement* SQLParser::parseSQLString(const char *text) {
state = hsql__scan_string(text, scanner);
if (hsql_parse(&stmt, scanner)) {
if (hsql_parse(&result, scanner)) {
// Returns an error stmt object
return stmt;
return result;
}
hsql__delete_buffer(state, scanner);
hsql_lex_destroy(scanner);
return stmt;
return result;
}
} // namespace hsql

View File

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

View File

@ -19,9 +19,13 @@
using namespace hsql;
int yyerror(Statement **stmt, yyscan_t scanner, const char *msg) {
*stmt = new Statement(kStmtError);
(*stmt)->parser_msg = strdup(msg);
int yyerror(StatementList** result, yyscan_t scanner, const char *msg) {
StatementList* list = new StatementList();
list->isValid = false;
list->parser_msg = strdup(msg);
*result = list;
return 0;
}
@ -60,7 +64,7 @@ typedef void* yyscan_t;
%lex-param { yyscan_t scanner }
// Define additional parameters for yyparse
%parse-param { hsql::Statement **statement }
%parse-param { hsql::StatementList** result }
%parse-param { yyscan_t scanner }
@ -83,9 +87,10 @@ typedef void* yyscan_t;
hsql::OrderType order_type;
hsql::LimitDescription* limit;
hsql::StatementList* stmt_list;
hsql::List<char*>* slist;
hsql::List<hsql::Expr*>* explist;
hsql::List<hsql::TableRef*>* tbllist;
hsql::List<hsql::Expr*>* expr_list;
hsql::List<hsql::TableRef*>* table_list;
}
@ -107,6 +112,7 @@ typedef void* yyscan_t;
/*********************************
** Non-Terminal types (http://www.gnu.org/software/bison/manual/html_node/Type-Decl.html)
*********************************/
%type <stmt_list> statement_list
%type <statement> statement
%type <select_stmt> select_statement
%type <import_stmt> import_statement
@ -114,10 +120,10 @@ typedef void* yyscan_t;
%type <table> from_clause table_ref table_ref_atomic table_ref_name
%type <table> join_clause join_table
%type <expr> expr scalar_expr unary_expr binary_expr function_expr star_expr
%type <expr> column_name literal int_literal num_literal
%type <expr> column_name literal int_literal num_literal string_literal
%type <expr> comp_expr where_clause join_condition
%type <explist> expr_list group_clause select_list
%type <tbllist> table_ref_commalist
%type <expr_list> expr_list group_clause select_list
%type <table_list> table_ref_commalist
%type <order> order_by_clause
%type <limit> limit_clause
%type <order_type> order_type
@ -156,9 +162,16 @@ typedef void* yyscan_t;
// Defines our general input.
// TODO: Support list of statements
input:
statement opt_semicolon { *statement = $1; }
statement_list opt_semicolon { *result = $1; }
;
statement_list:
statement { $$ = new StatementList($1); }
| statement_list ';' statement { $1->push_back($3); $$ = $1; }
;
// All types of statements
// TODO: insert, delete, etc...
statement:
@ -186,7 +199,7 @@ import_file_type:
;
file_path:
STRING
string_literal { $$ = $1->name; }
;
@ -308,10 +321,15 @@ column_name:
;
literal:
STRING { $$ = Expr::makeLiteral($1); }
string_literal
| num_literal
;
string_literal:
STRING { $$ = Expr::makeLiteral($1); }
;
num_literal:
FLOAT { $$ = Expr::makeLiteral($1); }
| int_literal

View File

@ -15,23 +15,30 @@ int main(int argc, char *argv[]) {
for (int n = 1; n < argc; ++n) {
char* sql = argv[n];
printf("\nEvaluating Statement \"%s\"\n", sql);
Statement* stmt = SQLParser::parseSQLString(sql);
printf("\nEvaluating Query \"%s\"\n", sql);
StatementList* stmt_list = SQLParser::parseSQLString(sql);
if (stmt == NULL) {
fprintf(stderr, "Parsing of \"%s\" failed!\n", sql);
if (!stmt_list->isValid) {
fprintf(stderr, "Parsing of \"%s\" failed! Reason: %s\n", sql, stmt_list->parser_msg);
continue;
}
if (stmt->type == kStmtSelect) {
printSelectStatementInfo((SelectStatement*) stmt, 0);
} else {
if (stmt->type == kStmtError) {
fprintf(stderr, "%s!\n", stmt->parser_msg);
} else {
fprintf(stderr, "Unsupported Statement Type %u!\n", stmt->type);
int i = 0;
for (Statement* stmt : stmt_list->vector()) {
printf("Statement %d:\n", i++);
switch (stmt->type) {
case kStmtSelect:
printSelectStatementInfo((SelectStatement*) stmt, 1);
break;
case kStmtImport:
printImportStatementInfo((ImportStatement*) stmt, 1);
break;
default:
fprintf(stderr, "\tStatement Type %u. No detailed print method available.\n", stmt->type);
break;
}
}
}
}
return 0;

View File

@ -23,17 +23,17 @@ int main(int argc, char *argv[]) {
start = std::chrono::system_clock::now();
// Parsing
Statement* stmt = SQLParser::parseSQLString(sql);
StatementList* stmt_list = SQLParser::parseSQLString(sql);
end = std::chrono::system_clock::now();
std::chrono::duration<double> elapsed_seconds = end-start;
if (expectFalse != (stmt->type == kStmtError)) {
fprintf(stderr, "-> Failed (%.3fms)! %s: \"%s\"\n", elapsed_seconds.count()*1000, stmt->parser_msg, sql);
if (expectFalse == stmt_list->isValid) {
fprintf(stderr, "-> Failed (%.3fms)! %s: \"%s\"\n", elapsed_seconds.count()*1000, stmt_list->parser_msg, sql);
continue;
} else {
if (expectFalse) {
printf("Success (%.3fms)! %s: \"%s\"\n", elapsed_seconds.count()*1000, stmt->parser_msg, sql);
printf("Success (%.3fms)! %s: \"%s\"\n", elapsed_seconds.count()*1000, stmt_list->parser_msg, sql);
} else {
printf("Success (%.3fms)! \"%s\"\n", elapsed_seconds.count()*1000, sql);