/ Check-in [82152027]
Login

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

Overview
Comment:Merge recent trunk changes into the threads branch.
Downloads: Tarball | ZIP archive | SQL archive
Timelines: family | ancestors | descendants | both | threads
Files: files | file ages | folders
SHA1:8215202759dbd863edf20aa26ff21da20bc35d73
User & Date: drh 2014-05-26 20:15:21
Context
2014-05-29
20:24
Merge changes from the trunk into the threads branch. check-in: 416cb091 user: drh tags: threads
2014-05-26
20:15
Merge recent trunk changes into the threads branch. check-in: 82152027 user: drh tags: threads
18:27
Fix a problem in the shell when importing CSV files. If the leftmost field of the first row in the CSV file was both zero bytes in size and unquoted, no data was imported. check-in: 856d44a2 user: dan tags: trunk
2014-05-20
19:11
Improvements to the testability of the threads.c module. check-in: 386e0888 user: drh tags: threads
Changes
Hide Diffs Side-by-Side Diffs Ignore Whitespace Patch

Changes to ext/fts3/fts3.c.

  1372   1372     }
  1373   1373   
  1374   1374     /* Fill in the abNotindexed array */
  1375   1375     for(iCol=0; iCol<nCol; iCol++){
  1376   1376       int n = (int)strlen(p->azColumn[iCol]);
  1377   1377       for(i=0; i<nNotindexed; i++){
  1378   1378         char *zNot = azNotindexed[i];
  1379         -      if( zNot && 0==sqlite3_strnicmp(p->azColumn[iCol], zNot, n) ){
         1379  +      if( zNot && strlen(zNot)==n 
         1380  +       && 0==sqlite3_strnicmp(p->azColumn[iCol], zNot, n) 
         1381  +      ){
  1380   1382           p->abNotindexed[iCol] = 1;
  1381   1383           sqlite3_free(zNot);
  1382   1384           azNotindexed[i] = 0;
  1383   1385         }
  1384   1386       }
  1385   1387     }
  1386   1388     for(i=0; i<nNotindexed; i++){

Changes to src/btree.c.

  8525   8525   ** set the mask of hint flags for cursor pCsr. Currently the only valid
  8526   8526   ** values are 0 and BTREE_BULKLOAD.
  8527   8527   */
  8528   8528   void sqlite3BtreeCursorHints(BtCursor *pCsr, unsigned int mask){
  8529   8529     assert( mask==BTREE_BULKLOAD || mask==0 );
  8530   8530     pCsr->hints = mask;
  8531   8531   }
         8532  +
         8533  +/*
         8534  +** Return true if the given Btree is read-only.
         8535  +*/
         8536  +int sqlite3BtreeIsReadonly(Btree *p){
         8537  +  return (p->pBt->btsFlags & BTS_READ_ONLY)!=0;
         8538  +}

Changes to src/btree.h.

   190    190   struct Pager *sqlite3BtreePager(Btree*);
   191    191   
   192    192   int sqlite3BtreePutData(BtCursor*, u32 offset, u32 amt, void*);
   193    193   void sqlite3BtreeIncrblobCursor(BtCursor *);
   194    194   void sqlite3BtreeClearCursor(BtCursor *);
   195    195   int sqlite3BtreeSetVersion(Btree *pBt, int iVersion);
   196    196   void sqlite3BtreeCursorHints(BtCursor *, unsigned int mask);
          197  +int sqlite3BtreeIsReadonly(Btree *pBt);
   197    198   
   198    199   #ifndef NDEBUG
   199    200   int sqlite3BtreeCursorIsValid(BtCursor*);
   200    201   #endif
   201    202   
   202    203   #ifndef SQLITE_OMIT_BTREECOUNT
   203    204   int sqlite3BtreeCount(BtCursor *, i64 *);

Changes to src/build.c.

  1302   1302   */
  1303   1303   void sqlite3AddCheckConstraint(
  1304   1304     Parse *pParse,    /* Parsing context */
  1305   1305     Expr *pCheckExpr  /* The check expression */
  1306   1306   ){
  1307   1307   #ifndef SQLITE_OMIT_CHECK
  1308   1308     Table *pTab = pParse->pNewTable;
  1309         -  if( pTab && !IN_DECLARE_VTAB ){
         1309  +  sqlite3 *db = pParse->db;
         1310  +  if( pTab && !IN_DECLARE_VTAB
         1311  +   && !sqlite3BtreeIsReadonly(db->aDb[db->init.iDb].pBt)
         1312  +  ){
  1310   1313       pTab->pCheck = sqlite3ExprListAppend(pParse, pTab->pCheck, pCheckExpr);
  1311   1314       if( pParse->constraintName.n ){
  1312   1315         sqlite3ExprListSetName(pParse, pTab->pCheck, &pParse->constraintName, 1);
  1313   1316       }
  1314   1317     }else
  1315   1318   #endif
  1316   1319     {

Changes to src/insert.c.

   610    610             }
   611    611             break;
   612    612           }
   613    613         }
   614    614         if( j>=pTab->nCol ){
   615    615           if( sqlite3IsRowid(pColumn->a[i].zName) && !withoutRowid ){
   616    616             ipkColumn = i;
          617  +          bIdListInOrder = 0;
   617    618           }else{
   618    619             sqlite3ErrorMsg(pParse, "table %S has no column named %s",
   619    620                 pTabList, 0, pColumn->a[i].zName);
   620    621             pParse->checkSchema = 1;
   621    622             goto insert_cleanup;
   622    623           }
   623    624         }

Changes to src/main.c.

  3458   3458   
  3459   3459   /*
  3460   3460   ** Return 1 if database is read-only or 0 if read/write.  Return -1 if
  3461   3461   ** no such database exists.
  3462   3462   */
  3463   3463   int sqlite3_db_readonly(sqlite3 *db, const char *zDbName){
  3464   3464     Btree *pBt = sqlite3DbNameToBtree(db, zDbName);
  3465         -  return pBt ? sqlite3PagerIsreadonly(sqlite3BtreePager(pBt)) : -1;
         3465  +  return pBt ? sqlite3BtreeIsReadonly(pBt) : -1;
  3466   3466   }

Changes to src/select.c.

  4523   4523   #ifndef SQLITE_OMIT_EXPLAIN
  4524   4524   static void explainSimpleCount(
  4525   4525     Parse *pParse,                  /* Parse context */
  4526   4526     Table *pTab,                    /* Table being queried */
  4527   4527     Index *pIdx                     /* Index used to optimize scan, or NULL */
  4528   4528   ){
  4529   4529     if( pParse->explain==2 ){
         4530  +    int bCover = (pIdx!=0 && (HasRowid(pTab) || pIdx->autoIndex!=2));
  4530   4531       char *zEqp = sqlite3MPrintf(pParse->db, "SCAN TABLE %s%s%s",
  4531         -        pTab->zName, 
  4532         -        pIdx ? " USING COVERING INDEX " : "",
  4533         -        pIdx ? pIdx->zName : ""
         4532  +        pTab->zName,
         4533  +        bCover ? " USING COVERING INDEX " : "",
         4534  +        bCover ? pIdx->zName : ""
  4534   4535       );
  4535   4536       sqlite3VdbeAddOp4(
  4536   4537           pParse->pVdbe, OP_Explain, pParse->iSelectId, 0, 0, zEqp, P4_DYNAMIC
  4537   4538       );
  4538   4539     }
  4539   4540   }
  4540   4541   #else

Changes to src/shell.c.

   693    693   
   694    694   #ifdef SIGINT
   695    695   /*
   696    696   ** This routine runs when the user presses Ctrl-C
   697    697   */
   698    698   static void interrupt_handler(int NotUsed){
   699    699     UNUSED_PARAMETER(NotUsed);
   700         -  seenInterrupt = 1;
          700  +  seenInterrupt++;
          701  +  if( seenInterrupt>2 ) exit(1);
   701    702     if( db ) sqlite3_interrupt(db);
   702    703   }
   703    704   #endif
   704    705   
   705    706   /*
   706    707   ** This is the callback routine that the shell
   707    708   ** invokes for each row of a query result.
................................................................................
  2426   2427       if( zSql==0 ){
  2427   2428         fprintf(stderr, "Error: out of memory\n");
  2428   2429         xCloser(sCsv.in);
  2429   2430         return 1;
  2430   2431       }
  2431   2432       nByte = strlen30(zSql);
  2432   2433       rc = sqlite3_prepare_v2(p->db, zSql, -1, &pStmt, 0);
         2434  +    csv_append_char(&sCsv, 0);    /* To ensure sCsv.z is allocated */
  2433   2435       if( rc && sqlite3_strglob("no such table: *", sqlite3_errmsg(db))==0 ){
  2434   2436         char *zCreate = sqlite3_mprintf("CREATE TABLE %s", zTable);
  2435   2437         char cSep = '(';
  2436   2438         while( csv_read_one_field(&sCsv) ){
  2437   2439           zCreate = sqlite3_mprintf("%z%c\n  \"%s\" TEXT", zCreate, cSep, sCsv.z);
  2438   2440           cSep = ',';
  2439   2441           if( sCsv.cTerm!=sCsv.cSeparator ) break;

Changes to src/vdbe.c.

  3482   3482   ** to an SQL index, then P3 is the first in an array of P4 registers 
  3483   3483   ** that are used as an unpacked index key. 
  3484   3484   **
  3485   3485   ** Reposition cursor P1 so that  it points to the smallest entry that 
  3486   3486   ** is greater than or equal to the key value. If there are no records 
  3487   3487   ** greater than or equal to the key and P2 is not zero, then jump to P2.
  3488   3488   **
  3489         -** See also: Found, NotFound, Distinct, SeekLt, SeekGt, SeekLe
         3489  +** See also: Found, NotFound, SeekLt, SeekGt, SeekLe
  3490   3490   */
  3491   3491   /* Opcode: SeekGt P1 P2 P3 P4 *
  3492   3492   ** Synopsis: key=r[P3@P4]
  3493   3493   **
  3494   3494   ** If cursor P1 refers to an SQL table (B-Tree that uses integer keys), 
  3495   3495   ** use the value in register P3 as a key. If cursor P1 refers 
  3496   3496   ** to an SQL index, then P3 is the first in an array of P4 registers 
  3497   3497   ** that are used as an unpacked index key. 
  3498   3498   **
  3499   3499   ** Reposition cursor P1 so that  it points to the smallest entry that 
  3500   3500   ** is greater than the key value. If there are no records greater than 
  3501   3501   ** the key and P2 is not zero, then jump to P2.
  3502   3502   **
  3503         -** See also: Found, NotFound, Distinct, SeekLt, SeekGe, SeekLe
         3503  +** See also: Found, NotFound, SeekLt, SeekGe, SeekLe
  3504   3504   */
  3505   3505   /* Opcode: SeekLt P1 P2 P3 P4 * 
  3506   3506   ** Synopsis: key=r[P3@P4]
  3507   3507   **
  3508   3508   ** If cursor P1 refers to an SQL table (B-Tree that uses integer keys), 
  3509   3509   ** use the value in register P3 as a key. If cursor P1 refers 
  3510   3510   ** to an SQL index, then P3 is the first in an array of P4 registers 
  3511   3511   ** that are used as an unpacked index key. 
  3512   3512   **
  3513   3513   ** Reposition cursor P1 so that  it points to the largest entry that 
  3514   3514   ** is less than the key value. If there are no records less than 
  3515   3515   ** the key and P2 is not zero, then jump to P2.
  3516   3516   **
  3517         -** See also: Found, NotFound, Distinct, SeekGt, SeekGe, SeekLe
         3517  +** See also: Found, NotFound, SeekGt, SeekGe, SeekLe
  3518   3518   */
  3519   3519   /* Opcode: SeekLe P1 P2 P3 P4 *
  3520   3520   ** Synopsis: key=r[P3@P4]
  3521   3521   **
  3522   3522   ** If cursor P1 refers to an SQL table (B-Tree that uses integer keys), 
  3523   3523   ** use the value in register P3 as a key. If cursor P1 refers 
  3524   3524   ** to an SQL index, then P3 is the first in an array of P4 registers 
  3525   3525   ** that are used as an unpacked index key. 
  3526   3526   **
  3527   3527   ** Reposition cursor P1 so that it points to the largest entry that 
  3528   3528   ** is less than or equal to the key value. If there are no records 
  3529   3529   ** less than or equal to the key and P2 is not zero, then jump to P2.
  3530   3530   **
  3531         -** See also: Found, NotFound, Distinct, SeekGt, SeekGe, SeekLt
         3531  +** See also: Found, NotFound, SeekGt, SeekGe, SeekLt
  3532   3532   */
  3533   3533   case OP_SeekLT:         /* jump, in3 */
  3534   3534   case OP_SeekLE:         /* jump, in3 */
  3535   3535   case OP_SeekGE:         /* jump, in3 */
  3536   3536   case OP_SeekGT: {       /* jump, in3 */
  3537   3537     int res;
  3538   3538     int oc;

Changes to src/where.c.

  2714   2714   
  2715   2715       if( pItem->zAlias ){
  2716   2716         zMsg = sqlite3MAppendf(db, zMsg, "%s AS %s", zMsg, pItem->zAlias);
  2717   2717       }
  2718   2718       if( (flags & (WHERE_IPK|WHERE_VIRTUALTABLE))==0
  2719   2719        && ALWAYS(pLoop->u.btree.pIndex!=0)
  2720   2720       ){
         2721  +      const char *zFmt;
         2722  +      Index *pIdx = pLoop->u.btree.pIndex;
  2721   2723         char *zWhere = explainIndexRange(db, pLoop, pItem->pTab);
  2722         -      zMsg = sqlite3MAppendf(db, zMsg,
  2723         -               ((flags & WHERE_AUTO_INDEX) ? 
  2724         -                   "%s USING AUTOMATIC %sINDEX%.0s%s" :
  2725         -                   "%s USING %sINDEX %s%s"), 
  2726         -               zMsg, ((flags & WHERE_IDX_ONLY) ? "COVERING " : ""),
  2727         -               pLoop->u.btree.pIndex->zName, zWhere);
         2724  +      assert( !(flags&WHERE_AUTO_INDEX) || (flags&WHERE_IDX_ONLY) );
         2725  +      if( !HasRowid(pItem->pTab) && pIdx->autoIndex==2 ){
         2726  +        zFmt = zWhere ? "%s USING PRIMARY KEY%.0s%s" : "%s%.0s%s";
         2727  +      }else if( flags & WHERE_AUTO_INDEX ){
         2728  +        zFmt = "%s USING AUTOMATIC COVERING INDEX%.0s%s";
         2729  +      }else if( flags & WHERE_IDX_ONLY ){
         2730  +        zFmt = "%s USING COVERING INDEX %s%s";
         2731  +      }else{
         2732  +        zFmt = "%s USING INDEX %s%s";
         2733  +      }
         2734  +      zMsg = sqlite3MAppendf(db, zMsg, zFmt, zMsg, pIdx->zName, zWhere);
  2728   2735         sqlite3DbFree(db, zWhere);
  2729   2736       }else if( (flags & WHERE_IPK)!=0 && (flags & WHERE_CONSTRAINT)!=0 ){
  2730   2737         zMsg = sqlite3MAppendf(db, zMsg, "%s USING INTEGER PRIMARY KEY", zMsg);
  2731   2738   
  2732   2739         if( flags&(WHERE_COLUMN_EQ|WHERE_COLUMN_IN) ){
  2733   2740           zMsg = sqlite3MAppendf(db, zMsg, "%s (rowid=?)", zMsg);
  2734   2741         }else if( (flags&WHERE_BOTH_LIMIT)==WHERE_BOTH_LIMIT ){

Changes to test/eqp.test.

   593    593   det 7.4 "SELECT count(*) FROM t1" {
   594    594     0 0 0 {SCAN TABLE t1}
   595    595   }
   596    596   
   597    597   det 7.5 "SELECT count(*) FROM t2" {
   598    598     0 0 0 {SCAN TABLE t2 USING COVERING INDEX i1}
   599    599   }
          600  +
          601  +#-------------------------------------------------------------------------
          602  +# The following tests - eqp-8.* - test that queries that use the OP_Count
          603  +# optimization return something sensible with EQP.
          604  +#
          605  +drop_all_tables
          606  +
          607  +do_execsql_test 8.0 {
          608  +  CREATE TABLE t1(a, b, c, PRIMARY KEY(b, c)) WITHOUT ROWID;
          609  +  CREATE TABLE t2(a, b, c);
          610  +}
          611  +
          612  +det 8.1.1 "SELECT * FROM t2" {
          613  +  0 0 0 {SCAN TABLE t2}
          614  +}
          615  +
          616  +det 8.1.2 "SELECT * FROM t2 WHERE rowid=?" {
          617  +  0 0 0 {SEARCH TABLE t2 USING INTEGER PRIMARY KEY (rowid=?)}
          618  +}
          619  +
          620  +det 8.1.3 "SELECT count(*) FROM t2" {
          621  +  0 0 0 {SCAN TABLE t2}
          622  +}
          623  +
          624  +det 8.2.1 "SELECT * FROM t1" {
          625  +  0 0 0 {SCAN TABLE t1}
          626  +}
          627  +
          628  +det 8.2.2 "SELECT * FROM t1 WHERE b=?" {
          629  +  0 0 0 {SEARCH TABLE t1 USING PRIMARY KEY (b=?)}
          630  +}
          631  +
          632  +det 8.2.3 "SELECT * FROM t1 WHERE b=? AND c=?" {
          633  +  0 0 0 {SEARCH TABLE t1 USING PRIMARY KEY (b=? AND c=?)}
          634  +}
          635  +
          636  +det 8.2.4 "SELECT count(*) FROM t1" {
          637  +  0 0 0 {SCAN TABLE t1}
          638  +}
          639  +
          640  +
          641  +
          642  +
          643  +
   600    644   
   601    645   
   602    646   finish_test

Changes to test/fts4noti.test.

   160    160     INSERT INTO t2 VALUES('b', 'c', 'a');
   161    161   }
   162    162   do_execsql_test 5.2 { SELECT docid FROM t2 WHERE t2 MATCH 'a' } {2}
   163    163   do_execsql_test 5.3 { SELECT docid FROM t2 WHERE t2 MATCH 'b' } {1}
   164    164   do_execsql_test 5.4 { SELECT docid FROM t2 WHERE t2 MATCH 'c' } {3}
   165    165   
   166    166   do_execsql_test 5.x { DROP TABLE t2 }
          167  +
          168  +#-------------------------------------------------------------------------
          169  +# Check that if an indexed column name is a prefix of a notindexed column
          170  +# name, the column is still correctly tokenized. This was a problem at one
          171  +# point.
          172  +do_execsql_test 6.1.1 {
          173  +  CREATE VIRTUAL TABLE t1 USING fts4(
          174  +    poiCategory, poiCategoryId, notindexed=poiCategoryId
          175  +  );
          176  +  INSERT INTO t1(poiCategory, poiCategoryId) values ("Restaurant", 6021);
          177  +}
          178  +
          179  +do_execsql_test 6.1.2 {
          180  +  SELECT * FROM t1 WHERE t1 MATCH 'restaurant';
          181  +} { Restaurant 6021 }
          182  +do_execsql_test 6.1.3 {
          183  +  SELECT * FROM t1 WHERE t1 MATCH 're*';
          184  +} { Restaurant 6021 }
          185  +do_execsql_test 6.1.4 {
          186  +  SELECT * FROM t1 WHERE t1 MATCH '6021';
          187  +} {}
          188  +do_execsql_test 6.1.5 {
          189  +  SELECT * FROM t1 WHERE t1 MATCH '60*';
          190  +} {}
          191  +
          192  +do_execsql_test 6.2.1 {
          193  +  DROP TABLE t1;
          194  +  CREATE VIRTUAL TABLE t1 USING fts4(
          195  +    poiCategory, poiCategoryId, notindexed=poiCategory
          196  +  );
          197  +  INSERT INTO t1(poiCategory, poiCategoryId) values ("Restaurant", 6021);
          198  +}
          199  +
          200  +do_execsql_test 6.2.2 {
          201  +  SELECT * FROM t1 WHERE t1 MATCH 'restaurant';
          202  +} {}
          203  +do_execsql_test 6.2.3 {
          204  +  SELECT * FROM t1 WHERE t1 MATCH 're*';
          205  +} {}
          206  +do_execsql_test 6.2.4 {
          207  +  SELECT * FROM t1 WHERE t1 MATCH '6021';
          208  +} { Restaurant 6021 }
          209  +do_execsql_test 6.2.5 {
          210  +  SELECT * FROM t1 WHERE t1 MATCH '60*';
          211  +} { Restaurant 6021 }
   167    212   
   168    213   finish_test
   169    214   
   170    215   
   171    216   

Changes to test/insert.test.

   408    408   do_execsql_test insert-11.1 {
   409    409     CREATE TABLE t11a AS SELECT '123456789' AS x;
   410    410     CREATE TABLE t11b (a INTEGER PRIMARY KEY, b, c);
   411    411     INSERT INTO t11b SELECT x, x, x FROM t11a;
   412    412     SELECT quote(a), quote(b), quote(c) FROM t11b;
   413    413   } {123456789 '123456789' '123456789'}
   414    414   
          415  +
          416  +# More columns of input than there are columns in the table.
          417  +# Ticket http://www.sqlite.org/src/info/e9654505cfda9361
          418  +#
          419  +do_execsql_test insert-12.1 {
          420  +  CREATE TABLE t12a(a,b,c,d,e,f,g);
          421  +  INSERT INTO t12a VALUES(101,102,103,104,105,106,107);
          422  +  CREATE TABLE t12b(x);
          423  +  INSERT INTO t12b(x,rowid,x,x,x,x,x) SELECT * FROM t12a;
          424  +  SELECT rowid, x FROM t12b;
          425  +} {102 101}
          426  +do_execsql_test insert-12.2 {
          427  +  CREATE TABLE tab1( value INTEGER);
          428  +  INSERT INTO tab1 (value, _rowid_) values( 11, 1);
          429  +  INSERT INTO tab1 (value, _rowid_) SELECT 22,999;
          430  +  SELECT * FROM tab1;
          431  +} {11 22}
          432  +do_execsql_test insert-12.3 {
          433  +  CREATE TABLE t12c(a, b DEFAULT 'xyzzy', c);
          434  +  INSERT INTO t12c(a, rowid, c) SELECT 'one', 999, 'two';
          435  +  SELECT * FROM t12c;
          436  +} {one xyzzy two}
          437  +
   415    438   
   416    439   integrity_check insert-99.0
   417    440   
   418    441   finish_test

Changes to test/rdonly.test.

    28     28   do_test rdonly-1.1 {
    29     29     execsql {
    30     30       CREATE TABLE t1(x);
    31     31       INSERT INTO t1 VALUES(1);
    32     32       SELECT * FROM t1;
    33     33     }
    34     34   } {1}
           35  +do_test rdonly-1.1.1 {
           36  +  sqlite3_db_readonly db main
           37  +} {0}
    35     38   
    36     39   # Changes the write version from 1 to 3.  Verify that the database
    37     40   # can be read but not written.
    38     41   #
    39     42   do_test rdonly-1.2 {
    40     43     db close
    41     44     hexio_get_int [hexio_read test.db 18 1]
................................................................................
    43     46   do_test rdonly-1.3 {
    44     47     hexio_write test.db 18 03
    45     48     sqlite3 db test.db
    46     49     execsql {
    47     50       SELECT * FROM t1;
    48     51     }
    49     52   } {1}
           53  +do_test rdonly-1.3.1 {
           54  +  sqlite3_db_readonly db main
           55  +} {1}
    50     56   do_test rdonly-1.4 {
    51     57     catchsql {
    52     58       INSERT INTO t1 VALUES(2)
    53     59     }
    54     60   } {1 {attempt to write a readonly database}}
    55     61   
    56     62   # Change the write version back to 1.  Verify that the database

Changes to test/shell5.test.

   298    298     forcedelete test.db
   299    299     catchcmd test.db {.mode csv
   300    300   .import shell5.csv t1
   301    301     }
   302    302     sqlite3 db test.db
   303    303     db eval {SELECT *, '|' FROM t1}
   304    304   } {a b { } | x y {} | p q r |}
          305  +db close
          306  +
          307  +#----------------------------------------------------------------------------
          308  +# 
          309  +reset_db
          310  +sqlite3 db test.db
          311  +do_test shell5-2.1 {
          312  +  set fd [open shell5.csv w]
          313  +  puts $fd ",hello"
          314  +  close $fd
          315  +  catchcmd test.db [string trim {
          316  +.mode csv
          317  +CREATE TABLE t1(a, b);
          318  +.import shell5.csv t1
          319  +  }]
          320  +  db eval { SELECT * FROM t1 }
          321  +} {{} hello}
          322  +
          323  +do_test shell5-2.2 {
          324  +  set fd [open shell5.csv w]
          325  +  puts $fd {"",hello}
          326  +  close $fd
          327  +  catchcmd test.db [string trim {
          328  +.mode csv
          329  +CREATE TABLE t2(a, b);
          330  +.import shell5.csv t2
          331  +  }]
          332  +  db eval { SELECT * FROM t2 }
          333  +} {{} hello}
          334  +
          335  +do_test shell5-2.3 {
          336  +  set fd [open shell5.csv w]
          337  +  puts $fd {"x""y",hello}
          338  +  close $fd
          339  +  catchcmd test.db [string trim {
          340  +.mode csv
          341  +CREATE TABLE t3(a, b);
          342  +.import shell5.csv t3
          343  +  }]
          344  +  db eval { SELECT * FROM t3 }
          345  +} {x\"y hello}
          346  +
          347  +do_test shell5-2.4 {
          348  +  set fd [open shell5.csv w]
          349  +  puts $fd {"xy""",hello}
          350  +  close $fd
          351  +  catchcmd test.db [string trim {
          352  +.mode csv
          353  +CREATE TABLE t4(a, b);
          354  +.import shell5.csv t4
          355  +  }]
          356  +  db eval { SELECT * FROM t4 }
          357  +} {xy\" hello}
   305    358   
   306    359   
   307         -db close
   308    360   
   309    361   finish_test

Changes to test/skipscan1.test.

   177    177   
   178    178   do_execsql_test skipscan1-3.2 {
   179    179     SELECT a,b,c,d,'|' FROM t3 WHERE b=345 ORDER BY a;
   180    180   } {abc 345 7 8 | def 345 9 10 |}
   181    181   do_execsql_test skipscan1-3.2eqp {
   182    182     EXPLAIN QUERY PLAN
   183    183     SELECT a,b,c,d,'|' FROM t3 WHERE b=345 ORDER BY a;
   184         -} {/* INDEX sqlite_autoindex_t3_1 (ANY(a) AND b=?)*/}
          184  +} {/* PRIMARY KEY (ANY(a) AND b=?)*/}
   185    185   do_execsql_test skipscan1-3.2sort {
   186    186     EXPLAIN QUERY PLAN
   187    187     SELECT a,b,c,d,'|' FROM t3 WHERE b=345 ORDER BY a;
   188    188   } {~/*ORDER BY*/}
   189    189   
   190    190   # Ticket 520070ec7fbaac: Array overrun in the skip-scan optimization
   191    191   # 2013-12-22

Changes to test/skipscan2.test.

   182    182     SELECT name FROM peoplew WHERE height>=180 ORDER BY +name;
   183    183   } {David Jack Patrick Quiana Xavier}
   184    184   do_execsql_test skipscan2-2.5eqp {
   185    185     EXPLAIN QUERY PLAN
   186    186     SELECT name FROM peoplew WHERE height>=180 ORDER BY +name;
   187    187   } {/*INDEX peoplew_idx1 */}
   188    188   
          189  +# A skip-scan on a PK index of a WITHOUT ROWID table.
          190  +#
          191  +do_execsql_test skipscan2-3.1 {
          192  +  CREATE TABLE t3(a, b, c, PRIMARY KEY(a, b)) WITHOUT ROWID;
          193  +}
          194  +do_test skipscan2-3.2 {
          195  +  for {set i 0} {$i < 1000} {incr i} {
          196  +    execsql { INSERT INTO t3 VALUES($i%2, $i, 'xyz') }
          197  +  }
          198  +  execsql { ANALYZE }
          199  +} {}
          200  +do_eqp_test skipscan2-3.3eqp {
          201  +  SELECT * FROM t3 WHERE b=42;
          202  +} {0 0 0 {SEARCH TABLE t3 USING PRIMARY KEY (ANY(a) AND b=?)}}
   189    203   
   190    204   
   191    205   finish_test