major improvements to expr-structure
This commit is contained in:
parent
67d2ad9336
commit
e24a2ae88d
|
@ -12,7 +12,6 @@
|
|||
*********************************/
|
||||
|
||||
#include "Statement.h"
|
||||
#include "List.h"
|
||||
#include "bison_parser.h"
|
||||
#include "flex_lexer.h"
|
||||
|
||||
|
@ -82,7 +81,7 @@ typedef void* yyscan_t;
|
|||
%token SELECT FROM WHERE GROUP BY HAVING
|
||||
%token JOIN ON INNER OUTER LEFT RIGHT CROSS USING NATURAL
|
||||
%token CREATE TABLE DATABASE INDEX
|
||||
%token AS NOT AND OR NULL
|
||||
%token AS NOT AND OR NULL LIKE
|
||||
%token <sval> NAME STRING COMPARISON
|
||||
%token <number> FLOAT
|
||||
%token <uintnum> EQUALS NOTEQUALS LESS GREATER LESSEQ GREATEREQ
|
||||
|
@ -94,12 +93,34 @@ typedef void* yyscan_t;
|
|||
%type <select_statement> select_statement
|
||||
%type <sval> table_name
|
||||
%type <table> from_clause table_ref table_ref_atomic
|
||||
%type <expr> expr column_name scalar_exp literal
|
||||
%type <expr> comparison_predicate predicate search_condition where_clause
|
||||
%type <expr> expr scalar_expr unary_expr binary_expr function_expr star_expr
|
||||
%type <expr> column_name literal
|
||||
%type <expr> comp_expr where_clause
|
||||
%type <explist> expr_list group_clause select_list
|
||||
%type <tbllist> table_ref_commalist
|
||||
|
||||
|
||||
/******************************
|
||||
** Token Precedence and Associativity
|
||||
** Precedence: lowest to highest
|
||||
******************************/
|
||||
%left OR
|
||||
%left AND
|
||||
%right NOT
|
||||
%right '=' EQUALS NOTEQUALS
|
||||
%nonassoc '<' '>' LESS GREATER LESSEQ GREATEREQ
|
||||
|
||||
%nonassoc NOTNULL
|
||||
%nonassoc ISNULL
|
||||
%nonassoc IS /* sets precedence for IS NULL, etc */
|
||||
%left '+' '-'
|
||||
%left '*' '/' '%'
|
||||
%left '^'
|
||||
|
||||
/* Unary Operators */
|
||||
%left '[' ']'
|
||||
%left '(' ')'
|
||||
%left '.'
|
||||
|
||||
%%
|
||||
/*********************************
|
||||
|
@ -142,8 +163,8 @@ select_statement:
|
|||
|
||||
|
||||
select_list:
|
||||
'*' { $$ = new List<Expr*>(new Expr(eExprStar)); }
|
||||
| expr_list;
|
||||
expr_list
|
||||
;
|
||||
|
||||
|
||||
from_clause:
|
||||
|
@ -152,7 +173,7 @@ from_clause:
|
|||
|
||||
|
||||
where_clause:
|
||||
WHERE search_condition { $$ = $2; }
|
||||
WHERE expr { $$ = $2; }
|
||||
| /* empty */ { $$ = NULL; }
|
||||
;
|
||||
|
||||
|
@ -163,59 +184,70 @@ group_clause:
|
|||
;
|
||||
|
||||
|
||||
// TODO: multiple predicates
|
||||
search_condition:
|
||||
predicate
|
||||
/******************************
|
||||
** Expressions
|
||||
******************************/
|
||||
expr_list:
|
||||
expr { $$ = new List<Expr*>($1); }
|
||||
| expr_list ',' expr { $1->push_back($3); $$ = $1; }
|
||||
;
|
||||
|
||||
|
||||
predicate:
|
||||
comparison_predicate
|
||||
;
|
||||
|
||||
|
||||
comparison_predicate:
|
||||
scalar_exp EQUALS scalar_exp { $$ = makePredicate($1, SQL_EQUALS, $3); }
|
||||
| scalar_exp NOTEQUALS scalar_exp { $$ = makePredicate($1, SQL_NOTEQUALS, $3); }
|
||||
| scalar_exp LESS scalar_exp { $$ = makePredicate($1, SQL_LESS, $3); }
|
||||
| scalar_exp GREATER scalar_exp { $$ = makePredicate($1, SQL_GREATER, $3); }
|
||||
| scalar_exp LESSEQ scalar_exp { $$ = makePredicate($1, SQL_LESSEQ, $3); }
|
||||
| scalar_exp GREATEREQ scalar_exp { $$ = makePredicate($1, SQL_GREATEREQ, $3); }
|
||||
;
|
||||
|
||||
// TODO: Expression can also be scalar_exp
|
||||
expr:
|
||||
'(' expr ')' { $$ = $2; }
|
||||
| scalar_expr
|
||||
| unary_expr
|
||||
| binary_expr
|
||||
| function_expr
|
||||
;
|
||||
|
||||
scalar_expr:
|
||||
column_name
|
||||
| NAME '(' expr ')' { $$ = makeFunctionRef($1, $3); }
|
||||
| star_expr
|
||||
| literal
|
||||
;
|
||||
|
||||
unary_expr:
|
||||
'-' expr { $$ = NULL; } // TODO
|
||||
| '+' expr { $$ = NULL; }
|
||||
| NOT expr { $$ = NULL; }
|
||||
;
|
||||
|
||||
binary_expr:
|
||||
comp_expr
|
||||
| expr '-' expr { $$ = Expr::makeOpBinary($1, '-', $3); }
|
||||
| expr '+' expr { $$ = Expr::makeOpBinary($1, '+', $3); }
|
||||
| expr '/' expr { $$ = Expr::makeOpBinary($1, '/', $3); }
|
||||
| expr '*' expr { $$ = Expr::makeOpBinary($1, '*', $3); }
|
||||
| expr AND expr { $$ = Expr::makeOpBinary($1, AND, $3); }
|
||||
| expr OR expr { $$ = Expr::makeOpBinary($1, OR, $3); }
|
||||
;
|
||||
|
||||
|
||||
// TODO: Scalar expressions can also be arithmetic
|
||||
scalar_exp:
|
||||
column_name
|
||||
| literal
|
||||
comp_expr:
|
||||
expr EQUALS expr { $$ = Expr::makeOpBinary($1, '=', $3); }
|
||||
| expr NOTEQUALS expr { $$ = Expr::makeOpBinary($1, NOT_EQUALS, $3); }
|
||||
| expr LESS expr { $$ = Expr::makeOpBinary($1, '<', $3); }
|
||||
| expr GREATER expr { $$ = Expr::makeOpBinary($1, '>', $3); }
|
||||
| expr LESSEQ expr { $$ = Expr::makeOpBinary($1, LESS_EQ, $3); }
|
||||
| expr GREATEREQ expr { $$ = Expr::makeOpBinary($1, GREATER_EQ, $3); }
|
||||
;
|
||||
|
||||
function_expr:
|
||||
NAME '(' expr ')' { $$ = makeFunctionRef($1, $3); }
|
||||
;
|
||||
|
||||
column_name:
|
||||
NAME { $$ = makeColumnRef($1); }
|
||||
;
|
||||
|
||||
|
||||
literal:
|
||||
STRING { $$ = makeStringLiteral($1); }
|
||||
| FLOAT { $$ = makeFloatLiteral($1); }
|
||||
;
|
||||
|
||||
|
||||
opt_semicolon:
|
||||
';'
|
||||
| /* empty */
|
||||
;
|
||||
|
||||
|
||||
expr_list:
|
||||
expr { $$ = new List<Expr*>($1); }
|
||||
| expr_list ',' expr { $1->push_back($3); $$ = $1; }
|
||||
star_expr:
|
||||
'*' { $$ = new Expr(eExprStar); }
|
||||
;
|
||||
|
||||
|
||||
|
@ -256,6 +288,13 @@ table_name:
|
|||
;
|
||||
|
||||
|
||||
|
||||
opt_semicolon:
|
||||
';'
|
||||
| /* empty */
|
||||
;
|
||||
|
||||
|
||||
%%
|
||||
/*********************************
|
||||
** Section 4: Additional C code
|
||||
|
|
|
@ -11,7 +11,6 @@
|
|||
%{
|
||||
|
||||
#include "Statement.h"
|
||||
#include "List.h"
|
||||
#include "bison_parser.h"
|
||||
#include <stdio.h>
|
||||
|
||||
|
|
|
@ -1,8 +1,9 @@
|
|||
|
||||
make clean
|
||||
|
||||
make tests
|
||||
./bin/tests
|
||||
# make tests
|
||||
# ./bin/tests
|
||||
|
||||
make execution
|
||||
./bin/sql_execution "SELECT col1, col2 FROM table, (SELECT * FROM a, table, (SELECT * FROM (SELECT * FROM foo))) GROUP BY col1;"
|
||||
./bin/sql_execution "SELECT a FROM foo WHERE a > 12 OR b > 3 AND c = 3"
|
||||
./bin/sql_execution "SELECT col1, col2, 'test' FROM table, foo WHERE age > 12 AND zipcode = 12345 GROUP BY col1;"
|
|
@ -1,6 +1,15 @@
|
|||
|
||||
#include "Expr.h"
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
|
||||
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* makeColumnRef(char* name) {
|
||||
ALLOC_EXPR(e, eExprColumnRef);
|
||||
|
@ -15,15 +24,6 @@ Expr* makeFunctionRef(char* func_name, Expr* expr) {
|
|||
return e;
|
||||
}
|
||||
|
||||
Expr* makePredicate(Expr* expr1, uint op, Expr* expr2) {
|
||||
ALLOC_EXPR(e, eExprPredicate);
|
||||
// printf("Pred: %u\n", op);
|
||||
e->pred_type = op;
|
||||
e->expr = expr1;
|
||||
e->expr2 = expr2;
|
||||
return e;
|
||||
}
|
||||
|
||||
Expr* makeFloatLiteral(float value) {
|
||||
ALLOC_EXPR(e, eExprLiteralFloat);
|
||||
e->float_literal = value;
|
||||
|
@ -32,6 +32,33 @@ Expr* makeFloatLiteral(float value) {
|
|||
|
||||
Expr* makeStringLiteral(char* string) {
|
||||
ALLOC_EXPR(e, eExprLiteralString);
|
||||
e->name = string;
|
||||
e->name = substr(string, 1, strlen(string)-1);
|
||||
delete string;
|
||||
return e;
|
||||
}
|
||||
|
||||
|
||||
Expr* Expr::makeOpUnary(OperatorType op, Expr* expr) {
|
||||
ALLOC_EXPR(e, eExprOperator);
|
||||
e->op_type = op;
|
||||
e->expr = expr;
|
||||
return e;
|
||||
}
|
||||
|
||||
Expr* Expr::makeOpBinary(Expr* expr1, OperatorType op, Expr* expr2) {
|
||||
ALLOC_EXPR(e, eExprOperator);
|
||||
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) {
|
||||
ALLOC_EXPR(e, eExprOperator);
|
||||
e->op_type = TRIVIAL_OP;
|
||||
e->op_char = op;
|
||||
e->expr = expr1;
|
||||
e->expr2 = expr2;
|
||||
return e;
|
||||
}
|
||||
|
|
|
@ -4,27 +4,54 @@
|
|||
#include <stdlib.h>
|
||||
|
||||
|
||||
|
||||
typedef enum {
|
||||
eExprLiteralFloat,
|
||||
eExprLiteralString,
|
||||
eExprStar,
|
||||
eExprColumnRef,
|
||||
eExprFunctionRef,
|
||||
eExprPredicate
|
||||
} EExprType;
|
||||
eExprOperator
|
||||
} ExprType;
|
||||
|
||||
|
||||
/**
|
||||
* Trivial types are those that can be descriped by a sigle character e.g:
|
||||
* + - * / < > = %
|
||||
* Non-trivial are:
|
||||
* <> <= >= LIKE ISNULL NOT
|
||||
*/
|
||||
typedef enum {
|
||||
TRIVIAL_OP,
|
||||
NOT_EQUALS,
|
||||
LESS_EQ,
|
||||
GREATER_EQ,
|
||||
LIKE,
|
||||
ISNULL,
|
||||
NOT,
|
||||
AND,
|
||||
OR
|
||||
} OperatorType;
|
||||
|
||||
|
||||
|
||||
typedef struct Expr Expr;
|
||||
|
||||
struct Expr {
|
||||
Expr(EExprType type) : type(type) {};
|
||||
Expr(ExprType type) : type(type) {};
|
||||
|
||||
EExprType type;
|
||||
ExprType type;
|
||||
|
||||
Expr* expr;
|
||||
Expr* expr2;
|
||||
char* name;
|
||||
uint pred_type;
|
||||
float float_literal;
|
||||
|
||||
OperatorType op_type;
|
||||
char op_char;
|
||||
|
||||
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);
|
||||
};
|
||||
|
||||
// Zero initializes an Expr object and assigns it to a space in the heap
|
||||
|
@ -40,7 +67,6 @@ struct Expr {
|
|||
|
||||
Expr* makeColumnRef(char* name);
|
||||
Expr* makeFunctionRef(char* func_name, Expr* expr);
|
||||
Expr* makePredicate(Expr* expr1, uint op, Expr* expr2);
|
||||
Expr* makeFloatLiteral(float value);
|
||||
Expr* makeStringLiteral(char* string);
|
||||
|
||||
|
|
|
@ -3,10 +3,14 @@
|
|||
#include <stdio.h>
|
||||
#include <string>
|
||||
|
||||
const char* indent(uint num_indent) { return std::string(num_indent, ' ').c_str(); }
|
||||
void printExpression(Expr* expr, uint num_indent);
|
||||
void printOperatorExpression(Expr* expr, uint num_indent);
|
||||
|
||||
const char* indent(uint num_indent) { return std::string(num_indent, '\t').c_str(); }
|
||||
void inprint(int val, uint num_indent) { printf("%s%d\n", indent(num_indent), val); }
|
||||
void inprint(float val, uint num_indent) { printf("%s%f\n", indent(num_indent), val); }
|
||||
void inprint(const char* val, uint num_indent) { printf("%s%s\n", indent(num_indent), val); }
|
||||
void inprint(char val, uint num_indent) { printf("%s%c\n", indent(num_indent), val); }
|
||||
|
||||
void printTableRefInfo(TableRef* table, uint num_indent) {
|
||||
switch (table->type) {
|
||||
|
@ -22,19 +26,39 @@ void printTableRefInfo(TableRef* table, uint num_indent) {
|
|||
}
|
||||
}
|
||||
|
||||
void printOperatorExpression(Expr* expr, uint num_indent) {
|
||||
switch (expr->op_type) {
|
||||
case TRIVIAL_OP: inprint(expr->op_char, num_indent); break;
|
||||
case AND: inprint("AND", num_indent); break;
|
||||
case OR: inprint("OR", num_indent); break;
|
||||
default: inprint(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 eExprStar: inprint("*", num_indent); break;
|
||||
case eExprColumnRef: inprint(expr->name, num_indent); break;
|
||||
case eExprLiteralFloat: inprint(expr->float_literal, num_indent); break;
|
||||
case eExprLiteralString: inprint(expr->name, num_indent); break;
|
||||
case eExprFunctionRef: /* todo */ break;
|
||||
case eExprOperator: printOperatorExpression(expr, num_indent); break;
|
||||
default:
|
||||
fprintf(stderr, "Unrecognized expression type %d\n", expr->type);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void printSelectStatementInfo(SelectStatement* stmt, uint num_indent) {
|
||||
inprint("SelectStatement", num_indent);
|
||||
inprint("Fields:", num_indent+1);
|
||||
for (Expr* expr : stmt->select_list->_vector) {
|
||||
switch (expr->type) {
|
||||
case eExprStar: inprint("*", num_indent+2); break;
|
||||
case eExprColumnRef: inprint(expr->name, num_indent+2); break;
|
||||
case eExprLiteralFloat: inprint(expr->float_literal, num_indent+2); break;
|
||||
case eExprLiteralString: inprint(expr->name, num_indent+2); break;
|
||||
case eExprFunctionRef: /* todo */ break;
|
||||
case eExprPredicate: /* todo */ break;
|
||||
}
|
||||
}
|
||||
for (Expr* expr : stmt->select_list->_vector) printExpression(expr, num_indent+2);
|
||||
|
||||
inprint("Sources:", num_indent+1);
|
||||
printTableRefInfo(stmt->from_table, num_indent+2);
|
||||
|
||||
inprint("Search Conditions:", num_indent+1);
|
||||
printExpression(stmt->where_clause, num_indent+2);
|
||||
}
|
||||
|
|
|
@ -18,7 +18,7 @@
|
|||
void SelectTest1() {
|
||||
printf("Test: SelectTest1... "); fflush(stdout);
|
||||
|
||||
const char* sql = "SELECT age, name, address from table WHERE age < 12.5;";
|
||||
const char* sql = "SELECT age, (name), address from table WHERE age < 12.5;";
|
||||
Statement* sqlStatement = SQLParser::parseSQLString(sql);
|
||||
ASSERT(sqlStatement != NULL);
|
||||
ASSERT(sqlStatement->type == eSelect);
|
||||
|
@ -48,7 +48,7 @@ void SelectTest1() {
|
|||
void SelectTest2() {
|
||||
printf("Test: SelectTest2... "); fflush(stdout);
|
||||
|
||||
const char* sql = "SELECT * FROM (SELECT age FROM table, table2);";
|
||||
const char* sql = "SELECT * FROM (SELECT age+zipcode FROM table, table2);";
|
||||
Statement* stmt = SQLParser::parseSQLString(sql);
|
||||
ASSERT(stmt != NULL);
|
||||
ASSERT(stmt->type == eSelect);
|
||||
|
|
Loading…
Reference in New Issue