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"
|
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 "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"
|
echo "\n\n"
|
||||||
|
|
||||||
|
|
|
@ -19,7 +19,11 @@ typedef enum {
|
||||||
* @struct CreateStatement
|
* @struct CreateStatement
|
||||||
*/
|
*/
|
||||||
struct CreateStatement : Statement {
|
struct CreateStatement : Statement {
|
||||||
CreateStatement() : Statement(kStmtCreate) {};
|
CreateStatement() :
|
||||||
|
Statement(kStmtCreate),
|
||||||
|
file_path(NULL),
|
||||||
|
table_name(NULL) {};
|
||||||
|
|
||||||
virtual ~CreateStatement(); // defined in destructors.cpp
|
virtual ~CreateStatement(); // defined in destructors.cpp
|
||||||
|
|
||||||
CreateType create_type;
|
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:
|
// Interesting side-effect:
|
||||||
// Making the destructor virtual causes segmentation faults
|
// Making the destructor virtual causes segmentation faults
|
||||||
|
|
|
@ -19,7 +19,11 @@ typedef enum {
|
||||||
* @struct ImportStatement
|
* @struct ImportStatement
|
||||||
*/
|
*/
|
||||||
struct ImportStatement : Statement {
|
struct ImportStatement : Statement {
|
||||||
ImportStatement() : Statement(kStmtImport) {};
|
ImportStatement() :
|
||||||
|
Statement(kStmtImport),
|
||||||
|
file_path(NULL),
|
||||||
|
table_name(NULL) {};
|
||||||
|
|
||||||
virtual ~ImportStatement(); // defined in destructors.cpp
|
virtual ~ImportStatement(); // defined in destructors.cpp
|
||||||
|
|
||||||
ImportFileType file_type;
|
ImportFileType file_type;
|
||||||
|
|
|
@ -20,7 +20,10 @@ typedef enum {
|
||||||
} OrderType;
|
} OrderType;
|
||||||
|
|
||||||
struct OrderDescription {
|
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
|
virtual ~OrderDescription(); // defined in destructors.cpp
|
||||||
|
|
||||||
OrderType type;
|
OrderType type;
|
||||||
|
@ -34,7 +37,10 @@ struct OrderDescription {
|
||||||
const int64_t kNoLimit = -1;
|
const int64_t kNoLimit = -1;
|
||||||
const int64_t kNoOffset = -1;
|
const int64_t kNoOffset = -1;
|
||||||
struct LimitDescription {
|
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 limit;
|
||||||
int64_t offset;
|
int64_t offset;
|
||||||
};
|
};
|
||||||
|
@ -44,15 +50,24 @@ struct LimitDescription {
|
||||||
* Representation of a full select statement.
|
* Representation of a full select statement.
|
||||||
*/
|
*/
|
||||||
struct SelectStatement : 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
|
virtual ~SelectStatement(); // defined in destructors.cpp
|
||||||
|
|
||||||
TableRef* from_table;
|
TableRef* from_table;
|
||||||
List<Expr*>* select_list;
|
List<Expr*>* select_list;
|
||||||
Expr* where_clause;
|
Expr* where_clause;
|
||||||
|
|
||||||
List<Expr*>* group_by;
|
List<Expr*>* group_by;
|
||||||
|
|
||||||
|
SelectStatement* union_select;
|
||||||
OrderDescription* order;
|
OrderDescription* order;
|
||||||
LimitDescription* limit;
|
LimitDescription* limit;
|
||||||
};
|
};
|
||||||
|
|
|
@ -11,7 +11,7 @@ namespace hsql {
|
||||||
|
|
||||||
|
|
||||||
typedef enum {
|
typedef enum {
|
||||||
kStmtError,
|
kStmtError, // Unused
|
||||||
kStmtSelect,
|
kStmtSelect,
|
||||||
kStmtImport,
|
kStmtImport,
|
||||||
// Following types are planned but not supported yet
|
// Following types are planned but not supported yet
|
||||||
|
@ -26,7 +26,9 @@ typedef enum {
|
||||||
|
|
||||||
|
|
||||||
struct Statement {
|
struct Statement {
|
||||||
Statement(StatementType type) : type(type) {};
|
Statement(StatementType type) :
|
||||||
|
type(type) {};
|
||||||
|
|
||||||
virtual ~Statement(); // defined in destructors.cpp
|
virtual ~Statement(); // defined in destructors.cpp
|
||||||
|
|
||||||
StatementType type;
|
StatementType type;
|
||||||
|
@ -35,8 +37,16 @@ struct Statement {
|
||||||
|
|
||||||
class StatementList : public List<Statement*> {
|
class StatementList : public List<Statement*> {
|
||||||
public:
|
public:
|
||||||
StatementList() : List<Statement*>(), isValid(true) {};
|
StatementList() :
|
||||||
StatementList(Statement* stmt) : List<Statement*>(stmt), isValid(true) {};
|
List<Statement*>(),
|
||||||
|
isValid(true),
|
||||||
|
parser_msg(NULL) {};
|
||||||
|
|
||||||
|
StatementList(Statement* stmt) :
|
||||||
|
List<Statement*>(stmt),
|
||||||
|
isValid(true),
|
||||||
|
parser_msg(NULL) {};
|
||||||
|
|
||||||
virtual ~StatementList(); // defined in destructors.cpp
|
virtual ~StatementList(); // defined in destructors.cpp
|
||||||
|
|
||||||
bool isValid;
|
bool isValid;
|
||||||
|
|
|
@ -29,7 +29,16 @@ typedef enum {
|
||||||
typedef struct TableRef TableRef;
|
typedef struct TableRef TableRef;
|
||||||
|
|
||||||
struct 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
|
virtual ~TableRef(); // defined in destructors.cpp
|
||||||
|
|
||||||
TableRefType type;
|
TableRefType type;
|
||||||
|
|
|
@ -70,7 +70,7 @@ void printExpression(Expr* expr, uint num_indent) {
|
||||||
default: fprintf(stderr, "Unrecognized expression type %d\n", expr->type); return;
|
default: fprintf(stderr, "Unrecognized expression type %d\n", expr->type); return;
|
||||||
}
|
}
|
||||||
if (expr->alias != NULL) {
|
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);
|
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) {
|
if (stmt->order != NULL) {
|
||||||
inprint("OrderBy:", num_indent+1);
|
inprint("OrderBy:", num_indent+1);
|
||||||
printExpression(stmt->order->expr, num_indent+2);
|
printExpression(stmt->order->expr, num_indent+2);
|
||||||
|
|
|
@ -105,12 +105,12 @@ typedef void* yyscan_t;
|
||||||
%token <uval> NOTEQUALS LESSEQ GREATEREQ
|
%token <uval> NOTEQUALS LESSEQ GREATEREQ
|
||||||
|
|
||||||
/* SQL Keywords */
|
/* SQL Keywords */
|
||||||
%token DISTINCT DATABASE NATURAL CONTROL BETWEEN SELECT
|
%token DATABASE DISTINCT BETWEEN CONTROL NATURAL COLUMN
|
||||||
%token HAVING OFFSET CREATE IMPORT RENAME DELETE INSERT
|
%token CREATE DELETE HAVING IMPORT INSERT ISNULL OFFSET
|
||||||
%token UPDATE UNLOAD COLUMN ISNULL WHERE GROUP ORDER LIMIT
|
%token RENAME SELECT UNLOAD UPDATE ALTER CROSS GROUP INDEX
|
||||||
%token INNER OUTER RIGHT CROSS USING TABLE INDEX ALTER FROM
|
%token INNER LIMIT ORDER OUTER RIGHT TABLE UNION USING WHERE
|
||||||
%token DESC JOIN LEFT FILE DROP LOAD INTO NULL LIKE TOP ASC
|
%token DESC DROP FILE FROM INTO JOIN LEFT LIKE LOAD NULL ALL
|
||||||
%token CSV TBL NOT AND BY ON AS OR IN IS
|
%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 <stmt_list> statement_list
|
||||||
%type <statement> statement
|
%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 <import_stmt> import_statement
|
||||||
%type <create_stmt> create_statement
|
%type <create_stmt> create_statement
|
||||||
%type <sval> table_name opt_alias alias file_path
|
%type <sval> table_name opt_alias alias file_path
|
||||||
|
@ -126,12 +126,12 @@ typedef void* yyscan_t;
|
||||||
%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 expr_alias
|
%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> column_name literal int_literal num_literal string_literal
|
||||||
%type <expr> comp_expr where_clause join_condition
|
%type <expr> comp_expr opt_where join_condition
|
||||||
%type <expr_list> expr_list group_clause select_list
|
%type <expr_list> expr_list opt_group select_list
|
||||||
%type <table_list> table_ref_commalist
|
%type <table_list> table_ref_commalist
|
||||||
%type <order> order_by_clause
|
%type <order> opt_order
|
||||||
%type <limit> limit_clause
|
%type <limit> opt_limit
|
||||||
%type <order_type> order_type
|
%type <order_type> opt_order_type
|
||||||
%type <uval> import_file_type
|
%type <uval> import_file_type
|
||||||
|
|
||||||
|
|
||||||
|
@ -226,18 +226,42 @@ create_statement:
|
||||||
******************************/
|
******************************/
|
||||||
|
|
||||||
select_statement:
|
select_statement:
|
||||||
SELECT select_list from_clause where_clause group_clause order_by_clause limit_clause
|
select_with_paren
|
||||||
{
|
| select_no_paren
|
||||||
SelectStatement* s = new SelectStatement();
|
;
|
||||||
s->select_list = $2;
|
|
||||||
s->from_table = $3;
|
select_with_paren:
|
||||||
s->where_clause = $4;
|
'(' select_no_paren ')' { $$ = $2; }
|
||||||
s->group_by = $5;
|
| '(' select_with_paren ')' { $$ = $2; }
|
||||||
s->order = $6;
|
;
|
||||||
s->limit = $7;
|
|
||||||
$$ = s;
|
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; }
|
WHERE expr { $$ = $2; }
|
||||||
| /* empty */ { $$ = NULL; }
|
| /* empty */ { $$ = NULL; }
|
||||||
;
|
;
|
||||||
|
|
||||||
// TODO: having
|
// TODO: having
|
||||||
group_clause:
|
opt_group:
|
||||||
GROUP BY expr_list { $$ = $3; }
|
GROUP BY expr_list { $$ = $3; }
|
||||||
| /* empty */ { $$ = NULL; }
|
| /* empty */ { $$ = NULL; }
|
||||||
;
|
;
|
||||||
|
|
||||||
|
|
||||||
order_by_clause:
|
opt_order:
|
||||||
ORDER BY expr order_type { $$ = new OrderDescription($4, $3); }
|
ORDER BY expr opt_order_type { $$ = new OrderDescription($4, $3); }
|
||||||
| /* empty */ { $$ = NULL; }
|
| /* empty */ { $$ = NULL; }
|
||||||
;
|
;
|
||||||
|
|
||||||
order_type:
|
opt_order_type:
|
||||||
ASC { $$ = kOrderAsc; }
|
ASC { $$ = kOrderAsc; }
|
||||||
| DESC { $$ = kOrderDesc; }
|
| DESC { $$ = kOrderDesc; }
|
||||||
| /* empty */ { $$ = kOrderAsc; }
|
| /* empty */ { $$ = kOrderAsc; }
|
||||||
;
|
;
|
||||||
|
|
||||||
limit_clause:
|
|
||||||
|
opt_limit:
|
||||||
LIMIT int_literal { $$ = new LimitDescription($2->ival, kNoOffset); delete $2; }
|
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; }
|
| /* empty */ { $$ = NULL; }
|
||||||
;
|
;
|
||||||
|
|
||||||
|
|
|
@ -56,57 +56,59 @@
|
||||||
[ \t\n]+ /* skip whitespace */;
|
[ \t\n]+ /* skip whitespace */;
|
||||||
|
|
||||||
|
|
||||||
DISTINCT TOKEN(DISTINCT)
|
|
||||||
DATABASE TOKEN(DATABASE)
|
DATABASE TOKEN(DATABASE)
|
||||||
NATURAL TOKEN(NATURAL)
|
DISTINCT TOKEN(DISTINCT)
|
||||||
CONTROL TOKEN(CONTROL)
|
|
||||||
BETWEEN TOKEN(BETWEEN)
|
BETWEEN TOKEN(BETWEEN)
|
||||||
SELECT TOKEN(SELECT)
|
CONTROL TOKEN(CONTROL)
|
||||||
HAVING TOKEN(HAVING)
|
NATURAL TOKEN(NATURAL)
|
||||||
OFFSET TOKEN(OFFSET)
|
|
||||||
CREATE TOKEN(CREATE)
|
|
||||||
IMPORT TOKEN(IMPORT)
|
|
||||||
RENAME TOKEN(RENAME)
|
|
||||||
DELETE TOKEN(DELETE)
|
|
||||||
INSERT TOKEN(INSERT)
|
|
||||||
UPDATE TOKEN(UPDATE)
|
|
||||||
UNLOAD TOKEN(UNLOAD)
|
|
||||||
COLUMN TOKEN(COLUMN)
|
COLUMN TOKEN(COLUMN)
|
||||||
|
CREATE TOKEN(CREATE)
|
||||||
|
DELETE TOKEN(DELETE)
|
||||||
|
HAVING TOKEN(HAVING)
|
||||||
|
IMPORT TOKEN(IMPORT)
|
||||||
|
INSERT TOKEN(INSERT)
|
||||||
ISNULL TOKEN(ISNULL)
|
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)
|
GROUP TOKEN(GROUP)
|
||||||
ORDER TOKEN(ORDER)
|
INDEX TOKEN(INDEX)
|
||||||
LIMIT TOKEN(LIMIT)
|
|
||||||
INNER TOKEN(INNER)
|
INNER TOKEN(INNER)
|
||||||
|
LIMIT TOKEN(LIMIT)
|
||||||
|
ORDER TOKEN(ORDER)
|
||||||
OUTER TOKEN(OUTER)
|
OUTER TOKEN(OUTER)
|
||||||
RIGHT TOKEN(RIGHT)
|
RIGHT TOKEN(RIGHT)
|
||||||
CROSS TOKEN(CROSS)
|
|
||||||
USING TOKEN(USING)
|
|
||||||
TABLE TOKEN(TABLE)
|
TABLE TOKEN(TABLE)
|
||||||
INDEX TOKEN(INDEX)
|
UNION TOKEN(UNION)
|
||||||
ALTER TOKEN(ALTER)
|
USING TOKEN(USING)
|
||||||
FROM TOKEN(FROM)
|
WHERE TOKEN(WHERE)
|
||||||
DESC TOKEN(DESC)
|
DESC TOKEN(DESC)
|
||||||
|
DROP TOKEN(DROP)
|
||||||
|
FILE TOKEN(FILE)
|
||||||
|
FROM TOKEN(FROM)
|
||||||
|
INTO TOKEN(INTO)
|
||||||
JOIN TOKEN(JOIN)
|
JOIN TOKEN(JOIN)
|
||||||
LEFT TOKEN(LEFT)
|
LEFT TOKEN(LEFT)
|
||||||
FILE TOKEN(FILE)
|
|
||||||
DROP TOKEN(DROP)
|
|
||||||
LOAD TOKEN(LOAD)
|
|
||||||
INTO TOKEN(INTO)
|
|
||||||
NULL TOKEN(NULL)
|
|
||||||
LIKE TOKEN(LIKE)
|
LIKE TOKEN(LIKE)
|
||||||
TOP TOKEN(TOP)
|
LOAD TOKEN(LOAD)
|
||||||
|
NULL TOKEN(NULL)
|
||||||
|
ALL TOKEN(ALL)
|
||||||
|
AND TOKEN(AND)
|
||||||
ASC TOKEN(ASC)
|
ASC TOKEN(ASC)
|
||||||
CSV TOKEN(CSV)
|
CSV TOKEN(CSV)
|
||||||
TBL TOKEN(TBL)
|
|
||||||
NOT TOKEN(NOT)
|
NOT TOKEN(NOT)
|
||||||
AND TOKEN(AND)
|
TBL TOKEN(TBL)
|
||||||
BY TOKEN(BY)
|
TOP TOKEN(TOP)
|
||||||
ON TOKEN(ON)
|
|
||||||
AS TOKEN(AS)
|
AS TOKEN(AS)
|
||||||
OR TOKEN(OR)
|
BY TOKEN(BY)
|
||||||
IN TOKEN(IN)
|
IN TOKEN(IN)
|
||||||
IS TOKEN(IS)
|
IS TOKEN(IS)
|
||||||
|
ON TOKEN(ON)
|
||||||
|
OR TOKEN(OR)
|
||||||
|
|
||||||
|
|
||||||
"<>" TOKEN(NOTEQUALS)
|
"<>" TOKEN(NOTEQUALS)
|
||||||
|
|
|
@ -5,7 +5,8 @@ import math
|
||||||
with open("sql_keywords.txt", 'r') as fh:
|
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 = [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
|
# Flex
|
||||||
|
|
|
@ -14,6 +14,8 @@ DESC
|
||||||
LIMIT
|
LIMIT
|
||||||
DISTINCT
|
DISTINCT
|
||||||
OFFSET
|
OFFSET
|
||||||
|
UNION
|
||||||
|
ALL
|
||||||
|
|
||||||
// Join clause
|
// Join clause
|
||||||
JOIN
|
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 * 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 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 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 statement
|
||||||
CREATE TABLE "table" FROM TBL FILE 'students.tbl'
|
CREATE TABLE "table" FROM TBL FILE 'students.tbl'
|
||||||
# Multiple statements
|
# Multiple statements
|
||||||
|
|
Loading…
Reference in New Issue