Tweaks to the sqlite3_vtab_in() interface.
FossilOrigin-Name: 75040183b8e14f20bfedfdcc1a9fb968f2f0193bc698605d1b4791a3699b93d9
This commit is contained in:
parent
a9f18f0172
commit
b30298d3ea
16
manifest
16
manifest
@ -1,5 +1,5 @@
|
||||
C Index\sin\s2nd\sargument\sto\ssqlite3_vtab_in()\sshould\sbe\son\sthe\saConstraint[]\narray,\snot\sthe\sinternal\sarray\sof\sall\sconstraints.
|
||||
D 2022-02-01T16:30:57.444
|
||||
C Tweaks\sto\sthe\ssqlite3_vtab_in()\sinterface.
|
||||
D 2022-02-01T21:59:43.937
|
||||
F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1
|
||||
F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea
|
||||
F LICENSE.md df5091916dbb40e6e9686186587125e1b2ff51f022cc334e886c19a0e9982724
|
||||
@ -554,7 +554,7 @@ F src/resolve.c 24032ae57aec10df2f3fa2e20be0aae7d256bc704124b76c52d763440c7c0fe9
|
||||
F src/rowset.c ba9515a922af32abe1f7d39406b9d35730ed65efab9443dc5702693b60854c92
|
||||
F src/select.c a6d2d4bed279d7fe4fcedaf297eaf6441e8e17c6e3947a32d24d23be52ac02f2
|
||||
F src/shell.c.in 2f58e6aa6b3d2012db32f1c5fa4591e9d12fd582904632b4fc8f57a382b98fd3
|
||||
F src/sqlite.h.in 0aed2b88e91d03314121cd1e546441e37513929793c3cf7584b5b7ce445a9128
|
||||
F src/sqlite.h.in 72f3e57c4c0b4284ab9238312f7fd797967cc43f44558a80469a3d9b86a7be2b
|
||||
F src/sqlite3.rc 5121c9e10c3964d5755191c80dd1180c122fc3a8
|
||||
F src/sqlite3ext.h a95cb9ed106e3d39e2118e4dcc15a14faec3fa50d0093425083d340d9dfd96e6
|
||||
F src/sqliteInt.h 838df3e9ba9390058076d2f50c7efde9e0e8747303e788cf5bbe05402ab10924
|
||||
@ -627,7 +627,7 @@ F src/vacuum.c 6c38ddc52f0619865c91dae9c441d4d48bf3040d7dc1bc5b22da1e45547ed0b3
|
||||
F src/vdbe.c d6694187a2819df7c2df3bd568fd059617c3edef4aa87e28a8121b02818f4ebf
|
||||
F src/vdbe.h 25dabb25c7e157b84e59260cfb5b466c3ac103ede9f36f4db371332c47601abe
|
||||
F src/vdbeInt.h 24d58f12f642dcac102fa75d08e99ad06b6cbc66bf4948bb61e2e223ef9518b6
|
||||
F src/vdbeapi.c 4d26cc9eb1a0f937e8d360578dc56d00145bac08afd503ba6ac843007f7d8c1f
|
||||
F src/vdbeapi.c 84e7e8d161c8fb7259eaa5fe7234f2334ef9fb013674ce34705b56166052b5fa
|
||||
F src/vdbeaux.c e761b8011baec7a4773f0a7594783f2cd71f699ab187c4aad917529ab8acd3fe
|
||||
F src/vdbeblob.c 5e61ce31aca17db8fb60395407457a8c1c7fb471dde405e0cd675974611dcfcd
|
||||
F src/vdbemem.c eb6042667c02c3ef1f968235b4a170e31b23a4b6a57f65a8454eab4d36f14b7f
|
||||
@ -639,7 +639,7 @@ F src/vxworks.h d2988f4e5a61a4dfe82c6524dd3d6e4f2ce3cdb9
|
||||
F src/wal.c b9df133a705093da8977da5eb202eaadb844839f1c7297c08d33471f5491843d
|
||||
F src/wal.h c3aa7825bfa2fe0d85bef2db94655f99870a285778baa36307c0a16da32b226a
|
||||
F src/walker.c f890a3298418d7cba3b69b8803594fdc484ea241206a8dfa99db6dd36f8cbb3b
|
||||
F src/where.c cbf02091ed71784f7972ca39aaecb22822781f3b96905ece1a30e80161629769
|
||||
F src/where.c 392d552fa6636e94d242954247e277eb9b0d9c45446afb0c0a57f8c6fcb3f792
|
||||
F src/whereInt.h 1d821657238a0bd12b3c8f2926c7f8f9294bc5efe20af53c7c50d53a0a026cb9
|
||||
F src/wherecode.c 5879604677f0bdfb8d95ff616d834daecc12256346b7d9ad96a7e84a1cb08fdc
|
||||
F src/whereexpr.c ddb6ab49f745154c37dbdb291433c933e00175929647290a11f487af701d0392
|
||||
@ -1942,8 +1942,8 @@ F vsixtest/vsixtest.tcl 6a9a6ab600c25a91a7acc6293828957a386a8a93
|
||||
F vsixtest/vsixtest.vcxproj.data 2ed517e100c66dc455b492e1a33350c1b20fbcdc
|
||||
F vsixtest/vsixtest.vcxproj.filters 37e51ffedcdb064aad6ff33b6148725226cd608e
|
||||
F vsixtest/vsixtest_TemporaryKey.pfx e5b1b036facdb453873e7084e1cae9102ccc67a0
|
||||
P eb84b80e1f6d8c32bf0c9e1731f0233de0160a13f714f766779ae01fdf504e7b
|
||||
R 320e3be3dedfcb44854348cea4a95b96
|
||||
P 5acf90a931b27b7d627c0a8fee68170430e09b028d6643b959b0ec14fd59f7ac
|
||||
R e3dc8c48dc1f78fd77820f7d72429762
|
||||
U drh
|
||||
Z 4a8e49183eb36a5777c7e6fa2fd8d0f2
|
||||
Z 89712fde261ff7ce2e71753d08fff668
|
||||
# Remove this line to create a well-formed Fossil manifest.
|
||||
|
@ -1 +1 @@
|
||||
5acf90a931b27b7d627c0a8fee68170430e09b028d6643b959b0ec14fd59f7ac
|
||||
75040183b8e14f20bfedfdcc1a9fb968f2f0193bc698605d1b4791a3699b93d9
|
144
src/sqlite.h.in
144
src/sqlite.h.in
@ -9607,72 +9607,94 @@ int sqlite3_vtab_distinct(sqlite3_index_info*);
|
||||
/*
|
||||
** CAPI3REF: Identify and handle IN(...) constraints in xBestIndex
|
||||
**
|
||||
** This API may only be used from within an xBestIndex() callback. The
|
||||
** results of calling it from outside of an xBestIndex() callback are
|
||||
** undefined.
|
||||
** This interface may only be used from within an
|
||||
** [xBestIndex|xBestIndex() method of a [virtual table] implementation.
|
||||
** The result of invoking this interface from any other context is
|
||||
** undefined and probably harmful.
|
||||
**
|
||||
** When a column of a virtual table is subject to a "col IN (...)"
|
||||
** constraint, this is passed through to the xBestIndex method of the
|
||||
** virtual table as an SQLITE_INDEX_CONSTRAINT_EQ constraint. Then, if
|
||||
** the virtual table indicates that it can handle the constraint, SQLite
|
||||
** uses the xFilter and xNext methods of the virtual table to query
|
||||
** separately for each distinct element in RHS of the IN(...) expression.
|
||||
** This API allows a virtual table implementation to determine which
|
||||
** SQLITE_INDEX_CONSTRAINT_EQ constraints are actually IN(...) constraints,
|
||||
** and to handle them using a single xFilter scan.
|
||||
** A constraint on a virtual table of the form "column IN (...)" is
|
||||
** communicated to the xBestIndex method as a
|
||||
** [SQLITE_INDEX_CONSTRAINT_EQ] constraint. If xBestIndex wants to use
|
||||
** this constraint, it must set the corresponding
|
||||
** aConstraintUsage[].argvIndex to a postive integer. Then, under
|
||||
** the usual mode of handling IN operators, SQLite generate bytecode
|
||||
** that invokes the [xFilter|xFilter() method] once for each value
|
||||
** on the right-hand side of the IN operator. Thus the virtual table
|
||||
** only sees a single value from the right-hand side of the IN operator
|
||||
** at a time.
|
||||
**
|
||||
** In some cases, however, it would be advantageous for the virtual
|
||||
** table to see all values on the right-hand of the IN operator all at
|
||||
** once. The sqlite3_vtab_in() interfaces facilitates this in two ways:
|
||||
**
|
||||
** <ol>
|
||||
** <li><p>
|
||||
** A call to sqlite3_vtab_in(P,I,-1) will return true (non-zero)
|
||||
** if and only if the I-th constraint in P->aConstraint[] is
|
||||
** an IN operator that can be processed all at once. In other words,
|
||||
** sqlite3_vtab_in() with -1 in the third argument is a mechanism
|
||||
** by which the virtual table can ask SQLite if all-at-once processing
|
||||
** of the IN operator is even possible.
|
||||
**
|
||||
** <li><p>
|
||||
** A call to sqlite3_vtab_in(P,I,F) with F set to 1 or 0 indicates
|
||||
** to SQLite that the virtual table does or does not want to process
|
||||
** the IN operator all-at-once. Thus when the third parameter (F) is
|
||||
** non-negative, this interface is the mechanism by which the virtual
|
||||
** table tells SQLite how it wants to process in IN operator.
|
||||
** </ol>
|
||||
**
|
||||
** The sqlite3_vtab_in(P,I,F) interface can be invoked multiple times
|
||||
** within the same xBestIndex method call. For any given P and I parameters,
|
||||
** the return value from sqlite3_vtab_in(P,I,F) will always be the same
|
||||
** for every invocation within the same xBestIndex call. If the interface
|
||||
** returns true (non-zero), that means that the constraint is an IN operator
|
||||
** that can be processed all-at-once. If the constraint is not an IN
|
||||
** operator or cannot be processed all-at-once, then the interface returns
|
||||
** false.
|
||||
**
|
||||
** All-at-once processing of the IN operator is selected if both of the
|
||||
** following conditions are met:
|
||||
**
|
||||
** <ol>
|
||||
** <li><p> The P->aConstraintUsage[I].argvIndex value is set to a positive
|
||||
** integer. This is how the virtual table tells SQLite that it wants to
|
||||
** use the I-th constraint.
|
||||
**
|
||||
** <li><p> The last call to sqlite3_vtab_in(P,I,F) for which F was
|
||||
** non-negative had F>=1.
|
||||
** </ol>
|
||||
**
|
||||
** If the second argument passed to this function is not the index of an
|
||||
** SQLITE_INDEX_CONSTRAINT_EQ constraint in the aConstraint[] array of the
|
||||
** sqlite3_index_info object, or if the SQLITE_INDEX_CONSTRAINT_EQ is not
|
||||
** really an IN(...) expression, then this function is a no-op. Zero is
|
||||
** returned in this case.
|
||||
**
|
||||
** Otherwise, if parameter iCons is the index of an SQLITE_INDEX_CONSTRAINT_EQ
|
||||
** constraint that is really an IN(...) expression, then this function
|
||||
** returns non-zero. In this case, the call also specifies whether SQLite
|
||||
** should invoke xFilter() once for each element on the RHS of the IN(...)
|
||||
** expression (the default, if bHandle is zero), or just once for the entire
|
||||
** list (if bHandle is non-zero), should the associated
|
||||
** aConstraintUsage[].argvIndex variable be set by xBestIndex.
|
||||
**
|
||||
** In cases where the list on the RHS of an IN(...) constraint is passed to a
|
||||
** single xFilter() call, the (sqlite3_value*) passed appears in most
|
||||
** respects to be a NULL value. Except, it may be used with the
|
||||
** sqlite3_vtab_in_first() and sqlite3_vtab_in_next() APIs to interate through
|
||||
** the list of values.
|
||||
** If either or both of the conditions above are false, then uses the
|
||||
** traditional one-at-a-time processing strategy for IN constraint.
|
||||
** If both conditions are true, then the argvIndex-th parameter to the
|
||||
** xFilter method will be an [sqlite3_value] that appears to be NULL,
|
||||
** but which can be passed to [sqlite3_vtab_in_first()] and
|
||||
** [sqlite3_vtab_in_next()] to find all values on the right-hand side
|
||||
** of the IN constraint.
|
||||
*/
|
||||
int sqlite3_vtab_in(sqlite3_index_info*, int iCons, int bHandle);
|
||||
|
||||
/*
|
||||
** CAPI3REF: Visit the first element of an IN(...) list passed to xFilter
|
||||
** CAPI3REF: Find all elements on the right-hand side of an IN constraint.
|
||||
**
|
||||
** This API may only be used from within an xFilter() callback. The
|
||||
** results of calling it from outside of an xFilter() callback are
|
||||
** undefined.
|
||||
** These interfaces are only useful from within the
|
||||
** [xFilter|xFilter() method] of a virtual table implementation.
|
||||
** The result of invoking these interfaces from any other context
|
||||
** is undefined and probably harmful.
|
||||
**
|
||||
** If the (sqlite3_value*) passed as the first argument to this function
|
||||
** is not a value representing the RHS of an IN(...) operator (see
|
||||
** API function sqlite3_vtab_in()), of if the RHS of the IN(...) operator
|
||||
** is an empty set, this function sets (*ppOut) to NULL and returns
|
||||
** SQLITE_OK.
|
||||
** The X parameter in a call to sqlite3_vtab_in_first(X,P) or
|
||||
** sqlite3_vtab_in_next(X,P) must be one of the parameters to the
|
||||
** xFilter method which invokes those routines, and specifically
|
||||
** a parameter that was previously selected for all-at-once IN constraint
|
||||
** processing use the [sqlite3_vtab_in()] interface in the
|
||||
** [xBestIndex|xBestIndex method]. If the X parameter is not
|
||||
** an xFilter argument that was selected for all-at-once IN constraint
|
||||
** processing, then these routines return SQLITE_MISUSE or perhaps
|
||||
** exhibit some other undefined or harmful behavior.
|
||||
**
|
||||
** Otherwise, if no error occurs, it sets (*ppOut) to point to an object
|
||||
** containing the first value in the list and returns SQLITE_OK. The
|
||||
** pointer is valid until either the xFilter() call returns or until the
|
||||
** next call to sqlite3_vtab_in_first() or sqlite3_vtab_in_next() with
|
||||
** the same first argument.
|
||||
**
|
||||
** If an error occurs, (*ppOut) is set to NULL and an SQLite error code
|
||||
** returned.
|
||||
*/
|
||||
int sqlite3_vtab_in_first(sqlite3_value *pVal, sqlite3_value **ppOut);
|
||||
|
||||
/*
|
||||
** CAPI3REF: Visit the next element of an IN(...) list passed to xFilter
|
||||
**
|
||||
** This function is called after a successful call to sqlite3_vtab_in_first()
|
||||
** to visit the next and subsequent elements of an IN(...) list passed
|
||||
** to an xFilter callback. Example usage:
|
||||
** Use these routines to access all values on the right-hand side
|
||||
** of the IN constraint using code like the following:
|
||||
**
|
||||
** <pre>
|
||||
** for(rc=sqlite3_vtab_in_first(pList, &pVal);
|
||||
@ -9685,7 +9707,15 @@ int sqlite3_vtab_in_first(sqlite3_value *pVal, sqlite3_value **ppOut);
|
||||
** // an error has occurred
|
||||
** }
|
||||
** </pre>
|
||||
**
|
||||
** On success, the sqlite3_vtab_in_first(X,P) and sqlite3_vtab_in_next(X,P)
|
||||
** routines return SQLITE_OK and set *P to point to the first or next value
|
||||
** on the RHS of the IN constraint. If there are no more values on the
|
||||
** right hand side of the IN constraint, then *P is set to NULL and these
|
||||
** routines return [SQLITE_DONE]. The return value might be
|
||||
** some other value, such as SQLITE_NOMEM, in the event of a malfunction.
|
||||
*/
|
||||
int sqlite3_vtab_in_first(sqlite3_value *pVal, sqlite3_value **ppOut);
|
||||
int sqlite3_vtab_in_next(sqlite3_value *pVal, sqlite3_value **ppOut);
|
||||
|
||||
/*
|
||||
|
@ -888,21 +888,21 @@ static int vtabInLoadValue(sqlite3_value *pVal, sqlite3_value **ppOut){
|
||||
** sqlite3_vtab_in_next() (if bNext!=0).
|
||||
*/
|
||||
static int vtabInOp(sqlite3_value *pVal, sqlite3_value **ppOut, int bNext){
|
||||
int rc = SQLITE_OK;
|
||||
int rc;
|
||||
BtCursor *pCsr;
|
||||
*ppOut = 0;
|
||||
if( pVal && pVal->uTemp==SQLITE_VTAB_IN_MAGIC ){
|
||||
BtCursor *pCsr = (BtCursor*)pVal->z;
|
||||
|
||||
if( bNext ){
|
||||
rc = sqlite3BtreeNext(pCsr, 0);
|
||||
}else{
|
||||
int dummy = 0;
|
||||
rc = sqlite3BtreeFirst(pCsr, &dummy);
|
||||
}
|
||||
|
||||
if( rc==SQLITE_OK && sqlite3BtreeEof(pCsr)==0 ){
|
||||
rc = vtabInLoadValue(pVal, ppOut);
|
||||
}
|
||||
if( pVal==0 ) return SQLITE_MISUSE;
|
||||
if( pVal->uTemp!=SQLITE_VTAB_IN_MAGIC ) return SQLITE_MISUSE;
|
||||
pCsr = (BtCursor*)pVal->z;
|
||||
if( bNext ){
|
||||
rc = sqlite3BtreeNext(pCsr, 0);
|
||||
}else{
|
||||
int dummy = 0;
|
||||
rc = sqlite3BtreeFirst(pCsr, &dummy);
|
||||
if( rc==SQLITE_OK && sqlite3BtreeEof(pCsr) ) rc = SQLITE_DONE;
|
||||
}
|
||||
if( rc==SQLITE_OK ){
|
||||
rc = vtabInLoadValue(pVal, ppOut);
|
||||
}
|
||||
return rc;
|
||||
}
|
||||
|
@ -3605,7 +3605,7 @@ static int whereLoopAddVirtualOne(
|
||||
}
|
||||
}
|
||||
if( SMASKBIT32(i) & pHidden->mHandleIn ){
|
||||
pNew->u.vtab.mHandleIn |= SMASKBIT32(iTerm);
|
||||
pNew->u.vtab.mHandleIn |= MASKBIT32(iTerm);
|
||||
}else if( (pTerm->eOperator & WO_IN)!=0 ){
|
||||
/* A virtual table that is constrained by an IN clause may not
|
||||
** consume the ORDER BY clause because (1) the order of IN terms
|
||||
@ -3715,7 +3715,7 @@ int sqlite3_vtab_in(sqlite3_index_info *pIdxInfo, int iCons, int bHandle){
|
||||
if( m & pHidden->mIn ){
|
||||
if( bHandle==0 ){
|
||||
pHidden->mHandleIn &= ~m;
|
||||
}else{
|
||||
}else if( bHandle>0 ){
|
||||
pHidden->mHandleIn |= m;
|
||||
}
|
||||
return 1;
|
||||
|
Loading…
x
Reference in New Issue
Block a user