-C Reduce\sthe\ssize\sof\sthe\sparser\stables\sgenerated\sby\sLemon\sby\ssplitting\sthe\nyyRuleInfo\sstructure\sinto\sseparate\syyRuleInfoLhs\sand\syyRuleInfoNRhs\sarrays.
-D 2018-12-03T23:57:27.083
+C Attempt\sto\smake\sthe\sparser\sa\slittle\sfaster\sby\sstoring\sthe\sON\sand\sUSING\nclause\sin\sa\ssingle\sOnUsing\sobject.
+D 2018-12-04T01:18:36.851
F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1
F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea
F Makefile.in a050c8670ea0d7b37b2192306cbb50d392acd9902b84e9b56f3444d006f97a6c
F src/btree.c ba7c7eef4461790f37c309936bfc5d0d6ba9b194b02d3c8ff1fd53b420ea6d3b
F src/btree.h febb2e817be499570b7a2e32a9bbb4b607a9234f6b84bb9ae84916d4806e96f2
F src/btreeInt.h 620ab4c7235f43572cf3ac2ac8723cbdf68073be4d29da24897c7b77dda5fd96
-F src/build.c fce47a9789704e65c63299b01be8153745faee7919f5137d3f29b7c3c0b549bd
+F src/build.c 0bd866f9ac68f823d8a93e3c6464be687960132ac44c9435fd1a5e3b942086f9
F src/callback.c 789bd33d188146f66c0dd8306472a72d1c05f71924b24a91caf6bd45cf9aba73
F src/complete.c a3634ab1e687055cd002e11b8f43eb75c17da23e
F src/ctime.c 109e58d00f62e8e71ee1eb5944ac18b90171c928ab2e082e058056e1137cc20b
F src/os_win.h 7b073010f1451abe501be30d12f6bc599824944a
F src/pager.c 75e0f3cfa3962c714f519f8a3d1e67ecca1c91de0e010a036b988e40ce9e4c73
F src/pager.h 217921e81eb5fe455caa5cda96061959706bcdd29ddb57166198645ef7822ac3
-F src/parse.y 5cf85c2b9dfac38ac4e2bf2776484705186ce2eda8631e65cc0b04bf566c1173
+F src/parse.y c4da3ae9f0482f5916849b58a93d702625376c452bdd4be4bd42798f83ff7e4a
F src/pcache.c 696a01f1a6370c1b50a09c15972bc3bee3333f8fcd1f2da8e9a76b1b062c59ee
F src/pcache.h 4f87acd914cef5016fae3030343540d75f5b85a1877eed1a2a19b9f284248586
F src/pcache1.c ad0ffc5b35b0280d045ac569d34d4b842e3e6a4a118f6396b320987a0957afcc
F src/random.c 80f5d666f23feb3e6665a6ce04c7197212a88384
F src/resolve.c 976e7879286a1eecdc71ceff64f6d1b3f58c8f8096537ba668b3dc0887f410c1
F src/rowset.c d977b011993aaea002cab3e0bb2ce50cf346000dff94e944d547b989f4b1fe93
-F src/select.c 61e867a906f140b73baf4ce7a201ad6dcba30820969f5618ee40e9a0d32c6f5f
+F src/select.c 8a0fb4fd971c0364006f6a69b56aced36a773956483acfcc260e83b49e8c0da5
F src/shell.c.in 482e23a370cbe5b0d4c73a0f0f5fce34f7caa08a14a8d75e12f0225c4e14915c
F src/sqlite.h.in cce9feede1c1c03923c091b4bbbd081dd77aaf92024cc2cdbf65f712c2f668c3
F src/sqlite3.rc 5121c9e10c3964d5755191c80dd1180c122fc3a8
F src/sqlite3ext.h 960f1b86c3610fa23cb6a267572a97dcf286e77aa0dd3b9b23292ffaa1ea8683
-F src/sqliteInt.h 1161f7579cdd6217737a66517ef27f4016426603eff492e9b31f45a7d7d4c61f
+F src/sqliteInt.h 1e26dff5cb1b0805ac2f8e775b1ef5bb8d3f082db30b64eeaf2341263036aae7
F src/sqliteLimit.h 1513bfb7b20378aa0041e7022d04acb73525de35b80b252f1b83fedb4de6a76b
F src/status.c 46e7aec11f79dad50965a5ca5fa9de009f7d6bde08be2156f1538a0a296d4d0e
F src/table.c b46ad567748f24a326d9de40e5b9659f96ffff34
F vsixtest/vsixtest.vcxproj.data 2ed517e100c66dc455b492e1a33350c1b20fbcdc
F vsixtest/vsixtest.vcxproj.filters 37e51ffedcdb064aad6ff33b6148725226cd608e
F vsixtest/vsixtest_TemporaryKey.pfx e5b1b036facdb453873e7084e1cae9102ccc67a0
-P 7149dacf1d440a19f62808b4591c3fa8da202b2ec742d5490a63f2ec005ff9e7
-R 457633af26ab8489c6f274ab3a7ad9fc
+P 70fe8ec2ae3099b8773834c7ac2e56768addbecd57956ac523e71a7dc264049c
+R ba0d657988bc149b80ac7a1558e95ccf
+T *branch * on-using-opt
+T *sym-on-using-opt *
+T -sym-trunk *
U drh
-Z 7836770a12b5a3ad0791dca5d89f1095
+Z c13436380c54aa625889c6261f0708c3
-70fe8ec2ae3099b8773834c7ac2e56768addbecd57956ac523e71a7dc264049c
\ No newline at end of file
+6770ed0873a0f152bae5849c0e596d46173fd480bb8f07cb90d07739ba2cafb5
\ No newline at end of file
Token *pDatabase, /* Name of the database containing pTable */
Token *pAlias, /* The right-hand side of the AS subexpression */
Select *pSubquery, /* A subquery used in place of a table name */
- Expr *pOn, /* The ON clause of a join */
- IdList *pUsing /* The USING clause of a join */
+ const OnUsing *pOnUsing /* The ON or USING clause */
){
struct SrcList_item *pItem;
sqlite3 *db = pParse->db;
- if( !p && (pOn || pUsing) ){
+ assert( pOnUsing!=0 );
+ if( !p && (pOnUsing->pOn || pOnUsing->pUsing) ){
sqlite3ErrorMsg(pParse, "a JOIN clause is required before %s",
- (pOn ? "ON" : "USING")
+ (pOnUsing->pOn ? "ON" : "USING")
);
goto append_from_error;
}
pItem->zAlias = sqlite3NameFromToken(db, pAlias);
}
pItem->pSelect = pSubquery;
- pItem->pOn = pOn;
- pItem->pUsing = pUsing;
+ pItem->pOn = pOnUsing->pOn;
+ pItem->pUsing = pOnUsing->pUsing;
return p;
append_from_error:
assert( p==0 );
- sqlite3ExprDelete(db, pOn);
- sqlite3IdListDelete(db, pUsing);
+ sqlite3ExprDelete(db, pOnUsing->pOn);
+ sqlite3IdListDelete(db, pOnUsing->pUsing);
sqlite3SelectDelete(db, pSubquery);
return 0;
}
Select *pRhs = Z;
Select *pLhs = A;
if( pRhs && pRhs->pPrior ){
+ static const OnUsing nullOnUsing = { 0, 0 };
SrcList *pFrom;
Token x;
x.n = 0;
parserDoubleLinkSelect(pParse, pRhs);
- pFrom = sqlite3SrcListAppendFromTerm(pParse,0,0,0,&x,pRhs,0,0);
+ pFrom = sqlite3SrcListAppendFromTerm(pParse,0,0,0,&x,pRhs,&nullOnUsing);
pRhs = sqlite3SelectNew(pParse,0,pFrom,0,0,0,0,0,0);
}
if( pRhs ){
}
stl_prefix(A) ::= . {A = 0;}
seltablist(A) ::= stl_prefix(A) nm(Y) dbnm(D) as(Z) indexed_opt(I)
- on_opt(N) using_opt(U). {
- A = sqlite3SrcListAppendFromTerm(pParse,A,&Y,&D,&Z,0,N,U);
+ onusing(U). {
+ A = sqlite3SrcListAppendFromTerm(pParse,A,&Y,&D,&Z,0,&U);
sqlite3SrcListIndexedBy(pParse, A, &I);
}
seltablist(A) ::= stl_prefix(A) nm(Y) dbnm(D) LP exprlist(E) RP as(Z)
- on_opt(N) using_opt(U). {
- A = sqlite3SrcListAppendFromTerm(pParse,A,&Y,&D,&Z,0,N,U);
+ onusing(U). {
+ A = sqlite3SrcListAppendFromTerm(pParse,A,&Y,&D,&Z,0,&U);
sqlite3SrcListFuncArgs(pParse, A, E);
}
%ifndef SQLITE_OMIT_SUBQUERY
seltablist(A) ::= stl_prefix(A) LP select(S) RP
- as(Z) on_opt(N) using_opt(U). {
- A = sqlite3SrcListAppendFromTerm(pParse,A,0,0,&Z,S,N,U);
+ as(Z) onusing(U). {
+ A = sqlite3SrcListAppendFromTerm(pParse,A,0,0,&Z,S,&U);
}
seltablist(A) ::= stl_prefix(A) LP seltablist(F) RP
- as(Z) on_opt(N) using_opt(U). {
- if( A==0 && Z.n==0 && N==0 && U==0 ){
+ as(Z) onusing(U). {
+ if( A==0 && Z.n==0 && U.pOn==0 && U.pUsing==0 ){
A = F;
}else if( F->nSrc==1 ){
- A = sqlite3SrcListAppendFromTerm(pParse,A,0,0,&Z,0,N,U);
+ A = sqlite3SrcListAppendFromTerm(pParse,A,0,0,&Z,0,&U);
if( A ){
struct SrcList_item *pNew = &A->a[A->nSrc-1];
struct SrcList_item *pOld = F->a;
Select *pSubquery;
sqlite3SrcListShiftJoinType(F);
pSubquery = sqlite3SelectNew(pParse,0,F,0,0,0,0,SF_NestedFrom,0);
- A = sqlite3SrcListAppendFromTerm(pParse,A,0,0,&Z,pSubquery,N,U);
+ A = sqlite3SrcListAppendFromTerm(pParse,A,0,0,&Z,pSubquery,&U);
}
}
%endif SQLITE_OMIT_SUBQUERY
// The [AND] and [OR] precedence marks in the rules for on_opt cause the
// ON in this context to always be interpreted as belonging to the JOIN.
//
-%type on_opt {Expr*}
-%destructor on_opt {sqlite3ExprDelete(pParse->db, $$);}
-on_opt(N) ::= ON expr(E). {N = E;}
-on_opt(N) ::= . [OR] {N = 0;}
+%type onusing {OnUsing}
+%destructor onusing {
+ sqlite3ExprDelete(pParse->db, $$.pOn);
+ sqlite3IdListDelete(pParse->db, $$.pUsing);
+}
+onusing(A) ::= . [OR] {A.pOn = 0; A.pUsing = 0;}
+onusing(A) ::= ON expr(E). {A.pOn = E; A.pUsing = 0;}
+onusing(A) ::= USING LP idlist(L) RP. {A.pOn = 0; A.pUsing=L;}
// Note that this block abuses the Token type just a little. If there is
// no "INDEXED BY" clause, the returned token is empty (z==0 && n==0). If
indexed_opt(A) ::= INDEXED BY nm(X). {A = X;}
indexed_opt(A) ::= NOT INDEXED. {A.z=0; A.n=1;}
-%type using_opt {IdList*}
-%destructor using_opt {sqlite3IdListDelete(pParse->db, $$);}
-using_opt(U) ::= USING LP idlist(L) RP. {U = L;}
-using_opt(U) ::= . {U = 0;}
-
-
%type orderby_opt {ExprList*}
%destructor orderby_opt {sqlite3ExprListDelete(pParse->db, $$);}
}
}
- /* Disallow both ON and USING clauses in the same join
+ /* Cannot both ON and USING clauses in the same join. The parser
+ ** does not allow this.
*/
- if( pRight->pOn && pRight->pUsing ){
- sqlite3ErrorMsg(pParse, "cannot have both ON and USING "
- "clauses in the same join");
- return 1;
- }
+ assert( pRight->pOn==0 || pRight->pUsing==0 );
/* Add the ON clause to the end of the WHERE clause, connected by
** an AND operator.
SrcList *pNewSrc;
Parse *pParse;
Token dummy;
+ static const OnUsing nullOnUsing = { 0, 0 };
if( p->pPrior==0 ) return WRC_Continue;
if( p->pOrderBy==0 ) return WRC_Continue;
pNew = sqlite3DbMallocZero(db, sizeof(*pNew) );
if( pNew==0 ) return WRC_Abort;
memset(&dummy, 0, sizeof(dummy));
- pNewSrc = sqlite3SrcListAppendFromTerm(pParse,0,0,0,&dummy,pNew,0,0);
+ pNewSrc = sqlite3SrcListAppendFromTerm(pParse,0,0,0,&dummy,pNew,&nullOnUsing);
if( pNewSrc==0 ) return WRC_Abort;
*pNew = *p;
p->pSrc = pNewSrc;
typedef struct LookasideSlot LookasideSlot;
typedef struct Module Module;
typedef struct NameContext NameContext;
+typedef struct OnUsing OnUsing;
typedef struct Parse Parse;
typedef struct PreUpdate PreUpdate;
typedef struct PrintfArguments PrintfArguments;
int nId; /* Number of identifiers on the list */
};
+/*
+** An instance of the following structure records the ON and USING clauses
+** as part of a join.
+**
+** ON expr USING exprlist
+**
+** The parser uses a single instance of this object to hold both elements
+** as a performance optimization - to reduce the number of "reduce" actions
+** required in the parser automaton.
+*/
+struct OnUsing {
+ Expr *pOn;
+ IdList *pUsing;
+};
+
/*
** The following structure describes the FROM clause of a SELECT statement.
** Each table or subquery in the FROM clause is a separate element of
SrcList *sqlite3SrcListEnlarge(sqlite3*, SrcList*, int, int);
SrcList *sqlite3SrcListAppend(sqlite3*, SrcList*, Token*, Token*);
SrcList *sqlite3SrcListAppendFromTerm(Parse*, SrcList*, Token*, Token*,
- Token*, Select*, Expr*, IdList*);
+ Token*, Select*, const OnUsing*);
void sqlite3SrcListIndexedBy(Parse *, SrcList *, Token *);
void sqlite3SrcListFuncArgs(Parse*, SrcList*, ExprList*);
int sqlite3IndexedByLookup(Parse *, struct SrcList_item *);