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