]> git.ipfire.org Git - thirdparty/sqlite.git/commitdiff
Redesign for better legacy compatibility. Add the sqlite3_uri_key() interface.
authordrh <drh@noemail.net>
Sat, 11 Jan 2020 16:08:31 +0000 (16:08 +0000)
committerdrh <drh@noemail.net>
Sat, 11 Jan 2020 16:08:31 +0000 (16:08 +0000)
FossilOrigin-Name: bcb43d11c4d0be36888c9e968ccdf85e7d7fccd72a29866f85c014e0562d4b93

ext/misc/urifuncs.c [new file with mode: 0644]
ext/rbu/sqlite3rbu.c
manifest
manifest.uuid
src/loadext.c
src/main.c
src/pager.c
src/pager.h
src/sqlite.h.in
src/sqlite3ext.h

diff --git a/ext/misc/urifuncs.c b/ext/misc/urifuncs.c
new file mode 100644 (file)
index 0000000..5fc520a
--- /dev/null
@@ -0,0 +1,207 @@
+/*
+** 2020-01-11
+**
+** 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.
+**
+******************************************************************************
+**
+** This SQLite extension implements various SQL functions used to access
+** the following SQLite C-language APIs:
+**
+**         sqlite3_uri_parameter()
+**         sqlite3_uri_boolean()
+**         sqlite3_uri_int64()
+**         sqlite3_uri_key()
+**         sqlite3_filename_database()
+**         sqlite3_filename_journal()
+**         sqlite3_filename_wal()
+**         sqlite3_db_filename()
+**
+** These SQL functions are for testing and demonstration purposes only.
+*/
+#include "sqlite3ext.h"
+SQLITE_EXTENSION_INIT1
+#include <assert.h>
+#include <string.h>
+
+/*
+** SQL function:    sqlite3_db_filename(SCHEMA) 
+**
+** Return the filename corresponding to SCHEMA.
+*/
+static void func_db_filename(
+  sqlite3_context *context,
+  int argc,
+  sqlite3_value **argv
+){
+  const char *zSchema = (const char*)sqlite3_value_text(argv[0]);
+  sqlite3 *db = sqlite3_context_db_handle(context);
+  const char *zFile = sqlite3_db_filename(db, zSchema);
+  sqlite3_result_text(context, zFile, -1, SQLITE_TRANSIENT);
+}
+
+/*
+** SQL function:    sqlite3_uri_parameter(SCHEMA,NAME) 
+**
+** Return the value of the NAME query parameter to the database for SCHEMA
+*/
+static void func_uri_parameter(
+  sqlite3_context *context,
+  int argc,
+  sqlite3_value **argv
+){
+  const char *zSchema = (const char*)sqlite3_value_text(argv[0]);
+  sqlite3 *db = sqlite3_context_db_handle(context);
+  const char *zName = (const char*)sqlite3_value_text(argv[1]);
+  const char *zFile = sqlite3_db_filename(db, zSchema);
+  const char *zRes = sqlite3_uri_parameter(zFile, zName);
+  sqlite3_result_text(context, zRes, -1, SQLITE_TRANSIENT);
+}
+
+/*
+** SQL function:    sqlite3_uri_boolean(SCHEMA,NAME,DEFAULT) 
+**
+** Return the boolean value of the NAME query parameter to
+** the database for SCHEMA
+*/
+static void func_uri_boolean(
+  sqlite3_context *context,
+  int argc,
+  sqlite3_value **argv
+){
+  const char *zSchema = (const char*)sqlite3_value_text(argv[0]);
+  sqlite3 *db = sqlite3_context_db_handle(context);
+  const char *zName = (const char*)sqlite3_value_text(argv[1]);
+  const char *zFile = sqlite3_db_filename(db, zSchema);
+  int iDflt = sqlite3_value_int(argv[2]);
+  int iRes = sqlite3_uri_boolean(zFile, zName, iDflt);
+  sqlite3_result_int(context, iRes);
+}
+
+/*
+** SQL function:    sqlite3_uri_key(SCHEMA,N)
+**
+** Return the name of the Nth query parameter
+*/
+static void func_uri_key(
+  sqlite3_context *context,
+  int argc,
+  sqlite3_value **argv
+){
+  const char *zSchema = (const char*)sqlite3_value_text(argv[0]);
+  sqlite3 *db = sqlite3_context_db_handle(context);
+  int N = sqlite3_value_int(argv[1]);
+  const char *zFile = sqlite3_db_filename(db, zSchema);
+  const char *zRes = sqlite3_uri_key(zFile, N);
+  sqlite3_result_text(context, zRes, -1, SQLITE_TRANSIENT);
+}
+
+/*
+** SQL function:    sqlite3_uri_int64(SCHEMA,NAME,DEFAULT) 
+**
+** Return the int64 value of the NAME query parameter to
+** the database for SCHEMA
+*/
+static void func_uri_int64(
+  sqlite3_context *context,
+  int argc,
+  sqlite3_value **argv
+){
+  const char *zSchema = (const char*)sqlite3_value_text(argv[0]);
+  sqlite3 *db = sqlite3_context_db_handle(context);
+  const char *zName = (const char*)sqlite3_value_text(argv[1]);
+  const char *zFile = sqlite3_db_filename(db, zSchema);
+  sqlite3_int64 iDflt = sqlite3_value_int64(argv[2]);
+  sqlite3_int64 iRes = sqlite3_uri_int64(zFile, zName, iDflt);
+  sqlite3_result_int64(context, iRes);
+}
+
+/*
+** SQL function:    sqlite3_filename_database(SCHEMA)
+**
+** Return the database filename for SCHEMA
+*/
+static void func_filename_database(
+  sqlite3_context *context,
+  int argc,
+  sqlite3_value **argv
+){
+  const char *zSchema = (const char*)sqlite3_value_text(argv[0]);
+  sqlite3 *db = sqlite3_context_db_handle(context);
+  const char *zFile = sqlite3_db_filename(db, zSchema);
+  const char *zRes = sqlite3_filename_database(zFile);
+  sqlite3_result_text(context, zRes, -1, SQLITE_TRANSIENT);
+}
+
+/*
+** SQL function:    sqlite3_filename_journal(SCHEMA)
+**
+** Return the rollback journal filename for SCHEMA
+*/
+static void func_filename_journal(
+  sqlite3_context *context,
+  int argc,
+  sqlite3_value **argv
+){
+  const char *zSchema = (const char*)sqlite3_value_text(argv[0]);
+  sqlite3 *db = sqlite3_context_db_handle(context);
+  const char *zFile = sqlite3_db_filename(db, zSchema);
+  const char *zRes = sqlite3_filename_journal(zFile);
+  sqlite3_result_text(context, zRes, -1, SQLITE_TRANSIENT);
+}
+
+/*
+** SQL function:    sqlite3_filename_wal(SCHEMA)
+**
+** Return the WAL filename for SCHEMA
+*/
+static void func_filename_wal(
+  sqlite3_context *context,
+  int argc,
+  sqlite3_value **argv
+){
+  const char *zSchema = (const char*)sqlite3_value_text(argv[0]);
+  sqlite3 *db = sqlite3_context_db_handle(context);
+  const char *zFile = sqlite3_db_filename(db, zSchema);
+  const char *zRes = sqlite3_filename_wal(zFile);
+  sqlite3_result_text(context, zRes, -1, SQLITE_TRANSIENT);
+}
+
+#ifdef _WIN32
+__declspec(dllexport)
+#endif
+int sqlite3_urifuncs_init(
+  sqlite3 *db, 
+  char **pzErrMsg, 
+  const sqlite3_api_routines *pApi
+){
+  static const struct {
+    const char *zFuncName;
+    int nArg;
+    void (*xFunc)(sqlite3_context*,int,sqlite3_value**);
+  } aFunc[] = {
+    { "sqlite3_db_filename",       1, func_db_filename       },
+    { "sqlite3_uri_parameter",     2, func_uri_parameter     },
+    { "sqlite3_uri_boolean",       3, func_uri_boolean       },
+    { "sqlite3_uri_int64",         3, func_uri_int64         },
+    { "sqlite3_uri_key",           2, func_uri_key           },
+    { "sqlite3_filename_database", 1, func_filename_database },
+    { "sqlite3_filename_journal",  1, func_filename_journal  },
+    { "sqlite3_filename_wal",      1, func_filename_wal      },
+  };
+  int rc = SQLITE_OK;
+  int i;
+  SQLITE_EXTENSION_INIT2(pApi);
+  (void)pzErrMsg;  /* Unused parameter */
+  for(i=0; rc==SQLITE_OK && i<sizeof(aFunc)/sizeof(aFunc[0]); i++){
+    rc = sqlite3_create_function(db, aFunc[i].zFuncName, aFunc[i].nArg,
+                     SQLITE_UTF8, 0,
+                     aFunc[i].xFunc, 0, 0);
+  }
+  return rc;
+}
index b2e23b16547b92b89d04e83d743bb78d050d7b3b..8e82cd8b92c27ae15f5334982769ef3173bea348 100644 (file)
@@ -4936,33 +4936,6 @@ static int rbuVfsShmUnmap(sqlite3_file *pFile, int delFlag){
   return rc;
 }
 
