]> git.ipfire.org Git - thirdparty/sqlite.git/commitdiff
Add experimental SQLITE_FCNTL_EXTERNAL_READER file control.
authordan <Dan Kennedy>
Fri, 2 Apr 2021 19:55:48 +0000 (19:55 +0000)
committerdan <Dan Kennedy>
Fri, 2 Apr 2021 19:55:48 +0000 (19:55 +0000)
FossilOrigin-Name: e16da5af822ef31d7e05992403cf9787fbb3d9abb0b5283aba55ea07e1830a72

manifest
manifest.uuid
src/os_unix.c
src/sqlite.h.in
src/test1.c
test/external_reader.test [new file with mode: 0644]

index eb22676dbf3e59935fb821a4d74696cda919ccd5..cc229d23fcdd28454dc69d2fdb03fa88a3677eb0 100644 (file)
--- a/manifest
+++ b/manifest
@@ -1,5 +1,5 @@
-C Fix\sa\sproblem\swith\sthe\sgeopoly_bbox()\sfunction.
-D 2021-04-02T18:59:13.666
+C Add\sexperimental\sSQLITE_FCNTL_EXTERNAL_READER\sfile\scontrol.
+D 2021-04-02T19:55:48.856
 F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1
 F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea
 F LICENSE.md df5091916dbb40e6e9686186587125e1b2ff51f022cc334e886c19a0e9982724
@@ -526,7 +526,7 @@ F src/os.c 2d6e646370b1aa78942c68d7edf124e518963adf4a90bce87f365a5a5495529a
 F src/os.h 48388821692e87da174ea198bf96b1b2d9d83be5dfc908f673ee21fafbe0d432
 F src/os_common.h b2f4707a603e36811d9b1a13278bffd757857b85
 F src/os_setup.h 0dbaea40a7d36bf311613d31342e0b99e2536586
-F src/os_unix.c 7a9eab7b11f552ab91ead980086b312c7e3b871efdee8c0c072b682bbec6592e
+F src/os_unix.c b5b7475bd1a8f1b83b6173a81f4fe50f9e077ccbacb62ce2fe7a5cb89916bce1
 F src/os_win.c 77d39873836f1831a9b0b91894fec45ab0e9ca8e067dc8c549e1d1eca1566fe9
 F src/os_win.h 7b073010f1451abe501be30d12f6bc599824944a
 F src/pager.c 970691daea03f9f15e34de671bd8675c1e136232b529e21bfd36d4dba6d41753
@@ -544,7 +544,7 @@ F src/resolve.c fc136d935f19966747663bed605ad7f06f84f9fe7bf7bf79e9bf844ef5c7556d
 F src/rowset.c ba9515a922af32abe1f7d39406b9d35730ed65efab9443dc5702693b60854c92
 F src/select.c 2d7a1f3d9f5970962b407cb4b38416fedc1a3b55efd010b40af375088653b6ce
 F src/shell.c.in dcce260883836c9b58847505fbccce8d5546af925046f7dacd9443e922ece036
-F src/sqlite.h.in 3426a080ea1f222a73e3bd91e7eacbd30570a0117c03d42c6dde606f33e5e318
+F src/sqlite.h.in 18ec33e32001721fd4e9c4705a24a85dff04956ac2c0a21775058884ba845b09
 F src/sqlite3.rc 5121c9e10c3964d5755191c80dd1180c122fc3a8
 F src/sqlite3ext.h 61b38c073d5e1e96a3d45271b257aef27d0d13da2bea5347692ae579475cd95e
 F src/sqliteInt.h c5cfae5891a6e643116f66f63769bcffeba89ca51f6278732da710eb0cf092b6
@@ -552,7 +552,7 @@ F src/sqliteLimit.h d7323ffea5208c6af2734574bae933ca8ed2ab728083caa117c9738581a3
 F src/status.c 4b8bc2a6905163a38b739854a35b826c737333fab5b1f8e03fa7eb9a4799c4c1
 F src/table.c 0f141b58a16de7e2fbe81c308379e7279f4c6b50eb08efeec5892794a0ba30d1
 F src/tclsqlite.c 986b6391f02cd9b53c1d688be55899f6ffddeb8e8014cd83c1b73ff912579a71
