fuzzer.c 36 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193
  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 applying 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 vocabulary.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 kept 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_malloc64( 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;
  326. pRule->zFrom += nTo + 1;
  327. pRule->nFrom = (fuzzer_len)nFrom;
  328. memcpy(pRule->zFrom, zFrom, nFrom+1);
  329. memcpy(pRule->zTo, zTo, nTo+1);
  330. pRule->nTo = (fuzzer_len)nTo;
  331. pRule->rCost = nCost;
  332. pRule->iRuleset = (int)iRuleset;
  333. }
  334. }
  335. *ppRule = pRule;
  336. return rc;
  337. }
  338. /*
  339. ** Load the content of the fuzzer data table into memory.
  340. */
  341. static int fuzzerLoadRules(
  342. sqlite3 *db, /* Database handle */
  343. fuzzer_vtab *p, /* Virtual fuzzer table to configure */
  344. const char *zDb, /* Database containing rules data */
  345. const char *zData, /* Table containing rules data */
  346. char **pzErr /* OUT: Error message */
  347. ){
  348. int rc = SQLITE_OK; /* Return code */
  349. char *zSql; /* SELECT used to read from rules table */
  350. fuzzer_rule *pHead = 0;
  351. zSql = sqlite3_mprintf("SELECT * FROM %Q.%Q", zDb, zData);
  352. if( zSql==0 ){
  353. rc = SQLITE_NOMEM;
  354. }else{
  355. int rc2; /* finalize() return code */
  356. sqlite3_stmt *pStmt = 0;
  357. rc = sqlite3_prepare_v2(db, zSql, -1, &pStmt, 0);
  358. if( rc!=SQLITE_OK ){
  359. *pzErr = sqlite3_mprintf("%s: %s", p->zClassName, sqlite3_errmsg(db));
  360. }else if( sqlite3_column_count(pStmt)!=4 ){
  361. *pzErr = sqlite3_mprintf("%s: %s has %d columns, expected 4",
  362. p->zClassName, zData, sqlite3_column_count(pStmt)
  363. );
  364. rc = SQLITE_ERROR;
  365. }else{
  366. while( rc==SQLITE_OK && SQLITE_ROW==sqlite3_step(pStmt) ){
  367. fuzzer_rule *pRule = 0;
  368. rc = fuzzerLoadOneRule(p, pStmt, &pRule, pzErr);
  369. if( pRule ){
  370. pRule->pNext = pHead;
  371. pHead = pRule;
  372. }
  373. }
  374. }
  375. rc2 = sqlite3_finalize(pStmt);
  376. if( rc==SQLITE_OK ) rc = rc2;
  377. }
  378. sqlite3_free(zSql);
  379. /* All rules are now in a singly linked list starting at pHead. This
  380. ** block sorts them by cost and then sets fuzzer_vtab.pRule to point to
  381. ** point to the head of the sorted list.
  382. */
  383. if( rc==SQLITE_OK ){
  384. unsigned int i;
  385. fuzzer_rule *pX;
  386. fuzzer_rule *a[15];
  387. for(i=0; i<sizeof(a)/sizeof(a[0]); i++) a[i] = 0;
  388. while( (pX = pHead)!=0 ){
  389. pHead = pX->pNext;
  390. pX->pNext = 0;
  391. for(i=0; a[i] && i<sizeof(a)/sizeof(a[0])-1; i++){
  392. pX = fuzzerMergeRules(a[i], pX);
  393. a[i] = 0;
  394. }
  395. a[i] = fuzzerMergeRules(a[i], pX);
  396. }
  397. for(pX=a[0], i=1; i<sizeof(a)/sizeof(a[0]); i++){
  398. pX = fuzzerMergeRules(a[i], pX);
  399. }
  400. p->pRule = fuzzerMergeRules(p->pRule, pX);
  401. }else{
  402. /* An error has occurred. Setting p->pRule to point to the head of the
  403. ** allocated list ensures that the list will be cleaned up in this case.
  404. */
  405. assert( p->pRule==0 );
  406. p->pRule = pHead;
  407. }
  408. return rc;
  409. }
  410. /*
  411. ** This function converts an SQL quoted string into an unquoted string
  412. ** and returns a pointer to a buffer allocated using sqlite3_malloc()
  413. ** containing the result. The caller should eventually free this buffer
  414. ** using sqlite3_free.
  415. **
  416. ** Examples:
  417. **
  418. ** "abc" becomes abc
  419. ** 'xyz' becomes xyz
  420. ** [pqr] becomes pqr
  421. ** `mno` becomes mno
  422. */
  423. static char *fuzzerDequote(const char *zIn){
  424. sqlite3_int64 nIn; /* Size of input string, in bytes */
  425. char *zOut; /* Output (dequoted) string */
  426. nIn = strlen(zIn);
  427. zOut = sqlite3_malloc64(nIn+1);
  428. if( zOut ){
  429. char q = zIn[0]; /* Quote character (if any ) */
  430. if( q!='[' && q!= '\'' && q!='"' && q!='`' ){
  431. memcpy(zOut, zIn, (size_t)(nIn+1));
  432. }else{
  433. int iOut = 0; /* Index of next byte to write to output */
  434. int iIn; /* Index of next byte to read from input */
  435. if( q=='[' ) q = ']';
  436. for(iIn=1; iIn<nIn; iIn++){
  437. if( zIn[iIn]==q ) iIn++;
  438. zOut[iOut++] = zIn[iIn];
  439. }
  440. }
  441. assert( (int)strlen(zOut)<=nIn );
  442. }
  443. return zOut;
  444. }
  445. /*
  446. ** xDisconnect/xDestroy method for the fuzzer module.
  447. */
  448. static int fuzzerDisconnect(sqlite3_vtab *pVtab){
  449. fuzzer_vtab *p = (fuzzer_vtab*)pVtab;
  450. assert( p->nCursor==0 );
  451. while( p->pRule ){
  452. fuzzer_rule *pRule = p->pRule;
  453. p->pRule = pRule->pNext;
  454. sqlite3_free(pRule);
  455. }
  456. sqlite3_free(p);
  457. return SQLITE_OK;
  458. }
  459. /*
  460. ** xConnect/xCreate method for the fuzzer module. Arguments are:
  461. **
  462. ** argv[0] -> module name ("fuzzer")
  463. ** argv[1] -> database name
  464. ** argv[2] -> table name
  465. ** argv[3] -> fuzzer rule table name
  466. */
  467. static int fuzzerConnect(
  468. sqlite3 *db,
  469. void *pAux,
  470. int argc, const char *const*argv,
  471. sqlite3_vtab **ppVtab,
  472. char **pzErr
  473. ){
  474. int rc = SQLITE_OK; /* Return code */
  475. fuzzer_vtab *pNew = 0; /* New virtual table */
  476. const char *zModule = argv[0];
  477. const char *zDb = argv[1];
  478. if( argc!=4 ){
  479. *pzErr = sqlite3_mprintf(
  480. "%s: wrong number of CREATE VIRTUAL TABLE arguments", zModule
  481. );
  482. rc = SQLITE_ERROR;
  483. }else{
  484. sqlite3_int64 nModule; /* Length of zModule, in bytes */
  485. nModule = strlen(zModule);
  486. pNew = sqlite3_malloc64( sizeof(*pNew) + nModule + 1);
  487. if( pNew==0 ){
  488. rc = SQLITE_NOMEM;
  489. }else{
  490. char *zTab; /* Dequoted name of fuzzer data table */
  491. memset(pNew, 0, sizeof(*pNew));
  492. pNew->zClassName = (char*)&pNew[1];
  493. memcpy(pNew->zClassName, zModule, (size_t)(nModule+1));
  494. zTab = fuzzerDequote(argv[3]);
  495. if( zTab==0 ){
  496. rc = SQLITE_NOMEM;
  497. }else{
  498. rc = fuzzerLoadRules(db, pNew, zDb, zTab, pzErr);
  499. sqlite3_free(zTab);
  500. }
  501. if( rc==SQLITE_OK ){
  502. rc = sqlite3_declare_vtab(db, "CREATE TABLE x(word,distance,ruleset)");
  503. }
  504. if( rc!=SQLITE_OK ){
  505. fuzzerDisconnect((sqlite3_vtab *)pNew);
  506. pNew = 0;
  507. }else{
  508. sqlite3_vtab_config(db, SQLITE_VTAB_INNOCUOUS);
  509. }
  510. }
  511. }
  512. *ppVtab = (sqlite3_vtab *)pNew;
  513. return rc;
  514. }
  515. /*
  516. ** Open a new fuzzer cursor.
  517. */
  518. static int fuzzerOpen(sqlite3_vtab *pVTab, sqlite3_vtab_cursor **ppCursor){
  519. fuzzer_vtab *p = (fuzzer_vtab*)pVTab;
  520. fuzzer_cursor *pCur;
  521. pCur = sqlite3_malloc( sizeof(*pCur) );
  522. if( pCur==0 ) return SQLITE_NOMEM;
  523. memset(pCur, 0, sizeof(*pCur));
  524. pCur->pVtab = p;
  525. *ppCursor = &pCur->base;
  526. p->nCursor++;
  527. return SQLITE_OK;
  528. }
  529. /*
  530. ** Free all stems in a list.
  531. */
  532. static void fuzzerClearStemList(fuzzer_stem *pStem){
  533. while( pStem ){
  534. fuzzer_stem *pNext = pStem->pNext;
  535. sqlite3_free(pStem);
  536. pStem = pNext;
  537. }
  538. }
  539. /*
  540. ** Free up all the memory allocated by a cursor. Set it rLimit to 0
  541. ** to indicate that it is at EOF.
  542. */
  543. static void fuzzerClearCursor(fuzzer_cursor *pCur, int clearHash){
  544. int i;
  545. fuzzerClearStemList(pCur->pStem);
  546. fuzzerClearStemList(pCur->pDone);
  547. for(i=0; i<FUZZER_NQUEUE; i++) fuzzerClearStemList(pCur->aQueue[i]);
  548. pCur->rLimit = (fuzzer_cost)0;
  549. if( clearHash && pCur->nStem ){
  550. pCur->mxQueue = 0;
  551. pCur->pStem = 0;
  552. pCur->pDone = 0;
  553. memset(pCur->aQueue, 0, sizeof(pCur->aQueue));
  554. memset(pCur->apHash, 0, sizeof(pCur->apHash));
  555. }
  556. pCur->nStem = 0;
  557. }
  558. /*
  559. ** Close a fuzzer cursor.
  560. */
  561. static int fuzzerClose(sqlite3_vtab_cursor *cur){
  562. fuzzer_cursor *pCur = (fuzzer_cursor *)cur;
  563. fuzzerClearCursor(pCur, 0);
  564. sqlite3_free(pCur->zBuf);
  565. pCur->pVtab->nCursor--;
  566. sqlite3_free(pCur);
  567. return SQLITE_OK;
  568. }
  569. /*
  570. ** Compute the current output term for a fuzzer_stem.
  571. */
  572. static int fuzzerRender(
  573. fuzzer_stem *pStem, /* The stem to be rendered */
  574. char **pzBuf, /* Write results into this buffer. realloc if needed */
  575. int *pnBuf /* Size of the buffer */
  576. ){
  577. const fuzzer_rule *pRule = pStem->pRule;
  578. int n; /* Size of output term without nul-term */
  579. char *z; /* Buffer to assemble output term in */
  580. n = pStem->nBasis + pRule->nTo - pRule->nFrom;
  581. if( (*pnBuf)<n+1 ){
  582. (*pzBuf) = sqlite3_realloc((*pzBuf), n+100);
  583. if( (*pzBuf)==0 ) return SQLITE_NOMEM;
  584. (*pnBuf) = n+100;
  585. }
  586. n = pStem->n;
  587. z = *pzBuf;
  588. if( n<0 ){
  589. memcpy(z, pStem->zBasis, pStem->nBasis+1);
  590. }else{
  591. memcpy(z, pStem->zBasis, n);
  592. memcpy(&z[n], pRule->zTo, pRule->nTo);
  593. memcpy(&z[n+pRule->nTo], &pStem->zBasis[n+pRule->nFrom],
  594. pStem->nBasis-n-pRule->nFrom+1);
  595. }
  596. assert( z[pStem->nBasis + pRule->nTo - pRule->nFrom]==0 );
  597. return SQLITE_OK;
  598. }
  599. /*
  600. ** Compute a hash on zBasis.
  601. */
  602. static unsigned int fuzzerHash(const char *z){
  603. unsigned int h = 0;
  604. while( *z ){ h = (h<<3) ^ (h>>29) ^ *(z++); }
  605. return h % FUZZER_HASH;
  606. }
  607. /*
  608. ** Current cost of a stem
  609. */
  610. static fuzzer_cost fuzzerCost(fuzzer_stem *pStem){
  611. return pStem->rCostX = pStem->rBaseCost + pStem->pRule->rCost;
  612. }
  613. #if 0
  614. /*
  615. ** Print a description of a fuzzer_stem on stderr.
  616. */
  617. static void fuzzerStemPrint(
  618. const char *zPrefix,
  619. fuzzer_stem *pStem,
  620. const char *zSuffix
  621. ){
  622. if( pStem->n<0 ){
  623. fprintf(stderr, "%s[%s](%d)-->self%s",
  624. zPrefix,
  625. pStem->zBasis, pStem->rBaseCost,
  626. zSuffix
  627. );
  628. }else{
  629. char *zBuf = 0;
  630. int nBuf = 0;
  631. if( fuzzerRender(pStem, &zBuf, &nBuf)!=SQLITE_OK ) return;
  632. fprintf(stderr, "%s[%s](%d)-->{%s}(%d)%s",
  633. zPrefix,
  634. pStem->zBasis, pStem->rBaseCost, zBuf, pStem->,
  635. zSuffix
  636. );
  637. sqlite3_free(zBuf);
  638. }
  639. }
  640. #endif
  641. /*
  642. ** Return 1 if the string to which the cursor is point has already
  643. ** been emitted. Return 0 if not. Return -1 on a memory allocation
  644. ** failures.
  645. */
  646. static int fuzzerSeen(fuzzer_cursor *pCur, fuzzer_stem *pStem){
  647. unsigned int h;
  648. fuzzer_stem *pLookup;
  649. if( fuzzerRender(pStem, &pCur->zBuf, &pCur->nBuf)==SQLITE_NOMEM ){
  650. return -1;
  651. }
  652. h = fuzzerHash(pCur->zBuf);
  653. pLookup = pCur->apHash[h];
  654. while( pLookup && strcmp(pLookup->zBasis, pCur->zBuf)!=0 ){
  655. pLookup = pLookup->pHash;
  656. }
  657. return pLookup!=0;
  658. }
  659. /*
  660. ** If argument pRule is NULL, this function returns false.
  661. **
  662. ** Otherwise, it returns true if rule pRule should be skipped. A rule
  663. ** should be skipped if it does not belong to rule-set iRuleset, or if
  664. ** applying it to stem pStem would create a string longer than
  665. ** FUZZER_MX_OUTPUT_LENGTH bytes.
  666. */
  667. static int fuzzerSkipRule(
  668. const fuzzer_rule *pRule, /* Determine whether or not to skip this */
  669. fuzzer_stem *pStem, /* Stem rule may be applied to */
  670. int iRuleset /* Rule-set used by the current query */
  671. ){
  672. return pRule && (
  673. (pRule->iRuleset!=iRuleset)
  674. || (pStem->nBasis + pRule->nTo - pRule->nFrom)>FUZZER_MX_OUTPUT_LENGTH
  675. );
  676. }
  677. /*
  678. ** Advance a fuzzer_stem to its next value. Return 0 if there are
  679. ** no more values that can be generated by this fuzzer_stem. Return
  680. ** -1 on a memory allocation failure.
  681. */
  682. static int fuzzerAdvance(fuzzer_cursor *pCur, fuzzer_stem *pStem){
  683. const fuzzer_rule *pRule;
  684. while( (pRule = pStem->pRule)!=0 ){
  685. assert( pRule==&pCur->nullRule || pRule->iRuleset==pCur->iRuleset );
  686. while( pStem->n < pStem->nBasis - pRule->nFrom ){
  687. pStem->n++;
  688. if( pRule->nFrom==0
  689. || memcmp(&pStem->zBasis[pStem->n], pRule->zFrom, pRule->nFrom)==0
  690. ){
  691. /* Found a rewrite case. Make sure it is not a duplicate */
  692. int rc = fuzzerSeen(pCur, pStem);
  693. if( rc<0 ) return -1;
  694. if( rc==0 ){
  695. fuzzerCost(pStem);
  696. return 1;
  697. }
  698. }
  699. }
  700. pStem->n = -1;
  701. do{
  702. pRule = pRule->pNext;
  703. }while( fuzzerSkipRule(pRule, pStem, pCur->iRuleset) );
  704. pStem->pRule = pRule;
  705. if( pRule && fuzzerCost(pStem)>pCur->rLimit ) pStem->pRule = 0;
  706. }
  707. return 0;
  708. }
  709. /*
  710. ** The two input stem lists are both sorted in order of increasing
  711. ** rCostX. Merge them together into a single list, sorted by rCostX, and
  712. ** return a pointer to the head of that new list.
  713. */
  714. static fuzzer_stem *fuzzerMergeStems(fuzzer_stem *pA, fuzzer_stem *pB){
  715. fuzzer_stem head;
  716. fuzzer_stem *pTail;
  717. pTail = &head;
  718. while( pA && pB ){
  719. if( pA->rCostX<=pB->rCostX ){
  720. pTail->pNext = pA;
  721. pTail = pA;
  722. pA = pA->pNext;
  723. }else{
  724. pTail->pNext = pB;
  725. pTail = pB;
  726. pB = pB->pNext;
  727. }
  728. }
  729. if( pA==0 ){
  730. pTail->pNext = pB;
  731. }else{
  732. pTail->pNext = pA;
  733. }
  734. return head.pNext;
  735. }
  736. /*
  737. ** Load pCur->pStem with the lowest-cost stem. Return a pointer
  738. ** to the lowest-cost stem.
  739. */
  740. static fuzzer_stem *fuzzerLowestCostStem(fuzzer_cursor *pCur){
  741. fuzzer_stem *pBest, *pX;
  742. int iBest;
  743. int i;
  744. if( pCur->pStem==0 ){
  745. iBest = -1;
  746. pBest = 0;
  747. for(i=0; i<=pCur->mxQueue; i++){
  748. pX = pCur->aQueue[i];
  749. if( pX==0 ) continue;
  750. if( pBest==0 || pBest->rCostX>pX->rCostX ){
  751. pBest = pX;
  752. iBest = i;
  753. }
  754. }
  755. if( pBest ){
  756. pCur->aQueue[iBest] = pBest->pNext;
  757. pBest->pNext = 0;
  758. pCur->pStem = pBest;
  759. }
  760. }
  761. return pCur->pStem;
  762. }
  763. /*
  764. ** Insert pNew into queue of pending stems. Then find the stem
  765. ** with the lowest rCostX and move it into pCur->pStem.
  766. ** list. The insert is done such the pNew is in the correct order
  767. ** according to fuzzer_stem.zBaseCost+fuzzer_stem.pRule->rCost.
  768. */
  769. static fuzzer_stem *fuzzerInsert(fuzzer_cursor *pCur, fuzzer_stem *pNew){
  770. fuzzer_stem *pX;
  771. int i;
  772. /* If pCur->pStem exists and is greater than pNew, then make pNew
  773. ** the new pCur->pStem and insert the old pCur->pStem instead.
  774. */
  775. if( (pX = pCur->pStem)!=0 && pX->rCostX>pNew->rCostX ){
  776. pNew->pNext = 0;
  777. pCur->pStem = pNew;
  778. pNew = pX;
  779. }
  780. /* Insert the new value */
  781. pNew->pNext = 0;
  782. pX = pNew;
  783. for(i=0; i<=pCur->mxQueue; i++){
  784. if( pCur->aQueue[i] ){
  785. pX = fuzzerMergeStems(pX, pCur->aQueue[i]);
  786. pCur->aQueue[i] = 0;
  787. }else{
  788. pCur->aQueue[i] = pX;
  789. break;
  790. }
  791. }
  792. if( i>pCur->mxQueue ){
  793. if( i<FUZZER_NQUEUE ){
  794. pCur->mxQueue = i;
  795. pCur->aQueue[i] = pX;
  796. }else{
  797. assert( pCur->mxQueue==FUZZER_NQUEUE-1 );
  798. pX = fuzzerMergeStems(pX, pCur->aQueue[FUZZER_NQUEUE-1]);
  799. pCur->aQueue[FUZZER_NQUEUE-1] = pX;
  800. }
  801. }
  802. return fuzzerLowestCostStem(pCur);
  803. }
  804. /*
  805. ** Allocate a new fuzzer_stem. Add it to the hash table but do not
  806. ** link it into either the pCur->pStem or pCur->pDone lists.
  807. */
  808. static fuzzer_stem *fuzzerNewStem(
  809. fuzzer_cursor *pCur,
  810. const char *zWord,
  811. fuzzer_cost rBaseCost
  812. ){
  813. fuzzer_stem *pNew;
  814. fuzzer_rule *pRule;
  815. unsigned int h;
  816. pNew = sqlite3_malloc64( sizeof(*pNew) + strlen(zWord) + 1 );
  817. if( pNew==0 ) return 0;
  818. memset(pNew, 0, sizeof(*pNew));
  819. pNew->zBasis = (char*)&pNew[1];
  820. pNew->nBasis = (fuzzer_len)strlen(zWord);
  821. memcpy(pNew->zBasis, zWord, pNew->nBasis+1);
  822. pRule = pCur->pVtab->pRule;
  823. while( fuzzerSkipRule(pRule, pNew, pCur->iRuleset) ){
  824. pRule = pRule->pNext;
  825. }
  826. pNew->pRule = pRule;
  827. pNew->n = -1;
  828. pNew->rBaseCost = pNew->rCostX = rBaseCost;
  829. h = fuzzerHash(pNew->zBasis);
  830. pNew->pHash = pCur->apHash[h];
  831. pCur->apHash[h] = pNew;
  832. pCur->nStem++;
  833. return pNew;
  834. }
  835. /*
  836. ** Advance a cursor to its next row of output
  837. */
  838. static int fuzzerNext(sqlite3_vtab_cursor *cur){
  839. fuzzer_cursor *pCur = (fuzzer_cursor*)cur;
  840. int rc;
  841. fuzzer_stem *pStem, *pNew;
  842. pCur->iRowid++;
  843. /* Use the element the cursor is currently point to to create
  844. ** a new stem and insert the new stem into the priority queue.
  845. */
  846. pStem = pCur->pStem;
  847. if( pStem->rCostX>0 ){
  848. rc = fuzzerRender(pStem, &pCur->zBuf, &pCur->nBuf);
  849. if( rc==SQLITE_NOMEM ) return SQLITE_NOMEM;
  850. pNew = fuzzerNewStem(pCur, pCur->zBuf, pStem->rCostX);
  851. if( pNew ){
  852. if( fuzzerAdvance(pCur, pNew)==0 ){
  853. pNew->pNext = pCur->pDone;
  854. pCur->pDone = pNew;
  855. }else{
  856. if( fuzzerInsert(pCur, pNew)==pNew ){
  857. return SQLITE_OK;
  858. }
  859. }
  860. }else{
  861. return SQLITE_NOMEM;
  862. }
  863. }
  864. /* Adjust the priority queue so that the first element of the
  865. ** stem list is the next lowest cost word.
  866. */
  867. while( (pStem = pCur->pStem)!=0 ){
  868. int res = fuzzerAdvance(pCur, pStem);
  869. if( res<0 ){
  870. return SQLITE_NOMEM;
  871. }else if( res>0 ){
  872. pCur->pStem = 0;
  873. pStem = fuzzerInsert(pCur, pStem);
  874. if( (rc = fuzzerSeen(pCur, pStem))!=0 ){
  875. if( rc<0 ) return SQLITE_NOMEM;
  876. continue;
  877. }
  878. return SQLITE_OK; /* New word found */
  879. }
  880. pCur->pStem = 0;
  881. pStem->pNext = pCur->pDone;
  882. pCur->pDone = pStem;
  883. if( fuzzerLowestCostStem(pCur) ){
  884. rc = fuzzerSeen(pCur, pCur->pStem);
  885. if( rc<0 ) return SQLITE_NOMEM;
  886. if( rc==0 ){
  887. return SQLITE_OK;
  888. }
  889. }
  890. }
  891. /* Reach this point only if queue has been exhausted and there is
  892. ** nothing left to be output. */
  893. pCur->rLimit = (fuzzer_cost)0;
  894. return SQLITE_OK;
  895. }
  896. /*
  897. ** Called to "rewind" a cursor back to the beginning so that
  898. ** it starts its output over again. Always called at least once
  899. ** prior to any fuzzerColumn, fuzzerRowid, or fuzzerEof call.
  900. */
  901. static int fuzzerFilter(
  902. sqlite3_vtab_cursor *pVtabCursor,
  903. int idxNum, const char *idxStr,
  904. int argc, sqlite3_value **argv
  905. ){
  906. fuzzer_cursor *pCur = (fuzzer_cursor *)pVtabCursor;
  907. const char *zWord = "";
  908. fuzzer_stem *pStem;
  909. int idx;
  910. fuzzerClearCursor(pCur, 1);
  911. pCur->rLimit = 2147483647;
  912. idx = 0;
  913. if( idxNum & 1 ){
  914. zWord = (const char*)sqlite3_value_text(argv[0]);
  915. idx++;
  916. }
  917. if( idxNum & 2 ){
  918. pCur->rLimit = (fuzzer_cost)sqlite3_value_int(argv[idx]);
  919. idx++;
  920. }
  921. if( idxNum & 4 ){
  922. pCur->iRuleset = (fuzzer_cost)sqlite3_value_int(argv[idx]);
  923. idx++;
  924. }
  925. pCur->nullRule.pNext = pCur->pVtab->pRule;
  926. pCur->nullRule.rCost = 0;
  927. pCur->nullRule.nFrom = 0;
  928. pCur->nullRule.nTo = 0;
  929. pCur->nullRule.zFrom = "";
  930. pCur->iRowid = 1;
  931. assert( pCur->pStem==0 );
  932. /* If the query term is longer than FUZZER_MX_OUTPUT_LENGTH bytes, this
  933. ** query will return zero rows. */
  934. if( (int)strlen(zWord)<FUZZER_MX_OUTPUT_LENGTH ){
  935. pCur->pStem = pStem = fuzzerNewStem(pCur, zWord, (fuzzer_cost)0);
  936. if( pStem==0 ) return SQLITE_NOMEM;
  937. pStem->pRule = &pCur->nullRule;
  938. pStem->n = pStem->nBasis;
  939. }else{
  940. pCur->rLimit = 0;
  941. }
  942. return SQLITE_OK;
  943. }
  944. /*
  945. ** Only the word and distance columns have values. All other columns
  946. ** return NULL
  947. */
  948. static int fuzzerColumn(sqlite3_vtab_cursor *cur, sqlite3_context *ctx, int i){
  949. fuzzer_cursor *pCur = (fuzzer_cursor*)cur;
  950. if( i==0 ){
  951. /* the "word" column */
  952. if( fuzzerRender(pCur->pStem, &pCur->zBuf, &pCur->nBuf)==SQLITE_NOMEM ){
  953. return SQLITE_NOMEM;
  954. }
  955. sqlite3_result_text(ctx, pCur->zBuf, -1, SQLITE_TRANSIENT);
  956. }else if( i==1 ){
  957. /* the "distance" column */
  958. sqlite3_result_int(ctx, pCur->pStem->rCostX);
  959. }else{
  960. /* All other columns are NULL */
  961. sqlite3_result_null(ctx);
  962. }
  963. return SQLITE_OK;
  964. }
  965. /*
  966. ** The rowid.
  967. */
  968. static int fuzzerRowid(sqlite3_vtab_cursor *cur, sqlite_int64 *pRowid){
  969. fuzzer_cursor *pCur = (fuzzer_cursor*)cur;
  970. *pRowid = pCur->iRowid;
  971. return SQLITE_OK;
  972. }
  973. /*
  974. ** When the fuzzer_cursor.rLimit value is 0 or less, that is a signal
  975. ** that the cursor has nothing more to output.
  976. */
  977. static int fuzzerEof(sqlite3_vtab_cursor *cur){
  978. fuzzer_cursor *pCur = (fuzzer_cursor*)cur;
  979. return pCur->rLimit<=(fuzzer_cost)0;
  980. }
  981. /*
  982. ** Search for terms of these forms:
  983. **
  984. ** (A) word MATCH $str
  985. ** (B1) distance < $value
  986. ** (B2) distance <= $value
  987. ** (C) ruleid == $ruleid
  988. **
  989. ** The distance< and distance<= are both treated as distance<=.
  990. ** The query plan number is a bit vector:
  991. **
  992. ** bit 1: Term of the form (A) found
  993. ** bit 2: Term like (B1) or (B2) found
  994. ** bit 3: Term like (C) found
  995. **
  996. ** If bit-1 is set, $str is always in filter.argv[0]. If bit-2 is set
  997. ** then $value is in filter.argv[0] if bit-1 is clear and is in
  998. ** filter.argv[1] if bit-1 is set. If bit-3 is set, then $ruleid is
  999. ** in filter.argv[0] if bit-1 and bit-2 are both zero, is in
  1000. ** filter.argv[1] if exactly one of bit-1 and bit-2 are set, and is in
  1001. ** filter.argv[2] if both bit-1 and bit-2 are set.
  1002. */
  1003. static int fuzzerBestIndex(sqlite3_vtab *tab, sqlite3_index_info *pIdxInfo){
  1004. int iPlan = 0;
  1005. int iDistTerm = -1;
  1006. int iRulesetTerm = -1;
  1007. int i;
  1008. int seenMatch = 0;
  1009. const struct sqlite3_index_constraint *pConstraint;
  1010. double rCost = 1e12;
  1011. pConstraint = pIdxInfo->aConstraint;
  1012. for(i=0; i<pIdxInfo->nConstraint; i++, pConstraint++){
  1013. if( pConstraint->iColumn==0
  1014. && pConstraint->op==SQLITE_INDEX_CONSTRAINT_MATCH ){
  1015. seenMatch = 1;
  1016. }
  1017. if( pConstraint->usable==0 ) continue;
  1018. if( (iPlan & 1)==0
  1019. && pConstraint->iColumn==0
  1020. && pConstraint->op==SQLITE_INDEX_CONSTRAINT_MATCH
  1021. ){
  1022. iPlan |= 1;
  1023. pIdxInfo->aConstraintUsage[i].argvIndex = 1;
  1024. pIdxInfo->aConstraintUsage[i].omit = 1;
  1025. rCost /= 1e6;
  1026. }
  1027. if( (iPlan & 2)==0
  1028. && pConstraint->iColumn==1
  1029. && (pConstraint->op==SQLITE_INDEX_CONSTRAINT_LT
  1030. || pConstraint->op==SQLITE_INDEX_CONSTRAINT_LE)
  1031. ){
  1032. iPlan |= 2;
  1033. iDistTerm = i;
  1034. rCost /= 10.0;
  1035. }
  1036. if( (iPlan & 4)==0
  1037. && pConstraint->iColumn==2
  1038. && pConstraint->op==SQLITE_INDEX_CONSTRAINT_EQ
  1039. ){
  1040. iPlan |= 4;
  1041. pIdxInfo->aConstraintUsage[i].omit = 1;
  1042. iRulesetTerm = i;
  1043. rCost /= 10.0;
  1044. }
  1045. }
  1046. if( iPlan & 2 ){
  1047. pIdxInfo->aConstraintUsage[iDistTerm].argvIndex = 1+((iPlan&1)!=0);
  1048. }
  1049. if( iPlan & 4 ){
  1050. int idx = 1;
  1051. if( iPlan & 1 ) idx++;
  1052. if( iPlan & 2 ) idx++;
  1053. pIdxInfo->aConstraintUsage[iRulesetTerm].argvIndex = idx;
  1054. }
  1055. pIdxInfo->idxNum = iPlan;
  1056. if( pIdxInfo->nOrderBy==1
  1057. && pIdxInfo->aOrderBy[0].iColumn==1
  1058. && pIdxInfo->aOrderBy[0].desc==0
  1059. ){
  1060. pIdxInfo->orderByConsumed = 1;
  1061. }
  1062. if( seenMatch && (iPlan&1)==0 ) rCost = 1e99;
  1063. pIdxInfo->estimatedCost = rCost;
  1064. return SQLITE_OK;
  1065. }
  1066. /*
  1067. ** A virtual table module that implements the "fuzzer".
  1068. */
  1069. static sqlite3_module fuzzerModule = {
  1070. 0, /* iVersion */
  1071. fuzzerConnect,
  1072. fuzzerConnect,
  1073. fuzzerBestIndex,
  1074. fuzzerDisconnect,
  1075. fuzzerDisconnect,
  1076. fuzzerOpen, /* xOpen - open a cursor */
  1077. fuzzerClose, /* xClose - close a cursor */
  1078. fuzzerFilter, /* xFilter - configure scan constraints */
  1079. fuzzerNext, /* xNext - advance a cursor */
  1080. fuzzerEof, /* xEof - check for end of scan */
  1081. fuzzerColumn, /* xColumn - read data */
  1082. fuzzerRowid, /* xRowid - read data */
  1083. 0, /* xUpdate */
  1084. 0, /* xBegin */
  1085. 0, /* xSync */
  1086. 0, /* xCommit */
  1087. 0, /* xRollback */
  1088. 0, /* xFindMethod */
  1089. 0, /* xRename */
  1090. 0, /* xSavepoint */
  1091. 0, /* xRelease */
  1092. 0, /* xRollbackTo */
  1093. 0, /* xShadowName */
  1094. 0 /* xIntegrity */
  1095. };
  1096. #endif /* SQLITE_OMIT_VIRTUALTABLE */
  1097. #ifdef _WIN32
  1098. __declspec(dllexport)
  1099. #endif
  1100. int sqlite3_fuzzer_init(
  1101. sqlite3 *db,
  1102. char **pzErrMsg,
  1103. const sqlite3_api_routines *pApi
  1104. ){
  1105. int rc = SQLITE_OK;
  1106. SQLITE_EXTENSION_INIT2(pApi);
  1107. #ifndef SQLITE_OMIT_VIRTUALTABLE
  1108. rc = sqlite3_create_module(db, "fuzzer", &fuzzerModule, 0);
  1109. #endif
  1110. return rc;
  1111. }