-/* 
-** A main database named zName has just been opened. The following 
-** function returns a pointer to a buffer owned by SQLite that contains
-** the name of the *-wal file this db connection will use. SQLite
-** happens to pass a pointer to this buffer when using xAccess()
-** or xOpen() to operate on the *-wal file.  
-*/
-static const char *rbuMainToWal(const char *zName, int flags){
-  int n = (int)strlen(zName);
-  const char *z = &zName[n];
-  if( flags & SQLITE_OPEN_URI ){
-    int odd = 0;
-    while( 1 ){
-      if( z[0]==0 ){
-        odd = 1 - odd;
-        if( odd && z[1]==0 ) break;
-      }
-      z++;
-    }
-    z += 2;
-  }else{
-    while( *z==0 ) z++;
-  }
-  z += (n + 8 + 2);
-  return z;
-}
-
 /*
 ** Open an rbu file handle.
 */
@@ -5011,7 +4984,7 @@ static int rbuVfsOpen(
       ** the name of the *-wal file this db connection will use. SQLite
       ** happens to pass a pointer to this buffer when using xAccess()
       ** or xOpen() to operate on the *-wal file.  */
-      pFd->zWal = rbuMainToWal(zName, flags);
+      pFd->zWal = sqlite3_filename_wal(zName);
     }
     else if( flags & SQLITE_OPEN_WAL ){
       rbu_file *pDb = rbuFindMaindb(pRbuVfs, zName, 0);
@@ -5026,7 +4999,7 @@ static int rbuVfsOpen(
           char *zCopy;
           if( rbuIsVacuum(pDb->pRbu) ){
             zBase = sqlite3_db_filename(pDb->pRbu->dbRbu, "main");
-            zBase = rbuMainToWal(zBase, SQLITE_OPEN_URI);
+            zBase = sqlite3_filename_wal(zBase);
           }
           nCopy = strlen(zBase);
           zCopy = sqlite3_malloc64(nCopy+2);
index e10370b83b34ccd8ad3d0830b7d5fb447dadc4c1..e02228bbba2b8b5f1ad8535fe08aa12d7294f39f 100644 (file)
--- a/manifest
+++ b/manifest
@@ -1,5 +1,5 @@
-C Rearchitect\sthe\sway\sin\swhich\sfilenames\sare\sstored\sin\sthe\sPager\sobject\sso\sthat\nthe\ssqlite3_uri_parameter()\sinterface\swill\swork\sfrom\sjournal\sand\sWAL\sfilenames\ntoo.\s\sThis\scheck-in\simplements\sthe\scentral\sidea,\sand\scompile\sand\sruns\ssomewhat,\nbut\scrashes\son\san\sextended\stest.
-D 2020-01-10T18:05:55.320
+C Redesign\sfor\sbetter\slegacy\scompatibility.\s\sAdd\sthe\ssqlite3_uri_key()\sinterface.
+D 2020-01-11T16:08:31.366
 F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1
 F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea
 F LICENSE.md df5091916dbb40e6e9686186587125e1b2ff51f022cc334e886c19a0e9982724
@@ -321,6 +321,7 @@ F ext/misc/stmt.c 8a8dc4675042e4551e4afe99b8d0cc7a4a2fc1a8dacc0a9ce1b1bbff145da9
 F ext/misc/templatevtab.c 8a16a91a5ceaccfcbd6aaaa56d46828806e460dd194965b3f77bf38f14b942c4
 F ext/misc/totype.c fa4aedeb07f66169005dffa8de3b0a2b621779fd44f85c103228a42afa71853b
 F ext/misc/unionvtab.c 36237f0607ca954ac13a4a0e2d2ac40c33bc6e032a5f55f431713061ef1625f9
+F ext/misc/urifuncs.c a0b02a607b4170552deeff26812bb2f09eed1cc72d1056a4296ae6be0c19d100
 F ext/misc/uuid.c 5bb2264c1b64d163efa46509544fd7500cb8769cb7c16dd52052da8d961505cf
 F ext/misc/vfslog.c 3b25c2f56ba60788db247287be6ab024b53c4afffd412b4876db563389be0d35
 F ext/misc/vfsstat.c 77b5b4235c9f7f11eddf82487c0a422944ac2f132dafd5af3be7a68a057b1cdb
@@ -369,7 +370,7 @@ F ext/rbu/rbuvacuum.test 55e101e90168c2b31df6c9638fe73dc7f7cc666b6142266d1563697
 F ext/rbu/rbuvacuum2.test b8e5b51dc8b2c0153373d024c0936be3f66f9234acbd6d0baab0869d56b14e6b
 F ext/rbu/rbuvacuum3.test 8addd82e4b83b4c93fa47428eae4fd0dbf410f8512c186f38e348feb49ba03dc
 F ext/rbu/rbuvacuum4.test a78898e438a44803eb2bc897ba3323373c9f277418e2d6d76e90f2f1dbccfd10
-F ext/rbu/sqlite3rbu.c 4e9a59aa80c03350a0ca5faa454dec894906537fbd98b3231604cc33baf174c8
+F ext/rbu/sqlite3rbu.c 77a47f3231f5f363b2c584dba3e310a7efdaf073ad8c18728ab846b38de2879c
 F ext/rbu/sqlite3rbu.h 1dc88ab7bd32d0f15890ea08d23476c4198d3da3056985403991f8c9cd389812
 F ext/rbu/test_rbu.c 03f6f177096a5f822d68d8e4069ad8907fe572c62ff2d19b141f59742821828a
 F ext/repair/README.md 92f5e8aae749a4dae14f02eea8e1bb42d4db2b6ce5e83dbcdd6b1446997e0c15
@@ -493,8 +494,8 @@ F src/hwtime.h cb1d7e3e1ed94b7aa6fde95ae2c2daccc3df826be26fc9ed7fd90d1750ae6144
 F src/in-operator.md 10cd8f4bcd225a32518407c2fb2484089112fd71
 F src/insert.c 5ba8fd376f539240939ae76b5bc9fa7ad9a0d86e9914ecd11eb7002204138c11
 F src/legacy.c d7874bc885906868cd51e6c2156698f2754f02d9eee1bae2d687323c3ca8e5aa
-F src/loadext.c d74f5e7bd51f3c9d283442473eb65aef359664efd6513591c03f01881c4ae2da
-F src/main.c abc034557685db2bead003e7d6b2bd74bf1a44c4d3bfe9ddcf35dc90524a8c21
+F src/loadext.c 8cd803f1747c03a50b32fe87ebfb5851998d0cdafefe02737daa95e0616b42bb
+F src/main.c 347687f4d843cb1660ec4bafe17fd3a9444d1208900308fddf6b6a418f091171
 F src/malloc.c eaa4dc9602ce28b077f7de2eb275db2be270c5cc56d7fec5466301bd9b80e2f5
 F src/mem0.c 6a55ebe57c46ca1a7d98da93aaa07f99f1059645
 F src/mem1.c c12a42539b1ba105e3707d0e628ad70e611040d8f5e38cf942cee30c867083de
@@ -517,8 +518,8 @@ F src/os_setup.h 0dbaea40a7d36bf311613d31342e0b99e2536586
 F src/os_unix.c ad7640c04eed946052a3b12856362a773d0a717696707313037186df0e2b59f2
 F src/os_win.c 035a813cbd17f355bdcad7ab894af214a9c13a1db8aeac902365350b98cd45a7
 F src/os_win.h 7b073010f1451abe501be30d12f6bc599824944a
-F src/pager.c 14ae8110bcb65a703d91131586848fe256c1a3cbbbc3eb1791090dbf925aa742
-F src/pager.h e541ff7e1931e6e2165c38c7ff38cd1af8df0e20472ee8596479fd53c6aa149d
+F src/pager.c 52a2923ebd6ca0e2ce917b5860ffe893a344481b5fa4c2a2568ad156168bc558
+F src/pager.h 71fe1d5016ec54d0cc5d344cd474e563450b438c59f535e8c1ec8a13b1373f14
 F src/parse.y c8d2de64db469fd56e0fa24da46cd8ec8523eb98626567d2708df371b47fdc3f
 F src/pcache.c 385ff064bca69789d199a98e2169445dc16e4291fa807babd61d4890c3b34177
 F src/pcache.h 4f87acd914cef5016fae3030343540d75f5b85a1877eed1a2a19b9f284248586
@@ -532,9 +533,9 @@ F src/resolve.c 1139e3157c710c6e6f04fe726f4e0d8bdb1ae89a276d3b0ca4975af163141c9c
 F src/rowset.c d977b011993aaea002cab3e0bb2ce50cf346000dff94e944d547b989f4b1fe93
 F src/select.c 924b61cef57033a8ca1ed3dcffd02445a7dd0c837cc849b2e4117251cac831f5
 F src/shell.c.in 43d3cfbee97d78ca5782dc53e4c1e22d3cc15c91beff20889dc60551f47eab9f
-F src/sqlite.h.in 4022f00351aec1ad99b9dcadc4fbe70a1db0e306e84fee509daf97a82ef044a4
+F src/sqlite.h.in c4713ccfa76dda5a96176d315ef5861d47f8d4815cc192d893b282a7f35669e9
 F src/sqlite3.rc 5121c9e10c3964d5755191c80dd1180c122fc3a8
-F src/sqlite3ext.h 72af51aa4e912e14cd495fb6e7fac65f0940db80ed950d90911aff292cc47ce2
+F src/sqlite3ext.h b0f776a0d042b23b6bcbb6b0943e8a3768c7f0b438a275e7168f0204e223a4db
 F src/sqliteInt.h 7a29ba700a51eeb925731749a570cf3859f6a58ed94797ecf47508875b0ba279
 F src/sqliteLimit.h 1513bfb7b20378aa0041e7022d04acb73525de35b80b252f1b83fedb4de6a76b
 F src/status.c 9ff2210207c6c3b4d9631a8241a7d45ab1b26a0e9c84cb07a9b5ce2de9a3b278
@@ -1856,10 +1857,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 0a500da6aa659a8e73206e6d22ddbf2da5e4f1d1d551eeb66433163a3e13109d
-R dd17ff42793e7be350eec0c77a1551ba
-T *branch * enhanced-uri
-T *sym-enhanced-uri *
-T -sym-trunk *
+P 2ae77bd2335708343bce4541b4d2cf16edfe3fd5bc2dfb93757238c926aa960b
+R 3c2b1115f362d773ce1134af1c5678e6
 U drh
-Z a098e9553bba752fd93040dc261a9c76
+Z d49a59ecf45703e7c01f38027d23c9e9
index 980ac6d4ce895c8331f456035ff5de7ed7325c89..5f0da69f8b941697ca9e185ef3c2597eb814b33a 100644 (file)
@@ -1 +1 @@
-2ae77bd2335708343bce4541b4d2cf16edfe3fd5bc2dfb93757238c926aa960b
\ No newline at end of file
+bcb43d11c4d0be36888c9e968ccdf85e7d7fccd72a29866f85c014e0562d4b93
\ No newline at end of file
index 2622a81711f1a9c5a94bbef90d32ec01e6289e18..245e9b004dbf7afe796c0888e6babda7cc79ab9f 100644 (file)
@@ -470,6 +470,10 @@ static const sqlite3_api_routines sqlite3Apis = {
 #endif
   /* Version 3.31.0 and later */
   sqlite3_hard_heap_limit64,
+  sqlite3_uri_key,
+  sqlite3_filename_database,
+  sqlite3_filename_journal,
+  sqlite3_filename_wal,
 };
 
 /*
index 5426c8d7153a7f4bb7b210919fef092f16f1e85a..deec659ec77bedaa8e92427b99266d7e2c7440c4 100644 (file)
@@ -4241,25 +4241,6 @@ int sqlite3_test_control(int op, ...){
   return rc;
 }
 
-#ifdef SQLITE_DEBUG
-/*
-** This routine appears inside assert() statements only.
-**
-** Return the number of URI parameters that follow the filename.
-*/
-int sqlite3UriCount(const char *z){
-  int n = 0;
-  if( z==0 ) return 0;
-  z += strlen(z)+1;
-  while( z[0] ){
-    z += strlen(z)+1;
-    z += strlen(z)+1;
-    n++;
-  }
-  return n;
-}
-#endif /* SQLITE_DEBUG */
-
 /*
 ** This is a utility routine, useful to VFS implementations, that checks
 ** to see if a database file was a URI that contained a specific query 
@@ -4272,21 +4253,30 @@ int sqlite3UriCount(const char *z){
 ** returns a NULL pointer.
 */
 const char *sqlite3_uri_parameter(const char *zFilename, const char *zParam){
-  const Pager *pPager;
-  const char *z;
   if( zFilename==0 || zParam==0 ) return 0;
-  pPager = sqlite3PagerFromFilename(zFilename);
-  assert( pPager!=0 );
-  z = sqlite3PagerQueryParameters(pPager);
-  while( z[0] ){
-    int x = strcmp(z, zParam);
-    z += sqlite3Strlen30(z) + 1;
-    if( x==0 ) return z;
-    z += sqlite3Strlen30(z) + 1;
+  zFilename += sqlite3Strlen30(zFilename) + 1;
+  while( zFilename[0] ){
+    int x = strcmp(zFilename, zParam);
+    zFilename += sqlite3Strlen30(zFilename) + 1;
+    if( x==0 ) return zFilename;
+    zFilename += sqlite3Strlen30(zFilename) + 1;
   }
   return 0;
 }
 
+/*
+** Return a pointer to the name of Nth query parameter of the filename.
+*/
+const char *sqlite3_uri_key(const char *zFilename, int N){
+  if( zFilename==0 || N<0 ) return 0;
+  zFilename += sqlite3Strlen30(zFilename) + 1;
+  while( zFilename[0] && (N--)>0 ){
+    zFilename += sqlite3Strlen30(zFilename) + 1;
+    zFilename += sqlite3Strlen30(zFilename) + 1;
+  }
+  return zFilename[0] ? zFilename : 0;
+}
+
 /*
 ** Return a boolean value for a query parameter.
 */
@@ -4312,6 +4302,25 @@ sqlite3_int64 sqlite3_uri_int64(
   return bDflt;
 }
 
+/*
+** The Pager stores the Journal filename, WAL filename, and Database filename
+** consecutively in memory, in that order, with prefixes \000\001\000,
+** \002\000, and \003\000, in that order.  Thus the three names look like query
+** parameters if you start at the first prefix.
+**
+** This routine backs up a filename to the start of the first prefix.
+**
+** This only works if the filenamed passed in was obtained from the Pager.
+*/
+static const char *startOfNameList(const char *zName){
+  while( zName[0]!='\001' || zName[1]!=0 ){
+    zName -= 3;
+    while( zName[0]!='\000' ){ zName--; }
+    zName++;
+  }
+  return zName-1;
+}
+
 /*
 ** Translate a filename that was handed to a VFS routine into the corresponding
 ** database, journal, or WAL file.
@@ -4323,19 +4332,13 @@ sqlite3_int64 sqlite3_uri_int64(
 ** corruption.
 */
 const char *sqlite3_filename_database(const char *zFilename){
-  const Pager *pPager = sqlite3PagerFromFilename(zFilename);
-  assert( pPager!=0 );
-  return sqlite3PagerFilename(pPager, 0);
+  return sqlite3_uri_parameter(zFilename - 3, "\003");
 }
 const char *sqlite3_filename_journal(const char *zFilename){
-  const Pager *pPager = sqlite3PagerFromFilename(zFilename);
-  assert( pPager!=0 );
-  return sqlite3PagerJournalFilename(pPager);
+  return sqlite3_uri_parameter(startOfNameList(zFilename), "\001");
 }
 const char *sqlite3_filename_wal(const char *zFilename){
-  const Pager *pPager = sqlite3PagerFromFilename(zFilename);
-  assert( pPager!=0 );
-  return sqlite3PagerWalFilename(pPager);
+  return sqlite3_uri_parameter(startOfNameList(zFilename), "\002");
 }
 
 /*
index 685f0462b12e9dec5432ab7b08bc28988f9d4f81..d023682b2a537c87760bd0a33a33a1806431f688 100644 (file)
@@ -696,7 +696,6 @@ struct Pager {
   Pgno mxPgno;                /* Maximum allowed size of the database */
   i64 journalSizeLimit;       /* Size limit for persistent journal files */
   char *zFilename;            /* Name of the database file */
-  char *zQueryParam;          /* URI query parameters on the filename */
   char *zJournal;             /* Name of the journal file */
   int (*xBusyHandler)(void*); /* Function to call when busy */
   void *pBusyHandlerArg;      /* Context argument for xBusyHandler */
@@ -4839,30 +4838,30 @@ int sqlite3PagerOpen(
   **     Database file handle            (pVfs->szOsFile bytes)
   **     Sub-journal file handle         (journalFileSize bytes)
   **     Main journal file handle        (journalFileSize bytes)
-  **     Pointer back to self            (sizeof(*Pager) bytes)
+  **     \0\1\0 journal prefix           (3 bytes)
+  **     Journal filename                (nPathname+8+1 bytes)
+  **     \2\0 WAL prefix                 (2 bytes)
+  **     WAL filename                    (nPathname+4+1 bytes)
+  **     \3\0 database prefix            (2 bytes)
   **     Database file name              (nPathname+1 bytes)
   **     URI query parameters            (nUriByte bytes)
-  **     padding for 8-byte alignment
-  **     Pointer back to self            (sizeof(*Pager) bytes)
-  **     WAL filename                    (nPathname+4+1 bytes)
-  **     padding for 8-byte alignment
-  **     Pointer back to self            (sizeof(*Pager) bytes)
-  **     Journal file name               (nPathname+8+1 bytes)
+  **     \0\0 terminator                 (2 bytes)
   */
   pPtr = (u8 *)sqlite3MallocZero(
     ROUND8(sizeof(*pPager)) +            /* Pager structure */
     ROUND8(pcacheSize) +                 /* PCache object */
     ROUND8(pVfs->szOsFile) +             /* The main db file */
     journalFileSize * 2 +                /* The two journal files */
-    sizeof(Pager*) +                     /* Self-pointer for database */
-    ROUND8(nPathname + 1 + nUriByte) +   /* database filename + query params */
-    sizeof(Pager*) +                     /* Self-pointer for journal */
-    ROUND8(nPathname + 8 + 2) +          /* zJournal */
+    3 +                                  /* Journal prefix */
+    nPathname + 8 + 1 +                  /* Journal filename */
 #ifndef SQLITE_OMIT_WAL
-    sizeof(Pager*) +                     /* Self-pointer for zWal */
-    ROUND8(nPathname + 4 + 2) +          /* zWal */
+    2 +                                  /* WAL prefix */
+    nPathname + 4 + 1 +                  /* WAL filename */
 #endif
-    0
+    2 +                                  /* Database prefix */
+    nPathname + 1 +                      /* database filename */
+    nUriByte +                           /* query parameters */
+    2                                    /* Terminator */
   );
   assert( EIGHT_BYTE_ALIGNMENT(SQLITE_INT_TO_PTR(journalFileSize)) );
   if( !pPtr ){
@@ -4876,33 +4875,47 @@ int sqlite3PagerOpen(
   pPager->jfd =  (sqlite3_file*)pPtr;     pPtr += journalFileSize;
   assert( EIGHT_BYTE_ALIGNMENT(pPager->jfd) );
 
-  /* Fill in the Pager.zFilename and pPager.zQueryParam fields */
-  assert( EIGHT_BYTE_ALIGNMENT(pPtr) );
-  memcpy(pPtr, &pPager, sizeof(pPager));  pPtr += sizeof(pPager);
-  pPager->zFilename = (char*)pPtr;
-  if( nPathname==0 ) zPathname = "";
-  memcpy(pPtr, zPathname, nPathname);
-  pPager->zQueryParam = pPager->zFilename + nPathname + 1;
-  if( zUri ) memcpy(pPager->zQueryParam, zUri, nUriByte);
-  assert( nUriByte>=1 );
-  assert( nUriByte >= nUri*3 + 1 );
-  pPtr += ROUND8(nPathname + 1 + nUriByte);
+
+  /* Fill in Pager.zJournal */
+  pPtr[1] = '\001';                       pPtr += 3;
+  if( nPathname>0 ){
+    pPager->zJournal = (char*)pPtr;
+    memcpy(pPtr, zPathname, nPathname);   pPtr += nPathname;
+    memcpy(pPtr, "-journal",8);           pPtr += 8 + 1;
+#ifdef SQLITE_ENABLE_8_3_NAMES
+    sqlite3FileSuffix3(zFilename,pPager->zJournal);
+    pPtr = (u8*)(pPager->zJournal + sqlite3Strlen30(pPager->zJournal)+1);
+#endif
+  }else{
+    pPager->zJournal = 0;
+    pPtr++;
+  }
 
 #ifndef SQLITE_OMIT_WAL
   /* Fill in Pager.zWal */
-  assert( EIGHT_BYTE_ALIGNMENT(pPtr) );
-  memcpy(pPtr, &pPager, sizeof(pPager));  pPtr += sizeof(pPager);
-  pPager->zWal = (char*)pPtr;
-  memcpy(pPtr, zPathname, nPathname);
-  memcpy(pPtr+nPathname, "-wal", 4);      pPtr += ROUND8(nPathname + 4 + 2);
+  pPtr[0] = '\002'; pPtr[1] = 0;          pPtr += 2;
+  if( nPathname>0 ){
+    pPager->zWal = (char*)pPtr;
+    memcpy(pPtr, zPathname, nPathname);   pPtr += nPathname;
+    memcpy(pPtr, "-wal", 4);              pPtr += 4 + 1;
+#ifdef SQLITE_ENABLE_8_3_NAMES
+    sqlite3FileSuffix3(zFilename, pPager->zWal);
+    pPtr = (u8*)(pPager->zWal + sqlite3Strlen30(pPager->zWal)+1);
+#endif
+  }else{
+    pPager->zWal = 0;
+    pPtr++;
+  }
 #endif
 
-  /* Fill in Pager.zJournal */
-  assert( EIGHT_BYTE_ALIGNMENT(pPtr) );
-  memcpy(pPtr, &pPager, sizeof(pPager));  pPtr += sizeof(pPager);
-  pPager->zJournal = (char*)pPtr;
-  memcpy(pPtr, zPathname, nPathname);
-  memcpy(pPtr+nPathname, "-journal",8); /*pPtr += ROUND8(nPathname + 8 + 2);*/
+  /* Fill in the Pager.zFilename and pPager.zQueryParam fields */
+  pPtr[0] = '\003'; pPtr[1] = 0;          pPtr += 2;
+  pPager->zFilename = (char*)pPtr;
+  memcpy(pPtr, zPathname, nPathname);     pPtr += nPathname + 1;
+  if( zUri ){
+    memcpy(pPtr, zUri, nUriByte);      /* pPtr += nUriByte; // not needed */
+  }
+  /* Double-zero terminator implied by the sqlite3MallocZero */
 
   if( nPathname ) sqlite3DbFree(0, zPathname);
   pPager->pVfs = pVfs;
@@ -7018,50 +7031,13 @@ int sqlite3PagerSavepoint(Pager *pPager, int op, int iSavepoint){
 ** behavior.  But when the Btree needs to know the filename for matching to
 ** shared cache, it uses nullIfMemDb==0 so that in-memory databases can
 ** participate in shared-cache.
-*/
-const char *sqlite3PagerFilename(const Pager *pPager, int nullIfMemDb){
-  return (nullIfMemDb && pPager->memDb) ? "" : pPager->zFilename;
-}
-
-/*
-** Return the name of the Journal file or WAL file of the given pager.
-*/
-const char *sqlite3PagerJournalFilename(const Pager *pPager){
-  assert( pPager!=0 );
-  return pPager->zJournal;
-}
-#ifndef SQLITE_OMIT_WAL
-const char *sqlite3PagerWalFilename(const Pager *pPager){
-  assert( pPager!=0 );
-  return pPager->zWal;
-}
-#endif /* SQLITE_OMIT_WAL */
-
-/* Return a pointer to the URI query parameters associated with the
-** pager.
 **
-** The query parameters are a sequence of strings pairs.  The first
-** string of each pair is the key and the second string is the value.
-** All strings are terminated by a single 0x00 byte.  The list is
-** terminated by the first empty-string key.
-*/
-const char *sqlite3PagerQueryParameters(const Pager *pPager){
-  assert( pPager!=0 );
-  return pPager->zQueryParam;
-}
-
-/* If zFilename is a filename passed to the xOpen method of the VFS - 
-** either the main database file, the WAL file, or the journal file - 
-** then this routine returns a pointer to the Pager object associated
-** with that file.
+** The return value to this routine is always safe to use with
+** sqlite3_uri_parameter() and sqlite3_filename_database() and friends.
 */
-const Pager *sqlite3PagerFromFilename(const char *zFilename){
-  const Pager **pp = (const Pager**)zFilename;
-  pp--;
-  assert( (*pp)->zFilename==zFilename
-       || (*pp)->zJournal==zFilename
-       || (*pp)->zWal==zFilename );
-  return *pp;
+const char *sqlite3PagerFilename(const Pager *pPager, int nullIfMemDb){
+  static const char zFake[] = { 0x01, 0x00, 0x00, 0x00 };
+  return (nullIfMemDb && pPager->memDb) ? &zFake[2] : pPager->zFilename;
 }
 
 /*
index 2e8ba30f38be4b9c381243efda36c110ad6adfa2..904278944c64dc9c6d337c638f5f5e7ffe95f0d1 100644 (file)
@@ -204,10 +204,6 @@ u32 sqlite3PagerDataVersion(Pager*);
 #endif
 int sqlite3PagerMemUsed(Pager*);
 const char *sqlite3PagerFilename(const Pager*, int);
-const char *sqlite3PagerWalFilename(const Pager*);
-const char *sqlite3PagerJournalFilename(const Pager*);
-const char *sqlite3PagerQueryParameters(const Pager*);
-const Pager *sqlite3PagerFromFilename(const char*);
 sqlite3_vfs *sqlite3PagerVfs(Pager*);
 sqlite3_file *sqlite3PagerFile(Pager*);
 sqlite3_file *sqlite3PagerJrnlFile(Pager*);
index 7f76e0855ac7c0507fb547b6c6238138b689fd2f..0d22b87d43c25ac9052b38dd89ededd5ce4158b3 100644 (file)
@@ -2794,7 +2794,7 @@ char *sqlite3_vsnprintf(int,char*,const char*, va_list);
 **
 ** The SQLite core uses these three routines for all of its own
 ** internal memory allocation needs. "Core" in the previous sentence
-** does not include operating-system specific VFS implementation.  The
+** does not include operating-system specific [VFS] implementation.  The
 ** Windows VFS uses native malloc() and free() for some operations.
 **
 ** ^The sqlite3_malloc() routine returns a pointer to a block
@@ -3494,14 +3494,13 @@ int sqlite3_open_v2(
 /*
 ** CAPI3REF: Obtain Values For URI Parameters
 **
-** These are utility routines, useful to VFS implementations, that check
-** to see if a database file was a URI that contained a specific query 
+** These are utility routines, useful to [VFS|custom VFS implementations],
+** that check if a database file was a URI that contained a specific query 
 ** parameter, and if so obtains the value of that query parameter.
 **
 ** If F is the database filename pointer passed into the xOpen() method of 
-** a VFS implementation when the flags parameter to xOpen() has one or 
-** more of the [SQLITE_OPEN_URI] or [SQLITE_OPEN_MAIN_DB] bits set and
-** P is the name of the query parameter, then
+** a VFS implementation or it is the return value of [sqlite3_db_filename()]
+** and if P is the name of the query parameter, then
 ** sqlite3_uri_parameter(F,P) returns the value of the P
 ** parameter if it exists or a NULL pointer if P does not appear as a 
 ** query parameter on F.  If P is a query parameter of F and it
@@ -3523,40 +3522,60 @@ int sqlite3_open_v2(
 ** 64-bit signed integer and returns that integer, or D if P does not
 ** exist.  If the value of P is something other than an integer, then
 ** zero is returned.
+**
+** The sqlite3_uri_key(F,N) returns a pointer to the name (not
+** the value) of the N-th query parameter for filename F, or a NULL
+** pointer if N is less than zero or greater than the number of query
+** parameters minus 1.  The N value is zero-based so N should be 0 to obtain
+** the name of the first query parameter, 1 for the second parameter, and
+** so forth.
 ** 
 ** If F is a NULL pointer, then sqlite3_uri_parameter(F,P) returns NULL and
 ** sqlite3_uri_boolean(F,P,B) returns B.  If F is not a NULL pointer and
-** is not a database file pathname pointer that SQLite passed into the xOpen
-** VFS method, then the behavior of this routine is undefined and probably
-** undesirable.
+** is not a database file pathname pointer that the SQLite core passed
+** into the xOpen VFS method, then the behavior of this routine is undefined
+** and probably undesirable.
+**
+** Beginning with SQLite [version 3.31.0] ([dateof:3.31.0]) the input F
+** parameter can also be the name of a rollback journal file or WAL file
+** in addition to the main database file.  Prior to version 3.31.0, these
+** routines would only work if F was the name of the main database file.
+** When the F parameter is the name of the rollback journal or WAL file,
+** it has access to all the same query parameters as were found on the
+** main database file.
 **
 ** See the [URI filename] documentation for additional information.
 */
 const char *sqlite3_uri_parameter(const char *zFilename, const char *zParam);
 int sqlite3_uri_boolean(const char *zFile, const char *zParam, int bDefault);
 sqlite3_int64 sqlite3_uri_int64(const char*, const char*, sqlite3_int64);
+const char *sqlite3_uri_key(const char *zFilename, int N);
 
 /*
 ** CAPI3REF:  Translate filenames
 **
-** These routines are available to VFS implementations for translating
-** filenames between the main database file, the journal file, and the
-** WAL file.
+** These routines are available to [VFS|custom VFS implementations] for
+** translating filenames between the main database file, the journal file,
+** and the WAL file.
 **
 ** If F is the name of an sqlite database file, journal file, or WAL file
-** then sqlite3_filename_database(F) returns the name of the corresponding
-** database file.
+** passed by the SQLite core into the VFS, then sqlite3_filename_database(F)
+** returns the name of the corresponding database file.
 **
 ** If F is the name of an sqlite database file, journal file, or WAL file
-** then sqlite3_filename_journal(F) returns the name of the corresponding
-** rollback journal file.
+** passed by the SQLite core into the VFS, or if F is a database filename
+** obtained from [sqlite3_db_filename()], then sqlite3_filename_journal(F)
+** returns the name of the corresponding rollback journal file.
 **
 ** If F is the name of an sqlite database file, journal file, or WAL file
-** then sqlite3_filename_wal(F) returns the name of the corresponding
+** that was passed by the SQLite core into the VFS, or if F is a database
+** filename obtained from [sqlite3_db_filename()], then
+** sqlite3_filename_wal(F) returns the name of the corresponding
 ** WAL file.
 **
 ** In all of the above, if F is not the name of a database, journal or WAL
-** filename passed into the VFS from the SQLite core, then the result is
+** filename passed into the VFS from the SQLite core and F is not the
+** return value from [sqlite3_db_filename()], then the result is
 ** undefined and is likely a memory access violation.
 */
 const char *sqlite3_filename_database(const char*);
@@ -6006,6 +6025,17 @@ sqlite3 *sqlite3_db_handle(sqlite3_stmt*);
 ** xFullPathname method of the [VFS].  ^In other words, the filename
 ** will be an absolute pathname, even if the filename used
 ** to open the database originally was a URI or relative pathname.
+**
+** If the filename pointer returned by this routine is not NULL, then it
+** can be used as the filename input parameter to these routines:
+** <ul>
+** <li> [sqlite3_uri_parameter()]
+** <li> [sqlite3_uri_boolean()]
+** <li> [sqlite3_uri_int64()]
+** <li> [sqlite3_filename_database()]
+** <li> [sqlite3_filename_journal()]
+** <li> [sqlite3_filename_wal()]
+** </ul>
 */
 const char *sqlite3_db_filename(sqlite3 *db, const char *zDbName);
 
index f7a0386a7a8207e43b3ed2520e4dfbb622f47a96..b5258e0da004deaecf434e619e36dddaa5006a62 100644 (file)
@@ -324,7 +324,12 @@ struct sqlite3_api_routines {
   int (*value_frombind)(sqlite3_value*);
   /* Version 3.30.0 and later */
   int (*drop_modules)(sqlite3*,const char**);
+  /* Version 3.31.0 and later */
   sqlite3_int64 (*hard_heap_limit64)(sqlite3_int64);
+  const char *(*uri_key)(const char*,int);
+  const char *(*filename_database)(const char*);
+  const char *(*filename_journal)(const char*);
+  const char *(*filename_wal)(const char*);
 };
 
 /*
@@ -619,7 +624,12 @@ typedef int (*sqlite3_loadext_entry)(
 #define sqlite3_value_frombind         sqlite3_api->frombind
 /* Version 3.30.0 and later */
 #define sqlite3_drop_modules           sqlite3_api->drop_modules
+/* Version 3.31.0 andn later */
 #define sqlite3_hard_heap_limit64      sqlite3_api->hard_heap_limit64
+#define sqlite3_uri_key                sqlite3_api->uri_key
+#define sqlite3_filename_database      sqlite3_api->filename_database
+#define sqlite3_filename_journal       sqlite3_api->filename_journal
+#define sqlite3_filename_wal           sqlite3_api->filename_wal
 #endif /* !defined(SQLITE_CORE) && !defined(SQLITE_OMIT_LOAD_EXTENSION) */
 
 #if !defined(SQLITE_CORE) && !defined(SQLITE_OMIT_LOAD_EXTENSION)