-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
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
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
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
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.
/*
** 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.
+**
+** 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:
**
-** 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.
-**
-** 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.
-*/
-int sqlite3_vtab_in(sqlite3_index_info*, int iCons, int bHandle);
-
-/*
-** CAPI3REF: Visit the first element of an IN(...) list passed to xFilter
+** <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>
**
-** This API may only be used from within an xFilter() callback. The
-** results of calling it from outside of an xFilter() callback are
-** undefined.
+** 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.
**
-** 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.
+** All-at-once processing of the IN operator is selected if both of the
+** following conditions are met:
**
-** 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.
+** <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.
**
-** If an error occurs, (*ppOut) is set to NULL and an SQLite error code
-** returned.
+** <li><p> The last call to sqlite3_vtab_in(P,I,F) for which F was
+** non-negative had F>=1.
+** </ol>
+**
+** 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_first(sqlite3_value *pVal, sqlite3_value **ppOut);
+int sqlite3_vtab_in(sqlite3_index_info*, int iCons, int bHandle);
/*
-** CAPI3REF: Visit the next element of an IN(...) list passed to xFilter
+** CAPI3REF: Find all elements on the right-hand side of an IN constraint.
**
-** 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:
+** 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.
+**
+** 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.
+**
+** 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);
** // 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);
/*