fuzzer.c 36 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184
  1. /*
  2. ** 2011 March 24
  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. ** Code for a demonstration virtual table that generates variations
  14. ** on an input word at increasing edit distances from the original.
  15. **
  16. ** A fuzzer virtual table is created like this:
  17. **
  18. ** CREATE VIRTUAL TABLE f USING fuzzer(<fuzzer-data-table>);
  19. **
  20. ** When it is created, the new fuzzer table must be supplied with the
  21. ** name of a "fuzzer data table", which must reside in the same database
  22. ** file as the new fuzzer table. The fuzzer data table contains the various
  23. ** transformations and their costs that the fuzzer logic uses to generate
  24. ** variations.
  25. **
  26. ** The fuzzer data table must contain exactly four columns (more precisely,
  27. ** the statement "SELECT * FROM <fuzzer_data_table>" must return records
  28. ** that consist of four columns). It does not matter what the columns are
  29. ** named.
  30. **
  31. ** Each row in the fuzzer data table represents a single character
  32. ** transformation. The left most column of the row (column 0) contains an
  33. ** integer value - the identifier of the ruleset to which the transformation
  34. ** rule belongs (see "MULTIPLE RULE SETS" below). The second column of the
  35. ** row (column 0) contains the input character or characters. The third
  36. ** column contains the output character or characters. And the fourth column
  37. ** contains the integer cost of making the transformation. For example:
  38. **
  39. ** CREATE TABLE f_data(ruleset, cFrom, cTo, Cost);
  40. ** INSERT INTO f_data(ruleset, cFrom, cTo, Cost) VALUES(0, '', 'a', 100);
  41. ** INSERT INTO f_data(ruleset, cFrom, cTo, Cost) VALUES(0, 'b', '', 87);
  42. ** INSERT INTO f_data(ruleset, cFrom, cTo, Cost) VALUES(0, 'o', 'oe', 38);
  43. ** INSERT INTO f_data(ruleset, cFrom, cTo, Cost) VALUES(0, 'oe', 'o', 40);
  44. **
  45. ** The first row inserted into the fuzzer data table by the SQL script
  46. ** above indicates that the cost of inserting a letter 'a' is 100. (All
  47. ** costs are integers. We recommend that costs be scaled so that the
  48. ** average cost is around 100.) The second INSERT statement creates a rule
  49. ** saying that the cost of deleting a single letter 'b' is 87. The third
  50. ** and fourth INSERT statements mean that the cost of transforming a
  51. ** single letter "o" into the two-letter sequence "oe" is 38 and that the
  52. ** cost of transforming "oe" back into "o" is 40.
  53. **
  54. ** The contents of the fuzzer data table are loaded into main memory when
  55. ** a fuzzer table is first created, and may be internally reloaded by the
  56. ** system at any subsequent time. Therefore, the fuzzer data table should be
  57. ** populated before the fuzzer table is created and not modified thereafter.
  58. ** If you do need to modify the contents of the fuzzer data table, it is
  59. ** recommended that the associated fuzzer table be dropped, the fuzzer data
  60. ** table edited, and the fuzzer table recreated within a single transaction.
  61. ** Alternatively, the fuzzer data table can be edited then the database
  62. ** connection can be closed and reopened.
  63. **
  64. ** Once it has been created, the fuzzer table can be queried as follows:
  65. **
  66. ** SELECT word, distance FROM f
  67. ** WHERE word MATCH 'abcdefg'
  68. ** AND distance<200;
  69. **
  70. ** This first query outputs the string "abcdefg" and all strings that
  71. ** can be derived from that string by appling the specified transformations.
  72. ** The strings are output together with their total transformation cost
  73. ** (called "distance") and appear in order of increasing cost. No string
  74. ** is output more than once. If there are multiple ways to transform the
  75. ** target string into the output string then the lowest cost transform is
  76. ** the one that is returned. In the example, the search is limited to
  77. ** strings with a total distance of less than 200.
  78. **
  79. ** The fuzzer is a read-only table. Any attempt to DELETE, INSERT, or
  80. ** UPDATE on a fuzzer table will throw an error.
  81. **
  82. ** It is important to put some kind of a limit on the fuzzer output. This
  83. ** can be either in the form of a LIMIT clause at the end of the query,
  84. ** or better, a "distance<NNN" constraint where NNN is some number. The
  85. ** running time and memory requirement is exponential in the value of NNN
  86. ** so you want to make sure that NNN is not too big. A value of NNN that
  87. ** is about twice the average transformation cost seems to give good results.
  88. **
  89. ** The fuzzer table can be useful for tasks such as spelling correction.
  90. ** Suppose there is a second table vocabulary(w) where the w column contains
  91. ** all correctly spelled words. Let $word be a word you want to look up.
  92. **
  93. ** SELECT vocabulary.w FROM f, vocabulary
  94. ** WHERE f.word MATCH $word
  95. ** AND f.distance<=200
  96. ** AND f.word=vocabulary.w
  97. ** LIMIT 20
  98. **
  99. ** The query above gives the 20 closest words to the $word being tested.
  100. ** (Note that for good performance, the vocubulary.w column should be
  101. ** indexed.)
  102. **
  103. ** A similar query can be used to find all words in the dictionary that
  104. ** begin with some prefix $prefix:
  105. **
  106. ** SELECT vocabulary.w FROM f, vocabulary
  107. ** WHERE f.word MATCH $prefix
  108. ** AND f.distance<=200
  109. ** AND vocabulary.w BETWEEN f.word AND (f.word || x'F7BFBFBF')
  110. ** LIMIT 50
  111. **
  112. ** This last query will show up to 50 words out of the vocabulary that
  113. ** match or nearly match the $prefix.
  114. **
  115. ** MULTIPLE RULE SETS
  116. **
  117. ** Normally, the "ruleset" value associated with all character transformations
  118. ** in the fuzzer data table is zero. However, if required, the fuzzer table
  119. ** allows multiple rulesets to be defined. Each query uses only a single
  120. ** ruleset. This allows, for example, a single fuzzer table to support
  121. ** multiple languages.
  122. **
  123. ** By default, only the rules from ruleset 0 are used. To specify an
  124. ** alternative ruleset, a "ruleset = ?" expression must be added to the
  125. ** WHERE clause of a SELECT, where ? is the identifier of the desired
  126. ** ruleset. For example:
  127. **
  128. ** SELECT vocabulary.w FROM f, vocabulary
  129. ** WHERE f.word MATCH $word
  130. ** AND f.distance<=200
  131. ** AND f.word=vocabulary.w
  132. ** AND f.ruleset=1 -- Specify the ruleset to use here
  133. ** LIMIT 20
  134. **
  135. ** If no "ruleset = ?" constraint is specified in the WHERE clause, ruleset
  136. ** 0 is used.
  137. **
  138. ** LIMITS
  139. **
  140. ** The maximum ruleset number is 2147483647. The maximum length of either
  141. ** of the strings in the second or third column of the fuzzer data table
  142. ** is 50 bytes. The maximum cost on a rule is 1000.
  143. */
  144. #include "sqlite3ext.h"
  145. SQLITE_EXTENSION_INIT1
  146. /* If SQLITE_DEBUG is not defined, disable assert statements. */
  147. #if !defined(NDEBUG) && !defined(SQLITE_DEBUG)
  148. # define NDEBUG
  149. #endif
  150. #include <stdlib.h>
  151. #include <string.h>
  152. #include <assert.h>
  153. #include <stdio.h>
  154. #ifndef SQLITE_OMIT_VIRTUALTABLE
  155. /*
  156. ** Forward declaration of objects used by this implementation
  157. */
  158. typedef struct fuzzer_vtab fuzzer_vtab;
  159. typedef struct fuzzer_cursor fuzzer_cursor;
  160. typedef struct fuzzer_rule fuzzer_rule;
  161. typedef struct fuzzer_seen fuzzer_seen;
  162. typedef struct fuzzer_stem fuzzer_stem;
  163. /*
  164. ** Various types.
  165. **
  166. ** fuzzer_cost is the "cost" of an edit operation.
  167. **
  168. ** fuzzer_len is the length of a matching string.
  169. **
  170. ** fuzzer_ruleid is an ruleset identifier.
  171. */
  172. typedef int fuzzer_cost;
  173. typedef signed char fuzzer_len;
  174. typedef int fuzzer_ruleid;
  175. /*
  176. ** Limits
  177. */
  178. #define FUZZER_MX_LENGTH 50 /* Maximum length of a rule string */
  179. #define FUZZER_MX_RULEID 2147483647 /* Maximum rule ID */
  180. #define FUZZER_MX_COST 1000 /* Maximum single-rule cost */
  181. #define FUZZER_MX_OUTPUT_LENGTH 100 /* Maximum length of an output string */
  182. /*
  183. ** Each transformation rule is stored as an instance of this object.
  184. ** All rules are kept on a linked list sorted by rCost.
  185. */
  186. struct fuzzer_rule {
  187. fuzzer_rule *pNext; /* Next rule in order of increasing rCost */
  188. char *zFrom; /* Transform from */
  189. fuzzer_cost rCost; /* Cost of this transformation */
  190. fuzzer_len nFrom, nTo; /* Length of the zFrom and zTo strings */
  191. fuzzer_ruleid iRuleset; /* The rule set to which this rule belongs */
  192. char zTo[4]; /* Transform to (extra space appended) */
  193. };
  194. /*
  195. ** A stem object is used to generate variants. It is also used to record
  196. ** previously generated outputs.
  197. **
  198. ** Every stem is added to a hash table as it is output. Generation of
  199. ** duplicate stems is suppressed.
  200. **
  201. ** Active stems (those that might generate new outputs) are kepts on a linked
  202. ** list sorted by increasing cost. The cost is the sum of rBaseCost and
  203. ** pRule->rCost.
  204. */
  205. struct fuzzer_stem {
  206. char *zBasis; /* Word being fuzzed */
  207. const fuzzer_rule *pRule; /* Current rule to apply */
  208. fuzzer_stem *pNext; /* Next stem in rCost order */
  209. fuzzer_stem *pHash; /* Next stem with same hash on zBasis */
  210. fuzzer_cost rBaseCost; /* Base cost of getting to zBasis */
  211. fuzzer_cost rCostX; /* Precomputed rBaseCost + pRule->rCost */
  212. fuzzer_len nBasis; /* Length of the zBasis string */
  213. fuzzer_len n; /* Apply pRule at this character offset */
  214. };
  215. /*
  216. ** A fuzzer virtual-table object
  217. */
  218. struct fuzzer_vtab {
  219. sqlite3_vtab base; /* Base class - must be first */
  220. char *zClassName; /* Name of this class. Default: "fuzzer" */
  221. fuzzer_rule *pRule; /* All active rules in this fuzzer */
  222. int nCursor; /* Number of active cursors */
  223. };
  224. #define FUZZER_HASH 4001 /* Hash table size */
  225. #define FUZZER_NQUEUE 20 /* Number of slots on the stem queue */
  226. /* A fuzzer cursor object */
  227. struct fuzzer_cursor {
  228. sqlite3_vtab_cursor base; /* Base class - must be first */
  229. sqlite3_int64 iRowid; /* The rowid of the current word */
  230. fuzzer_vtab *pVtab; /* The virtual table this cursor belongs to */
  231. fuzzer_cost rLimit; /* Maximum cost of any term */
  232. fuzzer_stem *pStem; /* Stem with smallest rCostX */
  233. fuzzer_stem *pDone; /* Stems already processed to completion */
  234. fuzzer_stem *aQueue[FUZZER_NQUEUE]; /* Queue of stems with higher rCostX */
  235. int mxQueue; /* Largest used index in aQueue[] */
  236. char *zBuf; /* Temporary use buffer */
  237. int nBuf; /* Bytes allocated for zBuf */
  238. int nStem; /* Number of stems allocated */
  239. int iRuleset; /* Only process rules from this ruleset */
  240. fuzzer_rule nullRule; /* Null rule used first */
  241. fuzzer_stem *apHash[FUZZER_HASH]; /* Hash of previously generated terms */
  242. };
  243. /*
  244. ** The two input rule lists are both sorted in order of increasing
  245. ** cost. Merge them together into a single list, sorted by cost, and
  246. ** return a pointer to the head of that list.
  247. */
  248. static fuzzer_rule *fuzzerMergeRules(fuzzer_rule *pA, fuzzer_rule *pB){
  249. fuzzer_rule head;
  250. fuzzer_rule *pTail;
  251. pTail = &head;
  252. while( pA && pB ){
  253. if( pA->rCost<=pB->rCost ){
  254. pTail->pNext = pA;
  255. pTail = pA;
  256. pA = pA->pNext;
  257. }else{
  258. pTail->pNext = pB;
  259. pTail = pB;
  260. pB = pB->pNext;
  261. }
  262. }
  263. if( pA==0 ){
  264. pTail->pNext = pB;
  265. }else{
  266. pTail->pNext = pA;
  267. }
  268. return head.pNext;
  269. }
  270. /*
  271. ** Statement pStmt currently points to a row in the fuzzer data table. This
  272. ** function allocates and populates a fuzzer_rule structure according to
  273. ** the content of the row.
  274. **
  275. ** If successful, *ppRule is set to point to the new object and SQLITE_OK
  276. ** is returned. Otherwise, *ppRule is zeroed, *pzErr may be set to point
  277. ** to an error message and an SQLite error code returned.
  278. */
  279. static int fuzzerLoadOneRule(
  280. fuzzer_vtab *p, /* Fuzzer virtual table handle */
  281. sqlite3_stmt *pStmt, /* Base rule on statements current row */
  282. fuzzer_rule **ppRule, /* OUT: New rule object */
  283. char **pzErr /* OUT: Error message */
  284. ){
  285. sqlite3_int64 iRuleset = sqlite3_column_int64(pStmt, 0);
  286. const char *zFrom = (const char *)sqlite3_column_text(pStmt, 1);
  287. const char *zTo = (const char *)sqlite3_column_text(pStmt, 2);
  288. int nCost = sqlite3_column_int(pStmt, 3);
  289. int rc = SQLITE_OK; /* Return code */
  290. int nFrom; /* Size of string zFrom, in bytes */
  291. int nTo; /* Size of string zTo, in bytes */
  292. fuzzer_rule *pRule = 0; /* New rule object to return */
  293. if( zFrom==0 ) zFrom = "";
  294. if( zTo==0 ) zTo = "";
  295. nFrom = (int)strlen(zFrom);
  296. nTo = (int)strlen(zTo);
  297. /* Silently ignore null transformations */
  298. if( strcmp(zFrom, zTo)==0 ){
  299. *ppRule = 0;
  300. return SQLITE_OK;
  301. }
  302. if( nCost<=0 || nCost>FUZZER_MX_COST ){
  303. *pzErr = sqlite3_mprintf("%s: cost must be between 1 and %d",
  304. p->zClassName, FUZZER_MX_COST
  305. );
  306. rc = SQLITE_ERROR;
  307. }else
  308. if( nFrom>FUZZER_MX_LENGTH || nTo>FUZZER_MX_LENGTH ){
  309. *pzErr = sqlite3_mprintf("%s: maximum string length is %d",
  310. p->zClassName, FUZZER_MX_LENGTH
  311. );
  312. rc = SQLITE_ERROR;
  313. }else
  314. if( iRuleset<0 || iRuleset>FUZZER_MX_RULEID ){
  315. *pzErr = sqlite3_mprintf("%s: ruleset must be between 0 and %d",
  316. p->zClassName, FUZZER_MX_RULEID
  317. );
  318. rc = SQLITE_ERROR;
  319. }else{
  320. pRule = sqlite3_malloc( sizeof(*pRule) + nFrom + nTo );
  321. if( pRule==0 ){
  322. rc = SQLITE_NOMEM;
  323. }else{
  324. memset(pRule, 0, sizeof(*pRule));
  325. pRule->zFrom = &pRule->zTo[nTo+1];
  326. pRule->nFrom = nFrom;
  327. memcpy(pRule->zFrom, zFrom, nFrom+1);
  328. memcpy(pRule->zTo, zTo, nTo+1);
  329. pRule->nTo = nTo;
  330. pRule->rCost = nCost;
  331. pRule->iRuleset = (int)iRuleset;
  332. }
  333. }
  334. *ppRule = pRule;
  335. return rc;
  336. }
  337. /*
  338. ** Load the content of the fuzzer data table into memory.
  339. */
  340. static int fuzzerLoadRules(
  341. sqlite3 *db, /* Database handle */
  342. fuzzer_vtab *p, /* Virtual fuzzer table to configure */
  343. const char *zDb, /* Database containing rules data */
  344. const char *zData, /* Table containing rules data */
  345. char **pzErr /* OUT: Error message */
  346. ){
  347. int rc = SQLITE_OK; /* Return code */
  348. char *zSql; /* SELECT used to read from rules table */
  349. fuzzer_rule *pHead = 0;
  350. zSql = sqlite3_mprintf("SELECT * FROM %Q.%Q", zDb, zData);
  351. if( zSql==0 ){
  352. rc = SQLITE_NOMEM;
  353. }else{
  354. int rc2; /* finalize() return code */
  355. sqlite3_stmt *pStmt = 0;
  356. rc = sqlite3_prepare_v2(db, zSql, -1, &pStmt, 0);
  357. if( rc!=SQLITE_OK ){
  358. *pzErr = sqlite3_mprintf("%s: %s", p->zClassName, sqlite3_errmsg(db));
  359. }else if( sqlite3_column_count(pStmt)!=4 ){
  360. *pzErr = sqlite3_mprintf("%s: %s has %d columns, expected 4",
  361. p->zClassName, zData, sqlite3_column_count(pStmt)
  362. );
  363. rc = SQLITE_ERROR;
  364. }else{
  365. while( rc==SQLITE_OK && SQLITE_ROW==sqlite3_step(pStmt) ){
  366. fuzzer_rule *pRule = 0;
  367. rc = fuzzerLoadOneRule(p, pStmt, &pRule, pzErr);
  368. if( pRule ){
  369. pRule->pNext = pHead;
  370. pHead = pRule;
  371. }
  372. }
  373. }
  374. rc2 = sqlite3_finalize(pStmt);
  375. if( rc==SQLITE_OK ) rc = rc2;
  376. }
  377. sqlite3_free(zSql);
  378. /* All rules are now in a singly linked list starting at pHead. This
  379. ** block sorts them by cost and then sets fuzzer_vtab.pRule to point to
  380. ** point to the head of the sorted list.
  381. */
  382. if( rc==SQLITE_OK ){
  383. unsigned int i;
  384. fuzzer_rule *pX;
  385. fuzzer_rule *a[15];
  386. for(i=0; i<sizeof(a)/sizeof(a[0]); i++) a[i] = 0;
  387. while( (pX = pHead)!=0 ){
  388. pHead = pX->pNext;
  389. pX->pNext = 0;
  390. for(i=0; a[i] && i<sizeof(a)/sizeof(a[0])-1; i++){
  391. pX = fuzzerMergeRules(a[i], pX);
  392. a[i] = 0;
  393. }
  394. a[i] = fuzzerMergeRules(a[i], pX);
  395. }
  396. for(pX=a[0], i=1; i<sizeof(a)/sizeof(a[0]); i++){
  397. pX = fuzzerMergeRules(a[i], pX);
  398. }
  399. p->pRule = fuzzerMergeRules(p->pRule, pX);
  400. }else{
  401. /* An error has occurred. Setting p->pRule to point to the head of the
  402. ** allocated list ensures that the list will be cleaned up in this case.
  403. */
  404. assert( p->pRule==0 );
  405. p->pRule = pHead;
  406. }
  407. return rc;
  408. }
  409. /*
  410. ** This function converts an SQL quoted string into an unquoted string
  411. ** and returns a pointer to a buffer allocated using sqlite3_malloc()
  412. ** containing the result. The caller should eventually free this buffer
  413. ** using sqlite3_free.
  414. **
  415. ** Examples:
  416. **
  417. ** "abc" becomes abc
  418. ** 'xyz' becomes xyz
  419. ** [pqr] becomes pqr
  420. ** `mno` becomes mno
  421. */
  422. static char *fuzzerDequote(const char *zIn){
  423. int nIn; /* Size of input string, in bytes */
  424. char *zOut; /* Output (dequoted) string */
  425. nIn = (int)strlen(zIn);
  426. zOut = sqlite3_malloc(nIn+1);
  427. if( zOut ){
  428. char q = zIn[0]; /* Quote character (if any ) */
  429. if( q!='[' && q!= '\'' && q!='"' && q!='`' ){
  430. memcpy(zOut, zIn, nIn+1);
  431. }else{
  432. int iOut = 0; /* Index of next byte to write to output */
  433. int iIn; /* Index of next byte to read from input */
  434. if( q=='[' ) q = ']';
  435. for(iIn=1; iIn<nIn; iIn++){
  436. if( zIn[iIn]==q ) iIn++;
  437. zOut[iOut++] = zIn[iIn];
  438. }
  439. }
  440. assert( (int)strlen(zOut)<=nIn );
  441. }
  442. return zOut;
  443. }
  444. /*
  445. ** xDisconnect/xDestroy method for the fuzzer module.
  446. */
  447. static int fuzzerDisconnect(sqlite3_vtab *pVtab){
  448. fuzzer_vtab *p = (fuzzer_vtab*)pVtab;
  449. assert( p->nCursor==0 );
  450. while( p->pRule ){
  451. fuzzer_rule *pRule = p->pRule;
  452. p->pRule = pRule->pNext;
  453. sqlite3_free(pRule);
  454. }
  455. sqlite3_free(p);
  456. return SQLITE_OK;
  457. }
  458. /*
  459. ** xConnect/xCreate method for the fuzzer module. Arguments are:
  460. **
  461. ** argv[0] -> module name ("fuzzer")
  462. ** argv[1] -> database name
  463. ** argv[2] -> table name
  464. ** argv[3] -> fuzzer rule table name
  465. */
  466. static int fuzzerConnect(
  467. sqlite3 *db,
  468. void *pAux,
  469. int argc, const char *const*argv,
  470. sqlite3_vtab **ppVtab,
  471. char **pzErr
  472. ){
  473. int rc = SQLITE_OK; /* Return code */
  474. fuzzer_vtab *pNew = 0; /* New virtual table */
  475. const char *zModule = argv[0];
  476. const char *zDb = argv[1];
  477. if( argc!=4 ){
  478. *pzErr = sqlite3_mprintf(
  479. "%s: wrong number of CREATE VIRTUAL TABLE arguments", zModule
  480. );
  481. rc = SQLITE_ERROR;
  482. }else{
  483. int nModule; /* Length of zModule, in bytes */
  484. nModule = (int)strlen(zModule);
  485. pNew = sqlite3_malloc( sizeof(*pNew) + nModule + 1);
  486. if( pNew==0 ){
  487. rc = SQLITE_NOMEM;
  488. }else{
  489. char *zTab; /* Dequoted name of fuzzer data table */
  490. memset(pNew, 0, sizeof(*pNew));
  491. pNew->zClassName = (char*)&pNew[1];
  492. memcpy(pNew->zClassName, zModule, nModule+1);
  493. zTab = fuzzerDequote(argv[3]);
  494. if( zTab==0 ){
  495. rc = SQLITE_NOMEM;
  496. }else{
  497. rc = fuzzerLoadRules(db, pNew, zDb, zTab, pzErr);
  498. sqlite3_free(zTab);
  499. }
  500. if( rc==SQLITE_OK ){
  501. rc = sqlite3_declare_vtab(db, "CREATE TABLE x(word,distance,ruleset)");
  502. }
  503. if( rc!=SQLITE_OK ){
  504. fuzzerDisconnect((sqlite3_vtab *)pNew);
  505. pNew = 0;
  506. }
  507. }
  508. }
  509. *ppVtab = (sqlite3_vtab *)pNew;
  510. return rc;
  511. }
  512. /*
  513. ** Open a new fuzzer cursor.
  514. */
  515. static int fuzzerOpen(sqlite3_vtab *pVTab, sqlite3_vtab_cursor **ppCursor){
  516. fuzzer_vtab *p = (fuzzer_vtab*)pVTab;
  517. fuzzer_cursor *pCur;
  518. pCur = sqlite3_malloc( sizeof(*pCur) );
  519. if( pCur==0 ) return SQLITE_NOMEM;
  520. memset(pCur, 0, sizeof(*pCur));
  521. pCur->pVtab = p;
  522. *ppCursor = &pCur->base;
  523. p->nCursor++;
  524. return SQLITE_OK;
  525. }
  526. /*
  527. ** Free all stems in a list.
  528. */
  529. static void fuzzerClearStemList(fuzzer_stem *pStem){
  530. while( pStem ){
  531. fuzzer_stem *pNext = pStem->pNext;
  532. sqlite3_free(pStem);
  533. pStem = pNext;
  534. }
  535. }
  536. /*
  537. ** Free up all the memory allocated by a cursor. Set it rLimit to 0
  538. ** to indicate that it is at EOF.
  539. */
  540. static void fuzzerClearCursor(fuzzer_cursor *pCur, int clearHash){
  541. int i;
  542. fuzzerClearStemList(pCur->pStem);
  543. fuzzerClearStemList(pCur->pDone);
  544. for(i=0; i<FUZZER_NQUEUE; i++) fuzzerClearStemList(pCur->aQueue[i]);
  545. pCur->rLimit = (fuzzer_cost)0;
  546. if( clearHash && pCur->nStem ){
  547. pCur->mxQueue = 0;
  548. pCur->pStem = 0;
  549. pCur->pDone = 0;
  550. memset(pCur->aQueue, 0, sizeof(pCur->aQueue));
  551. memset(pCur->apHash, 0, sizeof(pCur->apHash));
  552. }
  553. pCur->nStem = 0;
  554. }
  555. /*
  556. ** Close a fuzzer cursor.
  557. */
  558. static int fuzzerClose(sqlite3_vtab_cursor *cur){
  559. fuzzer_cursor *pCur = (fuzzer_cursor *)cur;
  560. fuzzerClearCursor(pCur, 0);
  561. sqlite3_free(pCur->zBuf);
  562. pCur->pVtab->nCursor--;
  563. sqlite3_free(pCur);
  564. return SQLITE_OK;
  565. }
  566. /*
  567. ** Compute the current output term for a fuzzer_stem.
  568. */
  569. static int fuzzerRender(
  570. fuzzer_stem *pStem, /* The stem to be rendered */
  571. char **pzBuf, /* Write results into this buffer. realloc if needed */
  572. int *pnBuf /* Size of the buffer */
  573. ){
  574. const fuzzer_rule *pRule = pStem->pRule;
  575. int n; /* Size of output term without nul-term */
  576. char *z; /* Buffer to assemble output term in */
  577. n = pStem->nBasis + pRule->nTo - pRule->nFrom;
  578. if( (*pnBuf)<n+1 ){
  579. (*pzBuf) = sqlite3_realloc((*pzBuf), n+100);
  580. if( (*pzBuf)==0 ) return SQLITE_NOMEM;
  581. (*pnBuf) = n+100;
  582. }
  583. n = pStem->n;
  584. z = *pzBuf;
  585. if( n<0 ){
  586. memcpy(z, pStem->zBasis, pStem->nBasis+1);
  587. }else{
  588. memcpy(z, pStem->zBasis, n);
  589. memcpy(&z[n], pRule->zTo, pRule->nTo);
  590. memcpy(&z[n+pRule->nTo], &pStem->zBasis[n+pRule->nFrom],
  591. pStem->nBasis-n-pRule->nFrom+1);
  592. }
  593. assert( z[pStem->nBasis + pRule->nTo - pRule->nFrom]==0 );
  594. return SQLITE_OK;
  595. }
  596. /*
  597. ** Compute a hash on zBasis.
  598. */
  599. static unsigned int fuzzerHash(const char *z){
  600. unsigned int h = 0;
  601. while( *z ){ h = (h<<3) ^ (h>>29) ^ *(z++); }
  602. return h % FUZZER_HASH;
  603. }
  604. /*
  605. ** Current cost of a stem
  606. */
  607. static fuzzer_cost fuzzerCost(fuzzer_stem *pStem){
  608. return pStem->rCostX = pStem->rBaseCost + pStem->pRule->rCost;
  609. }
  610. #if 0
  611. /*
  612. ** Print a description of a fuzzer_stem on stderr.
  613. */
  614. static void fuzzerStemPrint(
  615. const char *zPrefix,
  616. fuzzer_stem *pStem,
  617. const char *zSuffix
  618. ){
  619. if( pStem->n<0 ){
  620. fprintf(stderr, "%s[%s](%d)-->self%s",
  621. zPrefix,
  622. pStem->zBasis, pStem->rBaseCost,
  623. zSuffix
  624. );
  625. }else{
  626. char *zBuf = 0;
  627. int nBuf = 0;
  628. if( fuzzerRender(pStem, &zBuf, &nBuf)!=SQLITE_OK ) return;
  629. fprintf(stderr, "%s[%s](%d)-->{%s}(%d)%s",
  630. zPrefix,
  631. pStem->zBasis, pStem->rBaseCost, zBuf, pStem->,
  632. zSuffix
  633. );
  634. sqlite3_free(zBuf);
  635. }
  636. }
  637. #endif
  638. /*
  639. ** Return 1 if the string to which the cursor is point has already
  640. ** been emitted. Return 0 if not. Return -1 on a memory allocation
  641. ** failures.
  642. */
  643. static int fuzzerSeen(fuzzer_cursor *pCur, fuzzer_stem *pStem){
  644. unsigned int h;
  645. fuzzer_stem *pLookup;
  646. if( fuzzerRender(pStem, &pCur->zBuf, &pCur->nBuf)==SQLITE_NOMEM ){
  647. return -1;
  648. }
  649. h = fuzzerHash(pCur->zBuf);
  650. pLookup = pCur->apHash[h];
  651. while( pLookup && strcmp(pLookup->zBasis, pCur->zBuf)!=0 ){
  652. pLookup = pLookup->pHash;
  653. }
  654. return pLookup!=0;
  655. }
  656. /*
  657. ** If argument pRule is NULL, this function returns false.
  658. **
  659. ** Otherwise, it returns true if rule pRule should be skipped. A rule
  660. ** should be skipped if it does not belong to rule-set iRuleset, or if
  661. ** applying it to stem pStem would create a string longer than
  662. ** FUZZER_MX_OUTPUT_LENGTH bytes.
  663. */
  664. static int fuzzerSkipRule(
  665. const fuzzer_rule *pRule, /* Determine whether or not to skip this */
  666. fuzzer_stem *pStem, /* Stem rule may be applied to */
  667. int iRuleset /* Rule-set used by the current query */
  668. ){
  669. return pRule && (
  670. (pRule->iRuleset!=iRuleset)
  671. || (pStem->nBasis + pRule->nTo - pRule->nFrom)>FUZZER_MX_OUTPUT_LENGTH
  672. );
  673. }
  674. /*
  675. ** Advance a fuzzer_stem to its next value. Return 0 if there are
  676. ** no more values that can be generated by this fuzzer_stem. Return
  677. ** -1 on a memory allocation failure.
  678. */
  679. static int fuzzerAdvance(fuzzer_cursor *pCur, fuzzer_stem *pStem){
  680. const fuzzer_rule *pRule;
  681. while( (pRule = pStem->pRule)!=0 ){
  682. assert( pRule==&pCur->nullRule || pRule->iRuleset==pCur->iRuleset );
  683. while( pStem->n < pStem->nBasis - pRule->nFrom ){
  684. pStem->n++;
  685. if( pRule->nFrom==0
  686. || memcmp(&pStem->zBasis[pStem->n], pRule->zFrom, pRule->nFrom)==0
  687. ){
  688. /* Found a rewrite case. Make sure it is not a duplicate */
  689. int rc = fuzzerSeen(pCur, pStem);
  690. if( rc<0 ) return -1;
  691. if( rc==0 ){
  692. fuzzerCost(pStem);
  693. return 1;
  694. }
  695. }
  696. }
  697. pStem->n = -1;
  698. do{
  699. pRule = pRule->pNext;
  700. }while( fuzzerSkipRule(pRule, pStem, pCur->iRuleset) );
  701. pStem->pRule = pRule;
  702. if( pRule && fuzzerCost(pStem)>pCur->rLimit ) pStem->pRule = 0;
  703. }
  704. return 0;
  705. }
  706. /*
  707. ** The two input stem lists are both sorted in order of increasing
  708. ** rCostX. Merge them together into a single list, sorted by rCostX, and
  709. ** return a pointer to the head of that new list.
  710. */
  711. static fuzzer_stem *fuzzerMergeStems(fuzzer_stem *pA, fuzzer_stem *pB){
  712. fuzzer_stem head;
  713. fuzzer_stem *pTail;
  714. pTail = &head;
  715. while( pA && pB ){
  716. if( pA->rCostX<=pB->rCostX ){
  717. pTail->pNext = pA;
  718. pTail = pA;
  719. pA = pA->pNext;
  720. }else{
  721. pTail->pNext = pB;
  722. pTail = pB;
  723. pB = pB->pNext;
  724. }
  725. }
  726. if( pA==0 ){
  727. pTail->pNext = pB;
  728. }else{
  729. pTail->pNext = pA;
  730. }
  731. return head.pNext;
  732. }
  733. /*
  734. ** Load pCur->pStem with the lowest-cost stem. Return a pointer
  735. ** to the lowest-cost stem.
  736. */
  737. static fuzzer_stem *fuzzerLowestCostStem(fuzzer_cursor *pCur){
  738. fuzzer_stem *pBest, *pX;
  739. int iBest;
  740. int i;
  741. if( pCur->pStem==0 ){
  742. iBest = -1;
  743. pBest = 0;
  744. for(i=0; i<=pCur->mxQueue; i++){
  745. pX = pCur->aQueue[i];
  746. if( pX==0 ) continue;
  747. if( pBest==0 || pBest->rCostX>pX->rCostX ){
  748. pBest = pX;
  749. iBest = i;
  750. }
  751. }
  752. if( pBest ){
  753. pCur->aQueue[iBest] = pBest->pNext;
  754. pBest->pNext = 0;
  755. pCur->pStem = pBest;
  756. }
  757. }
  758. return pCur->pStem;
  759. }
  760. /*
  761. ** Insert pNew into queue of pending stems. Then find the stem
  762. ** with the lowest rCostX and move it into pCur->pStem.
  763. ** list. The insert is done such the pNew is in the correct order
  764. ** according to fuzzer_stem.zBaseCost+fuzzer_stem.pRule->rCost.
  765. */
  766. static fuzzer_stem *fuzzerInsert(fuzzer_cursor *pCur, fuzzer_stem *pNew){
  767. fuzzer_stem *pX;
  768. int i;
  769. /* If pCur->pStem exists and is greater than pNew, then make pNew
  770. ** the new pCur->pStem and insert the old pCur->pStem instead.
  771. */
  772. if( (pX = pCur->pStem)!=0 && pX->rCostX>pNew->rCostX ){
  773. pNew->pNext = 0;
  774. pCur->pStem = pNew;
  775. pNew = pX;
  776. }
  777. /* Insert the new value */
  778. pNew->pNext = 0;
  779. pX = pNew;
  780. for(i=0; i<=pCur->mxQueue; i++){
  781. if( pCur->aQueue[i] ){
  782. pX = fuzzerMergeStems(pX, pCur->aQueue[i]);
  783. pCur->aQueue[i] = 0;
  784. }else{
  785. pCur->aQueue[i] = pX;
  786. break;
  787. }
  788. }
  789. if( i>pCur->mxQueue ){
  790. if( i<FUZZER_NQUEUE ){
  791. pCur->mxQueue = i;
  792. pCur->aQueue[i] = pX;
  793. }else{
  794. assert( pCur->mxQueue==FUZZER_NQUEUE-1 );
  795. pX = fuzzerMergeStems(pX, pCur->aQueue[FUZZER_NQUEUE-1]);
  796. pCur->aQueue[FUZZER_NQUEUE-1] = pX;
  797. }
  798. }
  799. return fuzzerLowestCostStem(pCur);
  800. }
  801. /*
  802. ** Allocate a new fuzzer_stem. Add it to the hash table but do not
  803. ** link it into either the pCur->pStem or pCur->pDone lists.
  804. */
  805. static fuzzer_stem *fuzzerNewStem(
  806. fuzzer_cursor *pCur,
  807. const char *zWord,
  808. fuzzer_cost rBaseCost
  809. ){
  810. fuzzer_stem *pNew;
  811. fuzzer_rule *pRule;
  812. unsigned int h;
  813. pNew = sqlite3_malloc( sizeof(*pNew) + (int)strlen(zWord) + 1 );
  814. if( pNew==0 ) return 0;
  815. memset(pNew, 0, sizeof(*pNew));
  816. pNew->zBasis = (char*)&pNew[1];
  817. pNew->nBasis = (int)strlen(zWord);
  818. memcpy(pNew->zBasis, zWord, pNew->nBasis+1);
  819. pRule = pCur->pVtab->pRule;
  820. while( fuzzerSkipRule(pRule, pNew, pCur->iRuleset) ){
  821. pRule = pRule->pNext;
  822. }
  823. pNew->pRule = pRule;
  824. pNew->n = -1;
  825. pNew->rBaseCost = pNew->rCostX = rBaseCost;
  826. h = fuzzerHash(pNew->zBasis);
  827. pNew->pHash = pCur->apHash[h];
  828. pCur->apHash[h] = pNew;
  829. pCur->nStem++;
  830. return pNew;
  831. }
  832. /*
  833. ** Advance a cursor to its next row of output
  834. */
  835. static int fuzzerNext(sqlite3_vtab_cursor *cur){
  836. fuzzer_cursor *pCur = (fuzzer_cursor*)cur;
  837. int rc;
  838. fuzzer_stem *pStem, *pNew;
  839. pCur->iRowid++;
  840. /* Use the element the cursor is currently point to to create
  841. ** a new stem and insert the new stem into the priority queue.
  842. */
  843. pStem = pCur->pStem;
  844. if( pStem->rCostX>0 ){
  845. rc = fuzzerRender(pStem, &pCur->zBuf, &pCur->nBuf);
  846. if( rc==SQLITE_NOMEM ) return SQLITE_NOMEM;
  847. pNew = fuzzerNewStem(pCur, pCur->zBuf, pStem->rCostX);
  848. if( pNew ){
  849. if( fuzzerAdvance(pCur, pNew)==0 ){
  850. pNew->pNext = pCur->pDone;
  851. pCur->pDone = pNew;
  852. }else{
  853. if( fuzzerInsert(pCur, pNew)==pNew ){
  854. return SQLITE_OK;
  855. }
  856. }
  857. }else{
  858. return SQLITE_NOMEM;
  859. }
  860. }
  861. /* Adjust the priority queue so that the first element of the
  862. ** stem list is the next lowest cost word.
  863. */
  864. while( (pStem = pCur->pStem)!=0 ){
  865. int res = fuzzerAdvance(pCur, pStem);
  866. if( res<0 ){
  867. return SQLITE_NOMEM;
  868. }else if( res>0 ){
  869. pCur->pStem = 0;
  870. pStem = fuzzerInsert(pCur, pStem);
  871. if( (rc = fuzzerSeen(pCur, pStem))!=0 ){
  872. if( rc<0 ) return SQLITE_NOMEM;
  873. continue;
  874. }
  875. return SQLITE_OK; /* New word found */
  876. }
  877. pCur->pStem = 0;
  878. pStem->pNext = pCur->pDone;
  879. pCur->pDone = pStem;
  880. if( fuzzerLowestCostStem(pCur) ){
  881. rc = fuzzerSeen(pCur, pCur->pStem);
  882. if( rc<0 ) return SQLITE_NOMEM;
  883. if( rc==0 ){
  884. return SQLITE_OK;
  885. }
  886. }
  887. }
  888. /* Reach this point only if queue has been exhausted and there is
  889. ** nothing left to be output. */
  890. pCur->rLimit = (fuzzer_cost)0;
  891. return SQLITE_OK;
  892. }
  893. /*
  894. ** Called to "rewind" a cursor back to the beginning so that
  895. ** it starts its output over again. Always called at least once
  896. ** prior to any fuzzerColumn, fuzzerRowid, or fuzzerEof call.
  897. */
  898. static int fuzzerFilter(
  899. sqlite3_vtab_cursor *pVtabCursor,
  900. int idxNum, const char *idxStr,
  901. int argc, sqlite3_value **argv
  902. ){
  903. fuzzer_cursor *pCur = (fuzzer_cursor *)pVtabCursor;
  904. const char *zWord = "";
  905. fuzzer_stem *pStem;
  906. int idx;
  907. fuzzerClearCursor(pCur, 1);
  908. pCur->rLimit = 2147483647;
  909. idx = 0;
  910. if( idxNum & 1 ){
  911. zWord = (const char*)sqlite3_value_text(argv[0]);
  912. idx++;
  913. }
  914. if( idxNum & 2 ){
  915. pCur->rLimit = (fuzzer_cost)sqlite3_value_int(argv[idx]);
  916. idx++;
  917. }
  918. if( idxNum & 4 ){
  919. pCur->iRuleset = (fuzzer_cost)sqlite3_value_int(argv[idx]);
  920. idx++;
  921. }
  922. pCur->nullRule.pNext = pCur->pVtab->pRule;
  923. pCur->nullRule.rCost = 0;
  924. pCur->nullRule.nFrom = 0;
  925. pCur->nullRule.nTo = 0;
  926. pCur->nullRule.zFrom = "";
  927. pCur->iRowid = 1;
  928. assert( pCur->pStem==0 );
  929. /* If the query term is longer than FUZZER_MX_OUTPUT_LENGTH bytes, this
  930. ** query will return zero rows. */
  931. if( (int)strlen(zWord)<FUZZER_MX_OUTPUT_LENGTH ){
  932. pCur->pStem = pStem = fuzzerNewStem(pCur, zWord, (fuzzer_cost)0);
  933. if( pStem==0 ) return SQLITE_NOMEM;
  934. pStem->pRule = &pCur->nullRule;
  935. pStem->n = pStem->nBasis;
  936. }else{
  937. pCur->rLimit = 0;
  938. }
  939. return SQLITE_OK;
  940. }
  941. /*
  942. ** Only the word and distance columns have values. All other columns
  943. ** return NULL
  944. */
  945. static int fuzzerColumn(sqlite3_vtab_cursor *cur, sqlite3_context *ctx, int i){
  946. fuzzer_cursor *pCur = (fuzzer_cursor*)cur;
  947. if( i==0 ){
  948. /* the "word" column */
  949. if( fuzzerRender(pCur->pStem, &pCur->zBuf, &pCur->nBuf)==SQLITE_NOMEM ){
  950. return SQLITE_NOMEM;
  951. }
  952. sqlite3_result_text(ctx, pCur->zBuf, -1, SQLITE_TRANSIENT);
  953. }else if( i==1 ){
  954. /* the "distance" column */
  955. sqlite3_result_int(ctx, pCur->pStem->rCostX);
  956. }else{
  957. /* All other columns are NULL */
  958. sqlite3_result_null(ctx);
  959. }
  960. return SQLITE_OK;
  961. }
  962. /*
  963. ** The rowid.
  964. */
  965. static int fuzzerRowid(sqlite3_vtab_cursor *cur, sqlite_int64 *pRowid){
  966. fuzzer_cursor *pCur = (fuzzer_cursor*)cur;
  967. *pRowid = pCur->iRowid;
  968. return SQLITE_OK;
  969. }
  970. /*
  971. ** When the fuzzer_cursor.rLimit value is 0 or less, that is a signal
  972. ** that the cursor has nothing more to output.
  973. */
  974. static int fuzzerEof(sqlite3_vtab_cursor *cur){
  975. fuzzer_cursor *pCur = (fuzzer_cursor*)cur;
  976. return pCur->rLimit<=(fuzzer_cost)0;
  977. }
  978. /*
  979. ** Search for terms of these forms:
  980. **
  981. ** (A) word MATCH $str
  982. ** (B1) distance < $value
  983. ** (B2) distance <= $value
  984. ** (C) ruleid == $ruleid
  985. **
  986. ** The distance< and distance<= are both treated as distance<=.
  987. ** The query plan number is a bit vector:
  988. **
  989. ** bit 1: Term of the form (A) found
  990. ** bit 2: Term like (B1) or (B2) found
  991. ** bit 3: Term like (C) found
  992. **
  993. ** If bit-1 is set, $str is always in filter.argv[0]. If bit-2 is set
  994. ** then $value is in filter.argv[0] if bit-1 is clear and is in
  995. ** filter.argv[1] if bit-1 is set. If bit-3 is set, then $ruleid is
  996. ** in filter.argv[0] if bit-1 and bit-2 are both zero, is in
  997. ** filter.argv[1] if exactly one of bit-1 and bit-2 are set, and is in
  998. ** filter.argv[2] if both bit-1 and bit-2 are set.
  999. */
  1000. static int fuzzerBestIndex(sqlite3_vtab *tab, sqlite3_index_info *pIdxInfo){
  1001. int iPlan = 0;
  1002. int iDistTerm = -1;
  1003. int iRulesetTerm = -1;
  1004. int i;
  1005. int seenMatch = 0;
  1006. const struct sqlite3_index_constraint *pConstraint;
  1007. double rCost = 1e12;
  1008. pConstraint = pIdxInfo->aConstraint;
  1009. for(i=0; i<pIdxInfo->nConstraint; i++, pConstraint++){
  1010. if( pConstraint->iColumn==0
  1011. && pConstraint->op==SQLITE_INDEX_CONSTRAINT_MATCH ){
  1012. seenMatch = 1;
  1013. }
  1014. if( pConstraint->usable==0 ) continue;
  1015. if( (iPlan & 1)==0
  1016. && pConstraint->iColumn==0
  1017. && pConstraint->op==SQLITE_INDEX_CONSTRAINT_MATCH
  1018. ){
  1019. iPlan |= 1;
  1020. pIdxInfo->aConstraintUsage[i].argvIndex = 1;
  1021. pIdxInfo->aConstraintUsage[i].omit = 1;
  1022. rCost /= 1e6;
  1023. }
  1024. if( (iPlan & 2)==0
  1025. && pConstraint->iColumn==1
  1026. && (pConstraint->op==SQLITE_INDEX_CONSTRAINT_LT
  1027. || pConstraint->op==SQLITE_INDEX_CONSTRAINT_LE)
  1028. ){
  1029. iPlan |= 2;
  1030. iDistTerm = i;
  1031. rCost /= 10.0;
  1032. }
  1033. if( (iPlan & 4)==0
  1034. && pConstraint->iColumn==2
  1035. && pConstraint->op==SQLITE_INDEX_CONSTRAINT_EQ
  1036. ){
  1037. iPlan |= 4;
  1038. pIdxInfo->aConstraintUsage[i].omit = 1;
  1039. iRulesetTerm = i;
  1040. rCost /= 10.0;
  1041. }
  1042. }
  1043. if( iPlan & 2 ){
  1044. pIdxInfo->aConstraintUsage[iDistTerm].argvIndex = 1+((iPlan&1)!=0);
  1045. }
  1046. if( iPlan & 4 ){
  1047. int idx = 1;
  1048. if( iPlan & 1 ) idx++;
  1049. if( iPlan & 2 ) idx++;
  1050. pIdxInfo->aConstraintUsage[iRulesetTerm].argvIndex = idx;
  1051. }
  1052. pIdxInfo->idxNum = iPlan;
  1053. if( pIdxInfo->nOrderBy==1
  1054. && pIdxInfo->aOrderBy[0].iColumn==1
  1055. && pIdxInfo->aOrderBy[0].desc==0
  1056. ){
  1057. pIdxInfo->orderByConsumed = 1;
  1058. }
  1059. if( seenMatch && (iPlan&1)==0 ) rCost = 1e99;
  1060. pIdxInfo->estimatedCost = rCost;
  1061. return SQLITE_OK;
  1062. }
  1063. /*
  1064. ** A virtual table module that implements the "fuzzer".
  1065. */
  1066. static sqlite3_module fuzzerModule = {
  1067. 0, /* iVersion */
  1068. fuzzerConnect,
  1069. fuzzerConnect,
  1070. fuzzerBestIndex,
  1071. fuzzerDisconnect,
  1072. fuzzerDisconnect,
  1073. fuzzerOpen, /* xOpen - open a cursor */
  1074. fuzzerClose, /* xClose - close a cursor */
  1075. fuzzerFilter, /* xFilter - configure scan constraints */
  1076. fuzzerNext, /* xNext - advance a cursor */
  1077. fuzzerEof, /* xEof - check for end of scan */
  1078. fuzzerColumn, /* xColumn - read data */
  1079. fuzzerRowid, /* xRowid - read data */
  1080. 0, /* xUpdate */
  1081. 0, /* xBegin */
  1082. 0, /* xSync */
  1083. 0, /* xCommit */
  1084. 0, /* xRollback */
  1085. 0, /* xFindMethod */
  1086. 0, /* xRename */
  1087. };
  1088. #endif /* SQLITE_OMIT_VIRTUALTABLE */
  1089. #ifdef _WIN32
  1090. __declspec(dllexport)
  1091. #endif
  1092. int sqlite3_fuzzer_init(
  1093. sqlite3 *db,
  1094. char **pzErrMsg,
  1095. const sqlite3_api_routines *pApi
  1096. ){
  1097. int rc = SQLITE_OK;
  1098. SQLITE_EXTENSION_INIT2(pApi);
  1099. #ifndef SQLITE_OMIT_VIRTUALTABLE
  1100. rc = sqlite3_create_module(db, "fuzzer", &fuzzerModule, 0);
  1101. #endif
  1102. return rc;
  1103. }