diff options
author | drh <drh@noemail.net> | 2020-02-18 19:49:48 +0000 |
---|---|---|
committer | drh <drh@noemail.net> | 2020-02-18 19:49:48 +0000 |
commit | 4defdddc31c9ad128ddc80860e794616664999ef (patch) | |
tree | 190f70d7d22d8182ab909ba30329b709e65ba1c6 /src | |
parent | 0184a256e3f4cc124ef0f72a207ba430796d28a6 (diff) | |
download | sqlite-4defdddc31c9ad128ddc80860e794616664999ef.tar.gz sqlite-4defdddc31c9ad128ddc80860e794616664999ef.zip |
Add the new sqlite3_create_filename() and sqlite3_free_filename() interfaces
for use by Shims. Use these interfaces inside the multiplexor.
FossilOrigin-Name: 9469f36ac89e4b75d0ab25fefbeff25201992c53141da915dcaa017083cab6db
Diffstat (limited to 'src')
-rw-r--r-- | src/loadext.c | 3 | ||||
-rw-r--r-- | src/main.c | 62 | ||||
-rw-r--r-- | src/pager.c | 5 | ||||
-rw-r--r-- | src/sqlite.h.in | 53 | ||||
-rw-r--r-- | src/sqlite3ext.h | 7 | ||||
-rw-r--r-- | src/test_multiplex.c | 7 |
6 files changed, 135 insertions, 2 deletions
diff --git a/src/loadext.c b/src/loadext.c index 245e9b004..06297e6bb 100644 --- a/src/loadext.c +++ b/src/loadext.c @@ -474,6 +474,9 @@ static const sqlite3_api_routines sqlite3Apis = { sqlite3_filename_database, sqlite3_filename_journal, sqlite3_filename_wal, + /* Version 3.32.0 and later */ + sqlite3_create_filename, + sqlite3_free_filename, }; /* diff --git a/src/main.c b/src/main.c index 3eccd08ea..4bfd94346 100644 --- a/src/main.c +++ b/src/main.c @@ -4243,6 +4243,68 @@ static const char *databaseName(const char *zName){ } /* +** Append text z[] to the end of p[]. Return a pointer to the first +** character after then zero terminator on the new text in p[]. +*/ +static char *appendText(char *p, const char *z){ + size_t n = strlen(z); + memcpy(p, z, n+1); + return p+n+1; +} + +/* +** Allocate memory to hold names for a database, journal file, WAL file, +** and query parameters. The pointer returned is valid for use by +** sqlite3_filename_database() and sqlite3_uri_parameter() and related +** functions. +** +** Memory layout must be compatible with that generated by the pager +** and expected by sqlite3_uri_parameter() and databaseName(). +*/ +char *sqlite3_create_filename( + const char *zDatabase, + const char *zJournal, + const char *zWal, + int nParam, + const char **azParam +){ + sqlite3_int64 nByte; + int i; + char *pResult, *p; + nByte = strlen(zDatabase) + strlen(zJournal) + strlen(zWal) + 10; + for(i=0; i<nParam*2; i++){ + nByte += strlen(azParam[i])+1; + } + pResult = p = sqlite3_malloc64( nByte ); + if( p==0 ) return 0; + memset(p, 0, 4); + p += 4; + p = appendText(p, zDatabase); + for(i=0; i<nParam*2; i++){ + p = appendText(p, azParam[i]); + } + *(p++) = 0; + p = appendText(p, zJournal); + p = appendText(p, zWal); + *(p++) = 0; + *(p++) = 0; + assert( (sqlite3_int64)(p - pResult)==nByte ); + return pResult + 4; +} + +/* +** Free memory obtained from sqlite3_create_filename(). It is a severe +** error to call this routine with any parameter other than a pointer +** previously obtained from sqlite3_create_filename() or a NULL pointer. +*/ +void sqlite3_free_filename(char *p){ + if( p==0 ) return; + p = (char*)databaseName(p); + sqlite3_free(p - 4); +} + + +/* ** 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 ** parameter, and if so obtains the value of the query parameter. diff --git a/src/pager.c b/src/pager.c index ff62926e7..21473bf25 100644 --- a/src/pager.c +++ b/src/pager.c @@ -4770,6 +4770,11 @@ int sqlite3PagerOpen( ** - \0 ** - WAL Path (zWALName) ** - \0 + ** + ** The sqlite3_create_filename() interface and the databaseFilename() utility + ** that is used by sqlite3_filename_database() and kin also depend on the + ** specific formatting and order of the various filenames, so if the format + ** changes here, be sure to change it there as well. */ pPtr = (u8 *)sqlite3MallocZero( ROUND8(sizeof(*pPager)) + /* Pager structure */ diff --git a/src/sqlite.h.in b/src/sqlite.h.in index 0537ab69f..7b2049ae0 100644 --- a/src/sqlite.h.in +++ b/src/sqlite.h.in @@ -3617,6 +3617,59 @@ const char *sqlite3_filename_database(const char*); const char *sqlite3_filename_journal(const char*); const char *sqlite3_filename_wal(const char*); +/* +** CAPI3REF: Create and Destroy VFS Filenames +** +** These interfces are provided for use by [VFS shim] implementations and +** are not useful outside of that context. +** +** The sqlite3_create_filename(D,J,W,N,P) allocates memory to hold a version of +** database filename D with corresponding journal file J and WAL file W and +** with N URI parameters key/values pairs in the array P. The result from +** sqlite3_create_filename(D,J,W,N,P) is a pointer to a database filename that +** is safe to pass to routines like: +** <ul> +** <li> [sqlite3_uri_parameter()], +** <li> [sqlite3_uri_boolean()], +** <li> [sqlite3_uri_int64()], +** <li> [sqlite3_uri_key()], +** <li> [sqlite3_filename_database()], +** <li> [sqlite3_filename_journal()], or +** <li> [sqlite3_filename_wal()]. +** </ul> +** If a memory allocation error occurs, sqlite3_create_filename() might +** return a NULL pointer. The memory obtained from sqlite3_create_filename(X) +** must be released by a corresponding call to sqlite3_free_filename(Y). +** +** The P parameter in sqlite3_create_filename(D,J,W,N,P) should be an array +** of 2*N pointers to strings. Each pair of pointers in this array corresponds +** to a key and value for a query parameter. The P parameter may be a NULL +** pointer if N is zero. None of the 2*N pointers in the P array may be +** NULL pointers and key pointers should not be empty strings. +** None of the D, J, or W parameters to sqlite3_create_filename(D,J,W,N,P) may +** be NULL pointers, though they can be empty strings. +** +** The sqlite3_free_filename(Y) routine releases a memory allocation +** previously obtained from sqlite3_create_filename(). Invoking +** sqlite3_free_filename(Y) is a NULL pointer is a harmless no-op. +** +** If the Y parameter to sqlite3_free_filename(Y) is anything other +** than a NULL pointer or a pointer previously acquired from +** sqlite3_create_filename(), then bad things such as heap +** corruption or segfaults may occur. The value Y should be +** used again after sqlite3_free_filename(Y) has been called. This means +** that if the [sqlite3_vfs.xOpen()] method of a VFS has been called using Y, +** then the corresponding [sqlite3_module.xClose() method should also be +** invoked prior to calling sqlite3_free_filename(Y). +*/ +char *sqlite3_create_filename( + const char *zDatabase, + const char *zJournal, + const char *zWal, + int nParam, + const char **azParam +); +void sqlite3_free_filename(char*); /* ** CAPI3REF: Error Codes And Messages diff --git a/src/sqlite3ext.h b/src/sqlite3ext.h index bdd0a85ed..a7c76a678 100644 --- a/src/sqlite3ext.h +++ b/src/sqlite3ext.h @@ -330,6 +330,10 @@ struct sqlite3_api_routines { const char *(*filename_database)(const char*); const char *(*filename_journal)(const char*); const char *(*filename_wal)(const char*); + /* Version 3.32.0 and later */ + char *(*create_filename)(const char*,const char*,const char*, + int,const char**); + void (*free_filename)(char*); }; /* @@ -630,6 +634,9 @@ typedef int (*sqlite3_loadext_entry)( #define sqlite3_filename_database sqlite3_api->filename_database #define sqlite3_filename_journal sqlite3_api->filename_journal #define sqlite3_filename_wal sqlite3_api->filename_wal +/* Version 3.32.0 and later */ +#define sqlite3_create_filename sqlite3_api->create_filename +#define sqlite3_free_filename sqlite3_api->free_filename #endif /* !defined(SQLITE_CORE) && !defined(SQLITE_OMIT_LOAD_EXTENSION) */ #if !defined(SQLITE_CORE) && !defined(SQLITE_OMIT_LOAD_EXTENSION) diff --git a/src/test_multiplex.c b/src/test_multiplex.c index 56e78c35f..3c9aa034c 100644 --- a/src/test_multiplex.c +++ b/src/test_multiplex.c @@ -267,11 +267,14 @@ static int multiplexSubFilename(multiplexGroup *pGroup, int iChunk){ if( pGroup->zName && pGroup->aReal[iChunk].z==0 ){ char *z; int n = pGroup->nName; - pGroup->aReal[iChunk].z = z = sqlite3_malloc64( n+5 ); + z = sqlite3_malloc64( n+5 ); if( z==0 ){ return SQLITE_NOMEM; } multiplexFilename(pGroup->zName, pGroup->nName, pGroup->flags, iChunk, z); + pGroup->aReal[iChunk].z = sqlite3_create_filename(z,"","",0,0); + sqlite3_free(z); + if( pGroup->aReal[iChunk].z==0 ) return SQLITE_NOMEM; } return SQLITE_OK; } @@ -438,7 +441,7 @@ static void multiplexSubClose( } sqlite3_free(pGroup->aReal[iChunk].p); } - sqlite3_free(pGroup->aReal[iChunk].z); + sqlite3_free_filename(pGroup->aReal[iChunk].z); memset(&pGroup->aReal[iChunk], 0, sizeof(pGroup->aReal[iChunk])); } |