modernc.org/cc@v1.0.1/v2/testdata/_sqlite/ext/misc/carray.c (about) 1 /* 2 ** 2016-06-29 3 ** 4 ** The author disclaims copyright to this source code. In place of 5 ** a legal notice, here is a blessing: 6 ** 7 ** May you do good and not evil. 8 ** May you find forgiveness for yourself and forgive others. 9 ** May you share freely, never taking more than you give. 10 ** 11 ************************************************************************* 12 ** 13 ** This file demonstrates how to create a table-valued-function that 14 ** returns the values in a C-language array. 15 ** Examples: 16 ** 17 ** SELECT * FROM carray($ptr,5) 18 ** 19 ** The query above returns 5 integers contained in a C-language array 20 ** at the address $ptr. $ptr is a pointer to the array of integers. 21 ** The pointer value must be assigned to $ptr using the 22 ** sqlite3_bind_pointer() interface with a pointer type of "carray". 23 ** For example: 24 ** 25 ** static int aX[] = { 53, 9, 17, 2231, 4, 99 }; 26 ** int i = sqlite3_bind_parameter_index(pStmt, "$ptr"); 27 ** sqlite3_bind_value(pStmt, i, aX, "carray", 0); 28 ** 29 ** There is an optional third parameter to determine the datatype of 30 ** the C-language array. Allowed values of the third parameter are 31 ** 'int32', 'int64', 'double', 'char*'. Example: 32 ** 33 ** SELECT * FROM carray($ptr,10,'char*'); 34 ** 35 ** The default value of the third parameter is 'int32'. 36 ** 37 ** HOW IT WORKS 38 ** 39 ** The carray "function" is really a virtual table with the 40 ** following schema: 41 ** 42 ** CREATE TABLE carray( 43 ** value, 44 ** pointer HIDDEN, 45 ** count HIDDEN, 46 ** ctype TEXT HIDDEN 47 ** ); 48 ** 49 ** If the hidden columns "pointer" and "count" are unconstrained, then 50 ** the virtual table has no rows. Otherwise, the virtual table interprets 51 ** the integer value of "pointer" as a pointer to the array and "count" 52 ** as the number of elements in the array. The virtual table steps through 53 ** the array, element by element. 54 */ 55 #include "sqlite3ext.h" 56 SQLITE_EXTENSION_INIT1 57 #include <assert.h> 58 #include <string.h> 59 60 #ifndef SQLITE_OMIT_VIRTUALTABLE 61 62 /* 63 ** Allowed datatypes 64 */ 65 #define CARRAY_INT32 0 66 #define CARRAY_INT64 1 67 #define CARRAY_DOUBLE 2 68 #define CARRAY_TEXT 3 69 70 /* 71 ** Names of types 72 */ 73 static const char *azType[] = { "int32", "int64", "double", "char*" }; 74 75 76 /* carray_cursor is a subclass of sqlite3_vtab_cursor which will 77 ** serve as the underlying representation of a cursor that scans 78 ** over rows of the result 79 */ 80 typedef struct carray_cursor carray_cursor; 81 struct carray_cursor { 82 sqlite3_vtab_cursor base; /* Base class - must be first */ 83 sqlite3_int64 iRowid; /* The rowid */ 84 void *pPtr; /* Pointer to the array of values */ 85 sqlite3_int64 iCnt; /* Number of integers in the array */ 86 unsigned char eType; /* One of the CARRAY_type values */ 87 }; 88 89 /* 90 ** The carrayConnect() method is invoked to create a new 91 ** carray_vtab that describes the carray virtual table. 92 ** 93 ** Think of this routine as the constructor for carray_vtab objects. 94 ** 95 ** All this routine needs to do is: 96 ** 97 ** (1) Allocate the carray_vtab object and initialize all fields. 98 ** 99 ** (2) Tell SQLite (via the sqlite3_declare_vtab() interface) what the 100 ** result set of queries against carray will look like. 101 */ 102 static int carrayConnect( 103 sqlite3 *db, 104 void *pAux, 105 int argc, const char *const*argv, 106 sqlite3_vtab **ppVtab, 107 char **pzErr 108 ){ 109 sqlite3_vtab *pNew; 110 int rc; 111 112 /* Column numbers */ 113 #define CARRAY_COLUMN_VALUE 0 114 #define CARRAY_COLUMN_POINTER 1 115 #define CARRAY_COLUMN_COUNT 2 116 #define CARRAY_COLUMN_CTYPE 3 117 118 rc = sqlite3_declare_vtab(db, 119 "CREATE TABLE x(value,pointer hidden,count hidden,ctype hidden)"); 120 if( rc==SQLITE_OK ){ 121 pNew = *ppVtab = sqlite3_malloc( sizeof(*pNew) ); 122 if( pNew==0 ) return SQLITE_NOMEM; 123 memset(pNew, 0, sizeof(*pNew)); 124 } 125 return rc; 126 } 127 128 /* 129 ** This method is the destructor for carray_cursor objects. 130 */ 131 static int carrayDisconnect(sqlite3_vtab *pVtab){ 132 sqlite3_free(pVtab); 133 return SQLITE_OK; 134 } 135 136 /* 137 ** Constructor for a new carray_cursor object. 138 */ 139 static int carrayOpen(sqlite3_vtab *p, sqlite3_vtab_cursor **ppCursor){ 140 carray_cursor *pCur; 141 pCur = sqlite3_malloc( sizeof(*pCur) ); 142 if( pCur==0 ) return SQLITE_NOMEM; 143 memset(pCur, 0, sizeof(*pCur)); 144 *ppCursor = &pCur->base; 145 return SQLITE_OK; 146 } 147 148 /* 149 ** Destructor for a carray_cursor. 150 */ 151 static int carrayClose(sqlite3_vtab_cursor *cur){ 152 sqlite3_free(cur); 153 return SQLITE_OK; 154 } 155 156 157 /* 158 ** Advance a carray_cursor to its next row of output. 159 */ 160 static int carrayNext(sqlite3_vtab_cursor *cur){ 161 carray_cursor *pCur = (carray_cursor*)cur; 162 pCur->iRowid++; 163 return SQLITE_OK; 164 } 165 166 /* 167 ** Return values of columns for the row at which the carray_cursor 168 ** is currently pointing. 169 */ 170 static int carrayColumn( 171 sqlite3_vtab_cursor *cur, /* The cursor */ 172 sqlite3_context *ctx, /* First argument to sqlite3_result_...() */ 173 int i /* Which column to return */ 174 ){ 175 carray_cursor *pCur = (carray_cursor*)cur; 176 sqlite3_int64 x = 0; 177 switch( i ){ 178 case CARRAY_COLUMN_POINTER: return SQLITE_OK; 179 case CARRAY_COLUMN_COUNT: x = pCur->iCnt; break; 180 case CARRAY_COLUMN_CTYPE: { 181 sqlite3_result_text(ctx, azType[pCur->eType], -1, SQLITE_STATIC); 182 return SQLITE_OK; 183 } 184 default: { 185 switch( pCur->eType ){ 186 case CARRAY_INT32: { 187 int *p = (int*)pCur->pPtr; 188 sqlite3_result_int(ctx, p[pCur->iRowid-1]); 189 return SQLITE_OK; 190 } 191 case CARRAY_INT64: { 192 sqlite3_int64 *p = (sqlite3_int64*)pCur->pPtr; 193 sqlite3_result_int64(ctx, p[pCur->iRowid-1]); 194 return SQLITE_OK; 195 } 196 case CARRAY_DOUBLE: { 197 double *p = (double*)pCur->pPtr; 198 sqlite3_result_double(ctx, p[pCur->iRowid-1]); 199 return SQLITE_OK; 200 } 201 case CARRAY_TEXT: { 202 const char **p = (const char**)pCur->pPtr; 203 sqlite3_result_text(ctx, p[pCur->iRowid-1], -1, SQLITE_TRANSIENT); 204 return SQLITE_OK; 205 } 206 } 207 } 208 } 209 sqlite3_result_int64(ctx, x); 210 return SQLITE_OK; 211 } 212 213 /* 214 ** Return the rowid for the current row. In this implementation, the 215 ** rowid is the same as the output value. 216 */ 217 static int carrayRowid(sqlite3_vtab_cursor *cur, sqlite_int64 *pRowid){ 218 carray_cursor *pCur = (carray_cursor*)cur; 219 *pRowid = pCur->iRowid; 220 return SQLITE_OK; 221 } 222 223 /* 224 ** Return TRUE if the cursor has been moved off of the last 225 ** row of output. 226 */ 227 static int carrayEof(sqlite3_vtab_cursor *cur){ 228 carray_cursor *pCur = (carray_cursor*)cur; 229 return pCur->iRowid>pCur->iCnt; 230 } 231 232 /* 233 ** This method is called to "rewind" the carray_cursor object back 234 ** to the first row of output. 235 */ 236 static int carrayFilter( 237 sqlite3_vtab_cursor *pVtabCursor, 238 int idxNum, const char *idxStr, 239 int argc, sqlite3_value **argv 240 ){ 241 carray_cursor *pCur = (carray_cursor *)pVtabCursor; 242 if( idxNum ){ 243 pCur->pPtr = sqlite3_value_pointer(argv[0], "carray"); 244 pCur->iCnt = pCur->pPtr ? sqlite3_value_int64(argv[1]) : 0; 245 if( idxNum<3 ){ 246 pCur->eType = CARRAY_INT32; 247 }else{ 248 unsigned char i; 249 const char *zType = (const char*)sqlite3_value_text(argv[2]); 250 for(i=0; i<sizeof(azType)/sizeof(azType[0]); i++){ 251 if( sqlite3_stricmp(zType, azType[i])==0 ) break; 252 } 253 if( i>=sizeof(azType)/sizeof(azType[0]) ){ 254 pVtabCursor->pVtab->zErrMsg = sqlite3_mprintf( 255 "unknown datatype: %Q", zType); 256 return SQLITE_ERROR; 257 }else{ 258 pCur->eType = i; 259 } 260 } 261 }else{ 262 pCur->pPtr = 0; 263 pCur->iCnt = 0; 264 } 265 pCur->iRowid = 1; 266 return SQLITE_OK; 267 } 268 269 /* 270 ** SQLite will invoke this method one or more times while planning a query 271 ** that uses the carray virtual table. This routine needs to create 272 ** a query plan for each invocation and compute an estimated cost for that 273 ** plan. 274 ** 275 ** In this implementation idxNum is used to represent the 276 ** query plan. idxStr is unused. 277 ** 278 ** idxNum is 2 if the pointer= and count= constraints exist, 279 ** 3 if the ctype= constraint also exists, and is 0 otherwise. 280 ** If idxNum is 0, then carray becomes an empty table. 281 */ 282 static int carrayBestIndex( 283 sqlite3_vtab *tab, 284 sqlite3_index_info *pIdxInfo 285 ){ 286 int i; /* Loop over constraints */ 287 int ptrIdx = -1; /* Index of the pointer= constraint, or -1 if none */ 288 int cntIdx = -1; /* Index of the count= constraint, or -1 if none */ 289 int ctypeIdx = -1; /* Index of the ctype= constraint, or -1 if none */ 290 291 const struct sqlite3_index_constraint *pConstraint; 292 pConstraint = pIdxInfo->aConstraint; 293 for(i=0; i<pIdxInfo->nConstraint; i++, pConstraint++){ 294 if( pConstraint->usable==0 ) continue; 295 if( pConstraint->op!=SQLITE_INDEX_CONSTRAINT_EQ ) continue; 296 switch( pConstraint->iColumn ){ 297 case CARRAY_COLUMN_POINTER: 298 ptrIdx = i; 299 break; 300 case CARRAY_COLUMN_COUNT: 301 cntIdx = i; 302 break; 303 case CARRAY_COLUMN_CTYPE: 304 ctypeIdx = i; 305 break; 306 } 307 } 308 if( ptrIdx>=0 && cntIdx>=0 ){ 309 pIdxInfo->aConstraintUsage[ptrIdx].argvIndex = 1; 310 pIdxInfo->aConstraintUsage[ptrIdx].omit = 1; 311 pIdxInfo->aConstraintUsage[cntIdx].argvIndex = 2; 312 pIdxInfo->aConstraintUsage[cntIdx].omit = 1; 313 pIdxInfo->estimatedCost = (double)1; 314 pIdxInfo->estimatedRows = 100; 315 pIdxInfo->idxNum = 2; 316 if( ctypeIdx>=0 ){ 317 pIdxInfo->aConstraintUsage[ctypeIdx].argvIndex = 3; 318 pIdxInfo->aConstraintUsage[ctypeIdx].omit = 1; 319 pIdxInfo->idxNum = 3; 320 } 321 }else{ 322 pIdxInfo->estimatedCost = (double)2147483647; 323 pIdxInfo->estimatedRows = 2147483647; 324 pIdxInfo->idxNum = 0; 325 } 326 return SQLITE_OK; 327 } 328 329 /* 330 ** This following structure defines all the methods for the 331 ** carray virtual table. 332 */ 333 static sqlite3_module carrayModule = { 334 0, /* iVersion */ 335 0, /* xCreate */ 336 carrayConnect, /* xConnect */ 337 carrayBestIndex, /* xBestIndex */ 338 carrayDisconnect, /* xDisconnect */ 339 0, /* xDestroy */ 340 carrayOpen, /* xOpen - open a cursor */ 341 carrayClose, /* xClose - close a cursor */ 342 carrayFilter, /* xFilter - configure scan constraints */ 343 carrayNext, /* xNext - advance a cursor */ 344 carrayEof, /* xEof - check for end of scan */ 345 carrayColumn, /* xColumn - read data */ 346 carrayRowid, /* xRowid - read data */ 347 0, /* xUpdate */ 348 0, /* xBegin */ 349 0, /* xSync */ 350 0, /* xCommit */ 351 0, /* xRollback */ 352 0, /* xFindMethod */ 353 0, /* xRename */ 354 }; 355 356 /* 357 ** For testing purpose in the TCL test harness, we need a method for 358 ** setting the pointer value. The inttoptr(X) SQL function accomplishes 359 ** this. Tcl script will bind an integer to X and the inttoptr() SQL 360 ** function will use sqlite3_result_pointer() to convert that integer into 361 ** a pointer. 362 ** 363 ** This is for testing on TCL only. 364 */ 365 #ifdef SQLITE_TEST 366 static void inttoptrFunc( 367 sqlite3_context *context, 368 int argc, 369 sqlite3_value **argv 370 ){ 371 void *p; 372 sqlite3_int64 i64; 373 i64 = sqlite3_value_int64(argv[0]); 374 if( sizeof(i64)==sizeof(p) ){ 375 memcpy(&p, &i64, sizeof(p)); 376 }else{ 377 int i32 = i64 & 0xffffffff; 378 memcpy(&p, &i32, sizeof(p)); 379 } 380 sqlite3_result_pointer(context, p, "carray", 0); 381 } 382 #endif /* SQLITE_TEST */ 383 384 #endif /* SQLITE_OMIT_VIRTUALTABLE */ 385 386 #ifdef _WIN32 387 __declspec(dllexport) 388 #endif 389 int sqlite3_carray_init( 390 sqlite3 *db, 391 char **pzErrMsg, 392 const sqlite3_api_routines *pApi 393 ){ 394 int rc = SQLITE_OK; 395 SQLITE_EXTENSION_INIT2(pApi); 396 #ifndef SQLITE_OMIT_VIRTUALTABLE 397 rc = sqlite3_create_module(db, "carray", &carrayModule, 0); 398 #ifdef SQLITE_TEST 399 if( rc==SQLITE_OK ){ 400 rc = sqlite3_create_function(db, "inttoptr", 1, SQLITE_UTF8, 0, 401 inttoptrFunc, 0, 0); 402 } 403 #endif /* SQLITE_TEST */ 404 #endif /* SQLITE_OMIT_VIRTUALTABLE */ 405 return rc; 406 }