New apis: sqlite3_filename_database(), sqlite3_filename_journal(), and
sqlite3_filename_wal(). Also sqlite3_uri_key(). And the other sqlite3_uri functions now work using the journal or wal filename in addition to the database file. And the sqlite3_db_filename() result is guaranteed to work as an argument to the sqlite3_uri functions. FossilOrigin-Name: fd7bcc53524096f5245e5ae04c12780d2c43b9b3af17ec529447aed21b82cc2b
This commit is contained in:
commit
ffe4d4a2d5
207
ext/misc/urifuncs.c
Normal file
207
ext/misc/urifuncs.c
Normal file
@ -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;
|
||||
}
|
@ -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);
|
||||
|
28
manifest
28
manifest
@ -1,5 +1,5 @@
|
||||
C Fix\sto\sthe\sregister\svalidity\stracking\slogic\sin\sdebug\sbuilds.\s\sNo\simpact\non\srelease\sbuilds.
|
||||
D 2020-01-10T01:05:49.616
|
||||
C New\sapis:\ssqlite3_filename_database(),\ssqlite3_filename_journal(),\sand\nsqlite3_filename_wal().\s\sAlso\ssqlite3_uri_key().\s\sAnd\sthe\sother\ssqlite3_uri\nfunctions\snow\swork\susing\sthe\sjournal\sor\swal\sfilename\sin\saddition\sto\sthe\ndatabase\sfile.\s\sAnd\sthe\ssqlite3_db_filename()\sresult\sis\sguaranteed\sto\swork\s\nas\san\sargument\sto\sthe\ssqlite3_uri\sfunctions.
|
||||
D 2020-01-11T21:08:59.397
|
||||
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 6ba00f15f0e7d36a12136ac390a403de4c4b47b76733d1cad60c2b23b4a2cf1d
|
||||
F src/loadext.c 8cd803f1747c03a50b32fe87ebfb5851998d0cdafefe02737daa95e0616b42bb
|
||||
F src/main.c da8b42cee9b83cc923bf23d1945c9fb48cf57cb0422d5fe43a1ff88dc453b97b
|
||||
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 b08541016855b06956cb34c4cddd8c9fa97793f3bfdc4f7809f09fda24702435
|
||||
F src/pager.h 217921e81eb5fe455caa5cda96061959706bcdd29ddb57166198645ef7822ac3
|
||||
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,10 +533,10 @@ 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 0ed2c973fcfa1e2ce120b35827a23e252719c3337ff64a1f76b800b53169d56e
|
||||
F src/sqlite.h.in c4713ccfa76dda5a96176d315ef5861d47f8d4815cc192d893b282a7f35669e9
|
||||
F src/sqlite3.rc 5121c9e10c3964d5755191c80dd1180c122fc3a8
|
||||
F src/sqlite3ext.h 72af51aa4e912e14cd495fb6e7fac65f0940db80ed950d90911aff292cc47ce2
|
||||
F src/sqliteInt.h ee242902766f9a96aeaca4315dbe1e204bbb2954cd455ffa085bba84fa47956b
|
||||
F src/sqlite3ext.h b0f776a0d042b23b6bcbb6b0943e8a3768c7f0b438a275e7168f0204e223a4db
|
||||
F src/sqliteInt.h 7a29ba700a51eeb925731749a570cf3859f6a58ed94797ecf47508875b0ba279
|
||||
F src/sqliteLimit.h 1513bfb7b20378aa0041e7022d04acb73525de35b80b252f1b83fedb4de6a76b
|
||||
F src/status.c 9ff2210207c6c3b4d9631a8241a7d45ab1b26a0e9c84cb07a9b5ce2de9a3b278
|
||||
F src/table.c b46ad567748f24a326d9de40e5b9659f96ffff34
|
||||
@ -1856,7 +1857,8 @@ F vsixtest/vsixtest.tcl 6a9a6ab600c25a91a7acc6293828957a386a8a93
|
||||
F vsixtest/vsixtest.vcxproj.data 2ed517e100c66dc455b492e1a33350c1b20fbcdc
|
||||
F vsixtest/vsixtest.vcxproj.filters 37e51ffedcdb064aad6ff33b6148725226cd608e
|
||||
F vsixtest/vsixtest_TemporaryKey.pfx e5b1b036facdb453873e7084e1cae9102ccc67a0
|
||||
P 8845a8c22a4ceabee130ce2addbe07e13b0496eeb542c89850f8658d21a48f89
|
||||
R da0f5b6fa0488473f060f2857ba231cf
|
||||
P 0a500da6aa659a8e73206e6d22ddbf2da5e4f1d1d551eeb66433163a3e13109d 9a70ff43a7b6848a71d5049f5a4ae24e3eb8a83d5c6651f5a9937abf03b3eccf
|
||||
R 871113a27520edbfc1ac5575d271c267
|
||||
T +closed 9a70ff43a7b6848a71d5049f5a4ae24e3eb8a83d5c6651f5a9937abf03b3eccf
|
||||
U drh
|
||||
Z 7914b326b60d9184810fac64aa24751d
|
||||
Z ad17285b3e2c7538416f668767f6cf45
|
||||
|
@ -1 +1 @@
|
||||
0a500da6aa659a8e73206e6d22ddbf2da5e4f1d1d551eeb66433163a3e13109d
|
||||
fd7bcc53524096f5245e5ae04c12780d2c43b9b3af17ec529447aed21b82cc2b
|
@ -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,
|
||||
};
|
||||
|
||||
/*
|
||||
|
72
src/main.c
72
src/main.c
@ -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
|
||||
@ -4283,6 +4264,19 @@ const char *sqlite3_uri_parameter(const char *zFilename, const char *zParam){
|
||||
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.
|
||||
*/
|
||||
@ -4308,6 +4302,46 @@ 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.
|
||||
**
|
||||
** It is an error to pass this routine a filename string that was not
|
||||
** passed into the VFS from the SQLite core. Doing so is similar to
|
||||
** passing free() a pointer that was not obtained from malloc() - it is
|
||||
** an error that we cannot easily detect but that will likely cause memory
|
||||
** corruption.
|
||||
*/
|
||||
const char *sqlite3_filename_database(const char *zFilename){
|
||||
return sqlite3_uri_parameter(zFilename - 3, "\003");
|
||||
}
|
||||
const char *sqlite3_filename_journal(const char *zFilename){
|
||||
const char *z = sqlite3_uri_parameter(startOfNameList(zFilename), "\001");
|
||||
return ALWAYS(z) && z[0] ? z : 0;
|
||||
}
|
||||
const char *sqlite3_filename_wal(const char *zFilename){
|
||||
return sqlite3_uri_parameter(startOfNameList(zFilename), "\002");
|
||||
}
|
||||
|
||||
/*
|
||||
** Return the Btree pointer identified by zDbName. Return NULL if not found.
|
||||
*/
|
||||
|
103
src/pager.c
103
src/pager.c
@ -4838,53 +4838,86 @@ int sqlite3PagerOpen(
|
||||
** Database file handle (pVfs->szOsFile bytes)
|
||||
** Sub-journal file handle (journalFileSize bytes)
|
||||
** Main journal file handle (journalFileSize 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)
|
||||
** Journal file name (nPathname+8+1 bytes)
|
||||
** URI query parameters (nUriByte 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 */
|
||||
nPathname + 1 + nUriByte + /* zFilename */
|
||||
nPathname + 8 + 2 /* zJournal */
|
||||
3 + /* Journal prefix */
|
||||
nPathname + 8 + 1 + /* Journal filename */
|
||||
#ifndef SQLITE_OMIT_WAL
|
||||
+ nPathname + 4 + 2 /* zWal */
|
||||
2 + /* WAL prefix */
|
||||
nPathname + 4 + 1 + /* WAL filename */
|
||||
#endif
|
||||
2 + /* Database prefix */
|
||||
nPathname + 1 + /* database filename */
|
||||
nUriByte + /* query parameters */
|
||||
2 /* Terminator */
|
||||
);
|
||||
assert( EIGHT_BYTE_ALIGNMENT(SQLITE_INT_TO_PTR(journalFileSize)) );
|
||||
if( !pPtr ){
|
||||
sqlite3DbFree(0, zPathname);
|
||||
return SQLITE_NOMEM_BKPT;
|
||||
}
|
||||
pPager = (Pager*)(pPtr);
|
||||
pPager->pPCache = (PCache*)(pPtr += ROUND8(sizeof(*pPager)));
|
||||
pPager->fd = (sqlite3_file*)(pPtr += ROUND8(pcacheSize));
|
||||
pPager->sjfd = (sqlite3_file*)(pPtr += ROUND8(pVfs->szOsFile));
|
||||
pPager->jfd = (sqlite3_file*)(pPtr += journalFileSize);
|
||||
pPager->zFilename = (char*)(pPtr += journalFileSize);
|
||||
pPager = (Pager*)pPtr; pPtr += ROUND8(sizeof(*pPager));
|
||||
pPager->pPCache = (PCache*)pPtr; pPtr += ROUND8(pcacheSize);
|
||||
pPager->fd = (sqlite3_file*)pPtr; pPtr += ROUND8(pVfs->szOsFile);
|
||||
pPager->sjfd = (sqlite3_file*)pPtr; pPtr += journalFileSize;
|
||||
pPager->jfd = (sqlite3_file*)pPtr; pPtr += journalFileSize;
|
||||
assert( EIGHT_BYTE_ALIGNMENT(pPager->jfd) );
|
||||
|
||||
/* Fill in the Pager.zFilename and Pager.zJournal buffers, if required. */
|
||||
if( zPathname ){
|
||||
assert( nPathname>0 );
|
||||
memcpy(pPager->zFilename, zPathname, nPathname);
|
||||
if( nUri ) memcpy(&pPager->zFilename[nPathname+1], zUri, nUriByte);
|
||||
pPager->zJournal = (char*)(pPtr += nPathname + 1 + nUriByte);
|
||||
memcpy(pPager->zJournal, zPathname, nPathname);
|
||||
memcpy(&pPager->zJournal[nPathname], "-journal", 8);
|
||||
sqlite3FileSuffix3(pPager->zFilename, pPager->zJournal);
|
||||
#ifndef SQLITE_OMIT_WAL
|
||||
pPager->zWal = (char*)(pPtr += nPathname + 8 + 2);
|
||||
memcpy(pPager->zWal, zPathname, nPathname);
|
||||
memcpy(&pPager->zWal[nPathname], "-wal", 4);
|
||||
sqlite3FileSuffix3(pPager->zFilename, pPager->zWal);
|
||||
assert( sqlite3UriCount(pPager->zWal)==0 );
|
||||
|
||||
/* 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
|
||||
assert( sqlite3UriCount(pPager->zFilename)==nUri );
|
||||
assert( sqlite3UriCount(pPager->zJournal)==0 );
|
||||
sqlite3DbFree(0, zPathname);
|
||||
}else{
|
||||
pPager->zJournal = 0;
|
||||
pPtr++;
|
||||
}
|
||||
|
||||
#ifndef SQLITE_OMIT_WAL
|
||||
/* Fill in Pager.zWal */
|
||||
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 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;
|
||||
pPager->vfsFlags = vfsFlags;
|
||||
|
||||
@ -4933,9 +4966,9 @@ int sqlite3PagerOpen(
|
||||
}
|
||||
#endif
|
||||
}
|
||||
pPager->noLock = sqlite3_uri_boolean(zFilename, "nolock", 0);
|
||||
pPager->noLock = sqlite3_uri_boolean(pPager->zFilename, "nolock", 0);
|
||||
if( (iDc & SQLITE_IOCAP_IMMUTABLE)!=0
|
||||
|| sqlite3_uri_boolean(zFilename, "immutable", 0) ){
|
||||
|| sqlite3_uri_boolean(pPager->zFilename, "immutable", 0) ){
|
||||
vfsFlags |= SQLITE_OPEN_READONLY;
|
||||
goto act_like_temp_file;
|
||||
}
|
||||
@ -6998,9 +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.
|
||||
**
|
||||
** The return value to this routine is always safe to use with
|
||||
** sqlite3_uri_parameter() and sqlite3_filename_database() and friends.
|
||||
*/
|
||||
const char *sqlite3PagerFilename(Pager *pPager, int nullIfMemDb){
|
||||
return (nullIfMemDb && pPager->memDb) ? "" : pPager->zFilename;
|
||||
const char *sqlite3PagerFilename(const Pager *pPager, int nullIfMemDb){
|
||||
static const char zFake[] = { 0x01, 0x00, 0x00, 0x00 };
|
||||
return (nullIfMemDb && pPager->memDb) ? &zFake[2] : pPager->zFilename;
|
||||
}
|
||||
|
||||
/*
|
||||
@ -7655,6 +7692,8 @@ int sqlite3PagerCloseWal(Pager *pPager, sqlite3 *db){
|
||||
return rc;
|
||||
}
|
||||
|
||||
|
||||
|
||||
#ifdef SQLITE_ENABLE_SNAPSHOT
|
||||
/*
|
||||
** If this is a WAL database, obtain a snapshot handle for the snapshot
|
||||
|
@ -203,7 +203,7 @@ u32 sqlite3PagerDataVersion(Pager*);
|
||||
int sqlite3PagerRefcount(Pager*);
|
||||
#endif
|
||||
int sqlite3PagerMemUsed(Pager*);
|
||||
const char *sqlite3PagerFilename(Pager*, int);
|
||||
const char *sqlite3PagerFilename(const Pager*, int);
|
||||
sqlite3_vfs *sqlite3PagerVfs(Pager*);
|
||||
sqlite3_file *sqlite3PagerFile(Pager*);
|
||||
sqlite3_file *sqlite3PagerJrnlFile(Pager*);
|
||||
|
@ -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
|
||||
@ -3524,17 +3523,64 @@ int sqlite3_open_v2(
|
||||
** 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|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
|
||||
** 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
|
||||
** 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
|
||||
** 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 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*);
|
||||
const char *sqlite3_filename_journal(const char*);
|
||||
const char *sqlite3_filename_wal(const char*);
|
||||
|
||||
|
||||
/*
|
||||
@ -5979,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);
|
||||
|
||||
|
@ -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)
|
||||
|
@ -4108,9 +4108,6 @@ void sqlite3AddDefaultValue(Parse*,Expr*,const char*,const char*);
|
||||
void sqlite3AddCollateType(Parse*, Token*);
|
||||
void sqlite3AddGenerated(Parse*,Expr*,Token*);
|
||||
void sqlite3EndTable(Parse*,Token*,Token*,u8,Select*);
|
||||
#ifdef SQLITE_DEBUG
|
||||
int sqlite3UriCount(const char*);
|
||||
#endif
|
||||
int sqlite3ParseUri(const char*,const char*,unsigned int*,
|
||||
sqlite3_vfs**,char**,char **);
|
||||
#ifdef SQLITE_HAS_CODEC
|
||||
|
Loading…
Reference in New Issue
Block a user