wholenumber.c 7.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274
  1. /*
  2. ** 2011 April 02
  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 implements a virtual table that returns the whole numbers
  14. ** between 1 and 4294967295, inclusive.
  15. **
  16. ** Example:
  17. **
  18. ** CREATE VIRTUAL TABLE nums USING wholenumber;
  19. ** SELECT value FROM nums WHERE value<10;
  20. **
  21. ** Results in:
  22. **
  23. ** 1 2 3 4 5 6 7 8 9
  24. */
  25. #include "sqlite3ext.h"
  26. SQLITE_EXTENSION_INIT1
  27. #include <assert.h>
  28. #include <string.h>
  29. #ifndef SQLITE_OMIT_VIRTUALTABLE
  30. /* A wholenumber cursor object */
  31. typedef struct wholenumber_cursor wholenumber_cursor;
  32. struct wholenumber_cursor {
  33. sqlite3_vtab_cursor base; /* Base class - must be first */
  34. sqlite3_int64 iValue; /* Current value */
  35. sqlite3_int64 mxValue; /* Maximum value */
  36. };
  37. /* Methods for the wholenumber module */
  38. static int wholenumberConnect(
  39. sqlite3 *db,
  40. void *pAux,
  41. int argc, const char *const*argv,
  42. sqlite3_vtab **ppVtab,
  43. char **pzErr
  44. ){
  45. sqlite3_vtab *pNew;
  46. pNew = *ppVtab = sqlite3_malloc( sizeof(*pNew) );
  47. if( pNew==0 ) return SQLITE_NOMEM;
  48. sqlite3_declare_vtab(db, "CREATE TABLE x(value)");
  49. memset(pNew, 0, sizeof(*pNew));
  50. return SQLITE_OK;
  51. }
  52. /* Note that for this virtual table, the xCreate and xConnect
  53. ** methods are identical. */
  54. static int wholenumberDisconnect(sqlite3_vtab *pVtab){
  55. sqlite3_free(pVtab);
  56. return SQLITE_OK;
  57. }
  58. /* The xDisconnect and xDestroy methods are also the same */
  59. /*
  60. ** Open a new wholenumber cursor.
  61. */
  62. static int wholenumberOpen(sqlite3_vtab *p, sqlite3_vtab_cursor **ppCursor){
  63. wholenumber_cursor *pCur;
  64. pCur = sqlite3_malloc( sizeof(*pCur) );
  65. if( pCur==0 ) return SQLITE_NOMEM;
  66. memset(pCur, 0, sizeof(*pCur));
  67. *ppCursor = &pCur->base;
  68. return SQLITE_OK;
  69. }
  70. /*
  71. ** Close a wholenumber cursor.
  72. */
  73. static int wholenumberClose(sqlite3_vtab_cursor *cur){
  74. sqlite3_free(cur);
  75. return SQLITE_OK;
  76. }
  77. /*
  78. ** Advance a cursor to its next row of output
  79. */
  80. static int wholenumberNext(sqlite3_vtab_cursor *cur){
  81. wholenumber_cursor *pCur = (wholenumber_cursor*)cur;
  82. pCur->iValue++;
  83. return SQLITE_OK;
  84. }
  85. /*
  86. ** Return the value associated with a wholenumber.
  87. */
  88. static int wholenumberColumn(
  89. sqlite3_vtab_cursor *cur,
  90. sqlite3_context *ctx,
  91. int i
  92. ){
  93. wholenumber_cursor *pCur = (wholenumber_cursor*)cur;
  94. sqlite3_result_int64(ctx, pCur->iValue);
  95. return SQLITE_OK;
  96. }
  97. /*
  98. ** The rowid.
  99. */
  100. static int wholenumberRowid(sqlite3_vtab_cursor *cur, sqlite_int64 *pRowid){
  101. wholenumber_cursor *pCur = (wholenumber_cursor*)cur;
  102. *pRowid = pCur->iValue;
  103. return SQLITE_OK;
  104. }
  105. /*
  106. ** When the wholenumber_cursor.rLimit value is 0 or less, that is a signal
  107. ** that the cursor has nothing more to output.
  108. */
  109. static int wholenumberEof(sqlite3_vtab_cursor *cur){
  110. wholenumber_cursor *pCur = (wholenumber_cursor*)cur;
  111. return pCur->iValue>pCur->mxValue || pCur->iValue==0;
  112. }
  113. /*
  114. ** Called to "rewind" a cursor back to the beginning so that
  115. ** it starts its output over again. Always called at least once
  116. ** prior to any wholenumberColumn, wholenumberRowid, or wholenumberEof call.
  117. **
  118. ** idxNum Constraints
  119. ** ------ ---------------------
  120. ** 0 (none)
  121. ** 1 value > $argv0
  122. ** 2 value >= $argv0
  123. ** 4 value < $argv0
  124. ** 8 value <= $argv0
  125. **
  126. ** 5 value > $argv0 AND value < $argv1
  127. ** 6 value >= $argv0 AND value < $argv1
  128. ** 9 value > $argv0 AND value <= $argv1
  129. ** 10 value >= $argv0 AND value <= $argv1
  130. */
  131. static int wholenumberFilter(
  132. sqlite3_vtab_cursor *pVtabCursor,
  133. int idxNum, const char *idxStr,
  134. int argc, sqlite3_value **argv
  135. ){
  136. wholenumber_cursor *pCur = (wholenumber_cursor *)pVtabCursor;
  137. sqlite3_int64 v;
  138. int i = 0;
  139. pCur->iValue = 1;
  140. pCur->mxValue = 0xffffffff; /* 4294967295 */
  141. if( idxNum & 3 ){
  142. v = sqlite3_value_int64(argv[0]) + (idxNum&1);
  143. if( v>pCur->iValue && v<=pCur->mxValue ) pCur->iValue = v;
  144. i++;
  145. }
  146. if( idxNum & 12 ){
  147. v = sqlite3_value_int64(argv[i]) - ((idxNum>>2)&1);
  148. if( v>=pCur->iValue && v<pCur->mxValue ) pCur->mxValue = v;
  149. }
  150. return SQLITE_OK;
  151. }
  152. /*
  153. ** Search for terms of these forms:
  154. **
  155. ** (1) value > $value
  156. ** (2) value >= $value
  157. ** (4) value < $value
  158. ** (8) value <= $value
  159. **
  160. ** idxNum is an ORed combination of 1 or 2 with 4 or 8.
  161. */
  162. static int wholenumberBestIndex(
  163. sqlite3_vtab *tab,
  164. sqlite3_index_info *pIdxInfo
  165. ){
  166. int i;
  167. int idxNum = 0;
  168. int argvIdx = 1;
  169. int ltIdx = -1;
  170. int gtIdx = -1;
  171. const struct sqlite3_index_constraint *pConstraint;
  172. pConstraint = pIdxInfo->aConstraint;
  173. for(i=0; i<pIdxInfo->nConstraint; i++, pConstraint++){
  174. if( pConstraint->usable==0 ) continue;
  175. if( (idxNum & 3)==0 && pConstraint->op==SQLITE_INDEX_CONSTRAINT_GT ){
  176. idxNum |= 1;
  177. ltIdx = i;
  178. }
  179. if( (idxNum & 3)==0 && pConstraint->op==SQLITE_INDEX_CONSTRAINT_GE ){
  180. idxNum |= 2;
  181. ltIdx = i;
  182. }
  183. if( (idxNum & 12)==0 && pConstraint->op==SQLITE_INDEX_CONSTRAINT_LT ){
  184. idxNum |= 4;
  185. gtIdx = i;
  186. }
  187. if( (idxNum & 12)==0 && pConstraint->op==SQLITE_INDEX_CONSTRAINT_LE ){
  188. idxNum |= 8;
  189. gtIdx = i;
  190. }
  191. }
  192. pIdxInfo->idxNum = idxNum;
  193. if( ltIdx>=0 ){
  194. pIdxInfo->aConstraintUsage[ltIdx].argvIndex = argvIdx++;
  195. pIdxInfo->aConstraintUsage[ltIdx].omit = 1;
  196. }
  197. if( gtIdx>=0 ){
  198. pIdxInfo->aConstraintUsage[gtIdx].argvIndex = argvIdx;
  199. pIdxInfo->aConstraintUsage[gtIdx].omit = 1;
  200. }
  201. if( pIdxInfo->nOrderBy==1
  202. && pIdxInfo->aOrderBy[0].desc==0
  203. ){
  204. pIdxInfo->orderByConsumed = 1;
  205. }
  206. if( (idxNum & 12)==0 ){
  207. pIdxInfo->estimatedCost = (double)100000000;
  208. }else if( (idxNum & 3)==0 ){
  209. pIdxInfo->estimatedCost = (double)5;
  210. }else{
  211. pIdxInfo->estimatedCost = (double)1;
  212. }
  213. return SQLITE_OK;
  214. }
  215. /*
  216. ** A virtual table module that provides read-only access to a
  217. ** Tcl global variable namespace.
  218. */
  219. static sqlite3_module wholenumberModule = {
  220. 0, /* iVersion */
  221. wholenumberConnect,
  222. wholenumberConnect,
  223. wholenumberBestIndex,
  224. wholenumberDisconnect,
  225. wholenumberDisconnect,
  226. wholenumberOpen, /* xOpen - open a cursor */
  227. wholenumberClose, /* xClose - close a cursor */
  228. wholenumberFilter, /* xFilter - configure scan constraints */
  229. wholenumberNext, /* xNext - advance a cursor */
  230. wholenumberEof, /* xEof - check for end of scan */
  231. wholenumberColumn, /* xColumn - read data */
  232. wholenumberRowid, /* xRowid - read data */
  233. 0, /* xUpdate */
  234. 0, /* xBegin */
  235. 0, /* xSync */
  236. 0, /* xCommit */
  237. 0, /* xRollback */
  238. 0, /* xFindMethod */
  239. 0, /* xRename */
  240. };
  241. #endif /* SQLITE_OMIT_VIRTUALTABLE */
  242. #ifdef _WIN32
  243. __declspec(dllexport)
  244. #endif
  245. int sqlite3_wholenumber_init(
  246. sqlite3 *db,
  247. char **pzErrMsg,
  248. const sqlite3_api_routines *pApi
  249. ){
  250. int rc = SQLITE_OK;
  251. SQLITE_EXTENSION_INIT2(pApi);
  252. #ifndef SQLITE_OMIT_VIRTUALTABLE
  253. rc = sqlite3_create_module(db, "wholenumber", &wholenumberModule, 0);
  254. #endif
  255. return rc;
  256. }