query parser now returns a list of statements
This commit is contained in:
parent
7c30786b53
commit
c5d3a84395
|
@ -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"
|
|
@ -86,4 +86,8 @@ Expr* Expr::makeFunctionRef(char* func_name, Expr* expr) {
|
|||
return e;
|
||||
}
|
||||
|
||||
// Expr::~Expr() {
|
||||
|
||||
// }
|
||||
|
||||
} // namespace hsql
|
|
@ -45,6 +45,7 @@ struct Expr {
|
|||
|
||||
|
||||
Expr(ExprType type) : type(type) {};
|
||||
// virtual ~Expr();
|
||||
|
||||
ExprType type;
|
||||
|
||||
|
|
|
@ -19,7 +19,7 @@ typedef enum {
|
|||
* @struct ImportStatement
|
||||
*/
|
||||
struct ImportStatement : Statement {
|
||||
ImportStatement() : Statement(kStmtSelect) {};
|
||||
ImportStatement() : Statement(kStmtImport) {};
|
||||
|
||||
ImportFileType file_type;
|
||||
const char* file_path;
|
||||
|
|
|
@ -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;
|
||||
|
||||
};
|
||||
|
||||
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -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
|
|
@ -8,6 +8,7 @@
|
|||
namespace hsql {
|
||||
|
||||
void printSelectStatementInfo(SelectStatement* stmt, uint num_indent);
|
||||
void printImportStatementInfo(ImportStatement* stmt, uint num_indent);
|
||||
|
||||
} // namespace hsql
|
||||
|
||||
|
|
|
@ -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
|
|
@ -8,7 +8,7 @@ namespace hsql {
|
|||
|
||||
class SQLParser {
|
||||
public:
|
||||
static Statement* parseSQLString(const char* sql);
|
||||
static StatementList* parseSQLString(const char* sql);
|
||||
|
||||
private:
|
||||
SQLParser();
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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);
|
||||
|
|
Loading…
Reference in New Issue