/ Check-in [7c3d441f]
Login
SQLite training in Houston TX on 2019-11-05 (details)
Part of the 2019 Tcl Conference

Many hyperlinks are disabled.
Use anonymous login to enable hyperlinks.

Overview
Comment:Fix an off-by-one comparison in the intarray() virtual table. Get the intarray() virtual table tests working using the legacy makefile.
Downloads: Tarball | ZIP archive | SQL archive
Timelines: family | ancestors | descendants | both | prototype-int-array
Files: files | file ages | folders
SHA1: 7c3d441f2a9f642f3d91dcee854a4d16d298bc34
User & Date: drh 2016-07-02 20:57:06
Context
2016-07-03
02:35
Change the name of the intarray() extension to carray() and give it an optional third parameter that specifies the datatype as one of 'int32', 'int64', 'double', or 'char*'. 'int32' is the default. Closed-Leaf check-in: a204ba99 user: drh tags: prototype-int-array
2016-07-02
20:57
Fix an off-by-one comparison in the intarray() virtual table. Get the intarray() virtual table tests working using the legacy makefile. check-in: 7c3d441f user: drh tags: prototype-int-array
20:51
Merge the alternative table-valued function RHS of IN operator implementation from trunk. check-in: 507fdbfb user: drh tags: prototype-int-array
Changes
Hide Diffs Unified Diffs Ignore Whitespace Patch

Changes to ext/misc/array.c.

21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
...
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
...
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
** has been cast to an integer.
**
** HOW IT WORKS
**
** The intarray "function" is really a virtual table with the
** following schema:
**
**     CREATE FUNCTION intarray(
**       value,
**       pointer HIDDEN,
**       count HIDDEN
**     );
*/
#include "sqlite3ext.h"
SQLITE_EXTENSION_INIT1
................................................................................

/*
** Return TRUE if the cursor has been moved off of the last
** row of output.
*/
static int intarrayEof(sqlite3_vtab_cursor *cur){
  intarray_cursor *pCur = (intarray_cursor*)cur;
  return pCur->iRowid>=pCur->iCnt;
}

