From: drh Date: Sat, 10 Jun 2006 13:29:31 +0000 (+0000) Subject: Basic parsing of CREATE VIRTUAL TABLE statements. (CVS 3210) X-Git-Tag: version-3.6.10~2957 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=e09daa90ac013c75806e582d7a073bf4d98783c2;p=thirdparty%2Fsqlite.git Basic parsing of CREATE VIRTUAL TABLE statements. (CVS 3210) FossilOrigin-Name: 66370cb99bd93abb33e1e8433672da45e1795f78 --- diff --git a/manifest b/manifest index fd6933a15e..d87618f2c1 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C In\sthe\sshell,\smake\ssure\sthe\sdatabase\sis\sopened\sbefore\strying\sto\sdo\nan\s".import".\s\sBug\sreported\son\sthe\smailing\slist.\s(CVS\s3209) -D 2006-06-08T16:10:15 +C Basic\sparsing\sof\sCREATE\sVIRTUAL\sTABLE\sstatements.\s(CVS\s3210) +D 2006-06-10T13:29:32 F Makefile.in 50d948a8c4eda30ebb5799b661bd4c2de11824d0 F Makefile.linux-gcc 74ba0eadf88748a9ce3fd03d2a3ede2e6715baec F README 9c4e2d6706bdcc3efdd773ce752a8cdab4f90028 @@ -36,7 +36,7 @@ F src/attach.c 27a31d3b89d7ebb5b358847607b1ec795384123c F src/auth.c 9ae84d2d94eb96195e04515715e08e85963e96c2 F src/btree.c ed343b3dbcbc7da9ac481ef2b98c4239fe6d9629 F src/btree.h 40055cfc09defd1146bc5b922399c035f969e56d -F src/build.c eefefdc88cb342bc0f7cb41ccdf3930739ab50e9 +F src/build.c a64e4765ca1148e191742af306db5b70d821d0c9 F src/callback.c fd9bb39f7ff6b52bad8365617abc61c720640429 F src/complete.c 7d1a44be8f37de125fcafd3d3a018690b3799675 F src/date.c cd2bd5d1ebc6fa12d6312f69789ae5b0a2766f2e @@ -64,7 +64,7 @@ F src/os_win.c c6976ae50b61fb5b7dce399e578aa1865f02b84f F src/os_win.h 41a946bea10f61c158ce8645e7646b29d44f122b F src/pager.c ddd05666bb89808a516baef2c186d6a75887ae90 F src/pager.h 43f32f3847421f7502cfbb66f4eb2302b8033818 -F src/parse.y 50ab45ec8e01a90cb5d75f53ce4bf95f0ca10481 +F src/parse.y 79c324627c8145d307a80a13fb18be1d1d63dff8 F src/pragma.c 27d5e395c5d950931c7ac4fe610e7c2993e2fa55 F src/prepare.c bbf12d3147116b284b157232efaef3bbe5df08fc F src/printf.c 7029e5f7344a478394a02c52837ff296ee1ab240 @@ -72,9 +72,9 @@ F src/random.c d40f8d356cecbd351ccfab6eaedd7ec1b54f5261 F src/select.c 8daba07a04a6d41f5267ea8353324cbe5a210e14 F src/server.c 087b92a39d883e3fa113cae259d64e4c7438bc96 F src/shell.c b9eb3ed4d3ab41fbf630eabb602f3c9d20fc737a -F src/sqlite.h.in d33c4688ba292af5f84fea49b2e3946b9129673a +F src/sqlite.h.in fadc690a16e8da1215d3f4bdf6a2501e41516c25 F src/sqlite3ext.h 127bd394c8eea481f2ac9b754bf399dbfc818b75 -F src/sqliteInt.h 029ae294180139e3ead077b548dd9e08f99010aa +F src/sqliteInt.h c1c752970e90570750be529d9d22111211614381 F src/table.c f64ec4fbfe333f8df925bc6ba494f55e05b0e75e F src/tclsqlite.c 5ae9f08f7af7fe80d38fbccc4f5359f272643af1 F src/test1.c becd9202b733debc607b5aec43002769730e1f71 @@ -289,12 +289,12 @@ F test/where.test ee7c9a6659b07e1ee61177f6e7ff71565ee2c9df F test/where2.test a16476a5913e75cf65b38f2daa6157a6b7791394 F test/where3.test 3b5ad2c58069e12be2bd86bc5e211a82810521aa F tool/diffdb.c 7524b1b5df217c20cd0431f6789851a4e0cb191b -F tool/lemon.c b0b881c172b5375444ef1c13d80ab01efec3605e -F tool/lempar.c 5112eda4ad6dc8694b6a68004542da174b436ad9 +F tool/lemon.c 64aa2436ef7fcc1a6dc49bf205225a542fc05c48 +F tool/lempar.c 880cc102baa30c521498b15f6de34dc4b2d56972 F tool/memleak.awk 4e7690a51bf3ed757e611273d43fe3f65b510133 F tool/memleak2.awk 9cc20c8e8f3c675efac71ea0721ee6874a1566e8 F tool/memleak3.tcl 7707006ee908cffff210c98158788d85bb3fcdbf -F tool/mkkeywordhash.c a36f0f5e0168e8f37d0771fb4331f5f462326940 +F tool/mkkeywordhash.c 966af86ab29e2d152eebd40dfd9c8f45b3f0716b F tool/mkopts.tcl 66ac10d240cc6e86abd37dc908d50382f84ff46e x F tool/omittest.tcl 3d07c8f67e7e6c369b07d31d97aaa3e434f0e9e7 F tool/opcodeDoc.awk b3a2a3d5d3075b8bd90b7afe24283efdd586659c @@ -360,7 +360,7 @@ F www/tclsqlite.tcl bb0d1357328a42b1993d78573e587c6dcbc964b9 F www/vdbe.tcl 87a31ace769f20d3627a64fa1fade7fed47b90d0 F www/version3.tcl 890248cf7b70e60c383b0e84d77d5132b3ead42b F www/whentouse.tcl 97e2b5cd296f7d8057e11f44427dea8a4c2db513 -P 327e6909c9d35b651ab6f3a1a270022b354538c6 -R 021001a8617a3717aaf8a0dc8bd5a726 +P 39e3427813135601a7417c96e55b410fa89ac1f5 +R ca50c82454da9812f6118b6e9d547ee0 U drh -Z b4d12d966b938862d92a3ccf0d06a9d1 +Z 20f490cb0723888395733c25c97f6fa4 diff --git a/manifest.uuid b/manifest.uuid index 66d4fd9192..cd1dbfe70c 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -39e3427813135601a7417c96e55b410fa89ac1f5 \ No newline at end of file +66370cb99bd93abb33e1e8433672da45e1795f78 \ No newline at end of file diff --git a/src/build.c b/src/build.c index 343c87525d..74cf00accc 100644 --- a/src/build.c +++ b/src/build.c @@ -22,7 +22,7 @@ ** COMMIT ** ROLLBACK ** -** $Id: build.c,v 1.394 2006/05/11 23:14:59 drh Exp $ +** $Id: build.c,v 1.395 2006/06/10 13:29:32 drh Exp $ */ #include "sqliteInt.h" #include @@ -533,6 +533,12 @@ void sqlite3DeleteTable(sqlite3 *db, Table *pTable){ #ifndef SQLITE_OMIT_CHECK sqlite3ExprDelete(pTable->pCheck); #endif +#ifndef SQLITE_OMIT_MODULE + sqliteFree(pTable->zModuleName); + if( pTable->pMod && pTable->pVTab ){ + pTable->pMod->xDisconnect(pTable->pVTab); + } +#endif SQLITE_OMIT_MODULE sqliteFree(pTable); } diff --git a/src/parse.y b/src/parse.y index dd25152777..922d4730b8 100644 --- a/src/parse.y +++ b/src/parse.y @@ -14,7 +14,7 @@ ** the parser. Lemon will also generate a header file containing ** numeric codes for all of the tokens. ** -** @(#) $Id: parse.y,v 1.200 2006/05/25 12:17:31 drh Exp $ +** @(#) $Id: parse.y,v 1.201 2006/06/10 13:29:33 drh Exp $ */ // All token codes are small integers with #defines that begin with "TK_" @@ -176,12 +176,13 @@ id(A) ::= ID(X). {A = X;} DATABASE DEFERRED DESC DETACH EACH END EXCLUSIVE EXPLAIN FAIL FOR IGNORE IMMEDIATE INITIALLY INSTEAD LIKE_KW MATCH PLAN QUERY KEY OF OFFSET PRAGMA RAISE REPLACE RESTRICT ROW STATEMENT - TEMP TRIGGER VACUUM VIEW + TEMP TRIGGER VACUUM VIEW VIRTUAL %ifdef SQLITE_OMIT_COMPOUND_SELECT EXCEPT INTERSECT UNION %endif REINDEX RENAME CTIME_KW IF . +%wildcard ANY. // Define operator precedence early so that this is the first occurance // of the operator tokens in the grammer. Keeping the operators together @@ -1058,3 +1059,14 @@ add_column_fullname ::= fullname(X). { kwcolumn_opt ::= . kwcolumn_opt ::= COLUMNKW. %endif + +//////////////////////// CREATE VIRTUAL TABLE ... ///////////////////////////// +%ifndef SQLITE_OMIT_VIRTUALTABLE +cmd ::= CREATE VIRTUAL TABLE nm(X) dbnm(Y) USING nm(Z) vtabargsopt. +vtabargsopt ::= . +vtabargsopt ::= LP vtabarglist RP. +vtabarglist ::= vtabarg. +vtabarglist ::= vtabarglist COMMA vtabarg. +vtabarg ::= ANY. +vtabarg ::= vtabarg ANY. +%endif diff --git a/src/sqlite.h.in b/src/sqlite.h.in index 375e694d12..6a25f67cc5 100644 --- a/src/sqlite.h.in +++ b/src/sqlite.h.in @@ -12,7 +12,7 @@ ** This header file defines the interface that the SQLite library ** presents to client programs. ** -** @(#) $Id: sqlite.h.in,v 1.166 2006/06/08 15:28:44 drh Exp $ +** @(#) $Id: sqlite.h.in,v 1.167 2006/06/10 13:29:33 drh Exp $ */ #ifndef _SQLITE3_H_ #define _SQLITE3_H_ @@ -1508,6 +1508,68 @@ int sqlite3_load_extension( char **pzErrMsg /* Put error message here if not 0 */ ); +/* +****** EXPERIMENTAL - subject to change without notice ************** +*/ +typedef struct sqlite3_vtab sqlite3_vtab; +typedef struct sqlite3_index_info sqlite3_index_info; +typedef struct sqlite3_vtab_cursor sqlite3_vtab_cursor; +typedef struct sqlite3_module sqlite3_module; +struct sqlite3_module { + int iVersion; + void *pAux; + int (*xCreate)(sqlite3*, const sqlite3_module *pModule, + int argc, char **argv, + sqlite3_vtab **ppVTab); + int (*xConnect)(sqlite3*, const sqlite3_module *pModule, + int argc, char **argv, + sqlite3_vtab **ppVTab); + int (*xBestIndex)(sqlite3_vtab *pVTab, sqlite3_index_info*); + int (*xDisconnect)(sqlite3_vtab *pVTab); + int (*xDestroy)(sqlite3_vtab *pVTab); + int (*xOpen)(sqlite3_vtab *pVTab, sqlite3_vtab_cursor **ppCursor); + int (*xClose)(sqlite3_vtab_cursor*); + int (*xFilter)(sqlite3_vtab_cursor*, int idx, + int argc, sqlite3_value **argv); + int (*xNext)(sqlite3_vtab_cursor*); + int (*xColumn)(sqlite3_vtab_cursor*, sqlite3_context*, int); + int (*xRowid)(sqlite3_vtab_cursor*, sqlite_int64 *pRowid); + int (*xInsert)(sqlite3_vtab *pVTab, sqlite3_value **apData); + int (*xDelete)(sqlite3_vtab *pVTab, sqlite_int64 rowid); + int (*xBegin)(sqlite3_vtab *pVTab); + int (*xSync)(sqlite3_vtab *pVTab); + int (*xCommit)(sqlite3_vtab *pVTab); + int (*xRollback)(sqlite3_vtab *pVTab); + int (*xIsInTrans)(sqlite3_vtab *pVTab); +}; +struct sqlite3_index_info { + /* Inputs */ + int nConstraint; + struct sqlite3_index_constraint { + int iColumn; + unsigned char op; + unsigned char omit; + } *aConstraint; + int nOrderBy; + struct sqlite3_index_orderby { + int iColumn; + unsigned char desc; + } *aOrderBy; + + /* Outputs */ + int idxNum; + int columnCount; + int *aColumn; + int orderByConsumed; +}; +#define SQLITE_INDEX_CONSTRAINT_EQ 1 +#define SQLITE_INDEX_CONSTRAINT_GT 3 +#define SQLITE_INDEX_CONSTRAINT_LE 4 +#define SQLITE_INDEX_CONSTRAINT_LT 5 +#define SQLITE_INDEX_CONSTRAINT_GE 6 +#define SQLITE_INDEX_CONSTRAINT_MATCH 7 + + /* ** Undo the hack that converts floating point types to integer for ** builds on processors without floating point support. diff --git a/src/sqliteInt.h b/src/sqliteInt.h index 44210e3604..6e78e07826 100644 --- a/src/sqliteInt.h +++ b/src/sqliteInt.h @@ -11,7 +11,7 @@ ************************************************************************* ** Internal interface definitions for SQLite. ** -** @(#) $Id: sqliteInt.h,v 1.495 2006/06/08 15:48:01 drh Exp $ +** @(#) $Id: sqliteInt.h,v 1.496 2006/06/10 13:29:33 drh Exp $ */ #ifndef _SQLITEINT_H_ #define _SQLITEINT_H_ @@ -702,6 +702,12 @@ struct Table { #endif #ifndef SQLITE_OMIT_ALTERTABLE int addColOffset; /* Offset in CREATE TABLE statement to add a new column */ +#endif +#ifndef SQLITE_OMIT_VIRTUALTABLE + char *zModuleName; /* Name of module implementing this virtual table */ + sqlite3_module *pMod; /* Pointer to the implementation of the module */ + sqlite3_vtab *pVTab; /* Pointer to the module instance */ + u8 needCreate; /* Need to call pMod->xCreate() */ #endif Schema *pSchema; }; diff --git a/tool/lemon.c b/tool/lemon.c index 3d5a3d1448..f7c12814bc 100644 --- a/tool/lemon.c +++ b/tool/lemon.c @@ -241,6 +241,7 @@ struct lemon { struct symbol **symbols; /* Sorted array of pointers to symbols */ int errorcnt; /* Number of errors */ struct symbol *errsym; /* The error symbol */ + struct symbol *wildcard; /* Token that matches anything */ char *name; /* Name of the generated parser */ char *arg; /* Declaration of the 3th argument to parser */ char *tokentype; /* Type of terminal symbols in the parser stack */ @@ -1442,6 +1443,7 @@ char **argv; lem.tablesize = 0; Symbol_new("$"); lem.errsym = Symbol_new("error"); + lem.wildcard = 0; /* Parse the input file */ Parse(&lem); @@ -1960,7 +1962,8 @@ struct pstate { RESYNC_AFTER_DECL_ERROR, WAITING_FOR_DESTRUCTOR_SYMBOL, WAITING_FOR_DATATYPE_SYMBOL, - WAITING_FOR_FALLBACK_ID + WAITING_FOR_FALLBACK_ID, + WAITING_FOR_WILDCARD_ID } state; /* The state of the parser */ struct symbol *fallback; /* The fallback token */ struct symbol *lhs; /* Left-hand side of current rule */ @@ -2264,6 +2267,8 @@ to follow the previous rule."); }else if( strcmp(x,"fallback")==0 ){ psp->fallback = 0; psp->state = WAITING_FOR_FALLBACK_ID; + }else if( strcmp(x,"wildcard")==0 ){ + psp->state = WAITING_FOR_WILDCARD_ID; }else{ ErrorMsg(psp->filename,psp->tokenlineno, "Unknown declaration keyword: \"%%%s\".",x); @@ -2364,6 +2369,24 @@ to follow the previous rule."); } } break; + case WAITING_FOR_WILDCARD_ID: + if( x[0]=='.' ){ + psp->state = WAITING_FOR_DECL_OR_RULE; + }else if( !isupper(x[0]) ){ + ErrorMsg(psp->filename, psp->tokenlineno, + "%%wildcard argument \"%s\" should be a token", x); + psp->errorcnt++; + }else{ + struct symbol *sp = Symbol_new(x); + if( psp->gp->wildcard==0 ){ + psp->gp->wildcard = sp; + }else{ + ErrorMsg(psp->filename, psp->tokenlineno, + "Extra wildcard to token: %s", x); + psp->errorcnt++; + } + } + break; case RESYNC_AFTER_RULE_ERROR: /* if( x[0]=='.' ) psp->state = WAITING_FOR_DECL_OR_RULE; ** break; */ @@ -3489,6 +3512,10 @@ int mhflag; /* Output in makeheaders format if true */ fprintf(out,"#define YYNOCODE %d\n",lemp->nsymbol+1); lineno++; fprintf(out,"#define YYACTIONTYPE %s\n", minimum_size_type(0, lemp->nstate+lemp->nrule+5)); lineno++; + if( lemp->wildcard ){ + fprintf(out,"#define YYWILDCARD %d\n", + lemp->wildcard->index); lineno++; + } print_stack_union(out,lemp,&lineno,mhflag); if( lemp->stacksize ){ if( atoi(lemp->stacksize)<=0 ){ @@ -3885,7 +3912,8 @@ struct lemon *lemp; ** of defaults. ** ** In this version, we take the most frequent REDUCE action and make -** it the default. +** it the default. Except, there is no default if the wildcard token +** is a possible look-ahead. */ void CompressTables(lemp) struct lemon *lemp; @@ -3895,13 +3923,18 @@ struct lemon *lemp; struct rule *rp, *rp2, *rbest; int nbest, n; int i; + int usesWildcard; for(i=0; instate; i++){ stp = lemp->sorted[i]; nbest = 0; rbest = 0; + usesWildcard = 0; for(ap=stp->ap; ap; ap=ap->next){ + if( ap->type==SHIFT && ap->sp==lemp->wildcard ){ + usesWildcard = 1; + } if( ap->type!=REDUCE ) continue; rp = ap->x.rp; if( rp==rbest ) continue; @@ -3919,8 +3952,10 @@ struct lemon *lemp; } /* Do not make a default if the number of rules to default - ** is not at least 1 */ - if( nbest<1 ) continue; + ** is not at least 1 or if the wildcard token is a possible + ** lookahead. + */ + if( nbest<1 || usesWildcard ) continue; /* Combine matching REDUCE actions into a single default */ diff --git a/tool/lempar.c b/tool/lempar.c index fb1e5c01ce..c220e0ff6b 100644 --- a/tool/lempar.c +++ b/tool/lempar.c @@ -334,19 +334,33 @@ static int yy_find_shift_action( } i += iLookAhead; if( i<0 || i>=YY_SZ_ACTTAB || yy_lookahead[i]!=iLookAhead ){ -#ifdef YYFALLBACK - int iFallback; /* Fallback token */ - if( iLookAhead %s\n", - yyTracePrompt, yyTokenName[iLookAhead], yyTokenName[iFallback]); + if( iLookAhead>0 ){ + #ifdef YYFALLBACK + int iFallback; /* Fallback token */ + if( iLookAhead %s\n", + yyTracePrompt, yyTokenName[iLookAhead], yyTokenName[iFallback]); + } + #endif + return yy_find_shift_action(pParser, iFallback); } -#endif - return yy_find_shift_action(pParser, iFallback); + #endif + #ifdef YYWILDCARD + int j = i - iLookAhead + YYWILDCARD; + if( j>=0 && j %s\n", + yyTracePrompt, yyTokenName[iLookAhead], yyTokenName[YYWILDCARD]); + } + #endif + return yy_action[j]; + } + #endif } -#endif return yy_default[stateno]; }else{ return yy_action[i]; diff --git a/tool/mkkeywordhash.c b/tool/mkkeywordhash.c index 8bbefa14fd..a1df7827cd 100644 --- a/tool/mkkeywordhash.c +++ b/tool/mkkeywordhash.c @@ -105,7 +105,11 @@ struct Keyword { #else # define VIEW 0x00008000 #endif - +#ifdef SQLITE_OMIT_VIRTUALTABLE +# define VTAB 0 +#else +# define VTAB 0x00010000 +#endif /* ** These are the keywords @@ -225,6 +229,7 @@ static Keyword aKeywordTable[] = { { "VACUUM", "TK_VACUUM", VACUUM }, { "VALUES", "TK_VALUES", ALWAYS }, { "VIEW", "TK_VIEW", VIEW }, + { "VIRTUAL", "TK_VIRTUAL", VTAB }, { "WHEN", "TK_WHEN", ALWAYS }, { "WHERE", "TK_WHERE", ALWAYS }, };