/ Check-in [0546d1cd]
Login

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

Overview
Comment:Merge all recent enhancements and fixes from trunk.
Downloads: Tarball | ZIP archive | SQL archive
Timelines: family | ancestors | descendants | both | sessions
Files: files | file ages | folders
SHA1: 0546d1cd1a3402890edade7970c269cc3f17bc98
User & Date: drh 2015-11-02 18:57:26
Context
2015-11-07
01:33
Merge recent enhancements and bug fixes from trunk. check-in: 78bc42e6 user: drh tags: sessions
2015-11-02
18:57
Merge all recent enhancements and fixes from trunk. check-in: 0546d1cd user: drh tags: sessions
15:08
On unix, if a file is opened via a symlink, create, read and write journal and wal files based on the name of the actual db file, not the symlink. check-in: 6d5ce3ed user: dan tags: trunk
2015-10-30
16:50
Merge all the latest enhancements from trunk. check-in: 395a153f user: drh tags: sessions
Changes
Hide Diffs Side-by-Side Diffs Ignore Whitespace Patch

Changes to src/build.c.

  1266   1266         sqlite3DbFree(db, pCol->zDflt);
  1267   1267         pCol->zDflt = sqlite3DbStrNDup(db, (char*)pSpan->zStart,
  1268   1268                                        (int)(pSpan->zEnd - pSpan->zStart));
  1269   1269       }
  1270   1270     }
  1271   1271     sqlite3ExprDelete(db, pSpan->pExpr);
  1272   1272   }
         1273  +
         1274  +/*
         1275  +** Backwards Compatibility Hack:
         1276  +** 
         1277  +** Historical versions of SQLite accepted strings as column names in
         1278  +** indexes and PRIMARY KEY constraints and in UNIQUE constraints.  Example:
         1279  +**
         1280  +**     CREATE TABLE xyz(a,b,c,d,e,PRIMARY KEY('a'),UNIQUE('b','c' COLLATE trim)
         1281  +**     CREATE INDEX abc ON xyz('c','d' DESC,'e' COLLATE nocase DESC);
         1282  +**
         1283  +** This is goofy.  But to preserve backwards compatibility we continue to
         1284  +** accept it.  This routine does the necessary conversion.  It converts
         1285  +** the expression given in its argument from a TK_STRING into a TK_ID
         1286  +** if the expression is just a TK_STRING with an optional COLLATE clause.
         1287  +** If the epxression is anything other than TK_STRING, the expression is
         1288  +** unchanged.
         1289  +*/
         1290  +static void sqlite3StringToId(Expr *p){
         1291  +  if( p->op==TK_STRING ){
         1292  +    p->op = TK_ID;
         1293  +  }else if( p->op==TK_COLLATE && p->pLeft->op==TK_STRING ){
         1294  +    p->pLeft->op = TK_ID;
         1295  +  }
         1296  +}
  1273   1297   
  1274   1298   /*
  1275   1299   ** Designate the PRIMARY KEY for the table.  pList is a list of names 
  1276   1300   ** of columns that form the primary key.  If pList is NULL, then the
  1277   1301   ** most recently added column of the table is the primary key.
  1278   1302   **
  1279   1303   ** A table can have at most one primary key.  If the table already has
................................................................................
  1313   1337       zType = pTab->aCol[iCol].zType;
  1314   1338       nTerm = 1;
  1315   1339     }else{
  1316   1340       nTerm = pList->nExpr;
  1317   1341       for(i=0; i<nTerm; i++){
  1318   1342         Expr *pCExpr = sqlite3ExprSkipCollate(pList->a[i].pExpr);
  1319   1343         assert( pCExpr!=0 );
         1344  +      sqlite3StringToId(pCExpr);
  1320   1345         if( pCExpr->op==TK_ID ){
  1321   1346           const char *zCName = pCExpr->u.zToken;
  1322   1347           for(iCol=0; iCol<pTab->nCol; iCol++){
  1323   1348             if( sqlite3StrICmp(zCName, pTab->aCol[iCol].zName)==0 ){
  1324   1349               pTab->aCol[iCol].colFlags |= COLFLAG_PRIMKEY;
  1325   1350               zType = pTab->aCol[iCol].zType;
  1326   1351               break;
................................................................................
  2851   2876       p->nColumn = nCol;
  2852   2877       p->nKeyCol = nCol - 1;
  2853   2878       *ppExtra = ((char*)p) + nByte;
  2854   2879     }
  2855   2880     return p;
  2856   2881   }
  2857   2882   
  2858         -/*
  2859         -** Backwards Compatibility Hack:
  2860         -** 
  2861         -** Historical versions of SQLite accepted strings as column names in
  2862         -** indexes and PRIMARY KEY constraints and in UNIQUE constraints.  Example:
  2863         -**
  2864         -**     CREATE TABLE xyz(a,b,c,d,e,PRIMARY KEY('a'),UNIQUE('b','c' COLLATE trim)
  2865         -**     CREATE INDEX abc ON xyz('c','d' DESC,'e' COLLATE nocase DESC);
  2866         -**
  2867         -** This is goofy.  But to preserve backwards compatibility we continue to
  2868         -** accept it.  This routine does the necessary conversion.  It converts
  2869         -** the expression given in its argument from a TK_STRING into a TK_ID
  2870         -** if the expression is just a TK_STRING with an optional COLLATE clause.
  2871         -** If the epxression is anything other than TK_STRING, the expression is
  2872         -** unchanged.
  2873         -*/
  2874         -static void sqlite3StringToId(Expr *p){
  2875         -  if( p->op==TK_STRING ){
  2876         -    p->op = TK_ID;
  2877         -  }else if( p->op==TK_COLLATE && p->pLeft->op==TK_STRING ){
  2878         -    p->pLeft->op = TK_ID;
  2879         -  }
  2880         -}
  2881         -
  2882   2883   /*
  2883   2884   ** Create a new index for an SQL table.  pName1.pName2 is the name of the index 
  2884   2885   ** and pTblList is the name of the table that is to be indexed.  Both will 
  2885   2886   ** be NULL for a primary key or an index that is created to satisfy a
  2886   2887   ** UNIQUE constraint.  If pTable and pIndex are NULL, use pParse->pNewTable
  2887   2888   ** as the table to be indexed.  pParse->pNewTable is a table that is
  2888   2889   ** currently being constructed by a CREATE TABLE statement.

Changes to src/os_unix.c.

   460    460   #else
   461    461     { "mremap",       (sqlite3_syscall_ptr)0,               0 },
   462    462   #endif
   463    463   #define osMremap ((void*(*)(void*,size_t,size_t,int,...))aSyscall[23].pCurrent)
   464    464     { "getpagesize",  (sqlite3_syscall_ptr)unixGetpagesize, 0 },
   465    465   #define osGetpagesize ((int(*)(void))aSyscall[24].pCurrent)
   466    466   
          467  +  { "readlink",     (sqlite3_syscall_ptr)readlink,        0 },
          468  +#define osReadlink ((ssize_t(*)(const char*,char*,size_t))aSyscall[25].pCurrent)
          469  +
   467    470   #endif
   468    471   
   469    472   }; /* End of the overrideable system calls */
   470    473   
   471    474   /*
   472    475   ** This is the xSetSystemCall() method of sqlite3_vfs for all of the
   473    476   ** "unix" VFSes.  Return SQLITE_OK opon successfully updating the
................................................................................
  6022   6025   */
  6023   6026   static int unixFullPathname(
  6024   6027     sqlite3_vfs *pVfs,            /* Pointer to vfs object */
  6025   6028     const char *zPath,            /* Possibly relative input path */
  6026   6029     int nOut,                     /* Size of output buffer in bytes */
  6027   6030     char *zOut                    /* Output buffer */
  6028   6031   ){
         6032  +  int nByte;
  6029   6033   
  6030   6034     /* It's odd to simulate an io-error here, but really this is just
  6031   6035     ** using the io-error infrastructure to test that SQLite handles this
  6032   6036     ** function failing. This function could fail if, for example, the
  6033   6037     ** current working directory has been unlinked.
  6034   6038     */
  6035   6039     SimulateIOError( return SQLITE_ERROR );
  6036   6040   
  6037   6041     assert( pVfs->mxPathname==MAX_PATHNAME );
  6038   6042     UNUSED_PARAMETER(pVfs);
  6039   6043   
  6040         -  zOut[nOut-1] = '\0';
  6041         -  if( zPath[0]=='/' ){
  6042         -    sqlite3_snprintf(nOut, zOut, "%s", zPath);
         6044  +  /* Attempt to resolve the path as if it were a symbolic link. If it is
         6045  +  ** a symbolic link, the resolved path is stored in buffer zOut[]. Or, if
         6046  +  ** the identified file is not a symbolic link or does not exist, then
         6047  +  ** zPath is copied directly into zOut. Either way, nByte is left set to
         6048  +  ** the size of the string copied into zOut[] in bytes.  */
         6049  +  nByte = osReadlink(zPath, zOut, nOut-1);
         6050  +  if( nByte<0 ){
         6051  +    if( errno!=EINVAL && errno!=ENOENT ){
         6052  +      return unixLogError(SQLITE_CANTOPEN_BKPT, "readlink", zPath);
         6053  +    }
         6054  +    zOut[nOut-1] = '\0';
         6055  +    sqlite3_snprintf(nOut-1, zOut, "%s", zPath);
         6056  +    nByte = sqlite3Strlen30(zOut);
  6043   6057     }else{
         6058  +    zOut[nByte] = '\0';
         6059  +  }
         6060  +
         6061  +  /* If buffer zOut[] now contains an absolute path there is nothing more
         6062  +  ** to do. If it contains a relative path, do the following:
         6063  +  **
         6064  +  **   * move the relative path string so that it is at the end of th
         6065  +  **     zOut[] buffer.
         6066  +  **   * Call getcwd() to read the path of the current working directory 
         6067  +  **     into the start of the zOut[] buffer.
         6068  +  **   * Append a '/' character to the cwd string and move the 
         6069  +  **     relative path back within the buffer so that it immediately 
         6070  +  **     follows the '/'.
         6071  +  **
         6072  +  ** This code is written so that if the combination of the CWD and relative
         6073  +  ** path are larger than the allocated size of zOut[] the CWD is silently
         6074  +  ** truncated to make it fit. This is Ok, as SQLite refuses to open any
         6075  +  ** file for which this function returns a full path larger than (nOut-8)
         6076  +  ** bytes in size.  */
         6077  +  if( zOut[0]!='/' ){
  6044   6078       int nCwd;
  6045         -    if( osGetcwd(zOut, nOut-1)==0 ){
         6079  +    int nRem = nOut-nByte-1;
         6080  +    memmove(&zOut[nRem], zOut, nByte+1);
         6081  +    zOut[nRem-1] = '\0';
         6082  +    if( osGetcwd(zOut, nRem-1)==0 ){
  6046   6083         return unixLogError(SQLITE_CANTOPEN_BKPT, "getcwd", zPath);
  6047   6084       }
  6048         -    nCwd = (int)strlen(zOut);
  6049         -    sqlite3_snprintf(nOut-nCwd, &zOut[nCwd], "/%s", zPath);
         6085  +    nCwd = sqlite3Strlen30(zOut);
         6086  +    assert( nCwd<=nRem-1 );
         6087  +    zOut[nCwd] = '/';
         6088  +    memmove(&zOut[nCwd+1], &zOut[nRem], nByte+1);
  6050   6089     }
         6090  +
  6051   6091     return SQLITE_OK;
  6052   6092   }
  6053   6093   
  6054   6094   
  6055   6095   #ifndef SQLITE_OMIT_LOAD_EXTENSION
  6056   6096   /*
  6057   6097   ** Interfaces for opening a shared library, finding entry points
................................................................................
  7538   7578       UNIXVFS("unix-proxy",    proxyIoFinder ),
  7539   7579   #endif
  7540   7580     };
  7541   7581     unsigned int i;          /* Loop counter */
  7542   7582   
  7543   7583     /* Double-check that the aSyscall[] array has been constructed
  7544   7584     ** correctly.  See ticket [bb3a86e890c8e96ab] */
  7545         -  assert( ArraySize(aSyscall)==25 );
         7585  +  assert( ArraySize(aSyscall)==26 );
  7546   7586   
  7547   7587     /* Register all VFSes defined in the aVfs[] array */
  7548   7588     for(i=0; i<(sizeof(aVfs)/sizeof(sqlite3_vfs)); i++){
  7549   7589       sqlite3_vfs_register(&aVfs[i], i==0);
  7550   7590     }
  7551   7591     return SQLITE_OK; 
  7552   7592   }

Changes to src/test3.c.

   213    213     }
   214    214     pBt = sqlite3TestTextToPtr(argv[1]);
   215    215     if( Tcl_GetInt(interp, argv[2], &iTable) ) return TCL_ERROR;
   216    216     if( Tcl_GetBoolean(interp, argv[3], &wrFlag) ) return TCL_ERROR;
   217    217     if( wrFlag ) wrFlag = BTREE_WRCSR;
   218    218     pCur = (BtCursor *)ckalloc(sqlite3BtreeCursorSize());
   219    219     memset(pCur, 0, sqlite3BtreeCursorSize());
          220  +  sqlite3_mutex_enter(pBt->db->mutex);
   220    221     sqlite3BtreeEnter(pBt);
   221    222   #ifndef SQLITE_OMIT_SHARED_CACHE
   222    223     rc = sqlite3BtreeLockTable(pBt, iTable, !!wrFlag);
   223    224   #endif
   224    225     if( rc==SQLITE_OK ){
   225    226       rc = sqlite3BtreeCursor(pBt, iTable, wrFlag, 0, pCur);
   226    227     }
   227    228     sqlite3BtreeLeave(pBt);
          229  +  sqlite3_mutex_leave(pBt->db->mutex);
   228    230     if( rc ){
   229    231       ckfree((char *)pCur);
   230    232       Tcl_AppendResult(interp, sqlite3ErrName(rc), 0);
   231    233       return TCL_ERROR;
   232    234     }
   233    235     sqlite3_snprintf(sizeof(zBuf), zBuf,"%p", pCur);
   234    236     Tcl_AppendResult(interp, zBuf, 0);