/*
** This method is called to "rewind" the intarray_cursor object back
** to the first row of output.
*/
static int intarrayFilter(
  sqlite3_vtab_cursor *pVtabCursor, 
  int idxNum, const char *idxStr,
  int argc, sqlite3_value **argv
){
  intarray_cursor *pCur = (intarray_cursor *)pVtabCursor;
  int i = 0;
  if( idxNum ){
    pCur->iPtr = sqlite3_value_int64(argv[0]);
    pCur->iCnt = sqlite3_value_int64(argv[1]);
  }else{
    pCur->iPtr = 0;
    pCur->iCnt = 0;
  }
................................................................................
** If idxNum is 0, then intarray becomes an empty table.
*/
static int intarrayBestIndex(
  sqlite3_vtab *tab,
  sqlite3_index_info *pIdxInfo
){
  int i;                 /* Loop over constraints */
  int idxNum = 0;        /* The query plan bitmask */
  int ptrIdx = -1;       /* Index of the pointer= constraint, or -1 if none */
  int cntIdx = -1;       /* Index of the count= constraint, or -1 if none */
  int nArg = 0;          /* Number of arguments that intarrayFilter() expects */

  const struct sqlite3_index_constraint *pConstraint;
  pConstraint = pIdxInfo->aConstraint;
  for(i=0; i<pIdxInfo->nConstraint; i++, pConstraint++){
    if( pConstraint->usable==0 ) continue;
    if( pConstraint->op!=SQLITE_INDEX_CONSTRAINT_EQ ) continue;
    switch( pConstraint->iColumn ){







|







 







|












<







 







<


<







21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
...
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183

184
185
186
187
188
189
190
...
205
206
207
208
209
210
211

212
213

214
215
216
217
218
219
220
** has been cast to an integer.
**
** HOW IT WORKS
**
** The intarray "function" is really a virtual table with the
** following schema:
**
**     CREATE TABLE intarray(
**       value,
**       pointer HIDDEN,
**       count HIDDEN
**     );
*/
#include "sqlite3ext.h"
SQLITE_EXTENSION_INIT1
................................................................................

/*
** Return TRUE if the cursor has been moved off of the last
** row of output.
*/
static int intarrayEof(sqlite3_vtab_cursor *cur){
  intarray_cursor *pCur = (intarray_cursor*)cur;
  return pCur->iRowid>pCur->iCnt;
}

/*
** This method is called to "rewind" the intarray_cursor object back
** to the first row of output.
*/
static int intarrayFilter(
  sqlite3_vtab_cursor *pVtabCursor, 
  int idxNum, const char *idxStr,
  int argc, sqlite3_value **argv
){
  intarray_cursor *pCur = (intarray_cursor *)pVtabCursor;

  if( idxNum ){
    pCur->iPtr = sqlite3_value_int64(argv[0]);
    pCur->iCnt = sqlite3_value_int64(argv[1]);
  }else{
    pCur->iPtr = 0;
    pCur->iCnt = 0;
  }
................................................................................
** If idxNum is 0, then intarray becomes an empty table.
*/
static int intarrayBestIndex(
  sqlite3_vtab *tab,
  sqlite3_index_info *pIdxInfo
){
  int i;                 /* Loop over constraints */

  int ptrIdx = -1;       /* Index of the pointer= constraint, or -1 if none */
  int cntIdx = -1;       /* Index of the count= constraint, or -1 if none */


  const struct sqlite3_index_constraint *pConstraint;
  pConstraint = pIdxInfo->aConstraint;
  for(i=0; i<pIdxInfo->nConstraint; i++, pConstraint++){
    if( pConstraint->usable==0 ) continue;
    if( pConstraint->op!=SQLITE_INDEX_CONSTRAINT_EQ ) continue;
    switch( pConstraint->iColumn ){

Changes to main.mk.

320
321
322
323
324
325
326

327
328
329
330
331
332
333
  $(TOP)/src/test_windirent.c \
  $(TOP)/src/test_wsd.c

# Extensions to be statically loaded.
#
TESTSRC += \
  $(TOP)/ext/misc/amatch.c \

  $(TOP)/ext/misc/closure.c \
  $(TOP)/ext/misc/csv.c \
  $(TOP)/ext/misc/eval.c \
  $(TOP)/ext/misc/fileio.c \
  $(TOP)/ext/misc/fuzzer.c \
  $(TOP)/ext/misc/ieee754.c \
  $(TOP)/ext/misc/nextchar.c \







>







320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
  $(TOP)/src/test_windirent.c \
  $(TOP)/src/test_wsd.c

# Extensions to be statically loaded.
#
TESTSRC += \
  $(TOP)/ext/misc/amatch.c \
  $(TOP)/ext/misc/array.c \
  $(TOP)/ext/misc/closure.c \
  $(TOP)/ext/misc/csv.c \
  $(TOP)/ext/misc/eval.c \
  $(TOP)/ext/misc/fileio.c \
  $(TOP)/ext/misc/fuzzer.c \
  $(TOP)/ext/misc/ieee754.c \
  $(TOP)/ext/misc/nextchar.c \

Changes to test/tabfunc01.test.

197
198
199
200
201
202
203











204
205
206
207
208
do_test tabfunc01-671 {
  sqlite3_bind_intarray $VM 1 11 22 33 44 55
  sqlite3_step $VM
} SQLITE_ROW
do_test tabfunc01-672 {
  sqlite3_column_int $VM 0
} 11











sqlite3_finalize $VM

catch {sqlite3_bind_intarray}

finish_test







>
>
>
>
>
>
>
>
>
>
>





197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
do_test tabfunc01-671 {
  sqlite3_bind_intarray $VM 1 11 22 33 44 55
  sqlite3_step $VM
} SQLITE_ROW
do_test tabfunc01-672 {
  sqlite3_column_int $VM 0
} 11
do_test tabfunc01-673 {
  sqlite3_step $VM
  sqlite3_column_int $VM 0
} 22
do_test tabfunc01-674 {
  sqlite3_step $VM
  sqlite3_column_int $VM 0
} 33
do_test tabfunc01-675 {
  sqlite3_step $VM
} {SQLITE_DONE}
sqlite3_finalize $VM

catch {sqlite3_bind_intarray}

finish_test