Implemented UNION and OFFSET
This commit is contained in:
parent
f2a9f5b3a8
commit
dfbc50ed27
|
@ -10,8 +10,9 @@ make grammar_test -C src/
|
|||
echo "\n\n"
|
||||
|
||||
|
||||
./bin/analysis "SELECT t1.a AS id, t1.b, t2.c FROM \"tbl\" AS t1 JOIN (SELECT * FROM foo JOIN bar ON foo.id = bar.id) t2 ON t1.a = t2.b WHERE (t1.b OR NOT t1.a) AND t2.c = 12.5"
|
||||
# ./bin/analysis "SELECT t1.a AS id, t1.b, t2.c FROM \"tbl\" AS t1 JOIN (SELECT * FROM foo JOIN bar ON foo.id = bar.id) t2 ON t1.a = t2.b WHERE (t1.b OR NOT t1.a) AND t2.c = 12.5"
|
||||
# ./bin/analysis "CREATE TABLE \"table\" FROM TBL FILE 'students.tbl'"
|
||||
./bin/analysis "SELECT * FROM t1 UNION (SELECT abc AS t FROM t2 ORDER BY col3 LIMIT 10) ORDER BY col1;"
|
||||
|
||||
echo "\n\n"
|
||||
|
||||
|
|
|
@ -19,7 +19,11 @@ typedef enum {
|
|||
* @struct CreateStatement
|
||||
*/
|
||||
struct CreateStatement : Statement {
|
||||
CreateStatement() : Statement(kStmtCreate) {};
|
||||
CreateStatement() :
|
||||
Statement(kStmtCreate),
|
||||
file_path(NULL),
|
||||
table_name(NULL) {};
|
||||
|
||||
virtual ~CreateStatement(); // defined in destructors.cpp
|
||||
|
||||
CreateType create_type;
|
||||
|
|
|
@ -50,7 +50,13 @@ struct Expr {
|
|||
|
||||
|
||||
|
||||
Expr(ExprType type) : type(type), expr(NULL), expr2(NULL), name(NULL), table(NULL), alias(NULL) {};
|
||||
Expr(ExprType type) :
|
||||
type(type),
|
||||
expr(NULL),
|
||||
expr2(NULL),
|
||||
name(NULL),
|
||||
table(NULL),
|
||||
alias(NULL) {};
|
||||
|
||||
// Interesting side-effect:
|
||||
// Making the destructor virtual causes segmentation faults
|
||||
|
|
|
@ -19,7 +19,11 @@ typedef enum {
|
|||
* @struct ImportStatement
|
||||
*/
|
||||
struct ImportStatement : Statement {
|
||||
ImportStatement() : Statement(kStmtImport) {};
|
||||
ImportStatement() :
|
||||
Statement(kStmtImport),
|
||||
file_path(NULL),
|
||||
table_name(NULL) {};
|
||||
|
||||
virtual ~ImportStatement(); // defined in destructors.cpp
|
||||
|
||||
ImportFileType file_type;
|
||||
|
|
|
@ -20,7 +20,10 @@ typedef enum {
|
|||
} OrderType;
|
||||
|
||||
struct OrderDescription {
|
||||
OrderDescription(OrderType type, Expr* expr) : type(type), expr(expr) {}
|
||||
OrderDescription(OrderType type, Expr* expr) :
|
||||
type(type),
|
||||
expr(expr) {}
|
||||
|
||||
virtual ~OrderDescription(); // defined in destructors.cpp
|
||||
|
||||
OrderType type;
|
||||
|
@ -34,7 +37,10 @@ struct OrderDescription {
|
|||
const int64_t kNoLimit = -1;
|
||||
const int64_t kNoOffset = -1;
|
||||
struct LimitDescription {
|
||||
LimitDescription(int64_t limit, int64_t offset) : limit(limit), offset(offset) {}
|
||||
LimitDescription(int64_t limit, int64_t offset) :
|
||||
limit(limit),
|
||||
offset(offset) {}
|
||||
|
||||
int64_t limit;
|
||||
int64_t offset;
|
||||
};
|
||||
|
@ -44,15 +50,24 @@ struct LimitDescription {
|
|||
* Representation of a full select statement.
|
||||
*/
|
||||
struct SelectStatement : Statement {
|
||||
SelectStatement() : Statement(kStmtSelect) {};
|
||||
SelectStatement() :
|
||||
Statement(kStmtSelect),
|
||||
from_table(NULL),
|
||||
select_list(NULL),
|
||||
where_clause(NULL),
|
||||
group_by(NULL),
|
||||
order(NULL),
|
||||
limit(NULL),
|
||||
union_select(NULL) {};
|
||||
|
||||
virtual ~SelectStatement(); // defined in destructors.cpp
|
||||
|
||||
TableRef* from_table;
|
||||
List<Expr*>* select_list;
|
||||
Expr* where_clause;
|
||||
|
||||
Expr* where_clause;
|
||||
List<Expr*>* group_by;
|
||||
|
||||
SelectStatement* union_select;
|
||||
OrderDescription* order;
|
||||
LimitDescription* limit;
|
||||
};
|
||||
|
|
|
@ -11,7 +11,7 @@ namespace hsql {
|
|||
|
||||
|
||||
typedef enum {
|
||||
kStmtError,
|
||||
kStmtError, // Unused
|
||||
kStmtSelect,
|
||||
kStmtImport,
|
||||
// Following types are planned but not supported yet
|
||||
|
@ -26,7 +26,9 @@ typedef enum {
|
|||
|
||||
|
||||
struct Statement {
|
||||
Statement(StatementType type) : type(type) {};
|
||||
Statement(StatementType type) :
|
||||
type(type) {};
|
||||
|
||||
virtual ~Statement(); // defined in destructors.cpp
|
||||
|
||||
StatementType type;
|
||||
|
@ -35,8 +37,16 @@ struct Statement {
|
|||
|
||||
class StatementList : public List<Statement*> {
|
||||
public:
|
||||
StatementList() : List<Statement*>(), isValid(true) {};
|
||||
StatementList(Statement* stmt) : List<Statement*>(stmt), isValid(true) {};
|
||||
StatementList() :
|
||||
List<Statement*>(),
|
||||
isValid(true),
|
||||
parser_msg(NULL) {};
|
||||
|
||||
StatementList(Statement* stmt) :
|
||||
List<Statement*>(stmt),
|
||||
isValid(true),
|
||||
parser_msg(NULL) {};
|
||||
|
||||
virtual ~StatementList(); // defined in destructors.cpp
|
||||
|
||||
bool isValid;
|
||||
|
|
|
@ -29,7 +29,16 @@ typedef enum {
|
|||
typedef struct TableRef TableRef;
|
||||
|
||||
struct TableRef {
|
||||
TableRef(TableRefType type) : type(type) {}
|
||||
TableRef(TableRefType type) :
|
||||
type(type),
|
||||
name(NULL),
|
||||
alias(NULL),
|
||||
select(NULL),
|
||||
list(NULL),
|
||||
left(NULL),
|
||||
right(NULL),
|
||||
join_condition(NULL) {}
|
||||
|
||||
virtual ~TableRef(); // defined in destructors.cpp
|
||||
|
||||
TableRefType type;
|
||||
|
|
|
@ -70,7 +70,7 @@ void printExpression(Expr* expr, uint num_indent) {
|
|||
default: fprintf(stderr, "Unrecognized expression type %d\n", expr->type); return;
|
||||
}
|
||||
if (expr->alias != NULL) {
|
||||
inprint("Alias", num_indent); inprint(expr->alias, num_indent+1);
|
||||
inprint("Alias", num_indent+1); inprint(expr->alias, num_indent+2);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -87,6 +87,12 @@ void printSelectStatementInfo(SelectStatement* stmt, uint num_indent) {
|
|||
printExpression(stmt->where_clause, num_indent+2);
|
||||
}
|
||||
|
||||
|
||||
if (stmt->union_select != NULL) {
|
||||
inprint("Union:", num_indent+1);
|
||||
printSelectStatementInfo(stmt->union_select, num_indent+2);
|
||||
}
|
||||
|
||||
if (stmt->order != NULL) {
|
||||
inprint("OrderBy:", num_indent+1);
|
||||
printExpression(stmt->order->expr, num_indent+2);
|
||||
|
|
|
@ -105,12 +105,12 @@ typedef void* yyscan_t;
|
|||
%token <uval> NOTEQUALS LESSEQ GREATEREQ
|
||||
|
||||
/* SQL Keywords */
|
||||
%token DISTINCT DATABASE NATURAL CONTROL BETWEEN SELECT
|
||||
%token HAVING OFFSET CREATE IMPORT RENAME DELETE INSERT
|
||||
%token UPDATE UNLOAD COLUMN ISNULL WHERE GROUP ORDER LIMIT
|
||||
%token INNER OUTER RIGHT CROSS USING TABLE INDEX ALTER FROM
|
||||
%token DESC JOIN LEFT FILE DROP LOAD INTO NULL LIKE TOP ASC
|
||||
%token CSV TBL NOT AND BY ON AS OR IN IS
|
||||
%token DATABASE DISTINCT BETWEEN CONTROL NATURAL COLUMN
|
||||
%token CREATE DELETE HAVING IMPORT INSERT ISNULL OFFSET
|
||||
%token RENAME SELECT UNLOAD UPDATE ALTER CROSS GROUP INDEX
|
||||
%token INNER LIMIT ORDER OUTER RIGHT TABLE UNION USING WHERE
|
||||
%token DESC DROP FILE FROM INTO JOIN LEFT LIKE LOAD NULL ALL
|
||||
%token AND ASC CSV NOT TBL TOP AS BY IN IS ON OR
|
||||
|
||||
|
||||
/*********************************
|
||||
|
@ -118,7 +118,7 @@ typedef void* yyscan_t;
|
|||
*********************************/
|
||||
%type <stmt_list> statement_list
|
||||
%type <statement> statement
|
||||
%type <select_stmt> select_statement
|
||||
%type <select_stmt> select_statement select_ref select_with_paren select_no_paren select_clause
|
||||
%type <import_stmt> import_statement
|
||||
%type <create_stmt> create_statement
|
||||
%type <sval> table_name opt_alias alias file_path
|
||||
|
@ -126,12 +126,12 @@ typedef void* yyscan_t;
|
|||
%type <table> join_clause join_table
|
||||
%type <expr> expr scalar_expr unary_expr binary_expr function_expr star_expr expr_alias
|
||||
%type <expr> column_name literal int_literal num_literal string_literal
|
||||
%type <expr> comp_expr where_clause join_condition
|
||||
%type <expr_list> expr_list group_clause select_list
|
||||
%type <expr> comp_expr opt_where join_condition
|
||||
%type <expr_list> expr_list opt_group select_list
|
||||
%type <table_list> table_ref_commalist
|
||||
%type <order> order_by_clause
|
||||
%type <limit> limit_clause
|
||||
%type <order_type> order_type
|
||||
%type <order> opt_order
|
||||
%type <limit> opt_limit
|
||||
%type <order_type> opt_order_type
|
||||
%type <uval> import_file_type
|
||||
|
||||
|
||||
|
@ -226,18 +226,42 @@ create_statement:
|
|||
******************************/
|
||||
|
||||
select_statement:
|
||||
SELECT select_list from_clause where_clause group_clause order_by_clause limit_clause
|
||||
{
|
||||
SelectStatement* s = new SelectStatement();
|
||||
s->select_list = $2;
|
||||
s->from_table = $3;
|
||||
s->where_clause = $4;
|
||||
s->group_by = $5;
|
||||
s->order = $6;
|
||||
s->limit = $7;
|
||||
$$ = s;
|
||||
select_with_paren
|
||||
| select_no_paren
|
||||
;
|
||||
|
||||
select_with_paren:
|
||||
'(' select_no_paren ')' { $$ = $2; }
|
||||
| '(' select_with_paren ')' { $$ = $2; }
|
||||
;
|
||||
|
||||
select_no_paren:
|
||||
select_clause opt_order opt_limit {
|
||||
$$ = $1;
|
||||
$$->order = $2;
|
||||
$$->limit = $3;
|
||||
}
|
||||
| select_ref UNION select_ref opt_order opt_limit {
|
||||
$$ = $1;
|
||||
$$->union_select = $3;
|
||||
$$->order = $4;
|
||||
$$->limit = $5;
|
||||
}
|
||||
;
|
||||
|
||||
select_ref:
|
||||
select_clause
|
||||
| select_with_paren
|
||||
;
|
||||
|
||||
select_clause:
|
||||
SELECT select_list from_clause opt_where opt_group {
|
||||
$$ = new SelectStatement();
|
||||
$$->select_list = $2;
|
||||
$$->from_table = $3;
|
||||
$$->where_clause = $4;
|
||||
$$->group_by = $5;
|
||||
}
|
||||
| '(' select_statement ')' { $$ = $2; }
|
||||
;
|
||||
|
||||
|
||||
|
@ -251,31 +275,33 @@ from_clause:
|
|||
;
|
||||
|
||||
|
||||
where_clause:
|
||||
opt_where:
|
||||
WHERE expr { $$ = $2; }
|
||||
| /* empty */ { $$ = NULL; }
|
||||
;
|
||||
|
||||
// TODO: having
|
||||
group_clause:
|
||||
opt_group:
|
||||
GROUP BY expr_list { $$ = $3; }
|
||||
| /* empty */ { $$ = NULL; }
|
||||
;
|
||||
|
||||
|
||||
order_by_clause:
|
||||
ORDER BY expr order_type { $$ = new OrderDescription($4, $3); }
|
||||
opt_order:
|
||||
ORDER BY expr opt_order_type { $$ = new OrderDescription($4, $3); }
|
||||
| /* empty */ { $$ = NULL; }
|
||||
;
|
||||
|
||||
order_type:
|
||||
opt_order_type:
|
||||
ASC { $$ = kOrderAsc; }
|
||||
| DESC { $$ = kOrderDesc; }
|
||||
| /* empty */ { $$ = kOrderAsc; }
|
||||
;
|
||||
|
||||
limit_clause:
|
||||
|
||||
opt_limit:
|
||||
LIMIT int_literal { $$ = new LimitDescription($2->ival, kNoOffset); delete $2; }
|
||||
| LIMIT int_literal OFFSET int_literal { $$ = new LimitDescription($2->ival, $4->ival); delete $2; delete $4; }
|
||||
| /* empty */ { $$ = NULL; }
|
||||
;
|
||||
|
||||
|
|
|
@ -56,57 +56,59 @@
|
|||
[ \t\n]+ /* skip whitespace */;
|
||||
|
||||
|
||||
DISTINCT TOKEN(DISTINCT)
|
||||
DATABASE TOKEN(DATABASE)
|
||||
NATURAL TOKEN(NATURAL)
|
||||
CONTROL TOKEN(CONTROL)
|
||||
DISTINCT TOKEN(DISTINCT)
|
||||
BETWEEN TOKEN(BETWEEN)
|
||||
SELECT TOKEN(SELECT)
|
||||
HAVING TOKEN(HAVING)
|
||||
OFFSET TOKEN(OFFSET)
|
||||
CREATE TOKEN(CREATE)
|
||||
IMPORT TOKEN(IMPORT)
|
||||
RENAME TOKEN(RENAME)
|
||||
DELETE TOKEN(DELETE)
|
||||
INSERT TOKEN(INSERT)
|
||||
UPDATE TOKEN(UPDATE)
|
||||
UNLOAD TOKEN(UNLOAD)
|
||||
CONTROL TOKEN(CONTROL)
|
||||
NATURAL TOKEN(NATURAL)
|
||||
COLUMN TOKEN(COLUMN)
|
||||
CREATE TOKEN(CREATE)
|
||||
DELETE TOKEN(DELETE)
|
||||
HAVING TOKEN(HAVING)
|
||||
IMPORT TOKEN(IMPORT)
|
||||
INSERT TOKEN(INSERT)
|
||||
ISNULL TOKEN(ISNULL)
|
||||
WHERE TOKEN(WHERE)
|
||||
OFFSET TOKEN(OFFSET)
|
||||
RENAME TOKEN(RENAME)
|
||||
SELECT TOKEN(SELECT)
|
||||
UNLOAD TOKEN(UNLOAD)
|
||||
UPDATE TOKEN(UPDATE)
|
||||
ALTER TOKEN(ALTER)
|
||||
CROSS TOKEN(CROSS)
|
||||
GROUP TOKEN(GROUP)
|
||||
ORDER TOKEN(ORDER)
|
||||
LIMIT TOKEN(LIMIT)
|
||||
INDEX TOKEN(INDEX)
|
||||
INNER TOKEN(INNER)
|
||||
LIMIT TOKEN(LIMIT)
|
||||
ORDER TOKEN(ORDER)
|
||||
OUTER TOKEN(OUTER)
|
||||
RIGHT TOKEN(RIGHT)
|
||||
CROSS TOKEN(CROSS)
|
||||
USING TOKEN(USING)
|
||||
TABLE TOKEN(TABLE)
|
||||
INDEX TOKEN(INDEX)
|
||||
ALTER TOKEN(ALTER)
|
||||
FROM TOKEN(FROM)
|
||||
UNION TOKEN(UNION)
|
||||
USING TOKEN(USING)
|
||||
WHERE TOKEN(WHERE)
|
||||
DESC TOKEN(DESC)
|
||||
DROP TOKEN(DROP)
|
||||
FILE TOKEN(FILE)
|
||||
FROM TOKEN(FROM)
|
||||
INTO TOKEN(INTO)
|
||||
JOIN TOKEN(JOIN)
|
||||
LEFT TOKEN(LEFT)
|
||||
FILE TOKEN(FILE)
|
||||
DROP TOKEN(DROP)
|
||||
LOAD TOKEN(LOAD)
|
||||
INTO TOKEN(INTO)
|
||||
NULL TOKEN(NULL)
|
||||
LIKE TOKEN(LIKE)
|
||||
TOP TOKEN(TOP)
|
||||
LOAD TOKEN(LOAD)
|
||||
NULL TOKEN(NULL)
|
||||
ALL TOKEN(ALL)
|
||||
AND TOKEN(AND)
|
||||
ASC TOKEN(ASC)
|
||||
CSV TOKEN(CSV)
|
||||
TBL TOKEN(TBL)
|
||||
NOT TOKEN(NOT)
|
||||
AND TOKEN(AND)
|
||||
BY TOKEN(BY)
|
||||
ON TOKEN(ON)
|
||||
TBL TOKEN(TBL)
|
||||
TOP TOKEN(TOP)
|
||||
AS TOKEN(AS)
|
||||
OR TOKEN(OR)
|
||||
BY TOKEN(BY)
|
||||
IN TOKEN(IN)
|
||||
IS TOKEN(IS)
|
||||
ON TOKEN(ON)
|
||||
OR TOKEN(OR)
|
||||
|
||||
|
||||
"<>" TOKEN(NOTEQUALS)
|
||||
|
|
|
@ -5,7 +5,8 @@ import math
|
|||
with open("sql_keywords.txt", 'r') as fh:
|
||||
keywords = [line.strip() for line in fh.readlines() if not line.strip().startswith("//") and len(line.strip()) > 0]
|
||||
|
||||
keywords = sorted(keywords, key=lambda x: len(x), reverse=True)
|
||||
keywords = sorted(keywords) # Sort by name
|
||||
keywords = sorted(keywords, key=lambda x: len(x), reverse=True) # Sort by length
|
||||
|
||||
#################
|
||||
# Flex
|
||||
|
|
|
@ -14,6 +14,8 @@ DESC
|
|||
LIMIT
|
||||
DISTINCT
|
||||
OFFSET
|
||||
UNION
|
||||
ALL
|
||||
|
||||
// Join clause
|
||||
JOIN
|
||||
|
|
|
@ -5,6 +5,10 @@ SELECT col1 AS myname, col2, 'test' FROM "table", foo AS t WHERE age > 12 AND zi
|
|||
SELECT * from "table" JOIN table2 ON a = b WHERE (b OR NOT a) AND a = 12.5
|
||||
(SELECT a FROM foo WHERE a > 12 OR b > 3 AND c NOT LIKE 's%' LIMIT 10);
|
||||
SELECT t1.a, t1.b, t2.c FROM "table" AS t1 JOIN (SELECT * FROM foo JOIN bar ON foo.id = bar.id) t2 ON t1.a = t2.b WHERE (t1.b OR NOT t1.a) AND t2.c = 12.5
|
||||
SELECT * FROM "table" LIMIT 10 OFFSET 10;
|
||||
SELECT * FROM t1 UNION SELECT * FROM t2 ORDER BY col1;
|
||||
SELECT * FROM t1 UNION (SELECT * FROM t2) ORDER BY col1;
|
||||
SELECT * FROM t1 UNION (SELECT * FROM t2 UNION SELECT * FROM t3) ORDER BY col1;
|
||||
# CREATE statement
|
||||
CREATE TABLE "table" FROM TBL FILE 'students.tbl'
|
||||
# Multiple statements
|
||||
|
|
Loading…
Reference in New Issue