summaryrefslogtreecommitdiff
path: root/ext/sqlite/libsqlite/src/parse.y
diff options
context:
space:
mode:
Diffstat (limited to 'ext/sqlite/libsqlite/src/parse.y')
-rw-r--r--ext/sqlite/libsqlite/src/parse.y78
1 files changed, 54 insertions, 24 deletions
diff --git a/ext/sqlite/libsqlite/src/parse.y b/ext/sqlite/libsqlite/src/parse.y
index 3aee9f0c95..cc236a5df8 100644
--- a/ext/sqlite/libsqlite/src/parse.y
+++ b/ext/sqlite/libsqlite/src/parse.y
@@ -23,13 +23,11 @@
%syntax_error {
if( pParse->zErrMsg==0 ){
if( TOKEN.z[0] ){
- sqliteSetNString(&pParse->zErrMsg,
- "near \"", -1, TOKEN.z, TOKEN.n, "\": syntax error", -1, 0);
+ sqliteErrorMsg(pParse, "near \"%T\": syntax error", &TOKEN);
}else{
- sqliteSetString(&pParse->zErrMsg, "incomplete SQL statement", (char*)0);
+ sqliteErrorMsg(pParse, "incomplete SQL statement");
}
}
- pParse->nErr++;
}
%name sqliteParser
%include {
@@ -65,13 +63,10 @@ struct TrigEvent { int a; IdList * b; };
%nonassoc END_OF_FILE ILLEGAL SPACE UNCLOSED_STRING COMMENT FUNCTION
COLUMN AGG_FUNCTION.
-// Input is zero or more commands.
+// Input is a single SQL command
input ::= cmdlist.
-
-// A list of commands is zero or more commands
-//
-cmdlist ::= ecmd.
cmdlist ::= cmdlist ecmd.
+cmdlist ::= ecmd.
ecmd ::= explain cmdx SEMI.
ecmd ::= SEMI.
cmdx ::= cmd. { sqliteExec(pParse); }
@@ -132,6 +127,22 @@ id(A) ::= ID(X). {A = X;}
OF OFFSET PRAGMA RAISE REPLACE RESTRICT ROW STATEMENT
TEMP TRIGGER VACUUM VIEW.
+// Define operator precedence early so that this is the first occurance
+// of the operator tokens in the grammer. Keeping the operators together
+// causes them to be assigned integer values that are close together,
+// which keeps parser tables smaller.
+//
+%left OR.
+%left AND.
+%right NOT.
+%left EQ NE ISNULL NOTNULL IS LIKE GLOB BETWEEN IN.
+%left GT GE LT LE.
+%left BITAND BITOR LSHIFT RSHIFT.
+%left PLUS MINUS.
+%left STAR SLASH REM.
+%left CONCAT.
+%right UMINUS UPLUS BITNOT.
+
// And "ids" is an identifer-or-string.
//
%type ids {Token}
@@ -366,7 +377,8 @@ seltablist(A) ::= stl_prefix(X) nm(Y) dbnm(D) as(Z) on_opt(N) using_opt(U). {
else { sqliteIdListDelete(U); }
}
}
-seltablist(A) ::= stl_prefix(X) LP select(S) RP as(Z) on_opt(N) using_opt(U). {
+seltablist(A) ::= stl_prefix(X) LP seltablist_paren(S) RP
+ as(Z) on_opt(N) using_opt(U). {
A = sqliteSrcListAppend(X,0,0);
A->a[A->nSrc-1].pSelect = S;
if( Z.n ) sqliteSrcListAddAlias(A,&Z);
@@ -380,6 +392,17 @@ seltablist(A) ::= stl_prefix(X) LP select(S) RP as(Z) on_opt(N) using_opt(U). {
}
}
+// A seltablist_paren nonterminal represents anything in a FROM that
+// is contained inside parentheses. This can be either a subquery or
+// a grouping of table and subqueries.
+//
+%type seltablist_paren {Select*}
+%destructor seltablist_paren {sqliteSelectDelete($$);}
+seltablist_paren(A) ::= select(S). {A = S;}
+seltablist_paren(A) ::= seltablist(F). {
+ A = sqliteSelectNew(0,F,0,0,0,0,0,-1,0);
+}
+
%type dbnm {Token}
dbnm(A) ::= . {A.z=0; A.n=0;}
dbnm(A) ::= DOT nm(X). {A = X;}
@@ -505,16 +528,6 @@ inscollist(A) ::= nm(Y). {A = sqliteIdListAppend(0,&Y);}
/////////////////////////// Expression Processing /////////////////////////////
//
-%left OR.
-%left AND.
-%right NOT.
-%left EQ NE ISNULL NOTNULL IS LIKE GLOB BETWEEN IN.
-%left GT GE LT LE.
-%left BITAND BITOR LSHIFT RSHIFT.
-%left PLUS MINUS.
-%left STAR SLASH REM.
-%left CONCAT.
-%right UMINUS UPLUS BITNOT.
%type expr {Expr*}
%destructor expr {sqliteExprDelete($$);}
@@ -664,6 +677,20 @@ expr(A) ::= expr(X) NOT IN LP select(Y) RP(E). {
A = sqliteExpr(TK_NOT, A, 0, 0);
sqliteExprSpan(A,&X->span,&E);
}
+expr(A) ::= expr(X) IN nm(Y) dbnm(D). {
+ SrcList *pSrc = sqliteSrcListAppend(0, &Y, &D);
+ A = sqliteExpr(TK_IN, X, 0, 0);
+ if( A ) A->pSelect = sqliteSelectNew(0,pSrc,0,0,0,0,0,-1,0);
+ sqliteExprSpan(A,&X->span,D.z?&D:&Y);
+}
+expr(A) ::= expr(X) NOT IN nm(Y) dbnm(D). {
+ SrcList *pSrc = sqliteSrcListAppend(0, &Y, &D);
+ A = sqliteExpr(TK_IN, X, 0, 0);
+ if( A ) A->pSelect = sqliteSelectNew(0,pSrc,0,0,0,0,0,-1,0);
+ A = sqliteExpr(TK_NOT, A, 0, 0);
+ sqliteExprSpan(A,&X->span,D.z?&D:&Y);
+}
+
/* CASE expressions */
expr(A) ::= CASE(C) case_operand(X) case_exprlist(Y) case_else(Z) END(E). {
@@ -812,11 +839,11 @@ trigger_cmd(A) ::= UPDATE orconf(R) nm(X) SET setlist(Y) where_opt(Z).
{ A = sqliteTriggerUpdateStep(&X, Y, Z, R); }
// INSERT
-trigger_cmd(A) ::= INSERT orconf(R) INTO nm(X) inscollist_opt(F)
+trigger_cmd(A) ::= insert_cmd(R) INTO nm(X) inscollist_opt(F)
VALUES LP itemlist(Y) RP.
{A = sqliteTriggerInsertStep(&X, F, Y, 0, R);}
-trigger_cmd(A) ::= INSERT orconf(R) INTO nm(X) inscollist_opt(F) select(S).
+trigger_cmd(A) ::= insert_cmd(R) INTO nm(X) inscollist_opt(F) select(S).
{A = sqliteTriggerInsertStep(&X, F, 0, S, R);}
// DELETE
@@ -854,9 +881,12 @@ cmd ::= DROP TRIGGER nm(X) dbnm(D). {
}
//////////////////////// ATTACH DATABASE file AS name /////////////////////////
-cmd ::= ATTACH database_kw_opt ids(F) AS nm(D). {
- sqliteAttach(pParse, &F, &D);
+cmd ::= ATTACH database_kw_opt ids(F) AS nm(D) key_opt(K). {
+ sqliteAttach(pParse, &F, &D, &K);
}
+%type key_opt {Token}
+key_opt(A) ::= USING ids(X). { A = X; }
+key_opt(A) ::= . { A.z = 0; A.n = 0; }
database_kw_opt ::= DATABASE.
database_kw_opt ::= .