................................................................................
   253    255     if( argc!=2 ){
   254    256       Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
   255    257          " ID\"", 0);
   256    258       return TCL_ERROR;
   257    259     }
   258    260     pCur = sqlite3TestTextToPtr(argv[1]);
   259    261     pBt = pCur->pBtree;
          262  +  sqlite3_mutex_enter(pBt->db->mutex);
   260    263     sqlite3BtreeEnter(pBt);
   261    264     rc = sqlite3BtreeCloseCursor(pCur);
   262    265     sqlite3BtreeLeave(pBt);
          266  +  sqlite3_mutex_leave(pBt->db->mutex);
   263    267     ckfree((char *)pCur);
   264    268     if( rc ){
   265    269       Tcl_AppendResult(interp, sqlite3ErrName(rc), 0);
   266    270       return TCL_ERROR;
   267    271     }
   268    272     return SQLITE_OK;
   269    273   }
................................................................................
   626    630       if( Tcl_GetIntFromObj(interp, objv[2], &nKey) ) return TCL_ERROR;
   627    631       pData = (void*)Tcl_GetByteArrayFromObj(objv[3], &nData);
   628    632     }else{
   629    633       pKey = (void*)Tcl_GetByteArrayFromObj(objv[2], &nKey);
   630    634     }
   631    635     pCur = (BtCursor*)sqlite3TestTextToPtr(Tcl_GetString(objv[1]));
   632    636   
          637  +  sqlite3_mutex_enter(pCur->pBtree->db->mutex);
   633    638     sqlite3BtreeEnter(pCur->pBtree);
   634    639     rc = sqlite3BtreeInsert(pCur, pKey, nKey, pData, nData, 0, 0, 0);
   635    640     sqlite3BtreeLeave(pCur->pBtree);
          641  +  sqlite3_mutex_leave(pCur->pBtree->db->mutex);
   636    642   
   637    643     Tcl_ResetResult(interp);
   638    644     if( rc ){
   639    645       Tcl_AppendResult(interp, sqlite3ErrName(rc), 0);
   640    646       return TCL_ERROR;
   641    647     }
   642    648     return TCL_OK;