-F src/test1.c f5262c95b95aeb2b580101dc4657e7c0df5b25a5a9b7c456e2d3f463cef83fa9
+F src/test1.c 2100f4c28bae21ce83a9a0c5ec6827efd0e15d11b93b569b614daa5654b3fcf6
 F src/test2.c 3efb99ab7f1fc8d154933e02ae1378bac9637da5
 F src/test3.c 61798bb0d38b915067a8c8e03f5a534b431181f802659a6616f9b4ff7d872644
 F src/test4.c 7c4420e01c577b5c4add2cb03119743b1a357543d347773b9e717195ea967159
@@ -888,6 +888,7 @@ F test/existsfault.test 72a0036c1424d9204d49f4d976c3277a1b8bb2eed3c67aa124ba2df2
 F test/expr.test 26cd01e8485bc48c8aa6a1add598e9ce1e706b4eb4f3f554e0b0223022e8c2cf
 F test/expr2.test c27327ae9c017a7ff6280123f67aff496f912da74d78c888926d68b46ec75fd8
 F test/extension01.test 00d13cec817f331a687a243e0e5a2d87b0e358c9
+F test/external_reader.test c7d34694f1b25c32d866f56ac80c1e29edddc42b4ef90cad589263ffac2cde0c
 F test/extraquick.test cb254400bd42bfb777ff675356aabf3287978f79
 F test/fallocate.test 37a62e396a68eeede8f8d2ecf23573a80faceb630788d314d0a073d862616717
 F test/filectrl.test 6e871c2d35dead1d9a88e176e8d2ca094fec6bb3
@@ -1911,7 +1912,7 @@ F vsixtest/vsixtest.tcl 6a9a6ab600c25a91a7acc6293828957a386a8a93
 F vsixtest/vsixtest.vcxproj.data 2ed517e100c66dc455b492e1a33350c1b20fbcdc
 F vsixtest/vsixtest.vcxproj.filters 37e51ffedcdb064aad6ff33b6148725226cd608e
 F vsixtest/vsixtest_TemporaryKey.pfx e5b1b036facdb453873e7084e1cae9102ccc67a0
-P fd4ea3f626b6e4957d56c2369be711895735cfc37cfde65650a6682ad5a3eb1a
-R 6950494a507d409a31ba9db8450c7ab5
-U drh
-Z 19246c5f3c2f1a430773bc8dc29b5ece
+P f3a2eb979f1003e8249e613b34afd345f157c0d54b4f05ea0db230ef70e71351
+R 7052bf13a0b7767c57dc2a61770c6de9
+U dan
+Z 52db8ae5f9c9b6085061c878477364c6
index 81c794e6642b2a71ad834132aa6d5b2d95362cb3..90bf8371f0b94d137ccd45c021b2d5d439e3127f 100644 (file)
@@ -1 +1 @@
-f3a2eb979f1003e8249e613b34afd345f157c0d54b4f05ea0db230ef70e71351
\ No newline at end of file
+e16da5af822ef31d7e05992403cf9787fbb3d9abb0b5283aba55ea07e1830a72
\ No newline at end of file
index e3cfe35cd29003e2ff1cb3349fef465318c7ff43..adc89f5a7c5d8b5922ff3295dffcb806f124fc5e 100644 (file)
@@ -3951,6 +3951,7 @@ static void unixModeBit(unixFile *pFile, unsigned char mask, int *pArg){
 
 /* Forward declaration */
 static int unixGetTempname(int nBuf, char *zBuf);
+static int unixFcntlExternalReader(unixFile*, int*);
 
 /*
 ** Information and control of an open file handle.
@@ -4067,6 +4068,10 @@ static int unixFileControl(sqlite3_file *id, int op, void *pArg){
       return proxyFileControl(id,op,pArg);
     }
 #endif /* SQLITE_ENABLE_LOCKING_STYLE && defined(__APPLE__) */
+
+    case SQLITE_FCNTL_EXTERNAL_READER: {
+      return unixFcntlExternalReader((unixFile*)id, (int*)pArg);
+    }
   }
   return SQLITE_NOTFOUND;
 }
