/ Check-in [135ce30f]
Login

Many hyperlinks are disabled.
Use anonymous login to enable hyperlinks.

Overview
Comment:Merge recent trunk changes into fts3-prefix-search branch.
Downloads: Tarball | ZIP archive | SQL archive
Timelines: family | ancestors | descendants | both | fts3-prefix-search
Files: files | file ages | folders
SHA1: 135ce30f62ebd6a1b239c18dbbd9c926ea507db4
User & Date: dan 2011-06-14 07:22:30
Context
2011-06-14
09:00
Fix another bug caused by NEAR/matchinfo/order=DESC interaction. check-in: 04907fba user: dan tags: fts3-prefix-search
07:22
Merge recent trunk changes into fts3-prefix-search branch. check-in: 135ce30f user: dan tags: fts3-prefix-search
07:14
Remove unused parameters from internal fts3 function. check-in: 06de3f2c user: dan tags: fts3-prefix-search
2011-06-13
12:19
Use only unsigned values in the implementatin of LIKE and GLOB so that values won't overflow to negative when dealing with malformed UTF8. check-in: 77f01578 user: drh tags: trunk
Changes
Hide Diffs Side-by-Side Diffs Ignore Whitespace Patch

Changes to ext/fts3/fts3.c.

  4110   4110         pCsr->isMatchinfoNeeded = 1;
  4111   4111         pCsr->iPrevId = pExpr->iDocid;
  4112   4112       }while( pCsr->isEof==0 && fts3EvalLoadDeferred(pCsr, &rc) );
  4113   4113     }
  4114   4114     return rc;
  4115   4115   }
  4116   4116   
         4117  +/*
         4118  +** Restart interation for expression pExpr so that the next call to
         4119  +** sqlite3Fts3EvalNext() visits the first row. Do not allow incremental 
         4120  +** loading or merging of phrase doclists for this iteration.
         4121  +**
         4122  +** If *pRc is other than SQLITE_OK when this function is called, it is
         4123  +** a no-op. If an error occurs within this function, *pRc is set to an
         4124  +** SQLite error code before returning.
         4125  +*/
  4117   4126   static void fts3EvalRestart(
  4118   4127     Fts3Cursor *pCsr,
  4119   4128     Fts3Expr *pExpr,
  4120   4129     int *pRc
  4121   4130   ){
  4122   4131     if( pExpr && *pRc==SQLITE_OK ){
  4123   4132       Fts3Phrase *pPhrase = pExpr->pPhrase;

Changes to src/fkey.c.

   382    382         for(i=0; i<nCol; i++){
   383    383           sqlite3VdbeAddOp2(v, OP_Copy, aiCol[i]+1+regData, regTemp+i);
   384    384         }
   385    385     
   386    386         /* If the parent table is the same as the child table, and we are about
   387    387         ** to increment the constraint-counter (i.e. this is an INSERT operation),
   388    388         ** then check if the row being inserted matches itself. If so, do not
   389         -      ** increment the constraint-counter.  */
          389  +      ** increment the constraint-counter. 
          390  +      **
          391  +      ** If any of the parent-key values are NULL, then the row cannot match 
          392  +      ** itself. So set JUMPIFNULL to make sure we do the OP_Found if any
          393  +      ** of the parent-key values are NULL (at this point it is known that
          394  +      ** none of the child key values are).
          395  +      */
   390    396         if( pTab==pFKey->pFrom && nIncr==1 ){
   391    397           int iJump = sqlite3VdbeCurrentAddr(v) + nCol + 1;
   392    398           for(i=0; i<nCol; i++){
   393    399             int iChild = aiCol[i]+1+regData;
   394    400             int iParent = pIdx->aiColumn[i]+1+regData;
          401  +          assert( aiCol[i]!=pTab->iPKey );
          402  +          if( pIdx->aiColumn[i]==pTab->iPKey ){
          403  +            /* The parent key is a composite key that includes the IPK column */
          404  +            iParent = regData;
          405  +          }
   395    406             sqlite3VdbeAddOp3(v, OP_Ne, iChild, iJump, iParent);
          407  +          sqlite3VdbeChangeP5(v, SQLITE_JUMPIFNULL);
   396    408           }
   397    409           sqlite3VdbeAddOp2(v, OP_Goto, 0, iOk);
   398    410         }
   399    411     
   400    412         sqlite3VdbeAddOp3(v, OP_MakeRecord, regTemp, nCol, regRec);
   401    413         sqlite3VdbeChangeP4(v, -1, sqlite3IndexAffinityStr(v,pIdx), P4_TRANSIENT);
   402    414         sqlite3VdbeAddOp4Int(v, OP_Found, iCur, iOk, regRec, 0);

Changes to src/func.c.

   502    502   /*
   503    503   ** For LIKE and GLOB matching on EBCDIC machines, assume that every
   504    504   ** character is exactly one byte in size.  Also, all characters are
   505    505   ** able to participate in upper-case-to-lower-case mappings in EBCDIC
   506    506   ** whereas only characters less than 0x80 do in ASCII.
   507    507   */
   508    508   #if defined(SQLITE_EBCDIC)
   509         -# define sqlite3Utf8Read(A,C)    (*(A++))
   510         -# define GlogUpperToLower(A)     A = sqlite3UpperToLower[A]
          509  +# define sqlite3Utf8Read(A,C)  (*(A++))
          510  +# define GlogUpperToLower(A)   A = sqlite3UpperToLower[A]
   511    511   #else
   512         -# define GlogUpperToLower(A)     if( A<0x80 ){ A = sqlite3UpperToLower[A]; }
          512  +# define GlogUpperToLower(A)   if( !((A)&~0x7f) ){ A = sqlite3UpperToLower[A]; }
   513    513   #endif
   514    514   
   515    515   static const struct compareInfo globInfo = { '*', '?', '[', 0 };
   516    516   /* The correct SQL-92 behavior is for the LIKE operator to ignore
   517    517   ** case.  Thus  'a' LIKE 'A' would be true. */
   518    518   static const struct compareInfo likeInfoNorm = { '%', '_',   0, 1 };
   519    519   /* If SQLITE_CASE_SENSITIVE_LIKE is defined, then the LIKE operator
................................................................................
   548    548   **
   549    549   **         abc[*]xyz        Matches "abc*xyz" only
   550    550   */
   551    551   static int patternCompare(
   552    552     const u8 *zPattern,              /* The glob pattern */
   553    553     const u8 *zString,               /* The string to compare against the glob */
   554    554     const struct compareInfo *pInfo, /* Information about how to do the compare */
   555         -  const int esc                    /* The escape character */
          555  +  u32 esc                          /* The escape character */
   556    556   ){
   557         -  int c, c2;
          557  +  u32 c, c2;
   558    558     int invert;
   559    559     int seen;
   560    560     u8 matchOne = pInfo->matchOne;
   561    561     u8 matchAll = pInfo->matchAll;
   562    562     u8 matchSet = pInfo->matchSet;
   563    563     u8 noCase = pInfo->noCase; 
   564    564     int prevEscape = 0;     /* True if the previous character was 'escape' */
................................................................................
   680    680   */
   681    681   static void likeFunc(
   682    682     sqlite3_context *context, 
   683    683     int argc, 
   684    684     sqlite3_value **argv
   685    685   ){
   686    686     const unsigned char *zA, *zB;
   687         -  int escape = 0;
          687  +  u32 escape = 0;
   688    688     int nPat;
   689    689     sqlite3 *db = sqlite3_context_db_handle(context);
   690    690   
   691    691     zB = sqlite3_value_text(argv[0]);
   692    692     zA = sqlite3_value_text(argv[1]);
   693    693   
   694    694     /* Limit the length of the LIKE or GLOB pattern to avoid problems

Changes to src/pcache1.c.

   570    570     pCache = (PCache1 *)sqlite3_malloc(sz);
   571    571     if( pCache ){
   572    572       memset(pCache, 0, sz);
   573    573       if( separateCache ){
   574    574         pGroup = (PGroup*)&pCache[1];
   575    575         pGroup->mxPinned = 10;
   576    576       }else{
   577         -      pGroup = &pcache1_g.grp;
          577  +      pGroup = &pcache1.grp;
   578    578       }
   579    579       pCache->pGroup = pGroup;
   580    580       pCache->szPage = szPage;
   581    581       pCache->bPurgeable = (bPurgeable ? 1 : 0);
   582    582       if( bPurgeable ){
   583    583         pCache->nMin = 10;
   584    584         pcache1EnterMutex(pGroup);

Changes to src/sqliteInt.h.

   678    678   ** Schema objects are automatically deallocated when the last Btree that
   679    679   ** references them is destroyed.   The TEMP Schema is manually freed by
   680    680   ** sqlite3_close().
   681    681   *
   682    682   ** A thread must be holding a mutex on the corresponding Btree in order
   683    683   ** to access Schema content.  This implies that the thread must also be
   684    684   ** holding a mutex on the sqlite3 connection pointer that owns the Btree.
   685         -** For a TEMP Schema, on the connection mutex is required.
          685  +** For a TEMP Schema, only the connection mutex is required.
   686    686   */
   687    687   struct Schema {
   688    688     int schema_cookie;   /* Database schema version number for this file */
   689    689     int iGeneration;     /* Generation counter.  Incremented with each change */
   690    690     Hash tblHash;        /* All tables indexed by name */
   691    691     Hash idxHash;        /* All (named) indices indexed by name */
   692    692     Hash trigHash;       /* All triggers indexed by name */
................................................................................
  2875   2875   int sqlite3FixExprList(DbFixer*, ExprList*);
  2876   2876   int sqlite3FixTriggerStep(DbFixer*, TriggerStep*);
  2877   2877   int sqlite3AtoF(const char *z, double*, int, u8);
  2878   2878   int sqlite3GetInt32(const char *, int*);
  2879   2879   int sqlite3Atoi(const char*);
  2880   2880   int sqlite3Utf16ByteLen(const void *pData, int nChar);
  2881   2881   int sqlite3Utf8CharLen(const char *pData, int nByte);
  2882         -int sqlite3Utf8Read(const u8*, const u8**);
         2882  +u32 sqlite3Utf8Read(const u8*, const u8**);
  2883   2883   
  2884   2884   /*
  2885   2885   ** Routines to read and write variable-length integers.  These used to
  2886   2886   ** be defined locally, but now we use the varint routines in the util.c
  2887   2887   ** file.  Code should use the MACRO forms below, as the Varint32 versions
  2888   2888   ** are coded to assume the single byte case is already handled (which 
  2889   2889   ** the MACRO form does).

Changes to src/update.c.

   240    240     for(nIdx=0, pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext, nIdx++){}
   241    241     if( nIdx>0 ){
   242    242       aRegIdx = sqlite3DbMallocRaw(db, sizeof(Index*) * nIdx );
   243    243       if( aRegIdx==0 ) goto update_cleanup;
   244    244     }
   245    245     for(j=0, pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext, j++){
   246    246       int reg;
   247         -    if( chngRowid ){
          247  +    if( hasFK || chngRowid ){
   248    248         reg = ++pParse->nMem;
   249    249       }else{
   250    250         reg = 0;
   251    251         for(i=0; i<pIdx->nColumn; i++){
   252    252           if( aXRef[pIdx->aiColumn[i]]>=0 ){
   253    253             reg = ++pParse->nMem;
   254    254             break;

Changes to src/utf.c.

   159    159       while( zIn!=zTerm && (*zIn & 0xc0)==0x80 ){            \
   160    160         c = (c<<6) + (0x3f & *(zIn++));                      \
   161    161       }                                                      \
   162    162       if( c<0x80                                             \
   163    163           || (c&0xFFFFF800)==0xD800                          \
   164    164           || (c&0xFFFFFFFE)==0xFFFE ){  c = 0xFFFD; }        \
   165    165     }
   166         -int sqlite3Utf8Read(
          166  +u32 sqlite3Utf8Read(
   167    167     const unsigned char *zIn,       /* First byte of UTF-8 character */
   168    168     const unsigned char **pzNext    /* Write first byte past UTF-8 char here */
   169    169   ){
   170    170     unsigned int c;
   171    171   
   172    172     /* Same as READ_UTF8() above but without the zTerm parameter.
   173    173     ** For this routine, we assume the UTF8 string is always zero-terminated.

Changes to test/fkey3.test.

    16     16   set testdir [file dirname $argv0]
    17     17   source $testdir/tester.tcl
    18     18   
    19     19   ifcapable {!foreignkey||!trigger} {
    20     20     finish_test
    21     21     return
    22     22   }
           23  +
           24  +set testprefix fkey3
    23     25   
    24     26   # Create a table and some data to work with.
    25     27   #
    26     28   do_test fkey3-1.1 {
    27     29     execsql {
    28     30       PRAGMA foreign_keys=ON;
    29     31       CREATE TABLE t1(x INTEGER PRIMARY KEY);
................................................................................
    73     75       INSERT INTO t2 VALUES(100);
    74     76       INSERT INTO t2 VALUES(101);
    75     77       SELECT 1, x FROM t1;
    76     78       SELECT 2, y FROM t2;
    77     79     }
    78     80   } {1 100 1 101 2 100 2 101}
    79     81   
           82  +
           83  +#-------------------------------------------------------------------------
           84  +# The following tests - fkey-3.* - test some edge cases to do with 
           85  +# inserting rows into tables that have foreign keys where the parent
           86  +# table is the same as the child table. Especially cases where the
           87  +# new row being inserted matches itself.
           88  +#
           89  +do_execsql_test 3.1.1 {
           90  +  CREATE TABLE t3(a, b, c, d, 
           91  +    UNIQUE(a, b),
           92  +    FOREIGN KEY(c, d) REFERENCES t3(a, b)
           93  +  );
           94  +  INSERT INTO t3 VALUES(1, 2, 1, 2);
           95  +} {}
           96  +do_catchsql_test 3.1.2 {
           97  +  INSERT INTO t3 VALUES(NULL, 2, 5, 2);
           98  +} {1 {foreign key constraint failed}}
           99  +do_catchsql_test 3.1.3 {
          100  +  INSERT INTO t3 VALUES(NULL, 3, 5, 2);
          101  +} {1 {foreign key constraint failed}}
          102  +
          103  +do_execsql_test 3.2.1 {
          104  +  CREATE TABLE t4(a UNIQUE, b REFERENCES t4(a));
          105  +}
          106  +do_catchsql_test 3.2.2 {
          107  +  INSERT INTO t4 VALUES(NULL, 1);
          108  +} {1 {foreign key constraint failed}}
          109  +
          110  +do_execsql_test 3.3.1 {
          111  +  CREATE TABLE t5(a INTEGER PRIMARY KEY, b REFERENCES t5(a));
          112  +  INSERT INTO t5 VALUES(NULL, 1);
          113  +} {}
          114  +do_catchsql_test 3.3.2 {
          115  +  INSERT INTO t5 VALUES(NULL, 3);
          116  +} {1 {foreign key constraint failed}}
          117  +
          118  +do_execsql_test 3.4.1 {
          119  +  CREATE TABLE t6(a INTEGER PRIMARY KEY, b, c, d,
          120  +    FOREIGN KEY(c, d) REFERENCES t6(a, b)
          121  +  );
          122  +  CREATE UNIQUE INDEX t6i ON t6(b, a);
          123  +}
          124  +do_execsql_test 3.4.2  { INSERT INTO t6 VALUES(NULL, 'a', 1, 'a'); } {}
          125  +do_execsql_test 3.4.3  { INSERT INTO t6 VALUES(2, 'a', 2, 'a');    } {}
          126  +do_execsql_test 3.4.4  { INSERT INTO t6 VALUES(NULL, 'a', 1, 'a'); } {}
          127  +do_execsql_test 3.4.5  { INSERT INTO t6 VALUES(5, 'a', 2, 'a'); } {}
          128  +do_catchsql_test 3.4.6 { 
          129  +  INSERT INTO t6 VALUES(NULL, 'a', 65, 'a');    
          130  +} {1 {foreign key constraint failed}}
          131  +
          132  +do_execsql_test 3.4.7 {
          133  +  INSERT INTO t6 VALUES(100, 'one', 100, 'one');
          134  +  DELETE FROM t6 WHERE a = 100;
          135  +}
          136  +do_execsql_test 3.4.8 {
          137  +  INSERT INTO t6 VALUES(100, 'one', 100, 'one');
          138  +  UPDATE t6 SET c = 1, d = 'a' WHERE a = 100;
          139  +  DELETE FROM t6 WHERE a = 100;
          140  +}
          141  +
          142  +do_execsql_test 3.5.1 {
          143  +  CREATE TABLE t7(a, b, c, d INTEGER PRIMARY KEY,
          144  +    FOREIGN KEY(c, d) REFERENCES t7(a, b)
          145  +  );
          146  +  CREATE UNIQUE INDEX t7i ON t7(a, b);
          147  +}
          148  +do_execsql_test 3.5.2  { INSERT INTO t7 VALUES('x', 1, 'x', NULL) } {}
          149  +do_execsql_test 3.5.3  { INSERT INTO t7 VALUES('x', 2, 'x', 2) } {}
          150  +do_catchsql_test 3.5.4  { 
          151  +  INSERT INTO t7 VALUES('x', 450, 'x', NULL);
          152  +} {1 {foreign key constraint failed}}
          153  +do_catchsql_test 3.5.5  { 
          154  +  INSERT INTO t7 VALUES('x', 450, 'x', 451);
          155  +} {1 {foreign key constraint failed}}
          156  +
          157  +
          158  +do_execsql_test 3.6.1 {
          159  +  CREATE TABLE t8(a, b, c, d, e, FOREIGN KEY(c, d) REFERENCES t8(a, b));
          160  +  CREATE UNIQUE INDEX t8i1 ON t8(a, b);
          161  +  CREATE UNIQUE INDEX t8i2 ON t8(c);
          162  +  INSERT INTO t8 VALUES(1, 1, 1, 1, 1);
          163  +}
          164  +do_catchsql_test 3.6.2 { 
          165  +  UPDATE t8 SET d = 2; 
          166  +} {1 {foreign key constraint failed}}
          167  +do_execsql_test 3.6.3 { UPDATE t8 SET d = 1; }
          168  +do_execsql_test 3.6.4 { UPDATE t8 SET e = 2; }
          169  +
          170  +do_catchsql_test 3.6.5 {
          171  +  CREATE TABLE TestTable (
          172  +    id INTEGER PRIMARY KEY,
          173  +    name text,
          174  +    source_id integer not null,
          175  +    parent_id integer,
          176  +
          177  +    foreign key(source_id, parent_id) references TestTable(source_id, id)
          178  +  );
          179  +  CREATE UNIQUE INDEX testindex on TestTable(source_id, id);
          180  +  PRAGMA foreign_keys=1;
          181  +  INSERT INTO TestTable VALUES (1, 'parent', 1, null);
          182  +  INSERT INTO TestTable VALUES (2, 'child', 1, 1);
          183  +  UPDATE TestTable SET parent_id=1000 where id=2;
          184  +} {1 {foreign key constraint failed}}
          185  +
    80    186   finish_test