15821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/*
25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** 2009 November 10
35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)**
45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** The author disclaims copyright to this source code.  In place of
55821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** a legal notice, here is a blessing:
65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)**
75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)**    May you do good and not evil.
85821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)**    May you find forgiveness for yourself and forgive others.
95821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)**    May you share freely, never taking more than you give.
105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)**
115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)*************************************************************************
125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)**
135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** This file implements a read-only VIRTUAL TABLE that contains the
145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** content of a C-language array of integer values.  See the corresponding
155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** header file for full details.
165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)*/
175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "test_intarray.h"
185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <string.h>
195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <assert.h>
205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/*
235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** Definition of the sqlite3_intarray object.
245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)**
255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** The internal representation of an intarray object is subject
265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** to change, is not externally visible, and should be used by
275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** the implementation of intarray only.  This object is opaque
285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** to users.
295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)*/
305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)struct sqlite3_intarray {
315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int n;                    /* Number of elements in the array */
325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  sqlite3_int64 *a;         /* Contents of the array */
335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void (*xFree)(void*);     /* Function used to free a[] */
345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/* Objects used internally by the virtual table implementation */
375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)typedef struct intarray_vtab intarray_vtab;
385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)typedef struct intarray_cursor intarray_cursor;
395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/* A intarray table object */
415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)struct intarray_vtab {
425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  sqlite3_vtab base;            /* Base class */
435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  sqlite3_intarray *pContent;   /* Content of the integer array */
445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/* A intarray cursor object */
475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)struct intarray_cursor {
485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  sqlite3_vtab_cursor base;    /* Base class */
495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int i;                       /* Current cursor position */
505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/*
535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** None of this works unless we have virtual tables.
545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)*/
555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#ifndef SQLITE_OMIT_VIRTUALTABLE
565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/*
585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** Free an sqlite3_intarray object.
595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)*/
605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static void intarrayFree(sqlite3_intarray *p){
615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if( p->xFree ){
625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    p->xFree(p->a);
635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  sqlite3_free(p);
655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/*
685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** Table destructor for the intarray module.
695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)*/
705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static int intarrayDestroy(sqlite3_vtab *p){
715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  intarray_vtab *pVtab = (intarray_vtab*)p;
725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  sqlite3_free(pVtab);
735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return 0;
745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/*
775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** Table constructor for the intarray module.
785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)*/
795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static int intarrayCreate(
805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  sqlite3 *db,              /* Database where module is created */
815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void *pAux,               /* clientdata for the module */
825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int argc,                 /* Number of arguments */
835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const char *const*argv,   /* Value for all arguments */
845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  sqlite3_vtab **ppVtab,    /* Write the new virtual table object here */
855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  char **pzErr              /* Put error message text here */
865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)){
875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int rc = SQLITE_NOMEM;
885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  intarray_vtab *pVtab = sqlite3_malloc(sizeof(intarray_vtab));
895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if( pVtab ){
915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    memset(pVtab, 0, sizeof(intarray_vtab));
925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    pVtab->pContent = (sqlite3_intarray*)pAux;
935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    rc = sqlite3_declare_vtab(db, "CREATE TABLE x(value INTEGER PRIMARY KEY)");
945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  *ppVtab = (sqlite3_vtab *)pVtab;
965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return rc;
975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/*
1005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** Open a new cursor on the intarray table.
1015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)*/
1025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static int intarrayOpen(sqlite3_vtab *pVTab, sqlite3_vtab_cursor **ppCursor){
1035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int rc = SQLITE_NOMEM;
1045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  intarray_cursor *pCur;
1055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  pCur = sqlite3_malloc(sizeof(intarray_cursor));
1065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if( pCur ){
1075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    memset(pCur, 0, sizeof(intarray_cursor));
1085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    *ppCursor = (sqlite3_vtab_cursor *)pCur;
1095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    rc = SQLITE_OK;
1105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return rc;
1125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/*
1155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** Close a intarray table cursor.
1165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)*/
1175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static int intarrayClose(sqlite3_vtab_cursor *cur){
1185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  intarray_cursor *pCur = (intarray_cursor *)cur;
1195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  sqlite3_free(pCur);
1205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return SQLITE_OK;
1215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/*
1245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** Retrieve a column of data.
1255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)*/
1265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static int intarrayColumn(sqlite3_vtab_cursor *cur, sqlite3_context *ctx, int i){
1275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  intarray_cursor *pCur = (intarray_cursor*)cur;
1285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  intarray_vtab *pVtab = (intarray_vtab*)cur->pVtab;
1295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if( pCur->i>=0 && pCur->i<pVtab->pContent->n ){
1305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    sqlite3_result_int64(ctx, pVtab->pContent->a[pCur->i]);
1315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return SQLITE_OK;
1335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/*
1365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** Retrieve the current rowid.
1375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)*/
1385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static int intarrayRowid(sqlite3_vtab_cursor *cur, sqlite_int64 *pRowid){
1395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  intarray_cursor *pCur = (intarray_cursor *)cur;
1405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  *pRowid = pCur->i;
1415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return SQLITE_OK;
1425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static int intarrayEof(sqlite3_vtab_cursor *cur){
1455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  intarray_cursor *pCur = (intarray_cursor *)cur;
1465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  intarray_vtab *pVtab = (intarray_vtab *)cur->pVtab;
1475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return pCur->i>=pVtab->pContent->n;
1485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/*
1515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** Advance the cursor to the next row.
1525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)*/
1535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static int intarrayNext(sqlite3_vtab_cursor *cur){
1545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  intarray_cursor *pCur = (intarray_cursor *)cur;
1555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  pCur->i++;
1565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return SQLITE_OK;
1575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/*
1605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** Reset a intarray table cursor.
1615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)*/
1625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static int intarrayFilter(
1635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  sqlite3_vtab_cursor *pVtabCursor,
1645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int idxNum, const char *idxStr,
1655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int argc, sqlite3_value **argv
1665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)){
1675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  intarray_cursor *pCur = (intarray_cursor *)pVtabCursor;
1685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  pCur->i = 0;
1695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return SQLITE_OK;
1705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/*
1735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** Analyse the WHERE condition.
1745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)*/
1755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static int intarrayBestIndex(sqlite3_vtab *tab, sqlite3_index_info *pIdxInfo){
1765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return SQLITE_OK;
1775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/*
1805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** A virtual table module that merely echos method calls into TCL
1815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** variables.
1825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)*/
1835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static sqlite3_module intarrayModule = {
1845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  0,                           /* iVersion */
1855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  intarrayCreate,              /* xCreate - create a new virtual table */
1865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  intarrayCreate,              /* xConnect - connect to an existing vtab */
1875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  intarrayBestIndex,           /* xBestIndex - find the best query index */
1885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  intarrayDestroy,             /* xDisconnect - disconnect a vtab */
1895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  intarrayDestroy,             /* xDestroy - destroy a vtab */
1905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  intarrayOpen,                /* xOpen - open a cursor */
1915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  intarrayClose,               /* xClose - close a cursor */
1925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  intarrayFilter,              /* xFilter - configure scan constraints */
1935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  intarrayNext,                /* xNext - advance a cursor */
1945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  intarrayEof,                 /* xEof */
1955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  intarrayColumn,              /* xColumn - read data */
1965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  intarrayRowid,               /* xRowid - read data */
1975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  0,                           /* xUpdate */
1985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  0,                           /* xBegin */
1995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  0,                           /* xSync */
2005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  0,                           /* xCommit */
2015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  0,                           /* xRollback */
2025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  0,                           /* xFindMethod */
2035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  0,                           /* xRename */
2045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
2055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif /* !defined(SQLITE_OMIT_VIRTUALTABLE) */
2075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/*
2095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** Invoke this routine to create a specific instance of an intarray object.
2105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** The new intarray object is returned by the 3rd parameter.
2115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)**
2125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** Each intarray object corresponds to a virtual table in the TEMP table
2135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** with a name of zName.
2145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)**
2155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** Destroy the intarray object by dropping the virtual table.  If not done
2165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** explicitly by the application, the virtual table will be dropped implicitly
2175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** by the system when the database connection is closed.
2185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)*/
2195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int sqlite3_intarray_create(
2205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  sqlite3 *db,
2215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const char *zName,
2225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  sqlite3_intarray **ppReturn
2235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)){
2245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int rc = SQLITE_OK;
2255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#ifndef SQLITE_OMIT_VIRTUALTABLE
2265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  sqlite3_intarray *p;
2275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  *ppReturn = p = sqlite3_malloc( sizeof(*p) );
2295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if( p==0 ){
2305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return SQLITE_NOMEM;
2315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  memset(p, 0, sizeof(*p));
2335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  rc = sqlite3_create_module_v2(db, zName, &intarrayModule, p,
2345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                (void(*)(void*))intarrayFree);
2355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if( rc==SQLITE_OK ){
2365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    char *zSql;
2375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    zSql = sqlite3_mprintf("CREATE VIRTUAL TABLE temp.%Q USING %Q",
2385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                           zName, zName);
2395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    rc = sqlite3_exec(db, zSql, 0, 0, 0);
2405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    sqlite3_free(zSql);
2415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif
2435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return rc;
2445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/*
2475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** Bind a new array array of integers to a specific intarray object.
2485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)**
2495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** The array of integers bound must be unchanged for the duration of
2505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** any query against the corresponding virtual table.  If the integer
2515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** array does change or is deallocated undefined behavior will result.
2525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)*/
2535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int sqlite3_intarray_bind(
2545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  sqlite3_intarray *pIntArray,   /* The intarray object to bind to */
2555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int nElements,                 /* Number of elements in the intarray */
2565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  sqlite3_int64 *aElements,      /* Content of the intarray */
2575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void (*xFree)(void*)           /* How to dispose of the intarray when done */
2585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)){
2595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if( pIntArray->xFree ){
2605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    pIntArray->xFree(pIntArray->a);
2615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  pIntArray->n = nElements;
2635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  pIntArray->a = aElements;
2645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  pIntArray->xFree = xFree;
2655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return SQLITE_OK;
2665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/*****************************************************************************
2705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** Everything below is interface for testing this module.
2715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)*/
2725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#ifdef SQLITE_TEST
2735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <tcl.h>
2745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/*
2765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** Routines to encode and decode pointers
2775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)*/
2785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)extern int getDbPointer(Tcl_Interp *interp, const char *zA, sqlite3 **ppDb);
2795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)extern void *sqlite3TestTextToPtr(const char*);
2805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)extern int sqlite3TestMakePointerStr(Tcl_Interp*, char *zPtr, void*);
2815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)extern const char *sqlite3TestErrorName(int);
2825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/*
2845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)**    sqlite3_intarray_create  DB  NAME
2855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)**
2865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** Invoke the sqlite3_intarray_create interface.  A string that becomes
2875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** the first parameter to sqlite3_intarray_bind.
2885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)*/
2895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static int test_intarray_create(
2905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ClientData clientData, /* Not used */
2915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  Tcl_Interp *interp,    /* The TCL interpreter that invoked this command */
2925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int objc,              /* Number of arguments */
2935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  Tcl_Obj *CONST objv[]  /* Command arguments */
2945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)){
2955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  sqlite3 *db;
2965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const char *zName;
2975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  sqlite3_intarray *pArray;
2985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int rc = SQLITE_OK;
2995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  char zPtr[100];
3005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if( objc!=3 ){
3025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    Tcl_WrongNumArgs(interp, 1, objv, "DB");
3035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return TCL_ERROR;
3045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
3055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if( getDbPointer(interp, Tcl_GetString(objv[1]), &db) ) return TCL_ERROR;
3065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  zName = Tcl_GetString(objv[2]);
3075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#ifndef SQLITE_OMIT_VIRTUALTABLE
3085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  rc = sqlite3_intarray_create(db, zName, &pArray);
3095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif
3105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if( rc!=SQLITE_OK ){
3115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    assert( pArray==0 );
3125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    Tcl_AppendResult(interp, sqlite3TestErrorName(rc), (char*)0);
3135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return TCL_ERROR;
3145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
3155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  sqlite3TestMakePointerStr(interp, zPtr, pArray);
3165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  Tcl_AppendResult(interp, zPtr, (char*)0);
3175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return TCL_OK;
3185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/*
3215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)**    sqlite3_intarray_bind  INTARRAY  ?VALUE ...?
3225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)**
3235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** Invoke the sqlite3_intarray_bind interface on the given array of integers.
3245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)*/
3255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static int test_intarray_bind(
3265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ClientData clientData, /* Not used */
3275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  Tcl_Interp *interp,    /* The TCL interpreter that invoked this command */
3285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int objc,              /* Number of arguments */
3295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  Tcl_Obj *CONST objv[]  /* Command arguments */
3305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)){
3315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  sqlite3_intarray *pArray;
3325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int rc = SQLITE_OK;
3335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int i, n;
3345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  sqlite3_int64 *a;
3355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if( objc<2 ){
3375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    Tcl_WrongNumArgs(interp, 1, objv, "INTARRAY");
3385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return TCL_ERROR;
3395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
3405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  pArray = (sqlite3_intarray*)sqlite3TestTextToPtr(Tcl_GetString(objv[1]));
3415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  n = objc - 2;
3425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#ifndef SQLITE_OMIT_VIRTUALTABLE
3435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  a = sqlite3_malloc( sizeof(a[0])*n );
3445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if( a==0 ){
3455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    Tcl_AppendResult(interp, "SQLITE_NOMEM", (char*)0);
3465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return TCL_ERROR;
3475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
3485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for(i=0; i<n; i++){
3495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    a[i] = 0;
3505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    Tcl_GetWideIntFromObj(0, objv[i+2], &a[i]);
3515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
3525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  rc = sqlite3_intarray_bind(pArray, n, a, sqlite3_free);
3535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if( rc!=SQLITE_OK ){
3545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    Tcl_AppendResult(interp, sqlite3TestErrorName(rc), (char*)0);
3555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return TCL_ERROR;
3565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
3575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif
3585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return TCL_OK;
3595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/*
3625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** Register commands with the TCL interpreter.
3635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)*/
3645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int Sqlitetestintarray_Init(Tcl_Interp *interp){
3655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  static struct {
3665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)     char *zName;
3675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)     Tcl_ObjCmdProc *xProc;
3685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)     void *clientData;
3695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  } aObjCmd[] = {
3705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)     { "sqlite3_intarray_create", test_intarray_create, 0 },
3715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)     { "sqlite3_intarray_bind", test_intarray_bind, 0 },
3725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  };
3735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int i;
3745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for(i=0; i<sizeof(aObjCmd)/sizeof(aObjCmd[0]); i++){
3755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    Tcl_CreateObjCommand(interp, aObjCmd[i].zName,
3765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        aObjCmd[i].xProc, aObjCmd[i].clientData, 0);
3775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
3785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return TCL_OK;
3795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif /* SQLITE_TEST */
382