@@ -4312,6 +4317,40 @@ struct unixShm {
 #define UNIX_SHM_BASE   ((22+SQLITE_SHM_NLOCK)*4)         /* first lock byte */
 #define UNIX_SHM_DMS    (UNIX_SHM_BASE+SQLITE_SHM_NLOCK)  /* deadman switch */
 
+/*
+** Use F_GETLK to check whether or not there are any readers with open
+** wal-mode transactions in other processes on database file pFile. If
+** no error occurs, return SQLITE_OK and set (*piOut) to 1 if there are 
+** such transactions, or 0 otherwise. If an error occurs, return an
+** SQLite error code. The final value of *piOut is undefined in this
+** case.
+*/
+static int unixFcntlExternalReader(unixFile *pFile, int *piOut){
+  int rc = SQLITE_OK;
+  *piOut = 0;
+  if( pFile->pShm){
+    unixShmNode *pShmNode = pFile->pShm->pShmNode;
+    struct flock f;
+
+    memset(&f, 0, sizeof(f));
+    f.l_type = F_WRLCK;
+    f.l_whence = SEEK_SET;
+    f.l_start = UNIX_SHM_BASE + 3;
+    f.l_len = SQLITE_SHM_NLOCK - 3;
+
+    sqlite3_mutex_enter(pShmNode->pShmMutex);
+    if( osFcntl(pShmNode->hShm, F_GETLK, &f)<0 ){
+      rc = SQLITE_IOERR_LOCK;
+    }else{
+      *piOut = (f.l_type!=F_UNLCK);
+    }
+    sqlite3_mutex_leave(pShmNode->pShmMutex);
+  }
+
+  return rc;
+}
+
+
 /*
 ** Apply posix advisory locks for all bytes from ofst through ofst+n-1.
 **
index c018767d13a64c33946c0fae7f31f193896b5f3f..9085dc882a2be5923522cdabc00dcd47d1a244a9 100644 (file)
@@ -1128,6 +1128,19 @@ struct sqlite3_io_methods {
 ** file to the database file, but before the *-shm file is updated to
 ** record the fact that the pages have been checkpointed.
 ** </ul>
+**
+** <li>[[SQLITE_FCNTL_EXTERNAL_READER]]
+** The EXPERIMENTAL [SQLITE_FCNTL_EXTERNAL_READER] opcode is used to detect
+** whether or not there is a database client in another process with a wal-mode 
+** transaction open on the database or not. It is only available on unix.The
+** (void*) argument passed with this file-control should be a pointer to a
+** value of type (int). The integer value is set to 1 if the database is a wal
+** mode database and there exists at least one client in another process that
+** currently has an SQL transaction open on the database. It is set to 0 if 
+** the database is not a wal-mode db, or if there is no such connection in any
+** other process. This opcode cannot be used to detect transactions opened
+** by clients within the current process, only within other processes.
+** </ul>
 */
 #define SQLITE_FCNTL_LOCKSTATE               1
 #define SQLITE_FCNTL_GET_LOCKPROXYFILE       2
@@ -1168,6 +1181,8 @@ struct sqlite3_io_methods {
 #define SQLITE_FCNTL_RESERVE_BYTES          38
 #define SQLITE_FCNTL_CKPT_START             39
 
+#define SQLITE_FCNTL_EXTERNAL_READER        40
+
 /* deprecated names */
 #define SQLITE_GET_LOCKPROXYFILE      SQLITE_FCNTL_GET_LOCKPROXYFILE
 #define SQLITE_SET_LOCKPROXYFILE      SQLITE_FCNTL_SET_LOCKPROXYFILE
index 7d13da3733959b95b06cb478cbc5e2a9851eaf3d..7cb56d3be9151c1c3b94b07d171b15d2459c3737 100644 (file)
@@ -6514,6 +6514,42 @@ static int SQLITE_TCLAPI file_control_tempfilename(
   return TCL_OK;  
 }
 
+/*
+** tclcmd:   file_control_external_reader DB ?AUXDB?
+**
+** Return a string that is a temporary filename
+*/
+static int SQLITE_TCLAPI file_control_external_reader(
+  ClientData clientData, /* Pointer to sqlite3_enable_XXX function */
+  Tcl_Interp *interp,    /* The TCL interpreter that invoked this command */
+  int objc,              /* Number of arguments */
+  Tcl_Obj *CONST objv[]  /* Command arguments */
+){
+  sqlite3 *db;
+  const char *zName = "main";
+  int iRes = 0;
+  int rc = SQLITE_OK;
+
+  if( objc!=2 && objc!=3 ){
+    Tcl_AppendResult(interp, "wrong # args: should be \"",
+        Tcl_GetStringFromObj(objv[0], 0), " DB ?AUXDB?", 0);
+    return TCL_ERROR;
+  }
+  if( getDbPointer(interp, Tcl_GetString(objv[1]), &db) ){
+    return TCL_ERROR;
+  }
+  if( objc==3 ){
+    zName = Tcl_GetString(objv[2]);
+  }
+  rc = sqlite3_file_control(db, zName, SQLITE_FCNTL_EXTERNAL_READER, &iRes);
+  if( rc!=SQLITE_OK ){
+    Tcl_SetResult(interp, (char *)t1ErrorName(rc), TCL_STATIC);
+    return TCL_ERROR;
+  }
+  Tcl_SetObjResult(interp, Tcl_NewIntObj(iRes));
+  return TCL_OK;
+}
+
 
 /*
 ** tclcmd:   sqlite3_vfs_list
@@ -8452,6 +8488,7 @@ int Sqlitetest1_Init(Tcl_Interp *interp){
      { "file_control_vfsname",        file_control_vfsname,         0   },
      { "file_control_reservebytes",   file_control_reservebytes,    0   },
      { "file_control_tempfilename",   file_control_tempfilename,    0   },
+     { "file_control_external_reader",   file_control_external_reader,    0   },
      { "sqlite3_vfs_list",           vfs_list,     0   },
      { "sqlite3_create_function_v2", test_create_function_v2, 0 },
 
diff --git a/test/external_reader.test b/test/external_reader.test
new file mode 100644 (file)
index 0000000..5d29398
--- /dev/null
@@ -0,0 +1,74 @@
+# 2021 April 2
+#
+# The author disclaims copyright to this source code.  In place of
+# a legal notice, here is a blessing:
+#
+#    May you do good and not evil.
+#    May you find forgiveness for yourself and forgive others.
+#    May you share freely, never taking more than you give.
+#
+#***********************************************************************
+#
+
+set testdir [file dirname $argv0]
+source $testdir/tester.tcl
+source $testdir/lock_common.tcl
+set testprefix external_reader
+
+ifcapable !wal {
+  finish_test 
+  return 
+}
+if {$::tcl_platform(platform)!="unix"} {
+  finish_test 
+  return
+}
+
+do_multiclient_test tn {
+
+  set bExternal 1
+  if {[info commands db3]!=""} { set bExternal 0 }
+
+  do_test 1.$tn.0 {
+    sql1 {
+      PRAGMA journal_mode = wal;
+      CREATE TABLE t1(a, b);
+      INSERT INTO t1 VALUES(1, 2);
+    }
+  } {wal}
+
+  do_test 1.$tn.1 {
+    sql2 { SELECT * FROM t1 }
+  } {1 2}
+
+  do_test 1.$tn.2 {
+    code1 {
+      file_control_external_reader db
+    } 
+  } {0}
+
+  do_test 1.$tn.3 {
+    sql2 { 
+      BEGIN;
+        SELECT * FROM t1;
+    }
+  } {1 2}
+
+  do_test 1.$tn.4 {
+    code1 {
+      file_control_external_reader db
+    } 
+  } $bExternal
+
+  do_test 1.$tn.5 {
+    sql2 { COMMIT }
+  } {}
+
+  do_test 1.$tn.6 {
+    code1 { file_control_external_reader db } 
+  } 0
+
+}
+
+
+finish_test