/ Check-in [ce4ac66a]
Login
SQLite training in Houston TX on 2019-11-05 (details)
Part of the 2019 Tcl Conference

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

Overview
Comment:Add the SQLITE_READONLY_ROLLBACK extended error code. Do not try to set the permissions on journal or wal files except if the filesize is initially zero (indicating that it is a new file.)
Downloads: Tarball | ZIP archive | SQL archive
Timelines: family | ancestors | descendants | both | trunk
Files: files | file ages | folders
SHA1: ce4ac66a4b623a3cee1a63089dd5ba8341244f1e
User & Date: drh 2013-03-06 01:48:20
Context
2013-03-06
01:55
Fix a bug (ticket [fc7bd6358f59]) that caused incorrect query results in three way queries that involved comparing INTEGER and TEXT columns for equality. check-in: 7097241c user: drh tags: trunk
01:48
Add the SQLITE_READONLY_ROLLBACK extended error code. Do not try to set the permissions on journal or wal files except if the filesize is initially zero (indicating that it is a new file.) check-in: ce4ac66a user: drh tags: trunk
01:41
Fix an operator precedence problem on the [1d8086902e] check-in. Closed-Leaf check-in: 4f5f3aeb user: drh tags: ex-robust-open
2013-03-05
11:27
Fix a bug in the recent incremental-vacuum related changes. check-in: 717863fc user: dan tags: trunk
Changes
Hide Diffs Unified Diffs Ignore Whitespace Patch

Changes to src/os_unix.c.

548
549
550
551
552
553
554
555



556
557
558
559
560
561
562
#else
    fd = osOpen(z,f,m2);
#endif
  }while( fd<0 && errno==EINTR );
  if( fd>=0 ){
    if( m!=0 ){
      struct stat statbuf;
      if( osFstat(fd, &statbuf)==0 && (statbuf.st_mode&0777)!=m ){



        osFchmod(fd, m);
      }
    }
#if defined(FD_CLOEXEC) && (!defined(O_CLOEXEC) || O_CLOEXEC==0)
    osFcntl(fd, F_SETFD, osFcntl(fd, F_GETFD, 0) | FD_CLOEXEC);
#endif
  }







|
>
>
>







548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
#else
    fd = osOpen(z,f,m2);
#endif
  }while( fd<0 && errno==EINTR );
  if( fd>=0 ){
    if( m!=0 ){
      struct stat statbuf;
      if( osFstat(fd, &statbuf)==0 
       && statbuf.st_size==0
       && (statbuf.st_mode&0777)!=m 
      ){
        osFchmod(fd, m);
      }
    }
#if defined(FD_CLOEXEC) && (!defined(O_CLOEXEC) || O_CLOEXEC==0)
    osFcntl(fd, F_SETFD, osFcntl(fd, F_GETFD, 0) | FD_CLOEXEC);
#endif
  }

Changes to src/pager.c.

4823
4824
4825
4826
4827
4828
4829





