Many hyperlinks are disabled.
Use anonymous login
to enable hyperlinks.
Changes In Branch sessions-value-dup Excluding Merge-Ins
This is equivalent to a diff from 7530e1bf55 to b9e45596d8
2015-05-22
| ||
23:26 | Merge enhancements from trunk, including the new sqlite3_value_dup() API and the addition of the apSqlParam field in the sqlite3_rtree_query_info object of R-Tree. (check-in: cdc0ca6fb3 user: drh tags: sessions) | |
16:08 | Have r-tree prefer to use the constraint "col MATCH ?" over "rowid = ?". (check-in: b9fb95194d user: dan tags: trunk) | |
2015-05-21
| ||
20:26 | Have r-tree prefer to use the constraint "col MATCH ?" over "rowid = ?". <i>drh added later:</i> All changes on this branch have been cherrypicked to trunk and will be merged into sessions from trunk. So this branch can close. (Closed-Leaf check-in: b9e45596d8 user: dan tags: sessions-value-dup) | |
2015-05-20
| ||
22:01 | Add the sqlite3_value_dup() and sqlite3_value_free() interfaces and use those to add the sqlite3_rtree_query_info.apSqlParam field to the query callback in R-Tree. (check-in: 2007391cec user: drh tags: sessions-value-dup) | |
2015-05-19
| ||
23:04 | Merge the Makefile.msc fix and the compiler warning fix from trunk. Also fix another compiler warning in sqlite3session_diff(). (check-in: 7530e1bf55 user: drh tags: sessions) | |
22:56 | Fix the MSVC makefile so that it works with OTA. Fix a harmless compiler warning in FTS3. (check-in: c7b1664530 user: drh tags: trunk) | |
22:42 | Merge recent trunk changes, include the R-Tree enhancement that allows 8-byte BLOB arguments to geometry functions, and the fix for the TEXT affinity problem that could cause corrupt indexes. (check-in: 0a0de8b72c user: drh tags: sessions) | |
Changes to ext/rtree/rtree.c.
︙ | ︙ | |||
347 348 349 350 351 352 353 354 355 356 357 358 359 360 | ** sqlite3_rtree_query_callback() create, and is read as the right-hand ** operand to the MATCH operator of an R-Tree. */ struct RtreeMatchArg { u32 magic; /* Always RTREE_GEOMETRY_MAGIC */ RtreeGeomCallback cb; /* Info about the callback functions */ int nParam; /* Number of parameters to the SQL function */ RtreeDValue aParam[1]; /* Values for parameters to the SQL function */ }; #ifndef MAX # define MAX(x,y) ((x) < (y) ? (y) : (x)) #endif #ifndef MIN | > | 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 | ** sqlite3_rtree_query_callback() create, and is read as the right-hand ** operand to the MATCH operator of an R-Tree. */ struct RtreeMatchArg { u32 magic; /* Always RTREE_GEOMETRY_MAGIC */ RtreeGeomCallback cb; /* Info about the callback functions */ int nParam; /* Number of parameters to the SQL function */ sqlite3_value **apSqlParam; /* Original SQL parameter values */ RtreeDValue aParam[1]; /* Values for parameters to the SQL function */ }; #ifndef MAX # define MAX(x,y) ((x) < (y) ? (y) : (x)) #endif #ifndef MIN |
︙ | ︙ | |||
1491 1492 1493 1494 1495 1496 1497 1498 1499 1500 1501 1502 1503 1504 1505 1506 1507 1508 1509 1510 1511 1512 | pInfo = (sqlite3_rtree_query_info*)sqlite3_malloc( sizeof(*pInfo)+nBlob ); if( !pInfo ) return SQLITE_NOMEM; memset(pInfo, 0, sizeof(*pInfo)); pBlob = (RtreeMatchArg*)&pInfo[1]; memcpy(pBlob, sqlite3_value_blob(pValue), nBlob); nExpected = (int)(sizeof(RtreeMatchArg) + (pBlob->nParam-1)*sizeof(RtreeDValue)); if( pBlob->magic!=RTREE_GEOMETRY_MAGIC || nBlob!=nExpected ){ sqlite3_free(pInfo); return SQLITE_ERROR; } pInfo->pContext = pBlob->cb.pContext; pInfo->nParam = pBlob->nParam; pInfo->aParam = pBlob->aParam; if( pBlob->cb.xGeom ){ pCons->u.xGeom = pBlob->cb.xGeom; }else{ pCons->op = RTREE_QUERY; pCons->u.xQueryFunc = pBlob->cb.xQueryFunc; } | > > | 1492 1493 1494 1495 1496 1497 1498 1499 1500 1501 1502 1503 1504 1505 1506 1507 1508 1509 1510 1511 1512 1513 1514 1515 | pInfo = (sqlite3_rtree_query_info*)sqlite3_malloc( sizeof(*pInfo)+nBlob ); if( !pInfo ) return SQLITE_NOMEM; memset(pInfo, 0, sizeof(*pInfo)); pBlob = (RtreeMatchArg*)&pInfo[1]; memcpy(pBlob, sqlite3_value_blob(pValue), nBlob); nExpected = (int)(sizeof(RtreeMatchArg) + pBlob->nParam*sizeof(sqlite3_value*) + (pBlob->nParam-1)*sizeof(RtreeDValue)); if( pBlob->magic!=RTREE_GEOMETRY_MAGIC || nBlob!=nExpected ){ sqlite3_free(pInfo); return SQLITE_ERROR; } pInfo->pContext = pBlob->cb.pContext; pInfo->nParam = pBlob->nParam; pInfo->aParam = pBlob->aParam; pInfo->apSqlParam = pBlob->apSqlParam; if( pBlob->cb.xGeom ){ pCons->u.xGeom = pBlob->cb.xGeom; }else{ pCons->op = RTREE_QUERY; pCons->u.xQueryFunc = pBlob->cb.xQueryFunc; } |
︙ | ︙ | |||
1665 1666 1667 1668 1669 1670 1671 1672 1673 1674 1675 1676 1677 1678 1679 1680 1681 | ** to which the constraint applies. The leftmost coordinate column ** is 'a', the second from the left 'b' etc. */ static int rtreeBestIndex(sqlite3_vtab *tab, sqlite3_index_info *pIdxInfo){ Rtree *pRtree = (Rtree*)tab; int rc = SQLITE_OK; int ii; i64 nRow; /* Estimated rows returned by this scan */ int iIdx = 0; char zIdxStr[RTREE_MAX_DIMENSIONS*8+1]; memset(zIdxStr, 0, sizeof(zIdxStr)); assert( pIdxInfo->idxStr==0 ); for(ii=0; ii<pIdxInfo->nConstraint && iIdx<(int)(sizeof(zIdxStr)-1); ii++){ struct sqlite3_index_constraint *p = &pIdxInfo->aConstraint[ii]; | > > > > > > > > > > > > | > | 1668 1669 1670 1671 1672 1673 1674 1675 1676 1677 1678 1679 1680 1681 1682 1683 1684 1685 1686 1687 1688 1689 1690 1691 1692 1693 1694 1695 1696 1697 1698 1699 1700 1701 1702 1703 1704 1705 | ** to which the constraint applies. The leftmost coordinate column ** is 'a', the second from the left 'b' etc. */ static int rtreeBestIndex(sqlite3_vtab *tab, sqlite3_index_info *pIdxInfo){ Rtree *pRtree = (Rtree*)tab; int rc = SQLITE_OK; int ii; int bMatch = 0; /* True if there exists a MATCH constraint */ i64 nRow; /* Estimated rows returned by this scan */ int iIdx = 0; char zIdxStr[RTREE_MAX_DIMENSIONS*8+1]; memset(zIdxStr, 0, sizeof(zIdxStr)); /* Check if there exists a MATCH constraint - even an unusable one. If there ** is, do not consider the lookup-by-rowid plan as using such a plan would ** require the VDBE to evaluate the MATCH constraint, which is not currently ** possible. */ for(ii=0; ii<pIdxInfo->nConstraint; ii++){ if( pIdxInfo->aConstraint[ii].op==SQLITE_INDEX_CONSTRAINT_MATCH ){ bMatch = 1; } } assert( pIdxInfo->idxStr==0 ); for(ii=0; ii<pIdxInfo->nConstraint && iIdx<(int)(sizeof(zIdxStr)-1); ii++){ struct sqlite3_index_constraint *p = &pIdxInfo->aConstraint[ii]; if( bMatch==0 && p->usable && p->iColumn==0 && p->op==SQLITE_INDEX_CONSTRAINT_EQ ){ /* We have an equality constraint on the rowid. Use strategy 1. */ int jj; for(jj=0; jj<ii; jj++){ pIdxInfo->aConstraintUsage[jj].argvIndex = 0; pIdxInfo->aConstraintUsage[jj].omit = 0; } pIdxInfo->idxNum = 1; |
︙ | ︙ | |||
3367 3368 3369 3370 3371 3372 3373 3374 3375 3376 3377 3378 3379 3380 3381 3382 3383 3384 3385 3386 3387 3388 3389 3390 3391 3392 3393 | ** the corresponding SQL function is deleted. */ static void rtreeFreeCallback(void *p){ RtreeGeomCallback *pInfo = (RtreeGeomCallback*)p; if( pInfo->xDestructor ) pInfo->xDestructor(pInfo->pContext); sqlite3_free(p); } /* ** Each call to sqlite3_rtree_geometry_callback() or ** sqlite3_rtree_query_callback() creates an ordinary SQLite ** scalar function that is implemented by this routine. ** ** All this function does is construct an RtreeMatchArg object that ** contains the geometry-checking callback routines and a list of ** parameters to this function, then return that RtreeMatchArg object ** as a BLOB. ** ** The R-Tree MATCH operator will read the returned BLOB, deserialize ** the RtreeMatchArg object, and use the RtreeMatchArg object to figure ** out which elements of the R-Tree should be returned by the query. */ static void geomCallback(sqlite3_context *ctx, int nArg, sqlite3_value **aArg){ RtreeGeomCallback *pGeomCtx = (RtreeGeomCallback *)sqlite3_user_data(ctx); RtreeMatchArg *pBlob; int nBlob; | > > > > > > > > > > > > > | > > | < < | < < | | | > > > | | > | 3383 3384 3385 3386 3387 3388 3389 3390 3391 3392 3393 3394 3395 3396 3397 3398 3399 3400 3401 3402 3403 3404 3405 3406 3407 3408 3409 3410 3411 3412 3413 3414 3415 3416 3417 3418 3419 3420 3421 3422 3423 3424 3425 3426 3427 3428 3429 3430 3431 3432 3433 3434 3435 3436 3437 3438 3439 3440 3441 3442 3443 3444 3445 3446 3447 3448 3449 3450 3451 3452 3453 3454 3455 | ** the corresponding SQL function is deleted. */ static void rtreeFreeCallback(void *p){ RtreeGeomCallback *pInfo = (RtreeGeomCallback*)p; if( pInfo->xDestructor ) pInfo->xDestructor(pInfo->pContext); sqlite3_free(p); } /* ** This routine frees the BLOB that is returned by geomCallback(). */ static void rtreeMatchArgFree(void *pArg){ int i; RtreeMatchArg *p = (RtreeMatchArg*)pArg; for(i=0; i<p->nParam; i++){ sqlite3_value_free(p->apSqlParam[i]); } sqlite3_free(p); } /* ** Each call to sqlite3_rtree_geometry_callback() or ** sqlite3_rtree_query_callback() creates an ordinary SQLite ** scalar function that is implemented by this routine. ** ** All this function does is construct an RtreeMatchArg object that ** contains the geometry-checking callback routines and a list of ** parameters to this function, then return that RtreeMatchArg object ** as a BLOB. ** ** The R-Tree MATCH operator will read the returned BLOB, deserialize ** the RtreeMatchArg object, and use the RtreeMatchArg object to figure ** out which elements of the R-Tree should be returned by the query. */ static void geomCallback(sqlite3_context *ctx, int nArg, sqlite3_value **aArg){ RtreeGeomCallback *pGeomCtx = (RtreeGeomCallback *)sqlite3_user_data(ctx); RtreeMatchArg *pBlob; int nBlob; int memErr = 0; nBlob = sizeof(RtreeMatchArg) + (nArg-1)*sizeof(RtreeDValue) + nArg*sizeof(sqlite3_value*); pBlob = (RtreeMatchArg *)sqlite3_malloc(nBlob); if( !pBlob ){ sqlite3_result_error_nomem(ctx); }else{ int i; pBlob->magic = RTREE_GEOMETRY_MAGIC; pBlob->cb = pGeomCtx[0]; pBlob->apSqlParam = (sqlite3_value**)&pBlob->aParam[nArg]; pBlob->nParam = nArg; for(i=0; i<nArg; i++){ pBlob->apSqlParam[i] = sqlite3_value_dup(aArg[i]); if( pBlob->apSqlParam[i]==0 ) memErr = 1; #ifdef SQLITE_RTREE_INT_ONLY pBlob->aParam[i] = sqlite3_value_int64(aArg[i]); #else pBlob->aParam[i] = sqlite3_value_double(aArg[i]); #endif } if( memErr ){ sqlite3_result_error_nomem(ctx); rtreeMatchArgFree(pBlob); }else{ sqlite3_result_blob(ctx, pBlob, nBlob, rtreeMatchArgFree); } } } /* ** Register a new geometry function for use with the r-tree MATCH operator. */ int sqlite3_rtree_geometry_callback( |
︙ | ︙ |
Changes to ext/rtree/rtreeE.test.
︙ | ︙ | |||
48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 | INSERT INTO rt1 SELECT 200+x+5*y, x*7, x*7+15, y*7+200, y*7+215 FROM x, y; } {} # Queries against each of the three clusters */ do_execsql_test rtreeE-1.1 { SELECT id FROM rt1 WHERE id MATCH Qcircle(0.0, 0.0, 50.0, 3) ORDER BY id; } {0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24} do_execsql_test rtreeE-1.2 { SELECT id FROM rt1 WHERE id MATCH Qcircle(100.0, 0.0, 50.0, 3) ORDER BY id; } {100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124} do_execsql_test rtreeE-1.3 { SELECT id FROM rt1 WHERE id MATCH Qcircle(0.0, 200.0, 50.0, 3) ORDER BY id; } {200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224} # The Qcircle geometry function gives a lower score to larger leaf-nodes. # This causes the 200s to sort before the 100s and the 0s to sort before # last. # do_execsql_test rtreeE-1.4 { | > > > | | > > > > > > > | 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 | INSERT INTO rt1 SELECT 200+x+5*y, x*7, x*7+15, y*7+200, y*7+215 FROM x, y; } {} # Queries against each of the three clusters */ do_execsql_test rtreeE-1.1 { SELECT id FROM rt1 WHERE id MATCH Qcircle(0.0, 0.0, 50.0, 3) ORDER BY id; } {0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24} do_execsql_test rtreeE-1.1x { SELECT id FROM rt1 WHERE id MATCH Qcircle('x:0 y:0 r:50.0 e:3') ORDER BY id; } {0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24} do_execsql_test rtreeE-1.2 { SELECT id FROM rt1 WHERE id MATCH Qcircle(100.0, 0.0, 50.0, 3) ORDER BY id; } {100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124} do_execsql_test rtreeE-1.3 { SELECT id FROM rt1 WHERE id MATCH Qcircle(0.0, 200.0, 50.0, 3) ORDER BY id; } {200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224} # The Qcircle geometry function gives a lower score to larger leaf-nodes. # This causes the 200s to sort before the 100s and the 0s to sort before # last. # do_execsql_test rtreeE-1.4 { SELECT id FROM rt1 WHERE id MATCH Qcircle('r:1000 e:3') AND id%100==0 } {200 100 0} # Exclude odd rowids on a depth-first search do_execsql_test rtreeE-1.5 { SELECT id FROM rt1 WHERE id MATCH Qcircle('r:1000 e:4') ORDER BY +id } {0 2 4 6 8 10 12 14 16 18 20 22 24 100 102 104 106 108 110 112 114 116 118 120 122 124 200 202 204 206 208 210 212 214 216 218 220 222 224} # Exclude odd rowids on a breadth-first search. do_execsql_test rtreeE-1.6 { SELECT id FROM rt1 WHERE id MATCH Qcircle(0,0,1000,5) ORDER BY +id } {0 2 4 6 8 10 12 14 16 18 20 22 24 100 102 104 106 108 110 112 114 116 118 120 122 124 200 202 204 206 208 210 212 214 216 218 220 222 224} # Test that rtree prefers MATCH to lookup-by-rowid. # do_execsql_test rtreeE-1.7 { SELECT id FROM rt1 WHERE id=18 AND id MATCH Qcircle(0,0,1000,5) } {18} # Construct a large 2-D RTree with thousands of random entries. # do_test rtreeE-2.1 { db eval { CREATE TABLE t2(id,x0,x1,y0,y1); CREATE VIRTUAL TABLE rt2 USING rtree(id,x0,x1,y0,y1); |
︙ | ︙ | |||
121 122 123 124 125 126 127 128 129 | do_execsql_test rtreeE-2.3 { SELECT id FROM rt2 WHERE id MATCH breadthfirstsearch(0,5000,0,5000) ORDER BY id } $ans set ans [db eval {SELECT id FROM t2 WHERE x1>=0 AND x0<=10000 AND y1>=0 AND y0<=10000 ORDER BY id}] do_execsql_test rtreeE-2.4 { SELECT id FROM rt2 WHERE id MATCH breadthfirstsearch(0,10000,0,10000) ORDER BY id } $ans finish_test | > | 131 132 133 134 135 136 137 138 139 140 | do_execsql_test rtreeE-2.3 { SELECT id FROM rt2 WHERE id MATCH breadthfirstsearch(0,5000,0,5000) ORDER BY id } $ans set ans [db eval {SELECT id FROM t2 WHERE x1>=0 AND x0<=10000 AND y1>=0 AND y0<=10000 ORDER BY id}] do_execsql_test rtreeE-2.4 { SELECT id FROM rt2 WHERE id MATCH breadthfirstsearch(0,10000,0,10000) ORDER BY id } $ans finish_test |
Changes to ext/rtree/sqlite3rtree.h.
︙ | ︙ | |||
94 95 96 97 98 99 100 101 102 103 104 105 106 107 | int iLevel; /* Level of current node or entry */ int mxLevel; /* The largest iLevel value in the tree */ sqlite3_int64 iRowid; /* Rowid for current entry */ sqlite3_rtree_dbl rParentScore; /* Score of parent node */ int eParentWithin; /* Visibility of parent node */ int eWithin; /* OUT: Visiblity */ sqlite3_rtree_dbl rScore; /* OUT: Write the score here */ }; /* ** Allowed values for sqlite3_rtree_query.eWithin and .eParentWithin. */ #define NOT_WITHIN 0 /* Object completely outside of query region */ #define PARTLY_WITHIN 1 /* Object partially overlaps query region */ | > > | 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 | int iLevel; /* Level of current node or entry */ int mxLevel; /* The largest iLevel value in the tree */ sqlite3_int64 iRowid; /* Rowid for current entry */ sqlite3_rtree_dbl rParentScore; /* Score of parent node */ int eParentWithin; /* Visibility of parent node */ int eWithin; /* OUT: Visiblity */ sqlite3_rtree_dbl rScore; /* OUT: Write the score here */ /* The following fields are only available in 3.8.11 and later */ sqlite3_value **apSqlParam; /* Original SQL values of parameters */ }; /* ** Allowed values for sqlite3_rtree_query.eWithin and .eParentWithin. */ #define NOT_WITHIN 0 /* Object completely outside of query region */ #define PARTLY_WITHIN 1 /* Object partially overlaps query region */ |
︙ | ︙ |
Changes to src/build.c.
︙ | ︙ | |||
1909 1910 1911 1912 1913 1914 1915 | ** ** A shared-cache write-lock is not required to write to the new table, ** as a schema-lock must have already been obtained to create it. Since ** a schema-lock excludes all other database users, the write-lock would ** be redundant. */ if( pSelect ){ | | > > > > > | > > > > > | | > | | | | | | | | | < > > > > > > > > > | 1909 1910 1911 1912 1913 1914 1915 1916 1917 1918 1919 1920 1921 1922 1923 1924 1925 1926 1927 1928 1929 1930 1931 1932 1933 1934 1935 1936 1937 1938 1939 1940 1941 1942 1943 1944 1945 1946 1947 1948 1949 1950 1951 1952 1953 1954 1955 1956 1957 1958 1959 1960 1961 | ** ** A shared-cache write-lock is not required to write to the new table, ** as a schema-lock must have already been obtained to create it. Since ** a schema-lock excludes all other database users, the write-lock would ** be redundant. */ if( pSelect ){ SelectDest dest; /* Where the SELECT should store results */ int regYield; /* Register holding co-routine entry-point */ int addrTop; /* Top of the co-routine */ int regRec; /* A record to be insert into the new table */ int regRowid; /* Rowid of the next row to insert */ int addrInsLoop; /* Top of the loop for inserting rows */ Table *pSelTab; /* A table that describes the SELECT results */ regYield = ++pParse->nMem; regRec = ++pParse->nMem; regRowid = ++pParse->nMem; assert(pParse->nTab==1); sqlite3VdbeAddOp3(v, OP_OpenWrite, 1, pParse->regRoot, iDb); sqlite3VdbeChangeP5(v, OPFLAG_P2ISREG); pParse->nTab = 2; addrTop = sqlite3VdbeCurrentAddr(v) + 1; sqlite3VdbeAddOp3(v, OP_InitCoroutine, regYield, 0, addrTop); sqlite3SelectDestInit(&dest, SRT_Coroutine, regYield); sqlite3Select(pParse, pSelect, &dest); sqlite3VdbeAddOp1(v, OP_EndCoroutine, regYield); sqlite3VdbeJumpHere(v, addrTop - 1); if( pParse->nErr ) return; pSelTab = sqlite3ResultSetOfSelect(pParse, pSelect); if( pSelTab==0 ) return; assert( p->aCol==0 ); p->nCol = pSelTab->nCol; p->aCol = pSelTab->aCol; pSelTab->nCol = 0; pSelTab->aCol = 0; sqlite3DeleteTable(db, pSelTab); addrInsLoop = sqlite3VdbeAddOp1(v, OP_Yield, dest.iSDParm); VdbeCoverage(v); sqlite3VdbeAddOp3(v, OP_MakeRecord, dest.iSdst, dest.nSdst, regRec); sqlite3TableAffinity(v, p, 0); sqlite3VdbeAddOp2(v, OP_NewRowid, 1, regRowid); sqlite3VdbeAddOp3(v, OP_Insert, 1, regRec, regRowid); sqlite3VdbeAddOp2(v, OP_Goto, 0, addrInsLoop); sqlite3VdbeJumpHere(v, addrInsLoop); sqlite3VdbeAddOp1(v, OP_Close, 1); } /* Compute the complete text of the CREATE statement */ if( pSelect ){ zStmt = createTableStmt(db, p); }else{ Token *pEnd2 = tabOpts ? &pParse->sLastToken : pEnd; |
︙ | ︙ |
Changes to src/parse.y.
︙ | ︙ | |||
444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 | A = p; } selectnowith(A) ::= oneselect(X). {A = X;} %ifndef SQLITE_OMIT_COMPOUND_SELECT selectnowith(A) ::= selectnowith(X) multiselect_op(Y) oneselect(Z). { Select *pRhs = Z; if( pRhs && pRhs->pPrior ){ SrcList *pFrom; Token x; x.n = 0; parserDoubleLinkSelect(pParse, pRhs); pFrom = sqlite3SrcListAppendFromTerm(pParse,0,0,0,&x,pRhs,0,0); pRhs = sqlite3SelectNew(pParse,0,pFrom,0,0,0,0,0,0,0); } if( pRhs ){ pRhs->op = (u8)Y; | > | > | | 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 | A = p; } selectnowith(A) ::= oneselect(X). {A = X;} %ifndef SQLITE_OMIT_COMPOUND_SELECT selectnowith(A) ::= selectnowith(X) multiselect_op(Y) oneselect(Z). { Select *pRhs = Z; Select *pLhs = X; if( pRhs && pRhs->pPrior ){ SrcList *pFrom; Token x; x.n = 0; parserDoubleLinkSelect(pParse, pRhs); pFrom = sqlite3SrcListAppendFromTerm(pParse,0,0,0,&x,pRhs,0,0); pRhs = sqlite3SelectNew(pParse,0,pFrom,0,0,0,0,0,0,0); } if( pRhs ){ pRhs->op = (u8)Y; pRhs->pPrior = pLhs; if( ALWAYS(pLhs) ) pLhs->selFlags &= ~SF_MultiValue; pRhs->selFlags &= ~SF_MultiValue; if( Y!=TK_ALL ) pParse->hasCompound = 1; }else{ sqlite3SelectDelete(pParse->db, pLhs); } A = pRhs; } %type multiselect_op {int} multiselect_op(A) ::= UNION(OP). {A = @OP;} multiselect_op(A) ::= UNION ALL. {A = TK_ALL;} multiselect_op(A) ::= EXCEPT|INTERSECT(OP). {A = @OP;} |
︙ | ︙ |
Changes to src/select.c.
︙ | ︙ | |||
5519 5520 5521 5522 5523 5524 5525 | #ifdef SQLITE_DEBUG /* ** Generate a human-readable description of a the Select object. */ void sqlite3TreeViewSelect(TreeView *pView, const Select *p, u8 moreToFollow){ int n = 0; pView = sqlite3TreeViewPush(pView, moreToFollow); | | | | 5519 5520 5521 5522 5523 5524 5525 5526 5527 5528 5529 5530 5531 5532 5533 5534 5535 | #ifdef SQLITE_DEBUG /* ** Generate a human-readable description of a the Select object. */ void sqlite3TreeViewSelect(TreeView *pView, const Select *p, u8 moreToFollow){ int n = 0; pView = sqlite3TreeViewPush(pView, moreToFollow); sqlite3TreeViewLine(pView, "SELECT%s%s (0x%p) selFlags=0x%x", ((p->selFlags & SF_Distinct) ? " DISTINCT" : ""), ((p->selFlags & SF_Aggregate) ? " agg_flag" : ""), p, p->selFlags ); if( p->pSrc && p->pSrc->nSrc ) n++; if( p->pWhere ) n++; if( p->pGroupBy ) n++; if( p->pHaving ) n++; if( p->pOrderBy ) n++; if( p->pLimit ) n++; |
︙ | ︙ |
Changes to src/sqlite.h.in.
︙ | ︙ | |||
4290 4291 4292 4293 4294 4295 4296 | SQLITE_DEPRECATED int sqlite3_global_recover(void); SQLITE_DEPRECATED void sqlite3_thread_cleanup(void); SQLITE_DEPRECATED int sqlite3_memory_alarm(void(*)(void*,sqlite3_int64,int), void*,sqlite3_int64); #endif /* | | | | 4290 4291 4292 4293 4294 4295 4296 4297 4298 4299 4300 4301 4302 4303 4304 4305 4306 4307 4308 4309 | SQLITE_DEPRECATED int sqlite3_global_recover(void); SQLITE_DEPRECATED void sqlite3_thread_cleanup(void); SQLITE_DEPRECATED int sqlite3_memory_alarm(void(*)(void*,sqlite3_int64,int), void*,sqlite3_int64); #endif /* ** CAPI3REF: Obtaining SQL Values ** METHOD: sqlite3_value ** ** The C-language implementation of SQL functions and aggregates uses ** this set of interface routines to access the parameter values on ** the function or aggregate. ** ** The xFunc (for scalar functions) or xStep (for aggregates) parameters ** to [sqlite3_create_function()] and [sqlite3_create_function16()] ** define callbacks that implement the SQL functions and aggregates. ** The 3rd parameter to these callbacks is an array of pointers to ** [protected sqlite3_value] objects. There is one [sqlite3_value] object for ** each parameter to the SQL function. These routines are used to |
︙ | ︙ | |||
4348 4349 4350 4351 4352 4353 4354 4355 4356 4357 4358 4359 4360 4361 | const unsigned char *sqlite3_value_text(sqlite3_value*); const void *sqlite3_value_text16(sqlite3_value*); const void *sqlite3_value_text16le(sqlite3_value*); const void *sqlite3_value_text16be(sqlite3_value*); int sqlite3_value_type(sqlite3_value*); int sqlite3_value_numeric_type(sqlite3_value*); /* ** CAPI3REF: Obtain Aggregate Function Context ** METHOD: sqlite3_context ** ** Implementations of aggregate SQL functions use this ** routine to allocate memory for storing their state. ** | > > > > > > > > > > > > > > > > > | 4348 4349 4350 4351 4352 4353 4354 4355 4356 4357 4358 4359 4360 4361 4362 4363 4364 4365 4366 4367 4368 4369 4370 4371 4372 4373 4374 4375 4376 4377 4378 | const unsigned char *sqlite3_value_text(sqlite3_value*); const void *sqlite3_value_text16(sqlite3_value*); const void *sqlite3_value_text16le(sqlite3_value*); const void *sqlite3_value_text16be(sqlite3_value*); int sqlite3_value_type(sqlite3_value*); int sqlite3_value_numeric_type(sqlite3_value*); /* ** CAPI3REF: Copy And Free SQL Values ** METHOD: sqlite3_value ** ** ^The sqlite3_value_dup(V) interface makes a copy of the [sqlite3_value] ** object D and returns a pointer to that copy. ^The [sqlite3_value] returned ** is a [protected sqlite3_value] object even if the input is not. ** ^The sqlite3_value_dup(V) interface returns NULL if V is NULL or if a ** memory allocation fails. ** ** ^The sqlite3_value_free(V) interface frees an [sqlite3_value] object ** previously obtained from [sqlite_value_dup()]. ^If V is a NULL pointer ** then sqlite3_value_free(V) is a harmless no-op. */ SQLITE_EXPERIMENTAL sqlite3_value *sqlite3_value_dup(const sqlite3_value*); SQLITE_EXPERIMENTAL void sqlite3_value_free(sqlite3_value*); /* ** CAPI3REF: Obtain Aggregate Function Context ** METHOD: sqlite3_context ** ** Implementations of aggregate SQL functions use this ** routine to allocate memory for storing their state. ** |
︙ | ︙ | |||
5871 5872 5873 5874 5875 5876 5877 | ** ^All subsequent calls to [sqlite3_blob_read()], [sqlite3_blob_write()] or ** [sqlite3_blob_reopen()] on an aborted blob handle immediately return ** SQLITE_ABORT. ^Calling [sqlite3_blob_bytes()] on an aborted blob handle ** always returns zero. ** ** ^This function sets the database handle error code and message. */ | | | 5888 5889 5890 5891 5892 5893 5894 5895 5896 5897 5898 5899 5900 5901 5902 | ** ^All subsequent calls to [sqlite3_blob_read()], [sqlite3_blob_write()] or ** [sqlite3_blob_reopen()] on an aborted blob handle immediately return ** SQLITE_ABORT. ^Calling [sqlite3_blob_bytes()] on an aborted blob handle ** always returns zero. ** ** ^This function sets the database handle error code and message. */ int sqlite3_blob_reopen(sqlite3_blob *, sqlite3_int64); /* ** CAPI3REF: Close A BLOB Handle ** DESTRUCTOR: sqlite3_blob ** ** ^This function closes an open [BLOB handle]. ^(The BLOB handle is closed ** unconditionally. Even if this routine returns an error code, the |
︙ | ︙ | |||
7681 7682 7683 7684 7685 7686 7687 | ** ^Statistics might not be available for all loops in all statements. ^In cases ** where there exist loops with no available statistics, this function behaves ** as if the loop did not exist - it returns non-zero and leave the variable ** that pOut points to unchanged. ** ** See also: [sqlite3_stmt_scanstatus_reset()] */ | | | | 7698 7699 7700 7701 7702 7703 7704 7705 7706 7707 7708 7709 7710 7711 7712 7713 7714 7715 7716 7717 7718 7719 7720 7721 7722 7723 7724 7725 7726 7727 7728 | ** ^Statistics might not be available for all loops in all statements. ^In cases ** where there exist loops with no available statistics, this function behaves ** as if the loop did not exist - it returns non-zero and leave the variable ** that pOut points to unchanged. ** ** See also: [sqlite3_stmt_scanstatus_reset()] */ int sqlite3_stmt_scanstatus( sqlite3_stmt *pStmt, /* Prepared statement for which info desired */ int idx, /* Index of loop to report on */ int iScanStatusOp, /* Information desired. SQLITE_SCANSTAT_* */ void *pOut /* Result written here */ ); /* ** CAPI3REF: Zero Scan-Status Counters ** METHOD: sqlite3_stmt ** ** ^Zero all [sqlite3_stmt_scanstatus()] related event counters. ** ** This API is only available if the library is built with pre-processor ** symbol [SQLITE_ENABLE_STMT_SCANSTATUS] defined. */ void sqlite3_stmt_scanstatus_reset(sqlite3_stmt*); /* ** CAPI3REF: The pre-update hook. ** EXPERIMENTAL ** ** ^These interfaces are only available if SQLite is compiled using the |
︙ | ︙ |
Changes to src/sqlite3ext.h.
︙ | ︙ | |||
263 264 265 266 267 268 269 270 271 272 273 274 275 276 | void *(*realloc64)(void*,sqlite3_uint64); void (*reset_auto_extension)(void); void (*result_blob64)(sqlite3_context*,const void*,sqlite3_uint64, void(*)(void*)); void (*result_text64)(sqlite3_context*,const char*,sqlite3_uint64, void(*)(void*), unsigned char); int (*strglob)(const char*,const char*); }; /* ** The following macros redefine the API routines so that they are ** redirected through the global sqlite3_api structure. ** ** This header file is also used by the loadext.c source file | > > | 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 | void *(*realloc64)(void*,sqlite3_uint64); void (*reset_auto_extension)(void); void (*result_blob64)(sqlite3_context*,const void*,sqlite3_uint64, void(*)(void*)); void (*result_text64)(sqlite3_context*,const char*,sqlite3_uint64, void(*)(void*), unsigned char); int (*strglob)(const char*,const char*); sqlite3_value (*value_dup)(const sqlite3_value*); void (*value_free)(sqlite3_value*); }; /* ** The following macros redefine the API routines so that they are ** redirected through the global sqlite3_api structure. ** ** This header file is also used by the loadext.c source file |
︙ | ︙ | |||
493 494 495 496 497 498 499 500 501 502 503 504 505 506 | #define sqlite3_malloc64 sqlite3_api->malloc64 #define sqlite3_msize sqlite3_api->msize #define sqlite3_realloc64 sqlite3_api->realloc64 #define sqlite3_reset_auto_extension sqlite3_api->reset_auto_extension #define sqlite3_result_blob64 sqlite3_api->result_blob64 #define sqlite3_result_text64 sqlite3_api->result_text64 #define sqlite3_strglob sqlite3_api->strglob #endif /* SQLITE_CORE */ #ifndef SQLITE_CORE /* This case when the file really is being compiled as a loadable ** extension */ # define SQLITE_EXTENSION_INIT1 const sqlite3_api_routines *sqlite3_api=0; # define SQLITE_EXTENSION_INIT2(v) sqlite3_api=v; | > > > | 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 | #define sqlite3_malloc64 sqlite3_api->malloc64 #define sqlite3_msize sqlite3_api->msize #define sqlite3_realloc64 sqlite3_api->realloc64 #define sqlite3_reset_auto_extension sqlite3_api->reset_auto_extension #define sqlite3_result_blob64 sqlite3_api->result_blob64 #define sqlite3_result_text64 sqlite3_api->result_text64 #define sqlite3_strglob sqlite3_api->strglob /* Version 3.8.11 and later */ #define sqlite3_value_dup sqlite3_api->value_dup #define sqlite3_value_free sqlite3_api->value_free #endif /* SQLITE_CORE */ #ifndef SQLITE_CORE /* This case when the file really is being compiled as a loadable ** extension */ # define SQLITE_EXTENSION_INIT1 const sqlite3_api_routines *sqlite3_api=0; # define SQLITE_EXTENSION_INIT2(v) sqlite3_api=v; |
︙ | ︙ |
Changes to src/test_rtree.c.
︙ | ︙ | |||
151 152 153 154 155 156 157 158 159 160 161 162 163 164 | *pRes = 0; return SQLITE_OK; } /* ** Implementation of "circle" r-tree geometry callback using the ** 2nd-generation interface that allows scoring. */ static int circle_query_func(sqlite3_rtree_query_info *p){ int i; /* Iterator variable */ Circle *pCircle; /* Structure defining circular region */ double xmin, xmax; /* X dimensions of box being tested */ double ymin, ymax; /* X dimensions of box being tested */ int nWithin = 0; /* Number of corners inside the circle */ | > > > > > | 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 | *pRes = 0; return SQLITE_OK; } /* ** Implementation of "circle" r-tree geometry callback using the ** 2nd-generation interface that allows scoring. ** ** Two calling forms: ** ** Qcircle(X,Y,Radius,eType) -- All values are doubles ** Qcircle('x:X y:Y r:R e:ETYPE') -- Single string parameter */ static int circle_query_func(sqlite3_rtree_query_info *p){ int i; /* Iterator variable */ Circle *pCircle; /* Structure defining circular region */ double xmin, xmax; /* X dimensions of box being tested */ double ymin, ymax; /* X dimensions of box being tested */ int nWithin = 0; /* Number of corners inside the circle */ |
︙ | ︙ | |||
172 173 174 175 176 177 178 | /* If pUser is still 0, then the parameter values have not been tested ** for correctness or stored into a Circle structure yet. Do this now. */ /* This geometry callback is for use with a 2-dimensional r-tree table. ** Return an error if the table does not have exactly 2 dimensions. */ if( p->nCoord!=4 ) return SQLITE_ERROR; | | | < | > | | | | > > > > > > > > > > > > > > > > > > > > > > > > > > > | 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 | /* If pUser is still 0, then the parameter values have not been tested ** for correctness or stored into a Circle structure yet. Do this now. */ /* This geometry callback is for use with a 2-dimensional r-tree table. ** Return an error if the table does not have exactly 2 dimensions. */ if( p->nCoord!=4 ) return SQLITE_ERROR; /* Test that the correct number of parameters (1 or 4) have been supplied. */ if( p->nParam!=4 && p->nParam!=1 ) return SQLITE_ERROR; /* Allocate a structure to cache parameter data in. Return SQLITE_NOMEM ** if the allocation fails. */ pCircle = (Circle *)(p->pUser = sqlite3_malloc(sizeof(Circle))); if( !pCircle ) return SQLITE_NOMEM; p->xDelUser = circle_del; /* Record the center and radius of the circular region. One way that ** tested bounding boxes that intersect the circular region are detected ** is by testing if each corner of the bounding box lies within radius ** units of the center of the circle. */ if( p->nParam==4 ){ pCircle->centerx = p->aParam[0]; pCircle->centery = p->aParam[1]; pCircle->radius = p->aParam[2]; pCircle->eScoreType = (int)p->aParam[3]; }else{ const char *z = (const char*)sqlite3_value_text(p->apSqlParam[0]); pCircle->centerx = 0.0; pCircle->centery = 0.0; pCircle->radius = 0.0; pCircle->eScoreType = 0; while( z && z[0] ){ if( z[0]=='r' && z[1]==':' ){ pCircle->radius = atof(&z[2]); }else if( z[0]=='x' && z[1]==':' ){ pCircle->centerx = atof(&z[2]); }else if( z[0]=='y' && z[1]==':' ){ pCircle->centery = atof(&z[2]); }else if( z[0]=='e' && z[1]==':' ){ pCircle->eScoreType = (int)atof(&z[2]); }else if( z[0]==' ' ){ z++; continue; } while( z[0]!=0 && z[0]!=' ' ) z++; while( z[0]==' ' ) z++; } } if( pCircle->radius<0.0 ){ sqlite3_free(pCircle); return SQLITE_NOMEM; } /* Define two bounding box regions. The first, aBox[0], extends to ** infinity in the X dimension. It covers the same range of the Y dimension ** as the circular region. The second, aBox[1], extends to infinity in ** the Y dimension and is constrained to the range of the circle in the ** X dimension. ** |
︙ | ︙ |
Changes to src/vdbeInt.h.
︙ | ︙ | |||
182 183 184 185 186 187 188 189 190 191 192 193 194 195 | void (*xDel)(void*);/* Destructor for Mem.z - only valid if MEM_Dyn */ #ifdef SQLITE_DEBUG Mem *pScopyFrom; /* This Mem is a shallow copy of pScopyFrom */ void *pFiller; /* So that sizeof(Mem) is a multiple of 8 */ #endif }; /* One or more of the following flags are set to indicate the validOK ** representations of the value stored in the Mem struct. ** ** If the MEM_Null flag is set, then the value is an SQL NULL value. ** No other flags may be set in this case. ** ** If the MEM_Str flag is set then Mem.z points at a string representation. | > > > > > > | 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 | void (*xDel)(void*);/* Destructor for Mem.z - only valid if MEM_Dyn */ #ifdef SQLITE_DEBUG Mem *pScopyFrom; /* This Mem is a shallow copy of pScopyFrom */ void *pFiller; /* So that sizeof(Mem) is a multiple of 8 */ #endif }; /* ** Size of struct Mem not including the Mem.zMalloc member or anything that ** follows. */ #define MEMCELLSIZE offsetof(Mem,zMalloc) /* One or more of the following flags are set to indicate the validOK ** representations of the value stored in the Mem struct. ** ** If the MEM_Null flag is set, then the value is an SQL NULL value. ** No other flags may be set in this case. ** ** If the MEM_Str flag is set then Mem.z points at a string representation. |
︙ | ︙ |
Changes to src/vdbeapi.c.
︙ | ︙ | |||
207 208 209 210 211 212 213 214 215 216 217 218 219 220 | SQLITE_INTEGER, /* 0x1c */ SQLITE_NULL, /* 0x1d */ SQLITE_INTEGER, /* 0x1e */ SQLITE_NULL, /* 0x1f */ }; return aType[pVal->flags&MEM_AffMask]; } /**************************** sqlite3_result_ ******************************* ** The following routines are used by user-defined functions to specify ** the function result. ** ** The setStrOrError() function calls sqlite3VdbeMemSetStr() to store the ** result as a string or blob but if the string or blob is too large, it | > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 | SQLITE_INTEGER, /* 0x1c */ SQLITE_NULL, /* 0x1d */ SQLITE_INTEGER, /* 0x1e */ SQLITE_NULL, /* 0x1f */ }; return aType[pVal->flags&MEM_AffMask]; } /* Make a copy of an sqlite3_value object */ sqlite3_value *sqlite3_value_dup(const sqlite3_value *pOrig){ sqlite3_value *pNew; if( pOrig==0 ) return 0; pNew = sqlite3_malloc( sizeof(*pNew) ); if( pNew==0 ) return 0; memset(pNew, 0, sizeof(*pNew)); memcpy(pNew, pOrig, MEMCELLSIZE); pNew->flags &= ~MEM_Dyn; pNew->db = 0; if( pNew->flags&(MEM_Str|MEM_Blob) ){ if( 0==(pOrig->flags&MEM_Static) ){ pNew->flags |= MEM_Ephem; sqlite3VdbeMemMakeWriteable(pNew); } } return pNew; } /* Destroy an sqlite3_value object previously obtained from ** sqlite3_value_dup(). */ void sqlite3_value_free(sqlite3_value *pOld){ sqlite3ValueFree(pOld); } /**************************** sqlite3_result_ ******************************* ** The following routines are used by user-defined functions to specify ** the function result. ** ** The setStrOrError() function calls sqlite3VdbeMemSetStr() to store the ** result as a string or blob but if the string or blob is too large, it |
︙ | ︙ |
Changes to src/vdbemem.c.
︙ | ︙ | |||
766 767 768 769 770 771 772 | pX->pScopyFrom = 0; } } pMem->pScopyFrom = 0; } #endif /* SQLITE_DEBUG */ | < < < < | 766 767 768 769 770 771 772 773 774 775 776 777 778 779 | pX->pScopyFrom = 0; } } pMem->pScopyFrom = 0; } #endif /* SQLITE_DEBUG */ /* ** Make an shallow copy of pFrom into pTo. Prior contents of ** pTo are freed. The pFrom->z field is not duplicated. If ** pFrom->z is used, then pTo->z points to the same thing as pFrom->z ** and flags gets srcType (either MEM_Ephem or MEM_Static). */ |
︙ | ︙ |
Changes to test/misc1.test.
︙ | ︙ | |||
598 599 600 601 602 603 604 605 606 607 608 609 610 611 | CREATE TABLE t19 AS SELECT 1, 2 AS '', 3; SELECT * FROM t19; } {1 2 3} do_execsql_test misc1-19.2 { CREATE TABLE t19b AS SELECT 4 AS '', 5 AS '', 6 AS ''; SELECT * FROM t19b; } {4 5 6} # 2014-05-16: Tests for the SQLITE_TESTCTRL_FAULT_INSTALL feature. # unset -nocomplain fault_callbacks set fault_callbacks {} proc fault_callback {n} { lappend ::fault_callbacks $n | > > > > > > > > > | 598 599 600 601 602 603 604 605 606 607 608 609 610 611 612 613 614 615 616 617 618 619 620 | CREATE TABLE t19 AS SELECT 1, 2 AS '', 3; SELECT * FROM t19; } {1 2 3} do_execsql_test misc1-19.2 { CREATE TABLE t19b AS SELECT 4 AS '', 5 AS '', 6 AS ''; SELECT * FROM t19b; } {4 5 6} # 2015-05-20: CREATE TABLE AS should not store INT value is a TEXT # column. # do_execsql_test misc1-19.3 { CREATE TABLE t19c(x TEXT); CREATE TABLE t19d AS SELECT * FROM t19c UNION ALL SELECT 1234; SELECT x, typeof(x) FROM t19d; } {1234 text} # 2014-05-16: Tests for the SQLITE_TESTCTRL_FAULT_INSTALL feature. # unset -nocomplain fault_callbacks set fault_callbacks {} proc fault_callback {n} { lappend ::fault_callbacks $n |
︙ | ︙ |
Changes to test/select4.test.
︙ | ︙ | |||
905 906 907 908 909 910 911 912 913 | } {1 3} do_execsql_test select4-14.14 { VALUES(1),(2),(3) EXCEPT VALUES(1),(3); } {2} do_execsql_test select4-14.15 { SELECT * FROM (SELECT 123), (SELECT 456) ON likely(0 OR 1) OR 0; } {123 456} finish_test | > > > > > > | 905 906 907 908 909 910 911 912 913 914 915 916 917 918 919 | } {1 3} do_execsql_test select4-14.14 { VALUES(1),(2),(3) EXCEPT VALUES(1),(3); } {2} do_execsql_test select4-14.15 { SELECT * FROM (SELECT 123), (SELECT 456) ON likely(0 OR 1) OR 0; } {123 456} do_execsql_test select4-14.16 { VALUES(1),(2),(3),(4) UNION ALL SELECT 5 LIMIT 99; } {1 2 3 4 5} do_execsql_test select4-14.17 { VALUES(1),(2),(3),(4) UNION ALL SELECT 5 LIMIT 3; } {1 2 3} finish_test |