Many hyperlinks are disabled.
Use anonymous login
to enable hyperlinks.
Changes In Branch table-valued-functions Excluding Merge-Ins
This is equivalent to a diff from c573b0a1 to 3efc7942
2015-08-20
| ||
19:55 | Add support for table-valued functions in the FROM clause implemented as virtual tables. check-in: 9b718b06 user: drh tags: trunk | |
18:28 | Prevent the series.c extension from loading on older versions of SQLite that do not support xCreate==NULL. Closed-Leaf check-in: 3efc7942 user: drh tags: table-valued-functions | |
17:18 | Make SQLITE_BUSY_SNAPSHOT and SQLITE_BUSY_RECOVERY retryable, just as a plain SQLITE_BUSY is. check-in: fd13dd95 user: drh tags: trunk | |
16:16 | Fix a typo in series.c. check-in: 23db7f50 user: dan tags: table-valued-functions | |
2015-08-19
| ||
12:52 | Merge changes from trunk. check-in: dddd792d user: drh tags: table-valued-functions | |
12:45 | Simplification to error handling in addModuleArgument() in the virtual table processing. check-in: c573b0a1 user: drh tags: trunk | |
08:34 | When updating a zipvfs database with RBU, set journal_mode=off to prevent the upper-level pager from creating a large temporary file. check-in: dec14a39 user: dan tags: trunk | |
Changes to Makefile.in.
416 416 $(TOP)/ext/misc/fuzzer.c \ 417 417 $(TOP)/ext/fts5/fts5_tcl.c \ 418 418 $(TOP)/ext/fts5/fts5_test_mi.c \ 419 419 $(TOP)/ext/misc/ieee754.c \ 420 420 $(TOP)/ext/misc/nextchar.c \ 421 421 $(TOP)/ext/misc/percentile.c \ 422 422 $(TOP)/ext/misc/regexp.c \ 423 + $(TOP)/ext/misc/series.c \ 423 424 $(TOP)/ext/misc/spellfix.c \ 424 425 $(TOP)/ext/misc/totype.c \ 425 426 $(TOP)/ext/misc/wholenumber.c 426 427 427 428 # Source code to the library files needed by the test fixture 428 429 # 429 430 TESTSRC2 = \
Changes to Makefile.msc.
1082 1082 fts5.c \ 1083 1083 $(TOP)\ext\fts5\fts5_tcl.c \ 1084 1084 $(TOP)\ext\fts5\fts5_test_mi.c \ 1085 1085 $(TOP)\ext\misc\ieee754.c \ 1086 1086 $(TOP)\ext\misc\nextchar.c \ 1087 1087 $(TOP)\ext\misc\percentile.c \ 1088 1088 $(TOP)\ext\misc\regexp.c \ 1089 + $(TOP)\ext\misc\series.c \ 1089 1090 $(TOP)\ext\misc\spellfix.c \ 1090 1091 $(TOP)\ext\misc\totype.c \ 1091 1092 $(TOP)\ext\misc\wholenumber.c 1092 1093 1093 1094 1094 1095 # Source code to the library files needed by the test fixture 1095 1096 #
Added ext/misc/series.c.
1 +/* 2 +** 2015-08-18 3 +** 4 +** The author disclaims copyright to this source code. In place of 5 +** a legal notice, here is a blessing: 6 +** 7 +** May you do good and not evil. 8 +** May you find forgiveness for yourself and forgive others. 9 +** May you share freely, never taking more than you give. 10 +** 11 +************************************************************************* 12 +** 13 +** This file demonstrates how to create a table-valued-function using 14 +** a virtual table. This demo implements the generate_series() function 15 +** which gives similar results to the eponymous function in PostgreSQL. 16 +** Examples: 17 +** 18 +** SELECT * FROM generate_series(0,100,5); 19 +** 20 +** The query above returns integers from 0 through 100 counting by steps 21 +** of 5. 22 +** 23 +** SELECT * FROM generate_series(0,100); 24 +** 25 +** Integers from 0 through 100 with a step size of 1. 26 +** 27 +** SELECT * FROM generate_series(20) LIMIT 10; 28 +** 29 +** Integers 20 through 29. 30 +** 31 +** HOW IT WORKS 32 +** 33 +** The generate_series "function" is really a virtual table with the 34 +** following schema: 35 +** 36 +** CREATE FUNCTION generate_series( 37 +** value, 38 +** start HIDDEN, 39 +** stop HIDDEN, 40 +** step HIDDEN 41 +** ); 42 +** 43 +** Function arguments in queries against this virtual table are translated 44 +** into equality constraints against successive hidden columns. In other 45 +** words, the following pairs of queries are equivalent to each other: 46 +** 47 +** SELECT * FROM generate_series(0,100,5); 48 +** SELECT * FROM generate_series WHERE start=0 AND stop=100 AND step=5; 49 +** 50 +** SELECT * FROM generate_series(0,100); 51 +** SELECT * FROM generate_series WHERE start=0 AND stop=100; 52 +** 53 +** SELECT * FROM generate_series(20) LIMIT 10; 54 +** SELECT * FROM generate_series WHERE start=20 LIMIT 10; 55 +** 56 +** The generate_series virtual table implementation leaves the xCreate method 57 +** set to NULL. This means that it is not possible to do a CREATE VIRTUAL 58 +** TABLE command with "generate_series" as the USING argument. Instead, there 59 +** is a single generate_series virtual table that is always available without 60 +** having to be created first. 61 +** 62 +** The xBestIndex method looks for equality constraints against the hidden 63 +** start, stop, and step columns, and if present, it uses those constraints 64 +** to bound the sequence of generated values. If the equality constraints 65 +** are missing, it uses 0 for start, 4294967295 for stop, and 1 for step. 66 +** xBestIndex returns a small cost when both start and stop are available, 67 +** and a very large cost if either start or stop are unavailable. This 68 +** encourages the query planner to order joins such that the bounds of the 69 +** series are well-defined. 70 +*/ 71 +#include "sqlite3ext.h" 72 +SQLITE_EXTENSION_INIT1 73 +#include <assert.h> 74 +#include <string.h> 75 + 76 +#ifndef SQLITE_OMIT_VIRTUALTABLE 77 + 78 + 79 +/* series_cursor is a subclass of sqlite3_vtab_cursor which will 80 +** serve as the underlying representation of a cursor that scans 81 +** over rows of the result 82 +*/ 83 +typedef struct series_cursor series_cursor; 84 +struct series_cursor { 85 + sqlite3_vtab_cursor base; /* Base class - must be first */ 86 + int isDesc; /* True to count down rather than up */ 87 + sqlite3_int64 iRowid; /* The rowid */ 88 + sqlite3_int64 iValue; /* Current value ("value") */ 89 + sqlite3_int64 mnValue; /* Mimimum value ("start") */ 90 + sqlite3_int64 mxValue; /* Maximum value ("stop") */ 91 + sqlite3_int64 iStep; /* Increment ("step") */ 92 +}; 93 + 94 +/* 95 +** The seriesConnect() method is invoked to create a new 96 +** series_vtab that describes the generate_series virtual table. 97 +** 98 +** Think of this routine as the constructor for series_vtab objects. 99 +** 100 +** All this routine needs to do is: 101 +** 102 +** (1) Allocate the series_vtab object and initialize all fields. 103 +** 104 +** (2) Tell SQLite (via the sqlite3_declare_vtab() interface) what the 105 +** result set of queries against generate_series will look like. 106 +*/ 107 +static int seriesConnect( 108 + sqlite3 *db, 109 + void *pAux, 110 + int argc, const char *const*argv, 111 + sqlite3_vtab **ppVtab, 112 + char **pzErr 113 +){ 114 + sqlite3_vtab *pNew; 115 + pNew = *ppVtab = sqlite3_malloc( sizeof(*pNew) ); 116 + if( pNew==0 ) return SQLITE_NOMEM; 117 + 118 +/* Column numbers */ 119 +#define SERIES_COLUMN_VALUE 0 120 +#define SERIES_COLUMN_START 1 121 +#define SERIES_COLUMN_STOP 2 122 +#define SERIES_COLUMN_STEP 3 123 + 124 + sqlite3_declare_vtab(db, 125 + "CREATE TABLE x(value,start hidden,stop hidden,step hidden)"); 126 + memset(pNew, 0, sizeof(*pNew)); 127 + return SQLITE_OK; 128 +} 129 + 130 +/* 131 +** This method is the destructor for series_cursor objects. 132 +*/ 133 +static int seriesDisconnect(sqlite3_vtab *pVtab){ 134 + sqlite3_free(pVtab); 135 + return SQLITE_OK; 136 +} 137 + 138 +/* 139 +** Constructor for a new series_cursor object. 140 +*/ 141 +static int seriesOpen(sqlite3_vtab *p, sqlite3_vtab_cursor **ppCursor){ 142 + series_cursor *pCur; 143 + pCur = sqlite3_malloc( sizeof(*pCur) ); 144 + if( pCur==0 ) return SQLITE_NOMEM; 145 + memset(pCur, 0, sizeof(*pCur)); 146 + *ppCursor = &pCur->base; 147 + return SQLITE_OK; 148 +} 149 + 150 +/* 151 +** Destructor for a series_cursor. 152 +*/ 153 +static int seriesClose(sqlite3_vtab_cursor *cur){ 154 + sqlite3_free(cur); 155 + return SQLITE_OK; 156 +} 157 + 158 + 159 +/* 160 +** Advance a series_cursor to its next row of output. 161 +*/ 162 +static int seriesNext(sqlite3_vtab_cursor *cur){ 163 + series_cursor *pCur = (series_cursor*)cur; 164 + if( pCur->isDesc ){ 165 + pCur->iValue -= pCur->iStep; 166 + }else{ 167 + pCur->iValue += pCur->iStep; 168 + } 169 + pCur->iRowid++; 170 + return SQLITE_OK; 171 +} 172 + 173 +/* 174 +** Return values of columns for the row at which the series_cursor 175 +** is currently pointing. 176 +*/ 177 +static int seriesColumn( 178 + sqlite3_vtab_cursor *cur, /* The cursor */ 179 + sqlite3_context *ctx, /* First argument to sqlite3_result_...() */ 180 + int i /* Which column to return */ 181 +){ 182 + series_cursor *pCur = (series_cursor*)cur; 183 + sqlite3_int64 x = 0; 184 + switch( i ){ 185 + case SERIES_COLUMN_START: x = pCur->mnValue; break; 186 + case SERIES_COLUMN_STOP: x = pCur->mxValue; break; 187 + case SERIES_COLUMN_STEP: x = pCur->iStep; break; 188 + default: x = pCur->iValue; break; 189 + } 190 + sqlite3_result_int64(ctx, x); 191 + return SQLITE_OK; 192 +} 193 + 194 +/* 195 +** Return the rowid for the current row. In this implementation, the 196 +** rowid is the same as the output value. 197 +*/ 198 +static int seriesRowid(sqlite3_vtab_cursor *cur, sqlite_int64 *pRowid){ 199 + series_cursor *pCur = (series_cursor*)cur; 200 + *pRowid = pCur->iRowid; 201 + return SQLITE_OK; 202 +} 203 + 204 +/* 205 +** Return TRUE if the cursor has been moved off of the last 206 +** row of output. 207 +*/ 208 +static int seriesEof(sqlite3_vtab_cursor *cur){ 209 + series_cursor *pCur = (series_cursor*)cur; 210 + if( pCur->isDesc ){ 211 + return pCur->iValue < pCur->mnValue; 212 + }else{ 213 + return pCur->iValue > pCur->mxValue; 214 + } 215 +} 216 + 217 +/* 218 +** This method is called to "rewind" the series_cursor object back 219 +** to the first row of output. This method is always called at least 220 +** once prior to any call to seriesColumn() or seriesRowid() or 221 +** seriesEof(). 222 +** 223 +** The query plan selected by seriesBestIndex is passed in the idxNum 224 +** parameter. (idxStr is not used in this implementation.) idxNum 225 +** is a bitmask showing which constraints are available: 226 +** 227 +** 1: start=VALUE 228 +** 2: stop=VALUE 229 +** 4: step=VALUE 230 +** 231 +** Also, if bit 8 is set, that means that the series should be output 232 +** in descending order rather than in ascending order. 233 +** 234 +** This routine should initialize the cursor and position it so that it 235 +** is pointing at the first row, or pointing off the end of the table 236 +** (so that seriesEof() will return true) if the table is empty. 237 +*/ 238 +static int seriesFilter( 239 + sqlite3_vtab_cursor *pVtabCursor, 240 + int idxNum, const char *idxStr, 241 + int argc, sqlite3_value **argv 242 +){ 243 + series_cursor *pCur = (series_cursor *)pVtabCursor; 244 + int i = 0; 245 + if( idxNum & 1 ){ 246 + pCur->mnValue = sqlite3_value_int64(argv[i++]); 247 + }else{ 248 + pCur->mnValue = 0; 249 + } 250 + if( idxNum & 2 ){ 251 + pCur->mxValue = sqlite3_value_int64(argv[i++]); 252 + }else{ 253 + pCur->mxValue = 0xffffffff; 254 + } 255 + if( idxNum & 4 ){ 256 + pCur->iStep = sqlite3_value_int64(argv[i++]); 257 + if( pCur->iStep<1 ) pCur->iStep = 1; 258 + }else{ 259 + pCur->iStep = 1; 260 + } 261 + if( idxNum & 8 ){ 262 + pCur->isDesc = 1; 263 + pCur->iValue = pCur->mxValue; 264 + if( pCur->iStep>0 ){ 265 + pCur->iValue -= (pCur->mxValue - pCur->mnValue)%pCur->iStep; 266 + } 267 + }else{ 268 + pCur->isDesc = 0; 269 + pCur->iValue = pCur->mnValue; 270 + } 271 + pCur->iRowid = 1; 272 + return SQLITE_OK; 273 +} 274 + 275 +/* 276 +** SQLite will invoke this method one or more times while planning a query 277 +** that uses the generate_series virtual table. This routine needs to create 278 +** a query plan for each invocation and compute an estimated cost for that 279 +** plan. 280 +** 281 +** In this implementation idxNum is used to represent the 282 +** query plan. idxStr is unused. 283 +** 284 +** The query plan is represented by bits in idxNum: 285 +** 286 +** (1) start = $value -- constraint exists 287 +** (2) stop = $value -- constraint exists 288 +** (4) step = $value -- constraint exists 289 +** (8) output in descending order 290 +*/ 291 +static int seriesBestIndex( 292 + sqlite3_vtab *tab, 293 + sqlite3_index_info *pIdxInfo 294 +){ 295 + int i; /* Loop over constraints */ 296 + int idxNum = 0; /* The query plan bitmask */ 297 + int startIdx = -1; /* Index of the start= constraint, or -1 if none */ 298 + int stopIdx = -1; /* Index of the stop= constraint, or -1 if none */ 299 + int stepIdx = -1; /* Index of the step= constraint, or -1 if none */ 300 + int nArg = 0; /* Number of arguments that seriesFilter() expects */ 301 + 302 + const struct sqlite3_index_constraint *pConstraint; 303 + pConstraint = pIdxInfo->aConstraint; 304 + for(i=0; i<pIdxInfo->nConstraint; i++, pConstraint++){ 305 + if( pConstraint->usable==0 ) continue; 306 + if( pConstraint->op!=SQLITE_INDEX_CONSTRAINT_EQ ) continue; 307 + switch( pConstraint->iColumn ){ 308 + case SERIES_COLUMN_START: 309 + startIdx = i; 310 + idxNum |= 1; 311 + break; 312 + case SERIES_COLUMN_STOP: 313 + stopIdx = i; 314 + idxNum |= 2; 315 + break; 316 + case SERIES_COLUMN_STEP: 317 + stepIdx = i; 318 + idxNum |= 4; 319 + break; 320 + } 321 + } 322 + if( startIdx>=0 ){ 323 + pIdxInfo->aConstraintUsage[startIdx].argvIndex = ++nArg; 324 + pIdxInfo->aConstraintUsage[startIdx].omit = 1; 325 + } 326 + if( stopIdx>=0 ){ 327 + pIdxInfo->aConstraintUsage[stopIdx].argvIndex = ++nArg; 328 + pIdxInfo->aConstraintUsage[stopIdx].omit = 1; 329 + } 330 + if( stepIdx>=0 ){ 331 + pIdxInfo->aConstraintUsage[stepIdx].argvIndex = ++nArg; 332 + pIdxInfo->aConstraintUsage[stepIdx].omit = 1; 333 + } 334 + if( pIdxInfo->nOrderBy==1 ){ 335 + if( pIdxInfo->aOrderBy[0].desc ) idxNum |= 8; 336 + pIdxInfo->orderByConsumed = 1; 337 + } 338 + if( (idxNum & 3)==3 ){ 339 + /* Both start= and stop= boundaries are available. This is the 340 + ** the preferred case */ 341 + pIdxInfo->estimatedCost = (double)1; 342 + }else{ 343 + /* If either boundary is missing, we have to generate a huge span 344 + ** of numbers. Make this case very expensive so that the query 345 + ** planner will work hard to avoid it. */ 346 + pIdxInfo->estimatedCost = (double)2000000000; 347 + } 348 + pIdxInfo->idxNum = idxNum; 349 + return SQLITE_OK; 350 +} 351 + 352 +/* 353 +** This following structure defines all the methods for the 354 +** generate_series virtual table. 355 +*/ 356 +static sqlite3_module seriesModule = { 357 + 0, /* iVersion */ 358 + 0, /* xCreate */ 359 + seriesConnect, /* xConnect */ 360 + seriesBestIndex, /* xBestIndex */ 361 + seriesDisconnect, /* xDisconnect */ 362 + 0, /* xDestroy */ 363 + seriesOpen, /* xOpen - open a cursor */ 364 + seriesClose, /* xClose - close a cursor */ 365 + seriesFilter, /* xFilter - configure scan constraints */ 366 + seriesNext, /* xNext - advance a cursor */ 367 + seriesEof, /* xEof - check for end of scan */ 368 + seriesColumn, /* xColumn - read data */ 369 + seriesRowid, /* xRowid - read data */ 370 + 0, /* xUpdate */ 371 + 0, /* xBegin */ 372 + 0, /* xSync */ 373 + 0, /* xCommit */ 374 + 0, /* xRollback */ 375 + 0, /* xFindMethod */ 376 + 0, /* xRename */ 377 +}; 378 + 379 +#endif /* SQLITE_OMIT_VIRTUALTABLE */ 380 + 381 +#ifdef _WIN32 382 +__declspec(dllexport) 383 +#endif 384 +int sqlite3_series_init( 385 + sqlite3 *db, 386 + char **pzErrMsg, 387 + const sqlite3_api_routines *pApi 388 +){ 389 + int rc = SQLITE_OK; 390 + SQLITE_EXTENSION_INIT2(pApi); 391 +#ifndef SQLITE_OMIT_VIRTUALTABLE 392 + if( sqlite3_libversion_number()<3008012 ){ 393 + *pzErrMsg = sqlite3_mprintf( 394 + "generate_series() requires SQLite 3.8.12 or later"); 395 + return SQLITE_ERROR; 396 + } 397 + rc = sqlite3_create_module(db, "generate_series", &seriesModule, 0); 398 +#endif 399 + return rc; 400 +}
Changes to main.mk.
296 296 $(TOP)/ext/misc/eval.c \ 297 297 $(TOP)/ext/misc/fileio.c \ 298 298 $(TOP)/ext/misc/fuzzer.c \ 299 299 $(TOP)/ext/misc/ieee754.c \ 300 300 $(TOP)/ext/misc/nextchar.c \ 301 301 $(TOP)/ext/misc/percentile.c \ 302 302 $(TOP)/ext/misc/regexp.c \ 303 + $(TOP)/ext/misc/series.c \ 303 304 $(TOP)/ext/misc/spellfix.c \ 304 305 $(TOP)/ext/misc/totype.c \ 305 306 $(TOP)/ext/misc/wholenumber.c \ 306 307 $(TOP)/ext/misc/vfslog.c \ 307 308 $(TOP)/ext/fts5/fts5_tcl.c \ 308 309 $(TOP)/ext/fts5/fts5_test_mi.c \ 309 310 fts5.c
Changes to src/build.c.
351 351 ** and code in pParse and return NULL. */ 352 352 if( SQLITE_OK!=sqlite3ReadSchema(pParse) ){ 353 353 return 0; 354 354 } 355 355 356 356 p = sqlite3FindTable(pParse->db, zName, zDbase); 357 357 if( p==0 ){ 358 +#ifndef SQLITE_OMIT_VIRTUAL_TABLE 359 + /* If zName is the not the name of a table in the schema created using 360 + ** CREATE, then check to see if it is the name of an virtual table that 361 + ** can be an eponymous virtual table. */ 362 + Module *pMod = (Module*)sqlite3HashFind(&pParse->db->aModule, zName); 363 + if( pMod && sqlite3VtabEponymousTableInit(pParse, pMod) ){ 364 + return pMod->pEpoTab; 365 + } 366 +#endif 358 367 const char *zMsg = isView ? "no such view" : "no such table"; 359 368 if( zDbase ){ 360 369 sqlite3ErrorMsg(pParse, "%s: %s.%s", zMsg, zDbase, zName); 361 370 }else{ 362 371 sqlite3ErrorMsg(pParse, "%s: %s", zMsg, zName); 363 372 } 364 373 pParse->checkSchema = 1; ................................................................................ 556 565 db->flags &= ~SQLITE_InternChanges; 557 566 } 558 567 559 568 /* 560 569 ** Delete memory allocated for the column names of a table or view (the 561 570 ** Table.aCol[] array). 562 571 */ 563 -static void sqliteDeleteColumnNames(sqlite3 *db, Table *pTable){ 572 +void sqlite3DeleteColumnNames(sqlite3 *db, Table *pTable){ 564 573 int i; 565 574 Column *pCol; 566 575 assert( pTable!=0 ); 567 576 if( (pCol = pTable->aCol)!=0 ){ 568 577 for(i=0; i<pTable->nCol; i++, pCol++){ 569 578 sqlite3DbFree(db, pCol->zName); 570 579 sqlite3ExprDelete(db, pCol->pDflt); ................................................................................ 623 632 } 624 633 625 634 /* Delete any foreign keys attached to this table. */ 626 635 sqlite3FkDelete(db, pTable); 627 636 628 637 /* Delete the Table structure itself. 629 638 */ 630 - sqliteDeleteColumnNames(db, pTable); 639 + sqlite3DeleteColumnNames(db, pTable); 631 640 sqlite3DbFree(db, pTable->zName); 632 641 sqlite3DbFree(db, pTable->zColAff); 633 642 sqlite3SelectDelete(db, pTable->pSelect); 634 643 #ifndef SQLITE_OMIT_CHECK 635 644 sqlite3ExprListDelete(db, pTable->pCheck); 636 645 #endif 637 646 #ifndef SQLITE_OMIT_VIRTUALTABLE ................................................................................ 2214 2223 static void sqliteViewResetAll(sqlite3 *db, int idx){ 2215 2224 HashElem *i; 2216 2225 assert( sqlite3SchemaMutexHeld(db, idx, 0) ); 2217 2226 if( !DbHasProperty(db, idx, DB_UnresetViews) ) return; 2218 2227 for(i=sqliteHashFirst(&db->aDb[idx].pSchema->tblHash); i;i=sqliteHashNext(i)){ 2219 2228 Table *pTab = sqliteHashData(i); 2220 2229 if( pTab->pSelect ){ 2221 - sqliteDeleteColumnNames(db, pTab); 2230 + sqlite3DeleteColumnNames(db, pTab); 2222 2231 pTab->aCol = 0; 2223 2232 pTab->nCol = 0; 2224 2233 } 2225 2234 } 2226 2235 DbClearProperty(db, idx, DB_UnresetViews); 2227 2236 } 2228 2237 #else ................................................................................ 3696 3705 int i; 3697 3706 struct SrcList_item *pItem; 3698 3707 if( pList==0 ) return; 3699 3708 for(pItem=pList->a, i=0; i<pList->nSrc; i++, pItem++){ 3700 3709 sqlite3DbFree(db, pItem->zDatabase); 3701 3710 sqlite3DbFree(db, pItem->zName); 3702 3711 sqlite3DbFree(db, pItem->zAlias); 3703 - sqlite3DbFree(db, pItem->zIndexedBy); 3712 + if( pItem->fg.isIndexedBy ) sqlite3DbFree(db, pItem->u1.zIndexedBy); 3713 + if( pItem->fg.isTabFunc ) sqlite3ExprListDelete(db, pItem->u1.pFuncArg); 3704 3714 sqlite3DeleteTable(db, pItem->pTab); 3705 3715 sqlite3SelectDelete(db, pItem->pSelect); 3706 3716 sqlite3ExprDelete(db, pItem->pOn); 3707 3717 sqlite3IdListDelete(db, pItem->pUsing); 3708 3718 } 3709 3719 sqlite3DbFree(db, pList); 3710 3720 } ................................................................................ 3769 3779 ** Add an INDEXED BY or NOT INDEXED clause to the most recently added 3770 3780 ** element of the source-list passed as the second argument. 3771 3781 */ 3772 3782 void sqlite3SrcListIndexedBy(Parse *pParse, SrcList *p, Token *pIndexedBy){ 3773 3783 assert( pIndexedBy!=0 ); 3774 3784 if( p && ALWAYS(p->nSrc>0) ){ 3775 3785 struct SrcList_item *pItem = &p->a[p->nSrc-1]; 3776 - assert( pItem->notIndexed==0 && pItem->zIndexedBy==0 ); 3786 + assert( pItem->fg.notIndexed==0 ); 3787 + assert( pItem->fg.isIndexedBy==0 ); 3788 + assert( pItem->fg.isTabFunc==0 ); 3777 3789 if( pIndexedBy->n==1 && !pIndexedBy->z ){ 3778 3790 /* A "NOT INDEXED" clause was supplied. See parse.y 3779 3791 ** construct "indexed_opt" for details. */ 3780 - pItem->notIndexed = 1; 3792 + pItem->fg.notIndexed = 1; 3781 3793 }else{ 3782 - pItem->zIndexedBy = sqlite3NameFromToken(pParse->db, pIndexedBy); 3794 + pItem->u1.zIndexedBy = sqlite3NameFromToken(pParse->db, pIndexedBy); 3795 + pItem->fg.isIndexedBy = (pItem->u1.zIndexedBy!=0); 3783 3796 } 3784 3797 } 3785 3798 } 3799 + 3800 +/* 3801 +** Add the list of function arguments to the SrcList entry for a 3802 +** table-valued-function. 3803 +*/ 3804 +void sqlite3SrcListFuncArgs(Parse *pParse, SrcList *p, ExprList *pList){ 3805 + if( p && ALWAYS(p->nSrc>0) ){ 3806 + struct SrcList_item *pItem = &p->a[p->nSrc-1]; 3807 + assert( pItem->fg.notIndexed==0 ); 3808 + assert( pItem->fg.isIndexedBy==0 ); 3809 + assert( pItem->fg.isTabFunc==0 ); 3810 + pItem->u1.pFuncArg = pList; 3811 + pItem->fg.isTabFunc = 1; 3812 + } 3813 +} 3786 3814 3787 3815 /* 3788 3816 ** When building up a FROM clause in the parser, the join operator 3789 3817 ** is initially attached to the left operand. But the code generator 3790 3818 ** expects the join operator to be on the right operand. This routine 3791 3819 ** Shifts all join operators from left to right for an entire FROM 3792 3820 ** clause. ................................................................................ 3799 3827 ** in p->a[0] and p->a[1], respectively. The parser initially stores the 3800 3828 ** operator with A. This routine shifts that operator over to B. 3801 3829 */ 3802 3830 void sqlite3SrcListShiftJoinType(SrcList *p){ 3803 3831 if( p ){ 3804 3832 int i; 3805 3833 for(i=p->nSrc-1; i>0; i--){ 3806 - p->a[i].jointype = p->a[i-1].jointype; 3834 + p->a[i].fg.jointype = p->a[i-1].fg.jointype; 3807 3835 } 3808 - p->a[0].jointype = 0; 3836 + p->a[0].fg.jointype = 0; 3809 3837 } 3810 3838 } 3811 3839 3812 3840 /* 3813 3841 ** Begin a transaction 3814 3842 */ 3815 3843 void sqlite3BeginTransaction(Parse *pParse, int type){
Changes to src/expr.c.
1030 1030 struct SrcList_item *pNewItem = &pNew->a[i]; 1031 1031 struct SrcList_item *pOldItem = &p->a[i]; 1032 1032 Table *pTab; 1033 1033 pNewItem->pSchema = pOldItem->pSchema; 1034 1034 pNewItem->zDatabase = sqlite3DbStrDup(db, pOldItem->zDatabase); 1035 1035 pNewItem->zName = sqlite3DbStrDup(db, pOldItem->zName); 1036 1036 pNewItem->zAlias = sqlite3DbStrDup(db, pOldItem->zAlias); 1037 - pNewItem->jointype = pOldItem->jointype; 1037 + pNewItem->fg = pOldItem->fg; 1038 1038 pNewItem->iCursor = pOldItem->iCursor; 1039 1039 pNewItem->addrFillSub = pOldItem->addrFillSub; 1040 1040 pNewItem->regReturn = pOldItem->regReturn; 1041 - pNewItem->isCorrelated = pOldItem->isCorrelated; 1042 - pNewItem->viaCoroutine = pOldItem->viaCoroutine; 1043 - pNewItem->isRecursive = pOldItem->isRecursive; 1044 - pNewItem->zIndexedBy = sqlite3DbStrDup(db, pOldItem->zIndexedBy); 1045 - pNewItem->notIndexed = pOldItem->notIndexed; 1046 - pNewItem->pIndex = pOldItem->pIndex; 1041 + if( pNewItem->fg.isIndexedBy ){ 1042 + pNewItem->u1.zIndexedBy = sqlite3DbStrDup(db, pOldItem->u1.zIndexedBy); 1043 + } 1044 + pNewItem->pIBIndex = pOldItem->pIBIndex; 1045 + if( pNewItem->fg.isTabFunc ){ 1046 + pNewItem->u1.pFuncArg = 1047 + sqlite3ExprListDup(db, pOldItem->u1.pFuncArg, flags); 1048 + } 1047 1049 pTab = pNewItem->pTab = pOldItem->pTab; 1048 1050 if( pTab ){ 1049 1051 pTab->nRef++; 1050 1052 } 1051 1053 pNewItem->pSelect = sqlite3SelectDup(db, pOldItem->pSelect, flags); 1052 1054 pNewItem->pOn = sqlite3ExprDup(db, pOldItem->pOn, flags); 1053 1055 pNewItem->pUsing = sqlite3IdListDup(db, pOldItem->pUsing);
Changes to src/main.c.
928 928 /* 929 929 ** Disconnect all sqlite3_vtab objects that belong to database connection 930 930 ** db. This is called when db is being closed. 931 931 */ 932 932 static void disconnectAllVtab(sqlite3 *db){ 933 933 #ifndef SQLITE_OMIT_VIRTUALTABLE 934 934 int i; 935 + HashElem *p; 935 936 sqlite3BtreeEnterAll(db); 936 937 for(i=0; i<db->nDb; i++){ 937 938 Schema *pSchema = db->aDb[i].pSchema; 938 939 if( db->aDb[i].pSchema ){ 939 - HashElem *p; 940 940 for(p=sqliteHashFirst(&pSchema->tblHash); p; p=sqliteHashNext(p)){ 941 941 Table *pTab = (Table *)sqliteHashData(p); 942 942 if( IsVirtual(pTab) ) sqlite3VtabDisconnect(db, pTab); 943 943 } 944 944 } 945 + } 946 + for(p=sqliteHashFirst(&db->aModule); p; p=sqliteHashNext(p)){ 947 + Module *pMod = (Module *)sqliteHashData(p); 948 + if( pMod->pEpoTab ){ 949 + sqlite3VtabDisconnect(db, pMod->pEpoTab); 950 + } 945 951 } 946 952 sqlite3VtabUnlockList(db); 947 953 sqlite3BtreeLeaveAll(db); 948 954 #else 949 955 UNUSED_PARAMETER(db); 950 956 #endif 951 957 } ................................................................................ 1116 1122 sqlite3HashClear(&db->aCollSeq); 1117 1123 #ifndef SQLITE_OMIT_VIRTUALTABLE 1118 1124 for(i=sqliteHashFirst(&db->aModule); i; i=sqliteHashNext(i)){ 1119 1125 Module *pMod = (Module *)sqliteHashData(i); 1120 1126 if( pMod->xDestroy ){ 1121 1127 pMod->xDestroy(pMod->pAux); 1122 1128 } 1129 + sqlite3VtabEponymousTableClear(db, pMod); 1123 1130 sqlite3DbFree(db, pMod); 1124 1131 } 1125 1132 sqlite3HashClear(&db->aModule); 1126 1133 #endif 1127 1134 1128 1135 sqlite3Error(db, SQLITE_OK); /* Deallocates any cached error strings. */ 1129 1136 sqlite3ValueFree(db->pErr);
Changes to src/parse.y.
582 582 } 583 583 584 584 // "seltablist" is a "Select Table List" - the content of the FROM clause 585 585 // in a SELECT statement. "stl_prefix" is a prefix of this list. 586 586 // 587 587 stl_prefix(A) ::= seltablist(X) joinop(Y). { 588 588 A = X; 589 - if( ALWAYS(A && A->nSrc>0) ) A->a[A->nSrc-1].jointype = (u8)Y; 589 + if( ALWAYS(A && A->nSrc>0) ) A->a[A->nSrc-1].fg.jointype = (u8)Y; 590 590 } 591 591 stl_prefix(A) ::= . {A = 0;} 592 592 seltablist(A) ::= stl_prefix(X) nm(Y) dbnm(D) as(Z) indexed_opt(I) 593 593 on_opt(N) using_opt(U). { 594 594 A = sqlite3SrcListAppendFromTerm(pParse,X,&Y,&D,&Z,0,N,U); 595 595 sqlite3SrcListIndexedBy(pParse, A, &I); 596 +} 597 +seltablist(A) ::= stl_prefix(X) nm(Y) dbnm(D) LP exprlist(E) RP as(Z) 598 + on_opt(N) using_opt(U). { 599 + A = sqlite3SrcListAppendFromTerm(pParse,X,&Y,&D,&Z,0,N,U); 600 + sqlite3SrcListFuncArgs(pParse, A, E); 596 601 } 597 602 %ifndef SQLITE_OMIT_SUBQUERY 598 603 seltablist(A) ::= stl_prefix(X) LP select(S) RP 599 604 as(Z) on_opt(N) using_opt(U). { 600 605 A = sqlite3SrcListAppendFromTerm(pParse,X,0,0,&Z,S,N,U); 601 606 } 602 607 seltablist(A) ::= stl_prefix(X) LP seltablist(F) RP
Changes to src/resolve.c.
302 302 for(j=0, pCol=pTab->aCol; j<pTab->nCol; j++, pCol++){ 303 303 if( sqlite3StrICmp(pCol->zName, zCol)==0 ){ 304 304 /* If there has been exactly one prior match and this match 305 305 ** is for the right-hand table of a NATURAL JOIN or is in a 306 306 ** USING clause, then skip this match. 307 307 */ 308 308 if( cnt==1 ){ 309 - if( pItem->jointype & JT_NATURAL ) continue; 309 + if( pItem->fg.jointype & JT_NATURAL ) continue; 310 310 if( nameInUsingClause(pItem->pUsing, zCol) ) continue; 311 311 } 312 312 cnt++; 313 313 pMatch = pItem; 314 314 /* Substitute the rowid (column -1) for the INTEGER PRIMARY KEY */ 315 315 pExpr->iColumn = j==pTab->iPKey ? -1 : (i16)j; 316 316 break; ................................................................................ 317 317 } 318 318 } 319 319 } 320 320 if( pMatch ){ 321 321 pExpr->iTable = pMatch->iCursor; 322 322 pExpr->pTab = pMatch->pTab; 323 323 /* RIGHT JOIN not (yet) supported */ 324 - assert( (pMatch->jointype & JT_RIGHT)==0 ); 325 - if( (pMatch->jointype & JT_LEFT)!=0 ){ 324 + assert( (pMatch->fg.jointype & JT_RIGHT)==0 ); 325 + if( (pMatch->fg.jointype & JT_LEFT)!=0 ){ 326 326 ExprSetProperty(pExpr, EP_CanBeNull); 327 327 } 328 328 pSchema = pExpr->pTab->pSchema; 329 329 } 330 330 } /* if( pSrcList ) */ 331 331 332 332 #ifndef SQLITE_OMIT_TRIGGER ................................................................................ 1138 1138 */ 1139 1139 static int resolveSelectStep(Walker *pWalker, Select *p){ 1140 1140 NameContext *pOuterNC; /* Context that contains this SELECT */ 1141 1141 NameContext sNC; /* Name context of this SELECT */ 1142 1142 int isCompound; /* True if p is a compound select */ 1143 1143 int nCompound; /* Number of compound terms processed so far */ 1144 1144 Parse *pParse; /* Parsing context */ 1145 - ExprList *pEList; /* Result set expression list */ 1146 1145 int i; /* Loop counter */ 1147 1146 ExprList *pGroupBy; /* The GROUP BY clause */ 1148 1147 Select *pLeftmost; /* Left-most of SELECT of a compound */ 1149 1148 sqlite3 *db; /* Database connection */ 1150 1149 1151 1150 1152 1151 assert( p!=0 ); ................................................................................ 1211 1210 int nRef = 0; /* Refcount for pOuterNC and outer contexts */ 1212 1211 const char *zSavedContext = pParse->zAuthContext; 1213 1212 1214 1213 /* Count the total number of references to pOuterNC and all of its 1215 1214 ** parent contexts. After resolving references to expressions in 1216 1215 ** pItem->pSelect, check if this value has changed. If so, then 1217 1216 ** SELECT statement pItem->pSelect must be correlated. Set the 1218 - ** pItem->isCorrelated flag if this is the case. */ 1217 + ** pItem->fg.isCorrelated flag if this is the case. */ 1219 1218 for(pNC=pOuterNC; pNC; pNC=pNC->pNext) nRef += pNC->nRef; 1220 1219 1221 1220 if( pItem->zName ) pParse->zAuthContext = pItem->zName; 1222 1221 sqlite3ResolveSelectNames(pParse, pItem->pSelect, pOuterNC); 1223 1222 pParse->zAuthContext = zSavedContext; 1224 1223 if( pParse->nErr || db->mallocFailed ) return WRC_Abort; 1225 1224 1226 1225 for(pNC=pOuterNC; pNC; pNC=pNC->pNext) nRef -= pNC->nRef; 1227 - assert( pItem->isCorrelated==0 && nRef<=0 ); 1228 - pItem->isCorrelated = (nRef!=0); 1226 + assert( pItem->fg.isCorrelated==0 && nRef<=0 ); 1227 + pItem->fg.isCorrelated = (nRef!=0); 1229 1228 } 1230 1229 } 1231 1230 1232 1231 /* Set up the local name-context to pass to sqlite3ResolveExprNames() to 1233 1232 ** resolve the result-set expression list. 1234 1233 */ 1235 1234 sNC.ncFlags = NC_AllowAgg; 1236 1235 sNC.pSrcList = p->pSrc; 1237 1236 sNC.pNext = pOuterNC; 1238 1237 1239 1238 /* Resolve names in the result set. */ 1240 - pEList = p->pEList; 1241 - assert( pEList!=0 ); 1242 - for(i=0; i<pEList->nExpr; i++){ 1243 - Expr *pX = pEList->a[i].pExpr; 1244 - if( sqlite3ResolveExprNames(&sNC, pX) ){ 1245 - return WRC_Abort; 1246 - } 1247 - } 1239 + if( sqlite3ResolveExprListNames(&sNC, p->pEList) ) return WRC_Abort; 1248 1240 1249 1241 /* If there are no aggregate functions in the result-set, and no GROUP BY 1250 1242 ** expression, do not allow aggregates in any of the other expressions. 1251 1243 */ 1252 1244 assert( (p->selFlags & SF_Aggregate)==0 ); 1253 1245 pGroupBy = p->pGroupBy; 1254 1246 if( pGroupBy || (sNC.ncFlags & NC_HasAgg)!=0 ){ ................................................................................ 1272 1264 ** 1273 1265 ** Minor point: If this is the case, then the expression will be 1274 1266 ** re-evaluated for each reference to it. 1275 1267 */ 1276 1268 sNC.pEList = p->pEList; 1277 1269 if( sqlite3ResolveExprNames(&sNC, p->pHaving) ) return WRC_Abort; 1278 1270 if( sqlite3ResolveExprNames(&sNC, p->pWhere) ) return WRC_Abort; 1271 + 1272 + /* Resolve names in table-valued-function arguments */ 1273 + for(i=0; i<p->pSrc->nSrc; i++){ 1274 + struct SrcList_item *pItem = &p->pSrc->a[i]; 1275 + if( pItem->fg.isTabFunc 1276 + && sqlite3ResolveExprListNames(&sNC, pItem->u1.pFuncArg) 1277 + ){ 1278 + return WRC_Abort; 1279 + } 1280 + } 1279 1281 1280 1282 /* The ORDER BY and GROUP BY clauses may not refer to terms in 1281 1283 ** outer queries 1282 1284 */ 1283 1285 sNC.pNext = 0; 1284 1286 sNC.ncFlags |= NC_AllowAgg; 1285 1287 ................................................................................ 1436 1438 if( pNC->ncFlags & NC_HasAgg ){ 1437 1439 ExprSetProperty(pExpr, EP_Agg); 1438 1440 } 1439 1441 pNC->ncFlags |= savedHasAgg; 1440 1442 return ExprHasProperty(pExpr, EP_Error); 1441 1443 } 1442 1444 1445 +/* 1446 +** Resolve all names for all expression in an expression list. This is 1447 +** just like sqlite3ResolveExprNames() except that it works for an expression 1448 +** list rather than a single expression. 1449 +*/ 1450 +int sqlite3ResolveExprListNames( 1451 + NameContext *pNC, /* Namespace to resolve expressions in. */ 1452 + ExprList *pList /* The expression list to be analyzed. */ 1453 +){ 1454 + int i; 1455 + for(i=0; i<pList->nExpr; i++){ 1456 + if( sqlite3ResolveExprNames(pNC, pList->a[i].pExpr) ) return WRC_Abort; 1457 + } 1458 + return WRC_Continue; 1459 +} 1443 1460 1444 1461 /* 1445 1462 ** Resolve all names in all expressions of a SELECT and in all 1446 1463 ** decendents of the SELECT, including compounds off of p->pPrior, 1447 1464 ** subqueries in expressions, and subqueries used as FROM clause 1448 1465 ** terms. 1449 1466 **
Changes to src/select.c.
402 402 pRight = &pLeft[1]; 403 403 for(i=0; i<pSrc->nSrc-1; i++, pRight++, pLeft++){ 404 404 Table *pLeftTab = pLeft->pTab; 405 405 Table *pRightTab = pRight->pTab; 406 406 int isOuter; 407 407 408 408 if( NEVER(pLeftTab==0 || pRightTab==0) ) continue; 409 - isOuter = (pRight->jointype & JT_OUTER)!=0; 409 + isOuter = (pRight->fg.jointype & JT_OUTER)!=0; 410 410 411 411 /* When the NATURAL keyword is present, add WHERE clause terms for 412 412 ** every column that the two tables have in common. 413 413 */ 414 - if( pRight->jointype & JT_NATURAL ){ 414 + if( pRight->fg.jointype & JT_NATURAL ){ 415 415 if( pRight->pOn || pRight->pUsing ){ 416 416 sqlite3ErrorMsg(pParse, "a NATURAL join may not have " 417 417 "an ON or USING clause", 0); 418 418 return 1; 419 419 } 420 420 for(j=0; j<pRightTab->nCol; j++){ 421 421 char *zName; /* Name of column in the right table */ ................................................................................ 1929 1929 ** 1930 1930 ** <recursive-table> AS (<setup-query> UNION [ALL] <recursive-query>) 1931 1931 ** \___________/ \_______________/ 1932 1932 ** p->pPrior p 1933 1933 ** 1934 1934 ** 1935 1935 ** There is exactly one reference to the recursive-table in the FROM clause 1936 -** of recursive-query, marked with the SrcList->a[].isRecursive flag. 1936 +** of recursive-query, marked with the SrcList->a[].fg.isRecursive flag. 1937 1937 ** 1938 1938 ** The setup-query runs once to generate an initial set of rows that go 1939 1939 ** into a Queue table. Rows are extracted from the Queue table one by 1940 1940 ** one. Each row extracted from Queue is output to pDest. Then the single 1941 1941 ** extracted row (now in the iCurrent table) becomes the content of the 1942 1942 ** recursive-table for a recursive-query run. The output of the recursive-query 1943 1943 ** is added back into the Queue table. Then another row is extracted from Queue ................................................................................ 1994 1994 regOffset = p->iOffset; 1995 1995 p->pLimit = p->pOffset = 0; 1996 1996 p->iLimit = p->iOffset = 0; 1997 1997 pOrderBy = p->pOrderBy; 1998 1998 1999 1999 /* Locate the cursor number of the Current table */ 2000 2000 for(i=0; ALWAYS(i<pSrc->nSrc); i++){ 2001 - if( pSrc->a[i].isRecursive ){ 2001 + if( pSrc->a[i].fg.isRecursive ){ 2002 2002 iCurrent = pSrc->a[i].iCursor; 2003 2003 break; 2004 2004 } 2005 2005 } 2006 2006 2007 2007 /* Allocate cursors numbers for Queue and Distinct. The cursor number for 2008 2008 ** the Distinct table must be exactly one greater than Queue in order ................................................................................ 3409 3409 ** effectively converts the OUTER JOIN into an INNER JOIN. 3410 3410 ** 3411 3411 ** THIS OVERRIDES OBSOLETE COMMENTS 1 AND 2 ABOVE: 3412 3412 ** Ticket #3300 shows that flattening the right term of a LEFT JOIN 3413 3413 ** is fraught with danger. Best to avoid the whole thing. If the 3414 3414 ** subquery is the right term of a LEFT JOIN, then do not flatten. 3415 3415 */ 3416 - if( (pSubitem->jointype & JT_OUTER)!=0 ){ 3416 + if( (pSubitem->fg.jointype & JT_OUTER)!=0 ){ 3417 3417 return 0; 3418 3418 } 3419 3419 3420 3420 /* Restriction 17: If the sub-query is a compound SELECT, then it must 3421 3421 ** use only the UNION ALL operator. And none of the simple select queries 3422 3422 ** that make up the compound SELECT are allowed to be aggregate or distinct 3423 3423 ** queries. ................................................................................ 3580 3580 u8 jointype = 0; 3581 3581 pSubSrc = pSub->pSrc; /* FROM clause of subquery */ 3582 3582 nSubSrc = pSubSrc->nSrc; /* Number of terms in subquery FROM clause */ 3583 3583 pSrc = pParent->pSrc; /* FROM clause of the outer query */ 3584 3584 3585 3585 if( pSrc ){ 3586 3586 assert( pParent==p ); /* First time through the loop */ 3587 - jointype = pSubitem->jointype; 3587 + jointype = pSubitem->fg.jointype; 3588 3588 }else{ 3589 3589 assert( pParent!=p ); /* 2nd and subsequent times through the loop */ 3590 3590 pSrc = pParent->pSrc = sqlite3SrcListAppend(db, 0, 0, 0); 3591 3591 if( pSrc==0 ){ 3592 3592 assert( db->mallocFailed ); 3593 3593 break; 3594 3594 } ................................................................................ 3620 3620 ** outer query. 3621 3621 */ 3622 3622 for(i=0; i<nSubSrc; i++){ 3623 3623 sqlite3IdListDelete(db, pSrc->a[i+iFrom].pUsing); 3624 3624 pSrc->a[i+iFrom] = pSubSrc->a[i]; 3625 3625 memset(&pSubSrc->a[i], 0, sizeof(pSubSrc->a[i])); 3626 3626 } 3627 - pSrc->a[iFrom].jointype = jointype; 3627 + pSrc->a[iFrom].fg.jointype = jointype; 3628 3628 3629 3629 /* Now begin substituting subquery result set expressions for 3630 3630 ** references to the iParent in the outer query. 3631 3631 ** 3632 3632 ** Example: 3633 3633 ** 3634 3634 ** SELECT a+5, b*10 FROM (SELECT x*3 AS a, y+10 AS b FROM t1) WHERE a>b; ................................................................................ 3871 3871 ** If the source-list item passed as an argument was augmented with an 3872 3872 ** INDEXED BY clause, then try to locate the specified index. If there 3873 3873 ** was such a clause and the named index cannot be found, return 3874 3874 ** SQLITE_ERROR and leave an error in pParse. Otherwise, populate 3875 3875 ** pFrom->pIndex and return SQLITE_OK. 3876 3876 */ 3877 3877 int sqlite3IndexedByLookup(Parse *pParse, struct SrcList_item *pFrom){ 3878 - if( pFrom->pTab && pFrom->zIndexedBy ){ 3878 + if( pFrom->pTab && pFrom->fg.isIndexedBy ){ 3879 3879 Table *pTab = pFrom->pTab; 3880 - char *zIndexedBy = pFrom->zIndexedBy; 3880 + char *zIndexedBy = pFrom->u1.zIndexedBy; 3881 3881 Index *pIdx; 3882 3882 for(pIdx=pTab->pIndex; 3883 3883 pIdx && sqlite3StrICmp(pIdx->zName, zIndexedBy); 3884 3884 pIdx=pIdx->pNext 3885 3885 ); 3886 3886 if( !pIdx ){ 3887 3887 sqlite3ErrorMsg(pParse, "no such index: %s", zIndexedBy, 0); 3888 3888 pParse->checkSchema = 1; 3889 3889 return SQLITE_ERROR; 3890 3890 } 3891 - pFrom->pIndex = pIdx; 3891 + pFrom->pIBIndex = pIdx; 3892 3892 } 3893 3893 return SQLITE_OK; 3894 3894 } 3895 3895 /* 3896 3896 ** Detect compound SELECT statements that use an ORDER BY clause with 3897 3897 ** an alternative collating sequence. 3898 3898 ** ................................................................................ 4079 4079 for(i=0; i<pSrc->nSrc; i++){ 4080 4080 struct SrcList_item *pItem = &pSrc->a[i]; 4081 4081 if( pItem->zDatabase==0 4082 4082 && pItem->zName!=0 4083 4083 && 0==sqlite3StrICmp(pItem->zName, pCte->zName) 4084 4084 ){ 4085 4085 pItem->pTab = pTab; 4086 - pItem->isRecursive = 1; 4086 + pItem->fg.isRecursive = 1; 4087 4087 pTab->nRef++; 4088 4088 pSel->selFlags |= SF_Recursive; 4089 4089 } 4090 4090 } 4091 4091 } 4092 4092 4093 4093 /* Only one recursive reference is permitted. */ ................................................................................ 4209 4209 4210 4210 /* Look up every table named in the FROM clause of the select. If 4211 4211 ** an entry of the FROM clause is a subquery instead of a table or view, 4212 4212 ** then create a transient table structure to describe the subquery. 4213 4213 */ 4214 4214 for(i=0, pFrom=pTabList->a; i<pTabList->nSrc; i++, pFrom++){ 4215 4215 Table *pTab; 4216 - assert( pFrom->isRecursive==0 || pFrom->pTab ); 4217 - if( pFrom->isRecursive ) continue; 4216 + assert( pFrom->fg.isRecursive==0 || pFrom->pTab ); 4217 + if( pFrom->fg.isRecursive ) continue; 4218 4218 if( pFrom->pTab!=0 ){ 4219 4219 /* This statement has already been prepared. There is no need 4220 4220 ** to go further. */ 4221 4221 assert( i==0 ); 4222 4222 #ifndef SQLITE_OMIT_CTE 4223 4223 selectPopWith(pWalker, p); 4224 4224 #endif ................................................................................ 4373 4373 if( IsHiddenColumn(&pTab->aCol[j]) ){ 4374 4374 assert(IsVirtual(pTab)); 4375 4375 continue; 4376 4376 } 4377 4377 tableSeen = 1; 4378 4378 4379 4379 if( i>0 && zTName==0 ){ 4380 - if( (pFrom->jointype & JT_NATURAL)!=0 4380 + if( (pFrom->fg.jointype & JT_NATURAL)!=0 4381 4381 && tableAndColumnIndex(pTabList, i, zName, 0, 0) 4382 4382 ){ 4383 4383 /* In a NATURAL join, omit the join columns from the 4384 4384 ** table to the right of the join */ 4385 4385 continue; 4386 4386 } 4387 4387 if( sqlite3IdListIndex(pFrom->pUsing, zName)>=0 ){ ................................................................................ 4900 4900 /* Sometimes the code for a subquery will be generated more than 4901 4901 ** once, if the subquery is part of the WHERE clause in a LEFT JOIN, 4902 4902 ** for example. In that case, do not regenerate the code to manifest 4903 4903 ** a view or the co-routine to implement a view. The first instance 4904 4904 ** is sufficient, though the subroutine to manifest the view does need 4905 4905 ** to be invoked again. */ 4906 4906 if( pItem->addrFillSub ){ 4907 - if( pItem->viaCoroutine==0 ){ 4907 + if( pItem->fg.viaCoroutine==0 ){ 4908 4908 sqlite3VdbeAddOp2(v, OP_Gosub, pItem->regReturn, pItem->addrFillSub); 4909 4909 } 4910 4910 continue; 4911 4911 } 4912 4912 4913 4913 /* Increment Parse.nHeight by the height of the largest expression 4914 4914 ** tree referred to by this, the parent select. The child select ................................................................................ 4918 4918 ** an exact limit. 4919 4919 */ 4920 4920 pParse->nHeight += sqlite3SelectExprHeight(p); 4921 4921 4922 4922 /* Make copies of constant WHERE-clause terms in the outer query down 4923 4923 ** inside the subquery. This can help the subquery to run more efficiently. 4924 4924 */ 4925 - if( (pItem->jointype & JT_OUTER)==0 4925 + if( (pItem->fg.jointype & JT_OUTER)==0 4926 4926 && pushDownWhereTerms(db, pSub, p->pWhere, pItem->iCursor) 4927 4927 ){ 4928 4928 #if SELECTTRACE_ENABLED 4929 4929 if( sqlite3SelectTrace & 0x100 ){ 4930 4930 SELECTTRACE(0x100,pParse,p,("After WHERE-clause push-down:\n")); 4931 4931 sqlite3TreeViewSelect(0, p, 0); 4932 4932 } ................................................................................ 4947 4947 sqlite3VdbeAddOp3(v, OP_InitCoroutine, pItem->regReturn, 0, addrTop); 4948 4948 VdbeComment((v, "%s", pItem->pTab->zName)); 4949 4949 pItem->addrFillSub = addrTop; 4950 4950 sqlite3SelectDestInit(&dest, SRT_Coroutine, pItem->regReturn); 4951 4951 explainSetInteger(pItem->iSelectId, (u8)pParse->iNextSelectId); 4952 4952 sqlite3Select(pParse, pSub, &dest); 4953 4953 pItem->pTab->nRowLogEst = sqlite3LogEst(pSub->nSelectRow); 4954 - pItem->viaCoroutine = 1; 4954 + pItem->fg.viaCoroutine = 1; 4955 4955 pItem->regResult = dest.iSdst; 4956 4956 sqlite3VdbeAddOp1(v, OP_EndCoroutine, pItem->regReturn); 4957 4957 sqlite3VdbeJumpHere(v, addrTop-1); 4958 4958 sqlite3ClearTempRegCache(pParse); 4959 4959 }else{ 4960 4960 /* Generate a subroutine that will fill an ephemeral table with 4961 4961 ** the content of this subquery. pItem->addrFillSub will point ................................................................................ 4965 4965 int topAddr; 4966 4966 int onceAddr = 0; 4967 4967 int retAddr; 4968 4968 assert( pItem->addrFillSub==0 ); 4969 4969 pItem->regReturn = ++pParse->nMem; 4970 4970 topAddr = sqlite3VdbeAddOp2(v, OP_Integer, 0, pItem->regReturn); 4971 4971 pItem->addrFillSub = topAddr+1; 4972 - if( pItem->isCorrelated==0 ){ 4972 + if( pItem->fg.isCorrelated==0 ){ 4973 4973 /* If the subquery is not correlated and if we are not inside of 4974 4974 ** a trigger, then we only need to compute the value of the subquery 4975 4975 ** once. */ 4976 4976 onceAddr = sqlite3CodeOnce(pParse); VdbeCoverage(v); 4977 4977 VdbeComment((v, "materialize \"%s\"", pItem->pTab->zName)); 4978 4978 }else{ 4979 4979 VdbeNoopComment((v, "materialize \"%s\"", pItem->pTab->zName));
Changes to src/sqliteInt.h.
1475 1475 ** hash table. 1476 1476 */ 1477 1477 struct Module { 1478 1478 const sqlite3_module *pModule; /* Callback pointers */ 1479 1479 const char *zName; /* Name passed to create_module() */ 1480 1480 void *pAux; /* pAux passed to create_module() */ 1481 1481 void (*xDestroy)(void *); /* Module destructor function */ 1482 + Table *pEpoTab; /* Eponymous table for this module */ 1482 1483 }; 1483 1484 1484 1485 /* 1485 1486 ** information about each column of an SQL table is held in an instance 1486 1487 ** of this structure. 1487 1488 */ 1488 1489 struct Column { ................................................................................ 1645 1646 u8 tabFlags; /* Mask of TF_* values */ 1646 1647 u8 keyConf; /* What to do in case of uniqueness conflict on iPKey */ 1647 1648 #ifndef SQLITE_OMIT_ALTERTABLE 1648 1649 int addColOffset; /* Offset in CREATE TABLE stmt to add a new column */ 1649 1650 #endif 1650 1651 #ifndef SQLITE_OMIT_VIRTUALTABLE 1651 1652 int nModuleArg; /* Number of arguments to the module */ 1652 - char **azModuleArg; /* Text of all module args. [0] is module name */ 1653 + char **azModuleArg; /* 0: module 1: schema 2: vtab name 3...: args */ 1653 1654 VTable *pVTable; /* List of VTable objects. */ 1654 1655 #endif 1655 1656 Trigger *pTrigger; /* List of triggers stored in pSchema */ 1656 1657 Schema *pSchema; /* Schema that contains this table */ 1657 1658 Table *pNextZombie; /* Next on the Parse.pZombieTab list */ 1658 1659 }; 1659 1660 ................................................................................ 2280 2281 char *zName; /* Name of the table */ 2281 2282 char *zAlias; /* The "B" part of a "A AS B" phrase. zName is the "A" */ 2282 2283 Table *pTab; /* An SQL table corresponding to zName */ 2283 2284 Select *pSelect; /* A SELECT statement used in place of a table name */ 2284 2285 int addrFillSub; /* Address of subroutine to manifest a subquery */ 2285 2286 int regReturn; /* Register holding return address of addrFillSub */ 2286 2287 int regResult; /* Registers holding results of a co-routine */ 2287 - u8 jointype; /* Type of join between this able and the previous */ 2288 - unsigned notIndexed :1; /* True if there is a NOT INDEXED clause */ 2289 - unsigned isCorrelated :1; /* True if sub-query is correlated */ 2290 - unsigned viaCoroutine :1; /* Implemented as a co-routine */ 2291 - unsigned isRecursive :1; /* True for recursive reference in WITH */ 2288 + struct { 2289 + u8 jointype; /* Type of join between this able and the previous */ 2290 + unsigned notIndexed :1; /* True if there is a NOT INDEXED clause */ 2291 + unsigned isIndexedBy :1; /* True if there is an INDEXED BY clause */ 2292 + unsigned isTabFunc :1; /* True if table-valued-function syntax */ 2293 + unsigned isCorrelated :1; /* True if sub-query is correlated */ 2294 + unsigned viaCoroutine :1; /* Implemented as a co-routine */ 2295 + unsigned isRecursive :1; /* True for recursive reference in WITH */ 2296 + } fg; 2292 2297 #ifndef SQLITE_OMIT_EXPLAIN 2293 2298 u8 iSelectId; /* If pSelect!=0, the id of the sub-select in EQP */ 2294 2299 #endif 2295 2300 int iCursor; /* The VDBE cursor number used to access this table */ 2296 2301 Expr *pOn; /* The ON clause of a join */ 2297 2302 IdList *pUsing; /* The USING clause of a join */ 2298 2303 Bitmask colUsed; /* Bit N (1<<N) set if column N of pTab is used */ 2299 - char *zIndexedBy; /* Identifier from "INDEXED BY <zIndex>" clause */ 2300 - Index *pIndex; /* Index structure corresponding to zIndex, if any */ 2304 + union { 2305 + char *zIndexedBy; /* Identifier from "INDEXED BY <zIndex>" clause */ 2306 + ExprList *pFuncArg; /* Arguments to table-valued-function */ 2307 + } u1; 2308 + Index *pIBIndex; /* Index structure corresponding to u1.zIndexedBy */ 2301 2309 } a[1]; /* One entry for each identifier on the list */ 2302 2310 }; 2303 2311 2304 2312 /* 2305 2313 ** Permitted values of the SrcList.a.jointype field 2306 2314 */ 2307 2315 #define JT_INNER 0x0001 /* Any kind of inner or cross join */ ................................................................................ 3244 3252 int sqlite3InitCallback(void*, int, char**, char**); 3245 3253 void sqlite3Pragma(Parse*,Token*,Token*,Token*,int); 3246 3254 void sqlite3ResetAllSchemasOfConnection(sqlite3*); 3247 3255 void sqlite3ResetOneSchema(sqlite3*,int); 3248 3256 void sqlite3CollapseDatabaseArray(sqlite3*); 3249 3257 void sqlite3BeginParse(Parse*,int); 3250 3258 void sqlite3CommitInternalChanges(sqlite3*); 3259 +void sqlite3DeleteColumnNames(sqlite3*,Table*); 3251 3260 Table *sqlite3ResultSetOfSelect(Parse*,Select*); 3252 3261 void sqlite3OpenMasterTable(Parse *, int); 3253 3262 Index *sqlite3PrimaryKeyIndex(Table*); 3254 3263 i16 sqlite3ColumnOfIndex(Index*, i16); 3255 3264 void sqlite3StartTable(Parse*,Token*,Token*,int,int,int,int); 3256 3265 void sqlite3AddColumn(Parse*,Token*); 3257 3266 void sqlite3AddNotNull(Parse*, int); ................................................................................ 3315 3324 IdList *sqlite3IdListAppend(sqlite3*, IdList*, Token*); 3316 3325 int sqlite3IdListIndex(IdList*,const char*); 3317 3326 SrcList *sqlite3SrcListEnlarge(sqlite3*, SrcList*, int, int); 3318 3327 SrcList *sqlite3SrcListAppend(sqlite3*, SrcList*, Token*, Token*); 3319 3328 SrcList *sqlite3SrcListAppendFromTerm(Parse*, SrcList*, Token*, Token*, 3320 3329 Token*, Select*, Expr*, IdList*); 3321 3330 void sqlite3SrcListIndexedBy(Parse *, SrcList *, Token *); 3331 +void sqlite3SrcListFuncArgs(Parse*, SrcList*, ExprList*); 3322 3332 int sqlite3IndexedByLookup(Parse *, struct SrcList_item *); 3323 3333 void sqlite3SrcListShiftJoinType(SrcList*); 3324 3334 void sqlite3SrcListAssignCursors(Parse*, SrcList*); 3325 3335 void sqlite3IdListDelete(sqlite3*, IdList*); 3326 3336 void sqlite3SrcListDelete(sqlite3*, SrcList*); 3327 3337 Index *sqlite3AllocateIndexObject(sqlite3*,i16,int,char**); 3328 3338 Index *sqlite3CreateIndex(Parse*,Token*,Token*,SrcList*,ExprList*,int,Token*, ................................................................................ 3606 3616 void sqlite3NestedParse(Parse*, const char*, ...); 3607 3617 void sqlite3ExpirePreparedStatements(sqlite3*); 3608 3618 int sqlite3CodeSubselect(Parse *, Expr *, int, int); 3609 3619 void sqlite3SelectPrep(Parse*, Select*, NameContext*); 3610 3620 void sqlite3SelectWrongNumTermsError(Parse *pParse, Select *p); 3611 3621 int sqlite3MatchSpanName(const char*, const char*, const char*, const char*); 3612 3622 int sqlite3ResolveExprNames(NameContext*, Expr*); 3623 +int sqlite3ResolveExprListNames(NameContext*, ExprList*); 3613 3624 void sqlite3ResolveSelectNames(Parse*, Select*, NameContext*); 3614 3625 void sqlite3ResolveSelfReference(Parse*,Table*,int,Expr*,ExprList*); 3615 3626 int sqlite3ResolveOrderGroupBy(Parse*, Select*, ExprList*, const char*); 3616 3627 void sqlite3ColumnDefault(Vdbe *, Table *, int, int); 3617 3628 void sqlite3AlterFinishAddColumn(Parse *, Token *); 3618 3629 void sqlite3AlterBeginAddColumn(Parse *, SrcList *); 3619 3630 CollSeq *sqlite3GetCollSeq(Parse*, u8, CollSeq *, const char*); ................................................................................ 3714 3725 void sqlite3VtabUnlock(VTable *); 3715 3726 void sqlite3VtabUnlockList(sqlite3*); 3716 3727 int sqlite3VtabSavepoint(sqlite3 *, int, int); 3717 3728 void sqlite3VtabImportErrmsg(Vdbe*, sqlite3_vtab*); 3718 3729 VTable *sqlite3GetVTable(sqlite3*, Table*); 3719 3730 # define sqlite3VtabInSync(db) ((db)->nVTrans>0 && (db)->aVTrans==0) 3720 3731 #endif 3732 +int sqlite3VtabEponymousTableInit(Parse*,Module*); 3733 +void sqlite3VtabEponymousTableClear(sqlite3*,Module*); 3721 3734 void sqlite3VtabMakeWritable(Parse*,Table*); 3722 3735 void sqlite3VtabBeginParse(Parse*, Token*, Token*, Token*, int); 3723 3736 void sqlite3VtabFinishParse(Parse*, Token*); 3724 3737 void sqlite3VtabArgInit(Parse*); 3725 3738 void sqlite3VtabArgExtend(Parse*, Token*); 3726 3739 int sqlite3VtabCallCreate(sqlite3*, int, const char *, char **); 3727 3740 int sqlite3VtabCallConnect(Parse*, Table*);
Changes to src/test1.c.
6376 6376 extern int sqlite3_eval_init(sqlite3*,char**,const sqlite3_api_routines*); 6377 6377 extern int sqlite3_fileio_init(sqlite3*,char**,const sqlite3_api_routines*); 6378 6378 extern int sqlite3_fuzzer_init(sqlite3*,char**,const sqlite3_api_routines*); 6379 6379 extern int sqlite3_ieee_init(sqlite3*,char**,const sqlite3_api_routines*); 6380 6380 extern int sqlite3_nextchar_init(sqlite3*,char**,const sqlite3_api_routines*); 6381 6381 extern int sqlite3_percentile_init(sqlite3*,char**,const sqlite3_api_routines*); 6382 6382 extern int sqlite3_regexp_init(sqlite3*,char**,const sqlite3_api_routines*); 6383 + extern int sqlite3_series_init(sqlite3*,char**,const sqlite3_api_routines*); 6383 6384 extern int sqlite3_spellfix_init(sqlite3*,char**,const sqlite3_api_routines*); 6384 6385 extern int sqlite3_totype_init(sqlite3*,char**,const sqlite3_api_routines*); 6385 6386 extern int sqlite3_wholenumber_init(sqlite3*,char**,const sqlite3_api_routines*); 6386 6387 extern int sqlite3_fts5_init(sqlite3*,char**,const sqlite3_api_routines*); 6387 6388 static const struct { 6388 6389 const char *zExtName; 6389 6390 int (*pInit)(sqlite3*,char**,const sqlite3_api_routines*); ................................................................................ 6396 6397 #endif 6397 6398 { "fileio", sqlite3_fileio_init }, 6398 6399 { "fuzzer", sqlite3_fuzzer_init }, 6399 6400 { "ieee754", sqlite3_ieee_init }, 6400 6401 { "nextchar", sqlite3_nextchar_init }, 6401 6402 { "percentile", sqlite3_percentile_init }, 6402 6403 { "regexp", sqlite3_regexp_init }, 6404 + { "series", sqlite3_series_init }, 6403 6405 { "spellfix", sqlite3_spellfix_init }, 6404 6406 { "totype", sqlite3_totype_init }, 6405 6407 { "wholenumber", sqlite3_wholenumber_init }, 6406 6408 }; 6407 6409 sqlite3 *db; 6408 6410 const char *zName; 6409 6411 int i, j, rc;
Changes to src/treeview.c.
116 116 } 117 117 if( pItem->pTab ){ 118 118 sqlite3XPrintf(&x, 0, " tabname=%Q", pItem->pTab->zName); 119 119 } 120 120 if( pItem->zAlias ){ 121 121 sqlite3XPrintf(&x, 0, " (AS %s)", pItem->zAlias); 122 122 } 123 - if( pItem->jointype & JT_LEFT ){ 123 + if( pItem->fg.jointype & JT_LEFT ){ 124 124 sqlite3XPrintf(&x, 0, " LEFT-JOIN"); 125 125 } 126 126 sqlite3StrAccumFinish(&x); 127 127 sqlite3TreeViewItem(pView, zLine, i<p->pSrc->nSrc-1); 128 128 if( pItem->pSelect ){ 129 129 sqlite3TreeViewSelect(pView, pItem->pSelect, 0); 130 130 } 131 + if( pItem->fg.isTabFunc ){ 132 + sqlite3TreeViewExprList(pView, pItem->u1.pFuncArg, 0, "func-args:"); 133 + } 131 134 sqlite3TreeViewPop(pView); 132 135 } 133 136 sqlite3TreeViewPop(pView); 134 137 } 135 138 if( p->pWhere ){ 136 139 sqlite3TreeViewItem(pView, "WHERE", (n--)>0); 137 140 sqlite3TreeViewExpr(pView, p->pWhere, 0);
Changes to src/vtab.c.
54 54 Module *pDel; 55 55 char *zCopy = (char *)(&pMod[1]); 56 56 memcpy(zCopy, zName, nName+1); 57 57 pMod->zName = zCopy; 58 58 pMod->pModule = pModule; 59 59 pMod->pAux = pAux; 60 60 pMod->xDestroy = xDestroy; 61 + pMod->pEpoTab = 0; 61 62 pDel = (Module *)sqlite3HashInsert(&db->aModule,zCopy,(void*)pMod); 62 63 assert( pDel==0 || pDel==pMod ); 63 64 if( pDel ){ 64 65 db->mallocFailed = 1; 65 66 sqlite3DbFree(db, pDel); 66 67 } 67 68 } ................................................................................ 694 695 zMod = pTab->azModuleArg[0]; 695 696 pMod = (Module*)sqlite3HashFind(&db->aModule, zMod); 696 697 697 698 /* If the module has been registered and includes a Create method, 698 699 ** invoke it now. If the module has not been registered, return an 699 700 ** error. Otherwise, do nothing. 700 701 */ 701 - if( !pMod ){ 702 + if( pMod==0 || pMod->pModule->xCreate==0 ){ 702 703 *pzErr = sqlite3MPrintf(db, "no such module: %s", zMod); 703 704 rc = SQLITE_ERROR; 704 705 }else{ 705 706 rc = vtabCallConstructor(db, pTab, pMod, pMod->pModule->xCreate, pzErr); 706 707 } 707 708 708 709 /* Justification of ALWAYS(): The xConstructor method is required to ................................................................................ 1081 1082 if( apVtabLock ){ 1082 1083 pToplevel->apVtabLock = apVtabLock; 1083 1084 pToplevel->apVtabLock[pToplevel->nVtabLock++] = pTab; 1084 1085 }else{ 1085 1086 pToplevel->db->mallocFailed = 1; 1086 1087 } 1087 1088 } 1089 + 1090 +/* 1091 +** Check to see if virtual tale module pMod can be have an eponymous 1092 +** virtual table instance. If it can, create one if one does not already 1093 +** exist. Return non-zero if the eponymous virtual table instance exists 1094 +** when this routine returns, and return zero if it does not exist. 1095 +** 1096 +** An eponymous virtual table instance is one that is named after its 1097 +** module, and more importantly, does not require a CREATE VIRTUAL TABLE 1098 +** statement in order to come into existance. Eponymous virtual table 1099 +** instances always exist. They cannot be DROP-ed. 1100 +** 1101 +** Any virtual table module for which xConnect and xCreate are the same 1102 +** method can have an eponymous virtual table instance. 1103 +*/ 1104 +int sqlite3VtabEponymousTableInit(Parse *pParse, Module *pMod){ 1105 + const sqlite3_module *pModule = pMod->pModule; 1106 + Table *pTab; 1107 + char *zErr = 0; 1108 + int nName; 1109 + int rc; 1110 + sqlite3 *db = pParse->db; 1111 + if( pMod->pEpoTab ) return 1; 1112 + if( pModule->xCreate!=0 && pModule->xCreate!=pModule->xConnect ) return 0; 1113 + nName = sqlite3Strlen30(pMod->zName) + 1; 1114 + pTab = sqlite3DbMallocZero(db, sizeof(Table) + nName); 1115 + if( pTab==0 ) return 0; 1116 + pMod->pEpoTab = pTab; 1117 + pTab->zName = (char*)&pTab[1]; 1118 + memcpy(pTab->zName, pMod->zName, nName); 1119 + pTab->nRef = 1; 1120 + pTab->pSchema = db->aDb[0].pSchema; 1121 + pTab->tabFlags |= TF_Virtual; 1122 + pTab->nModuleArg = 0; 1123 + pTab->iPKey = -1; 1124 + addModuleArgument(db, pTab, pTab->zName); 1125 + addModuleArgument(db, pTab, 0); 1126 + addModuleArgument(db, pTab, pTab->zName); 1127 + rc = vtabCallConstructor(db, pTab, pMod, pModule->xConnect, &zErr); 1128 + if( rc ){ 1129 + sqlite3ErrorMsg(pParse, "%s", zErr); 1130 + sqlite3DbFree(db, zErr); 1131 + sqlite3VtabEponymousTableClear(db, pMod); 1132 + return 0; 1133 + } 1134 + return 1; 1135 +} 1136 + 1137 +/* 1138 +** Erase the eponymous virtual table instance associated with 1139 +** virtual table module pMod, if it exists. 1140 +*/ 1141 +void sqlite3VtabEponymousTableClear(sqlite3 *db, Module *pMod){ 1142 + Table *pTab = pMod->pEpoTab; 1143 + if( (pTab = pMod->pEpoTab)!=0 ){ 1144 + sqlite3DeleteColumnNames(db, pTab); 1145 + sqlite3DbFree(db, pTab->azModuleArg); 1146 + sqlite3DbFree(db, pTab); 1147 + pMod->pEpoTab = 0; 1148 + } 1149 +} 1088 1150 1089 1151 /* 1090 1152 ** Return the ON CONFLICT resolution mode in effect for the virtual 1091 1153 ** table update operation currently in progress. 1092 1154 ** 1093 1155 ** The results of this routine are undefined unless it is called from 1094 1156 ** within an xUpdate method.
Changes to src/walker.c.
100 100 struct SrcList_item *pItem; 101 101 102 102 pSrc = p->pSrc; 103 103 if( ALWAYS(pSrc) ){ 104 104 for(i=pSrc->nSrc, pItem=pSrc->a; i>0; i--, pItem++){ 105 105 if( sqlite3WalkSelect(pWalker, pItem->pSelect) ){ 106 106 return WRC_Abort; 107 + } 108 + if( pItem->fg.isTabFunc 109 + && sqlite3WalkExprList(pWalker, pItem->u1.pFuncArg) 110 + ){ 111 + return WRC_Abort; 107 112 } 108 113 } 109 114 } 110 115 return WRC_Continue; 111 116 } 112 117 113 118 /*
Changes to src/where.c.
705 705 sqlite3VdbeAddOp2(v, OP_OpenAutoindex, pLevel->iIdxCur, nKeyCol+1); 706 706 sqlite3VdbeSetP4KeyInfo(pParse, pIdx); 707 707 VdbeComment((v, "for %s", pTable->zName)); 708 708 709 709 /* Fill the automatic index with content */ 710 710 sqlite3ExprCachePush(pParse); 711 711 pTabItem = &pWC->pWInfo->pTabList->a[pLevel->iFrom]; 712 - if( pTabItem->viaCoroutine ){ 712 + if( pTabItem->fg.viaCoroutine ){ 713 713 int regYield = pTabItem->regReturn; 714 714 sqlite3VdbeAddOp3(v, OP_InitCoroutine, regYield, 0, pTabItem->addrFillSub); 715 715 addrTop = sqlite3VdbeAddOp1(v, OP_Yield, regYield); 716 716 VdbeCoverage(v); 717 717 VdbeComment((v, "next row of \"%s\"", pTabItem->pTab->zName)); 718 718 }else{ 719 719 addrTop = sqlite3VdbeAddOp1(v, OP_Rewind, pLevel->iTabCur); VdbeCoverage(v); ................................................................................ 724 724 pLoop->wsFlags |= WHERE_PARTIALIDX; 725 725 } 726 726 regRecord = sqlite3GetTempReg(pParse); 727 727 sqlite3GenerateIndexKey(pParse, pIdx, pLevel->iTabCur, regRecord, 0, 0, 0, 0); 728 728 sqlite3VdbeAddOp2(v, OP_IdxInsert, pLevel->iIdxCur, regRecord); 729 729 sqlite3VdbeChangeP5(v, OPFLAG_USESEEKRESULT); 730 730 if( pPartial ) sqlite3VdbeResolveLabel(v, iContinue); 731 - if( pTabItem->viaCoroutine ){ 731 + if( pTabItem->fg.viaCoroutine ){ 732 732 translateColumnToCopy(v, addrTop, pLevel->iTabCur, pTabItem->regResult); 733 733 sqlite3VdbeAddOp2(v, OP_Goto, 0, addrTop); 734 - pTabItem->viaCoroutine = 0; 734 + pTabItem->fg.viaCoroutine = 0; 735 735 }else{ 736 736 sqlite3VdbeAddOp2(v, OP_Next, pLevel->iTabCur, addrTop+1); VdbeCoverage(v); 737 737 } 738 738 sqlite3VdbeChangeP5(v, SQLITE_STMTSTATUS_AUTOINDEX); 739 739 sqlite3VdbeJumpHere(v, addrTop); 740 740 sqlite3ReleaseTempReg(pParse, regRecord); 741 741 sqlite3ExprCachePop(pParse); ................................................................................ 2124 2124 pNew = pBuilder->pNew; 2125 2125 if( db->mallocFailed ) return SQLITE_NOMEM; 2126 2126 2127 2127 assert( (pNew->wsFlags & WHERE_VIRTUALTABLE)==0 ); 2128 2128 assert( (pNew->wsFlags & WHERE_TOP_LIMIT)==0 ); 2129 2129 if( pNew->wsFlags & WHERE_BTM_LIMIT ){ 2130 2130 opMask = WO_LT|WO_LE; 2131 - }else if( /*pProbe->tnum<=0 ||*/ (pSrc->jointype & JT_LEFT)!=0 ){ 2131 + }else if( /*pProbe->tnum<=0 ||*/ (pSrc->fg.jointype & JT_LEFT)!=0 ){ 2132 2132 opMask = WO_EQ|WO_IN|WO_GT|WO_GE|WO_LT|WO_LE; 2133 2133 }else{ 2134 2134 opMask = WO_EQ|WO_IN|WO_GT|WO_GE|WO_LT|WO_LE|WO_ISNULL|WO_IS; 2135 2135 } 2136 2136 if( pProbe->bUnordered ) opMask &= ~(WO_GT|WO_GE|WO_LT|WO_LE); 2137 2137 2138 2138 assert( pNew->u.btree.nEq<pProbe->nColumn ); ................................................................................ 2498 2498 pWInfo = pBuilder->pWInfo; 2499 2499 pTabList = pWInfo->pTabList; 2500 2500 pSrc = pTabList->a + pNew->iTab; 2501 2501 pTab = pSrc->pTab; 2502 2502 pWC = pBuilder->pWC; 2503 2503 assert( !IsVirtual(pSrc->pTab) ); 2504 2504 2505 - if( pSrc->pIndex ){ 2505 + if( pSrc->pIBIndex ){ 2506 2506 /* An INDEXED BY clause specifies a particular index to use */ 2507 - pProbe = pSrc->pIndex; 2507 + pProbe = pSrc->pIBIndex; 2508 2508 }else if( !HasRowid(pTab) ){ 2509 2509 pProbe = pTab->pIndex; 2510 2510 }else{ 2511 2511 /* There is no INDEXED BY clause. Create a fake Index object in local 2512 2512 ** variable sPk to represent the rowid primary key index. Make this 2513 2513 ** fake index the first in a chain of Index objects with all of the real 2514 2514 ** indices to follow */ ................................................................................ 2520 2520 sPk.aiRowLogEst = aiRowEstPk; 2521 2521 sPk.onError = OE_Replace; 2522 2522 sPk.pTable = pTab; 2523 2523 sPk.szIdxRow = pTab->szTabRow; 2524 2524 aiRowEstPk[0] = pTab->nRowLogEst; 2525 2525 aiRowEstPk[1] = 0; 2526 2526 pFirst = pSrc->pTab->pIndex; 2527 - if( pSrc->notIndexed==0 ){ 2527 + if( pSrc->fg.notIndexed==0 ){ 2528 2528 /* The real indices of the table are only considered if the 2529 2529 ** NOT INDEXED qualifier is omitted from the FROM clause */ 2530 2530 sPk.pNext = pFirst; 2531 2531 } 2532 2532 pProbe = &sPk; 2533 2533 } 2534 2534 rSize = pTab->nRowLogEst; 2535 2535 rLogSize = estLog(rSize); 2536 2536 2537 2537 #ifndef SQLITE_OMIT_AUTOMATIC_INDEX 2538 2538 /* Automatic indexes */ 2539 - if( !pBuilder->pOrSet /* Not part of an OR optimization */ 2539 + if( !pBuilder->pOrSet /* Not part of an OR optimization */ 2540 2540 && (pWInfo->wctrlFlags & WHERE_NO_AUTOINDEX)==0 2541 2541 && (pWInfo->pParse->db->flags & SQLITE_AutoIndex)!=0 2542 - && pSrc->pIndex==0 /* Has no INDEXED BY clause */ 2543 - && !pSrc->notIndexed /* Has no NOT INDEXED clause */ 2544 - && HasRowid(pTab) /* Is not a WITHOUT ROWID table. (FIXME: Why not?) */ 2545 - && !pSrc->isCorrelated /* Not a correlated subquery */ 2546 - && !pSrc->isRecursive /* Not a recursive common table expression. */ 2542 + && pSrc->pIBIndex==0 /* Has no INDEXED BY clause */ 2543 + && !pSrc->fg.notIndexed /* Has no NOT INDEXED clause */ 2544 + && HasRowid(pTab) /* Is not a WITHOUT ROWID table. (FIXME: Why not?) */ 2545 + && !pSrc->fg.isCorrelated /* Not a correlated subquery */ 2546 + && !pSrc->fg.isRecursive /* Not a recursive common table expression. */ 2547 2547 ){ 2548 2548 /* Generate auto-index WhereLoops */ 2549 2549 WhereTerm *pTerm; 2550 2550 WhereTerm *pWCEnd = pWC->a + pWC->nTerm; 2551 2551 for(pTerm=pWC->a; rc==SQLITE_OK && pTerm<pWCEnd; pTerm++){ 2552 2552 if( pTerm->prereqRight & pNew->maskSelf ) continue; 2553 2553 if( termCanDriveIndex(pTerm, pSrc, 0) ){ ................................................................................ 2660 2660 sqlite3Stat4ProbeFree(pBuilder->pRec); 2661 2661 pBuilder->nRecValid = 0; 2662 2662 pBuilder->pRec = 0; 2663 2663 #endif 2664 2664 2665 2665 /* If there was an INDEXED BY clause, then only that one index is 2666 2666 ** considered. */ 2667 - if( pSrc->pIndex ) break; 2667 + if( pSrc->pIBIndex ) break; 2668 2668 } 2669 2669 return rc; 2670 2670 } 2671 2671 2672 2672 #ifndef SQLITE_OMIT_VIRTUALTABLE 2673 2673 /* 2674 2674 ** Add all WhereLoop objects for a table of the join identified by ................................................................................ 3006 3006 /* Loop over the tables in the join, from left to right */ 3007 3007 pNew = pBuilder->pNew; 3008 3008 whereLoopInit(pNew); 3009 3009 for(iTab=0, pItem=pTabList->a; pItem<pEnd; iTab++, pItem++){ 3010 3010 Bitmask mUnusable = 0; 3011 3011 pNew->iTab = iTab; 3012 3012 pNew->maskSelf = sqlite3WhereGetMask(&pWInfo->sMaskSet, pItem->iCursor); 3013 - if( ((pItem->jointype|priorJointype) & (JT_LEFT|JT_CROSS))!=0 ){ 3013 + if( ((pItem->fg.jointype|priorJointype) & (JT_LEFT|JT_CROSS))!=0 ){ 3014 3014 /* This condition is true when pItem is the FROM clause term on the 3015 3015 ** right-hand-side of a LEFT or CROSS JOIN. */ 3016 3016 mExtra = mPrior; 3017 3017 } 3018 - priorJointype = pItem->jointype; 3018 + priorJointype = pItem->fg.jointype; 3019 3019 if( IsVirtual(pItem->pTab) ){ 3020 3020 struct SrcList_item *p; 3021 3021 for(p=&pItem[1]; p<pEnd; p++){ 3022 - if( mUnusable || (p->jointype & (JT_LEFT|JT_CROSS)) ){ 3022 + if( mUnusable || (p->fg.jointype & (JT_LEFT|JT_CROSS)) ){ 3023 3023 mUnusable |= sqlite3WhereGetMask(&pWInfo->sMaskSet, p->iCursor); 3024 3024 } 3025 3025 } 3026 3026 rc = whereLoopAddVirtual(pBuilder, mExtra, mUnusable); 3027 3027 }else{ 3028 3028 rc = whereLoopAddBtree(pBuilder, mExtra); 3029 3029 } ................................................................................ 3745 3745 3746 3746 pWInfo = pBuilder->pWInfo; 3747 3747 if( pWInfo->wctrlFlags & WHERE_FORCE_TABLE ) return 0; 3748 3748 assert( pWInfo->pTabList->nSrc>=1 ); 3749 3749 pItem = pWInfo->pTabList->a; 3750 3750 pTab = pItem->pTab; 3751 3751 if( IsVirtual(pTab) ) return 0; 3752 - if( pItem->zIndexedBy ) return 0; 3752 + if( pItem->fg.isIndexedBy ) return 0; 3753 3753 iCur = pItem->iCursor; 3754 3754 pWC = &pWInfo->sWC; 3755 3755 pLoop = pBuilder->pNew; 3756 3756 pLoop->wsFlags = 0; 3757 3757 pLoop->nSkip = 0; 3758 3758 pTerm = sqlite3WhereFindTerm(pWC, iCur, -1, 0, WO_EQ|WO_IS, 0); 3759 3759 if( pTerm ){ ................................................................................ 4026 4026 ** Note that bitmasks are created for all pTabList->nSrc tables in 4027 4027 ** pTabList, not just the first nTabList tables. nTabList is normally 4028 4028 ** equal to pTabList->nSrc but might be shortened to 1 if the 4029 4029 ** WHERE_ONETABLE_ONLY flag is set. 4030 4030 */ 4031 4031 for(ii=0; ii<pTabList->nSrc; ii++){ 4032 4032 createMask(pMaskSet, pTabList->a[ii].iCursor); 4033 + sqlite3WhereTabFuncArgs(pParse, &pTabList->a[ii], &pWInfo->sWC); 4033 4034 } 4034 4035 #ifndef NDEBUG 4035 4036 { 4036 4037 Bitmask toTheLeft = 0; 4037 4038 for(ii=0; ii<pTabList->nSrc; ii++){ 4038 4039 Bitmask m = sqlite3WhereGetMask(pMaskSet, pTabList->a[ii].iCursor); 4039 4040 assert( (m-1)==toTheLeft ); ................................................................................ 4132 4133 Bitmask tabUsed = sqlite3WhereExprListUsage(pMaskSet, pResultSet); 4133 4134 if( sWLB.pOrderBy ){ 4134 4135 tabUsed |= sqlite3WhereExprListUsage(pMaskSet, sWLB.pOrderBy); 4135 4136 } 4136 4137 while( pWInfo->nLevel>=2 ){ 4137 4138 WhereTerm *pTerm, *pEnd; 4138 4139 pLoop = pWInfo->a[pWInfo->nLevel-1].pWLoop; 4139 - if( (pWInfo->pTabList->a[pLoop->iTab].jointype & JT_LEFT)==0 ) break; 4140 + if( (pWInfo->pTabList->a[pLoop->iTab].fg.jointype & JT_LEFT)==0 ) break; 4140 4141 if( (wctrlFlags & WHERE_WANT_DISTINCT)==0 4141 4142 && (pLoop->wsFlags & WHERE_ONEROW)==0 4142 4143 ){ 4143 4144 break; 4144 4145 } 4145 4146 if( (tabUsed & pLoop->maskSelf)!=0 ) break; 4146 4147 pEnd = sWLB.pWC->a + sWLB.pWC->nTerm; ................................................................................ 4425 4426 assert( pTab!=0 ); 4426 4427 pLoop = pLevel->pWLoop; 4427 4428 4428 4429 /* For a co-routine, change all OP_Column references to the table of 4429 4430 ** the co-routine into OP_Copy of result contained in a register. 4430 4431 ** OP_Rowid becomes OP_Null. 4431 4432 */ 4432 - if( pTabItem->viaCoroutine && !db->mallocFailed ){ 4433 + if( pTabItem->fg.viaCoroutine && !db->mallocFailed ){ 4433 4434 translateColumnToCopy(v, pLevel->addrBody, pLevel->iTabCur, 4434 4435 pTabItem->regResult); 4435 4436 continue; 4436 4437 } 4437 4438 4438 4439 /* Close all of the cursors that were opened by sqlite3WhereBegin. 4439 4440 ** Except, do not close cursors that will be reused by the OR optimization
Changes to src/whereInt.h.
471 471 /* whereexpr.c: */ 472 472 void sqlite3WhereClauseInit(WhereClause*,WhereInfo*); 473 473 void sqlite3WhereClauseClear(WhereClause*); 474 474 void sqlite3WhereSplit(WhereClause*,Expr*,u8); 475 475 Bitmask sqlite3WhereExprUsage(WhereMaskSet*, Expr*); 476 476 Bitmask sqlite3WhereExprListUsage(WhereMaskSet*, ExprList*); 477 477 void sqlite3WhereExprAnalyze(SrcList*, WhereClause*); 478 +void sqlite3WhereTabFuncArgs(Parse*, struct SrcList_item*, WhereClause*); 478 479 479 480 480 481 481 482 482 483 483 484 /* 484 485 ** Bitmasks for the operators on WhereTerm objects. These are all
Changes to src/wherecode.c.
642 642 addrBrk = pLevel->addrBrk = pLevel->addrNxt = sqlite3VdbeMakeLabel(v); 643 643 addrCont = pLevel->addrCont = sqlite3VdbeMakeLabel(v); 644 644 645 645 /* If this is the right table of a LEFT OUTER JOIN, allocate and 646 646 ** initialize a memory cell that records if this table matches any 647 647 ** row of the left table of the join. 648 648 */ 649 - if( pLevel->iFrom>0 && (pTabItem[0].jointype & JT_LEFT)!=0 ){ 649 + if( pLevel->iFrom>0 && (pTabItem[0].fg.jointype & JT_LEFT)!=0 ){ 650 650 pLevel->iLeftJoin = ++pParse->nMem; 651 651 sqlite3VdbeAddOp2(v, OP_Integer, 0, pLevel->iLeftJoin); 652 652 VdbeComment((v, "init LEFT JOIN no-match flag")); 653 653 } 654 654 655 655 /* Special case of a FROM clause subquery implemented as a co-routine */ 656 - if( pTabItem->viaCoroutine ){ 656 + if( pTabItem->fg.viaCoroutine ){ 657 657 int regYield = pTabItem->regReturn; 658 658 sqlite3VdbeAddOp3(v, OP_InitCoroutine, regYield, 0, pTabItem->addrFillSub); 659 659 pLevel->p2 = sqlite3VdbeAddOp2(v, OP_Yield, regYield, addrBrk); 660 660 VdbeCoverage(v); 661 661 VdbeComment((v, "next row of \"%s\"", pTabItem->pTab->zName)); 662 662 pLevel->op = OP_Goto; 663 663 }else ................................................................................ 1391 1391 { 1392 1392 /* Case 6: There is no usable index. We must do a complete 1393 1393 ** scan of the entire table. 1394 1394 */ 1395 1395 static const u8 aStep[] = { OP_Next, OP_Prev }; 1396 1396 static const u8 aStart[] = { OP_Rewind, OP_Last }; 1397 1397 assert( bRev==0 || bRev==1 ); 1398 - if( pTabItem->isRecursive ){ 1398 + if( pTabItem->fg.isRecursive ){ 1399 1399 /* Tables marked isRecursive have only a single row that is stored in 1400 1400 ** a pseudo-cursor. No need to Rewind or Next such cursors. */ 1401 1401 pLevel->op = OP_Noop; 1402 1402 }else{ 1403 1403 pLevel->op = aStep[bRev]; 1404 1404 pLevel->p1 = iCur; 1405 1405 pLevel->p2 = 1 + sqlite3VdbeAddOp2(v, aStart[bRev], iCur, addrBrk);
Changes to src/whereexpr.c.
1243 1243 WhereClause *pWC /* the WHERE clause to be analyzed */ 1244 1244 ){ 1245 1245 int i; 1246 1246 for(i=pWC->nTerm-1; i>=0; i--){ 1247 1247 exprAnalyze(pTabList, pWC, i); 1248 1248 } 1249 1249 } 1250 + 1251 +/* 1252 +** For table-valued-functions, transform the function arguments into 1253 +** new WHERE clause terms. 1254 +** 1255 +** Each function argument translates into an equality constraint against 1256 +** a HIDDEN column in the table. 1257 +*/ 1258 +void sqlite3WhereTabFuncArgs( 1259 + Parse *pParse, /* Parsing context */ 1260 + struct SrcList_item *pItem, /* The FROM clause term to process */ 1261 + WhereClause *pWC /* Xfer function arguments to here */ 1262 +){ 1263 + Table *pTab; 1264 + int j, k; 1265 + ExprList *pArgs; 1266 + Expr *pColRef; 1267 + Expr *pTerm; 1268 + if( pItem->fg.isTabFunc==0 ) return; 1269 + pTab = pItem->pTab; 1270 + assert( pTab!=0 ); 1271 + pArgs = pItem->u1.pFuncArg; 1272 + assert( pArgs!=0 ); 1273 + for(j=k=0; j<pArgs->nExpr; j++){ 1274 + while( k<pTab->nCol && (pTab->aCol[k].colFlags & COLFLAG_HIDDEN)==0 ){ k++; } 1275 + if( k>=pTab->nCol ){ 1276 + sqlite3ErrorMsg(pParse, "too many arguments on %s - max %d", 1277 + pTab->zName, j); 1278 + return; 1279 + } 1280 + pColRef = sqlite3PExpr(pParse, TK_COLUMN, 0, 0, 0); 1281 + if( pColRef==0 ) return; 1282 + pColRef->iTable = pItem->iCursor; 1283 + pColRef->iColumn = k++; 1284 + pTerm = sqlite3PExpr(pParse, TK_EQ, pColRef, 1285 + sqlite3ExprDup(pParse->db, pArgs->a[j].pExpr, 0), 0); 1286 + whereClauseInsert(pWC, pTerm, TERM_DYNAMIC); 1287 + } 1288 +}
Added test/tabfunc01.test.
1 +# 2015-08-19 2 +# 3 +# The author disclaims copyright to this source code. In place of 4 +# a legal notice, here is a blessing: 5 +# 6 +# May you do good and not evil. 7 +# May you find forgiveness for yourself and forgive others. 8 +# May you share freely, never taking more than you give. 9 +# 10 +#*********************************************************************** 11 +# 12 +# This file implements tests for table-valued-functions implemented using 13 +# eponymous virtual tables. 14 +# 15 + 16 +set testdir [file dirname $argv0] 17 +source $testdir/tester.tcl 18 +set testprefix tabfunc01 19 + 20 +ifcapable !vtab { 21 + finish_test 22 + return 23 +} 24 +load_static_extension db series 25 + 26 +do_execsql_test tabfunc01-1.1 { 27 + SELECT *, '|' FROM generate_series WHERE start=1 AND stop=9 AND step=2; 28 +} {1 | 3 | 5 | 7 | 9 |} 29 +do_execsql_test tabfunc01-1.2 { 30 + SELECT *, '|' FROM generate_series LIMIT 5; 31 +} {0 | 1 | 2 | 3 | 4 |} 32 +do_catchsql_test tabfunc01-1.3 { 33 + CREATE VIRTUAL TABLE t1 USING generate_series; 34 +} {1 {no such module: generate_series}} 35 +do_execsql_test tabfunc01-1.4 { 36 + SELECT * FROM generate_series(1,9,2); 37 +} {1 3 5 7 9} 38 +do_execsql_test tabfunc01-1.5 { 39 + SELECT * FROM generate_series(1,9); 40 +} {1 2 3 4 5 6 7 8 9} 41 +do_execsql_test tabfunc01-1.6 { 42 + SELECT * FROM generate_series(1,10) WHERE step=3; 43 +} {1 4 7 10} 44 +do_catchsql_test tabfunc01-1.7 { 45 + SELECT * FROM generate_series(1,9,2,11); 46 +} {1 {too many arguments on generate_series - max 3}} 47 + 48 +do_execsql_test tabfunc01-1.8 { 49 + SELECT * FROM generate_series(0,32,5) ORDER BY rowid DESC; 50 +} {30 25 20 15 10 5 0} 51 +do_execsql_test tabfunc01-1.9 { 52 + SELECT rowid, * FROM generate_series(0,32,5) ORDER BY value DESC; 53 +} {1 30 2 25 3 20 4 15 5 10 6 5 7 0} 54 +do_execsql_test tabfunc01-1.10 { 55 + SELECT rowid, * FROM generate_series(0,32,5) ORDER BY +value DESC; 56 +} {7 30 6 25 5 20 4 15 3 10 2 5 1 0} 57 + 58 +do_execsql_test tabfunc01-2.1 { 59 + CREATE TABLE t1(x); 60 + INSERT INTO t1(x) VALUES(2),(3); 61 + SELECT *, '|' FROM t1, generate_series(1,x) ORDER BY 1, 2 62 +} {2 1 | 2 2 | 3 1 | 3 2 | 3 3 |} 63 + 64 +finish_test