4830
4831
4832
4833
4834
4835
4836
    if( pPager->eLock<=SHARED_LOCK ){
      rc = hasHotJournal(pPager, &bHotJournal);
    }
    if( rc!=SQLITE_OK ){
      goto failed;
    }
    if( bHotJournal ){





      /* Get an EXCLUSIVE lock on the database file. At this point it is
      ** important that a RESERVED lock is not obtained on the way to the
      ** EXCLUSIVE lock. If it were, another process might open the
      ** database file, detect the RESERVED lock, and conclude that the
      ** database is safe to read while this process is still rolling the 
      ** hot-journal back.
      ** 







>
>
>
>
>







4823
4824
4825
4826
4827
4828
4829
4830
4831
4832
4833
4834
4835
4836
4837
4838
4839
4840
4841
    if( pPager->eLock<=SHARED_LOCK ){
      rc = hasHotJournal(pPager, &bHotJournal);
    }
    if( rc!=SQLITE_OK ){
      goto failed;
    }
    if( bHotJournal ){
      if( pPager->readOnly ){
        rc = SQLITE_READONLY_ROLLBACK;
        goto failed;
      }

      /* Get an EXCLUSIVE lock on the database file. At this point it is
      ** important that a RESERVED lock is not obtained on the way to the
      ** EXCLUSIVE lock. If it were, another process might open the
      ** database file, detect the RESERVED lock, and conclude that the
      ** database is safe to read while this process is still rolling the 
      ** hot-journal back.
      ** 

Changes to src/sqlite.h.in.

474
475
476
477
478
479
480

481
482
483
484
485
486
487
#define SQLITE_BUSY_RECOVERY           (SQLITE_BUSY   |  (1<<8))
#define SQLITE_CANTOPEN_NOTEMPDIR      (SQLITE_CANTOPEN | (1<<8))
#define SQLITE_CANTOPEN_ISDIR          (SQLITE_CANTOPEN | (2<<8))
#define SQLITE_CANTOPEN_FULLPATH       (SQLITE_CANTOPEN | (3<<8))
#define SQLITE_CORRUPT_VTAB            (SQLITE_CORRUPT | (1<<8))
#define SQLITE_READONLY_RECOVERY       (SQLITE_READONLY | (1<<8))
#define SQLITE_READONLY_CANTLOCK       (SQLITE_READONLY | (2<<8))

#define SQLITE_ABORT_ROLLBACK          (SQLITE_ABORT | (2<<8))
#define SQLITE_CONSTRAINT_CHECK        (SQLITE_CONSTRAINT | (1<<8))
#define SQLITE_CONSTRAINT_COMMITHOOK   (SQLITE_CONSTRAINT | (2<<8))
#define SQLITE_CONSTRAINT_FOREIGNKEY   (SQLITE_CONSTRAINT | (3<<8))
#define SQLITE_CONSTRAINT_FUNCTION     (SQLITE_CONSTRAINT | (4<<8))
#define SQLITE_CONSTRAINT_NOTNULL      (SQLITE_CONSTRAINT | (5<<8))
#define SQLITE_CONSTRAINT_PRIMARYKEY   (SQLITE_CONSTRAINT | (6<<8))







>







474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
#define SQLITE_BUSY_RECOVERY           (SQLITE_BUSY   |  (1<<8))
#define SQLITE_CANTOPEN_NOTEMPDIR      (SQLITE_CANTOPEN | (1<<8))
#define SQLITE_CANTOPEN_ISDIR          (SQLITE_CANTOPEN | (2<<8))
#define SQLITE_CANTOPEN_FULLPATH       (SQLITE_CANTOPEN | (3<<8))
#define SQLITE_CORRUPT_VTAB            (SQLITE_CORRUPT | (1<<8))
#define SQLITE_READONLY_RECOVERY       (SQLITE_READONLY | (1<<8))
#define SQLITE_READONLY_CANTLOCK       (SQLITE_READONLY | (2<<8))
#define SQLITE_READONLY_ROLLBACK       (SQLITE_READONLY | (3<<8))
#define SQLITE_ABORT_ROLLBACK          (SQLITE_ABORT | (2<<8))
#define SQLITE_CONSTRAINT_CHECK        (SQLITE_CONSTRAINT | (1<<8))
#define SQLITE_CONSTRAINT_COMMITHOOK   (SQLITE_CONSTRAINT | (2<<8))
#define SQLITE_CONSTRAINT_FOREIGNKEY   (SQLITE_CONSTRAINT | (3<<8))
#define SQLITE_CONSTRAINT_FUNCTION     (SQLITE_CONSTRAINT | (4<<8))
#define SQLITE_CONSTRAINT_NOTNULL      (SQLITE_CONSTRAINT | (5<<8))
#define SQLITE_CONSTRAINT_PRIMARYKEY   (SQLITE_CONSTRAINT | (6<<8))

Changes to src/test1.c.

174
175
176
177
178
179
180

181
182
183
184
185
186
187
    case SQLITE_IOERR_ACCESS:        zName = "SQLITE_IOERR_ACCESS";      break;
    case SQLITE_IOERR_CHECKRESERVEDLOCK:
                               zName = "SQLITE_IOERR_CHECKRESERVEDLOCK"; break;
    case SQLITE_IOERR_LOCK:          zName = "SQLITE_IOERR_LOCK";        break;
    case SQLITE_CORRUPT_VTAB:        zName = "SQLITE_CORRUPT_VTAB";      break;
    case SQLITE_READONLY_RECOVERY:   zName = "SQLITE_READONLY_RECOVERY"; break;
    case SQLITE_READONLY_CANTLOCK:   zName = "SQLITE_READONLY_CANTLOCK"; break;

    default:                         zName = "SQLITE_Unknown";           break;
  }
  return zName;
}
#define t1ErrorName sqlite3TestErrorName

/*







>







174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
    case SQLITE_IOERR_ACCESS:        zName = "SQLITE_IOERR_ACCESS";      break;
    case SQLITE_IOERR_CHECKRESERVEDLOCK:
                               zName = "SQLITE_IOERR_CHECKRESERVEDLOCK"; break;
    case SQLITE_IOERR_LOCK:          zName = "SQLITE_IOERR_LOCK";        break;
    case SQLITE_CORRUPT_VTAB:        zName = "SQLITE_CORRUPT_VTAB";      break;
    case SQLITE_READONLY_RECOVERY:   zName = "SQLITE_READONLY_RECOVERY"; break;
    case SQLITE_READONLY_CANTLOCK:   zName = "SQLITE_READONLY_CANTLOCK"; break;
    case SQLITE_READONLY_ROLLBACK:   zName = "SQLITE_READONLY_ROLLBACK"; break;
    default:                         zName = "SQLITE_Unknown";           break;
  }
  return zName;
}
#define t1ErrorName sqlite3TestErrorName

/*

Changes to test/misc7.test.

484
485
486
487
488
489
490




























491
492
493
494
495
#
do_test misc7-21.1 {
  set zFile [file join [get_pwd] "[string repeat abcde 104].db"]
  set rc [catch {sqlite3 db2 $zFile} msg]
  list $rc $msg
} {1 {unable to open database file}}






























db close
forcedelete test.db

finish_test







>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>





484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
#
do_test misc7-21.1 {
  set zFile [file join [get_pwd] "[string repeat abcde 104].db"]
  set rc [catch {sqlite3 db2 $zFile} msg]
  list $rc $msg
} {1 {unable to open database file}}

# Try to do hot-journal rollback with a read-only connection. The 
# error code should be SQLITE_READONLY_ROLLBACK.
#
do_test misc7-22.1 {
  db close
  forcedelete test.db copy.db-journal
  sqlite3 db test.db
  execsql {
    CREATE TABLE t1(a, b);
    INSERT INTO t1 VALUES(1, 2);
    INSERT INTO t1 VALUES(3, 4);
  }
  db close
  sqlite3 db test.db -readonly 1
  catchsql {
    INSERT INTO t1 VALUES(5, 6);
  }
} {1 {attempt to write a readonly database}}
do_test misc7-22.2 { execsql { SELECT * FROM t1 } } {1 2 3 4}
do_test misc7-22.3 { 
  set fd [open test.db-journal w]
  puts $fd [string repeat abc 1000]
  close $fd
  catchsql { SELECT * FROM t1 }
} {1 {attempt to write a readonly database}}
do_test misc7-22.4 { 
  sqlite3_extended_errcode db
} SQLITE_READONLY_ROLLBACK

db close
forcedelete test.db

finish_test

Changes to test/pager1.test.

748
749
750
751
752
753
754
755
756
757
758
759
760
761
762

faultsim_restore_and_reopen
db close
sqlite3 db test.db -readonly 1
do_catchsql_test pager1.4.5.6 {
  SELECT * FROM t1;
  SELECT * FROM t2;
} {1 {disk I/O error}}
db close

# Snapshot the file-system just before multi-file commit. Save the name
# of the master journal file in $::mj_filename.
#
tv script copy_on_mj_delete
tv filter xDelete







|







748
749
750
751
752
753
754
755
756
757
758
759
760
761
762

faultsim_restore_and_reopen
db close
sqlite3 db test.db -readonly 1
do_catchsql_test pager1.4.5.6 {
  SELECT * FROM t1;
  SELECT * FROM t2;
} {1 {attempt to write a readonly database}}
db close

# Snapshot the file-system just before multi-file commit. Save the name
# of the master journal file in $::mj_filename.
#
tv script copy_on_mj_delete
tv filter xDelete