Changes to test/index3.test.

    58     58   do_execsql_test index3-2.2 {
    59     59     SELECT a FROM t1 WHERE b='ab005xy' COLLATE nocase;
    60     60   } {5}
    61     61   do_execsql_test index3-2.2eqp {
    62     62     EXPLAIN QUERY PLAN
    63     63     SELECT a FROM t1 WHERE b='ab005xy' COLLATE nocase;
    64     64   } {/USING INDEX/}
           65  +do_execsql_test index3-2.3 {
           66  +  SELECT name FROM sqlite_master WHERE tbl_name='t1' ORDER BY name
           67  +} {sqlite_autoindex_t1_1 sqlite_autoindex_t1_2 t1 t1c t1d}
           68  +do_execsql_test index3-2.4 {
           69  +  CREATE TABLE t2a(a integer, b, PRIMARY KEY(a));
           70  +  CREATE TABLE t2b("a" integer, b, PRIMARY KEY("a"));
           71  +  CREATE TABLE t2c([a] integer, b, PRIMARY KEY([a]));
           72  +  CREATE TABLE t2d('a' integer, b, PRIMARY KEY('a'));
           73  +}
           74  +do_execsql_test index3-2.5 {
           75  +  SELECT name FROM sqlite_master WHERE tbl_name LIKE 't2_' ORDER BY name
           76  +} {t2a t2b t2c t2d}
           77  + 
           78  +
           79  +
    65     80   
    66     81   
    67     82   # This test corrupts the database file so it must be the last test
    68     83   # in the series.
    69     84   #
    70     85   do_test index3-99.1 {
    71     86     execsql {

Changes to test/oserror.test.

    89     89   # Test a failure in open() due to the path not existing.
    90     90   #
    91     91   do_test 1.4.1 {
    92     92     set ::log [list]
    93     93     list [catch { sqlite3 dbh /root/test.db } msg] $msg
    94     94   } {1 {unable to open database file}}
    95     95   
    96         -do_re_test 1.4.2 { lindex $::log 0 } {^os_unix.c:\d*: \(\d+\) open\(.*test.db\) - }
           96  +do_re_test 1.4.2 { 
           97  +  lindex $::log 0
           98  +} {^os_unix.c:\d*: \(\d+\) (open|readlink)\(.*test.db\) - }
    97     99   
    98    100   #--------------------------------------------------------------------------
    99    101   # Tests oserror-1.* test failures in the unlink() system call.
   100    102   #
   101    103   ifcapable wal {
   102    104     do_test 2.1.1 {
   103    105       set ::log [list]

Added test/symlink.test.

            1  +# 2015 October 31
            2  +#
            3  +# The author disclaims copyright to this source code.  In place of
            4  +# a legal notice, here is a blessing:
            5  +#
            6  +#    May you do good and not evil.
            7  +#    May you find forgiveness for yourself and forgive others.
            8  +#    May you share freely, never taking more than you give.
            9  +#
           10  +#***********************************************************************
           11  +# This file implements regression tests for SQLite library.  The
           12  +# focus of this file is testing that SQLite can follow symbolic links.
           13  +#
           14  +
           15  +set testdir [file dirname $argv0]
           16  +source $testdir/tester.tcl
           17  +set testprefix symlink
           18  +
           19  +# This only runs on unix.
           20  +if {$::tcl_platform(platform)!="unix"} {
           21  +  finish_test
           22  +  return
           23  +}
           24  +
           25  +# Ensure that test.db has been created.
           26  +#
           27  +do_execsql_test 1.0 {
           28  +  CREATE TABLE t1(x, y);
           29  +}
           30  +
           31  +# Test that SQLite follows symlinks when opening files.
           32  +#
           33  +forcedelete test.db2
           34  +do_test 1.1 {
           35  +  file link test.db2 test.db
           36  +  sqlite3 db2 test.db2
           37  +  sqlite3_db_filename db2 main
           38  +} [file join [pwd] test.db]
           39  +
           40  +# Test that if the symlink points to a file that does not exists, it is
           41  +# created when it is opened.
           42  +#
           43  +do_test 1.2.1 {
           44  +  db2 close
           45  +  db close
           46  +  forcedelete test.db
           47  +  file exists test.db
           48  +} 0
           49  +do_test 1.2.2 {
           50  +  sqlite3 db2 test.db2
           51  +  file exists test.db
           52  +} 1
           53  +do_test 1.2.3 {
           54  +  sqlite3_db_filename db2 main
           55  +} [file join [pwd] test.db]
           56  +db2 close
           57  +
           58  +# Test that a loop of symlinks cannot be opened.
           59  +#
           60  +do_test 1.3 {
           61  +  forcedelete test.db
           62  +  # Note: Tcl [file link] command is too smart to create loops of symlinks.
           63  +  exec ln -s test.db2 test.db
           64  +  list [catch { sqlite3 db test.db } msg] $msg
           65  +} {1 {unable to open database file}}
           66  +
           67  +# Test that overly large paths cannot be opened.
           68  +#
           69  +do_test 1.4 {
           70  +  set name "test.db[string repeat x 502]"
           71  +  list [catch { sqlite3 db $name } msg] $msg
           72  +} {1 {unable to open database file}}
           73  +do_test 1.5 {
           74  +  set r [expr 510 - [string length test.db] - [string length [pwd]]]
           75  +  set name "test.db[string repeat x $r]"
           76  +  list [catch { sqlite3 db $name } msg] $msg
           77  +} {1 {unable to open database file}}
           78  +
           79  +#-------------------------------------------------------------------------
           80  +# Test that journal and wal files are created next to the real file,
           81  +# not the symlink.
           82  +#
           83  +do_test 2.0 {
           84  +  catch { db close }
           85  +  catch { db2 close }
           86  +  forcedelete test.db test.db2
           87  +  sqlite3 db test.db
           88  +  execsql { CREATE TABLE t1(x) }
           89  +  file link test.db2 test.db
           90  +  sqlite3 db2 test.db2
           91  +  file exists test.db-journal
           92  +} 0
           93  +
           94  +do_test 2.1 {
           95  +  execsql {
           96  +    BEGIN;
           97  +      INSERT INTO t1 VALUES(1);
           98  +  } db2
           99  +  file exists test.db-journal
          100  +} 1
          101  +do_test 2.2 {
          102  +  file exists test.db2-journal
          103  +} 0
          104  +do_test 2.3 {
          105  +  execsql {
          106  +    COMMIT;
          107  +    PRAGMA journal_mode = wal;
          108  +    INSERT INTO t1 VALUES(2);
          109  +  } db2
          110  +  file exists test.db-wal
          111  +} 1
          112  +do_test 2.4 {
          113  +  file exists test.db2-wal
          114  +} 0
          115  +do_execsql_test 2.5 {
          116  +  SELECT * FROM t1;
          117  +} {1 2}
          118  +
          119  +finish_test

Changes to test/syscall.test.

    57     57   # Tests for the xNextSystemCall method.
    58     58   #
    59     59   foreach s {
    60     60       open close access getcwd stat fstat ftruncate
    61     61       fcntl read pread write pwrite fchmod fallocate
    62     62       pread64 pwrite64 unlink openDirectory mkdir rmdir 
    63     63       statvfs fchown umask mmap munmap mremap
    64         -    getpagesize
           64  +    getpagesize readlink
    65     65   } {
    66     66     if {[test_syscall exists $s]} {lappend syscall_list $s}
    67     67   }
    68     68   do_test 3.1 { lsort [test_syscall list] } [lsort $syscall_list]
    69     69   
    70     70   #-------------------------------------------------------------------------
    71     71   # This test verifies that if a call to open() fails and errno is set to