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 # ./bin/analysis "-- test
# SELECT * FROM table WHERE a NOT LIKE '%s' -- inline comment # SELECT * FROM table WHERE a NOT LIKE '%s' -- inline comment
# --my 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" echo "\n\n"

View File

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

View File

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

View File

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

View File

@ -11,8 +11,6 @@ namespace hsql {
template <typename _T> template <typename _T>
class List { class List {
public: public:
std::vector<_T> _vector;
List() {} List() {}
List(_T first_value) { List(_T first_value) {
@ -23,7 +21,15 @@ public:
inline _T at(int i) { return _vector[i]; } inline _T at(int i) { return _vector[i]; }
inline _T &operator[](int i) { return _vector[i]; } inline _T &operator[](int i) { return _vector[i]; }
inline void push_back(_T value) { _vector.push_back(value); } 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__ #ifndef __STATEMENT_H__
#define __STATEMENT_H__ #define __STATEMENT_H__
#include "List.h"
namespace hsql { namespace hsql {
typedef enum { typedef enum {
kStmtError, kStmtError,
kStmtSelect, kStmtSelect,
@ -27,8 +29,19 @@ struct Statement {
Statement(StatementType type) : type(type) {}; Statement(StatementType type) : type(type) {};
StatementType 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; const char* parser_msg;
}; };
// typedef List<Statement*> StatementList;
} // namespace hsql } // namespace hsql

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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