Add PRAGMA 'temp_store_directory'. Added os_*.c function

sqlite3OsIsDirWritable(), split pragma.c changeTempStorage() function into
invalidateTempStorage(). (CVS 2171)

FossilOrigin-Name: 772e22cbd69463be41c2e73b4fd4eb33946193c4
This commit is contained in:
tpoindex 2004-12-20 19:01:32 +00:00
parent 9012bcbc0a
commit 9a09a3caed
11 changed files with 270 additions and 34 deletions

View File

@ -513,6 +513,9 @@ index.html: $(TOP)/www/index.tcl last_change
lang.html: $(TOP)/www/lang.tcl
tclsh $(TOP)/www/lang.tcl >lang.html
pragma.html: $(TOP)/www/pragma.tcl
tclsh $(TOP)/www/pragma.tcl >pragma.html
lockingv3.html: $(TOP)/www/lockingv3.tcl
tclsh $(TOP)/www/lockingv3.tcl >lockingv3.html

View File

@ -1,6 +1,6 @@
C The\soptimizer\snow\suses\sonly\sthe\sindex\sand\signores\sthe\stable\sif\sit\scan\sget\naway\swith\sdoing\sso,\sthus\ssaving\sa\ssingle\sBTree\ssearch\sper\srow\sof\sresult.\nThis\scould\spotentially\sdouble\sthe\sspeed\sof\scertain\squeries.\s\sThe\ncode\spasses\sall\sregression\stests\sbut\snew\stests\sto\sexercise\sthe\snew\nfunctionality\sare\syet\sto\sbe\sadded.\s(CVS\s2170)
D 2004-12-19T00:11:35
F Makefile.in da09f379b80c8cd78d78abaa0f32ca90a124e884
C Add\sPRAGMA\s'temp_store_directory'.\s\sAdded\sos_*.c\sfunction\nsqlite3OsIsDirWritable(),\ssplit\spragma.c\schangeTempStorage()\sfunction\sinto\ninvalidateTempStorage().\s(CVS\s2171)
D 2004-12-20T19:01:32
F Makefile.in 02a184d734a2b4bbbc1ecc2e3ef504fcb13de069
F Makefile.linux-gcc a9e5a0d309fa7c38e7c14d3ecf7690879d3a5457
F README a01693e454a00cc117967e3f9fdab2d4d52e9bc1
F VERSION 342b6d5fde93b6d45023e2fee0163dda6464b9d6
@ -43,25 +43,25 @@ F src/insert.c 0b9077c6752530e9919a8c84375cfa2c4652260a
F src/legacy.c d58ea507bce885298a2c8c3cbb0f4bff5d47830b
F src/main.c fc383dc9cf03847b96e5ed9942696467725cfdfd
F src/md5.c 7ae1c39044b95de2f62e066f47bb1deb880a1070
F src/os.h 38258df2db895499b6e2957dbf17f25e0df71667
F src/os.h c92a675533c75fea0f53559f34c7b91c5afe1a9d
F src/os_common.h 0e7f428ba0a6c40a61bc56c4e96f493231301b73
F src/os_mac.c 7367dab0c44ab0b2c4337e73ac6f6f97f171c2cb
F src/os_mac.c e2a35e96bdf57a113ae1c446532e3c0924d3d046
F src/os_mac.h 608fdf39eafa1ce25fc8cb223b8b0a073341d4da
F src/os_test.c 91e5f22dd89491e5e1554820e715805f43fa4ece
F src/os_test.h 6a26a4978492e4bbdbf385554958418ff02db162
F src/os_unix.c 5824b22ba41fe9d514ef9169aac1b5fde73af229
F src/os_unix.c f3835451ffa69072ea88f30cfd6f3ed12b728cfa
F src/os_unix.h f3097815e041e82e24d92505e1ff61ba24172d13
F src/os_win.c 9482dfc92f289b68205bb2c9315757c7e3946bfb
F src/os_win.c 39525c414e57ca3f18d860d40d6d38df85689522
F src/os_win.h 41a946bea10f61c158ce8645e7646b29d44f122b
F src/pager.c 7b4dc9a94228efde924f1d9f4b7751f332da4587
F src/pager.h 9eba8c53dd91eae7f3f90743b2ee242da02a9862
F src/parse.y ceba179b9703657180963568f54b0e75f33e36e1
F src/pragma.c d6406e12c9eac353b3a026b50d41e4fd561afcc2
F src/pragma.c 639a7e7ef0999211aafa1f3d474ecc7241033cb9
F src/printf.c 3d20b21cfecadacecac3fb7274e746cb81d3d357
F src/random.c eff68e3f257e05e81eae6c4d50a51eb88beb4ff3
F src/select.c ac6610b4b2c5bd5ffc46536b760dacc420119dac
F src/shell.c e8f4f486cbf6e60d81173146ac8a6522c930fa51
F src/sqlite.h.in fa75850f412808afd38fddc1fd6456f4efc6fb97
F src/sqlite.h.in 0d5e48e506845b74a845c9470e01d3f472b59611
F src/sqliteInt.h a922cfd13711c68538684619fb15a4d262b12b9d
F src/table.c 25b3ff2b39b7d87e8d4a5da0713d68dfc06cbee9
F src/tclsqlite.c 3a4044ef609565c8cc51e887d8b96933ba9f3b5c
@ -161,7 +161,7 @@ F test/pager.test 394455707a079804e8a4e431d12edce831a065f0
F test/pager2.test 49c0f57c7da0b060f0486b85fdd074025caa694e
F test/pager3.test 647f696a9cf7409df00a1e0047c2eb55585a1b85
F test/pagesize.test 1b826d1608fd86d2303aa895b5586052ad07eba1
F test/pragma.test 726167cc97de01445f645c6d7e52e427db9ce46f
F test/pragma.test 18b3f99853ff694211c2c69567b0a9426e2a5e7a
F test/printf.test 92ba4c510b4fc61120ffa4a01820446ed917ae57
F test/progress.test 5ddba78cb6011fba36093973cfb3ac473b8fb96a x
F test/quick.test 91e5b8ae6663dc9e3e754b271f0384f0cae706e6
@ -254,7 +254,7 @@ F www/nulls.tcl ec35193f92485b87b90a994a01d0171b58823fcf
F www/oldnews.tcl 7aa4478e64631859770a5fe4b413919ba6ee8a08
F www/omitted.tcl 7bd62b6f0f53b60c5360895b16b3af8407bbca03
F www/opcode.tcl dafa030a5a3cc24a2f9fd4cfbfb7d7323d2151b0
F www/pragma.tcl 39c4a2be847538360c5d3e234f40a11f2eb08916
F www/pragma.tcl 8c6b5662875bccde826324fe0e37edda39b870f4
F www/quickstart.tcl 6f6f694b6139be2d967b1492eb9a6bdf7058aa60
F www/speed.tcl de99c82c4729a10b6733463636f15473c4ec95bc
F www/sqlite.tcl b51fd15f0531a54874de785a9efba323eecd5975
@ -263,7 +263,7 @@ F www/tclsqlite.tcl e73f8f8e5f20e8277619433f7970060ab01088fc
F www/vdbe.tcl 095f106d93875c94b47367384ebc870517431618
F www/version3.tcl 092a01f5ef430d2c4acc0ae558d74c4bb89638a0
F www/whentouse.tcl fdacb0ba2d39831e8a6240d05a490026ad4c4e4c
P 9b86993ff721b577b920c7c67fb41d3d4355fe88
R 2476c11934030eade9ca4e863deb7247
U drh
Z 352407e4634c619fec9ef3761d4b80dd
P e5aa489453bf31126da6473ef93c89ec27935cde
R 80852dba2ab3f55be612ddeeffa02604
U tpoindex
Z 5d44d728827caef4bb2a5da252002b6d

View File

@ -1 +1 @@
e5aa489453bf31126da6473ef93c89ec27935cde
772e22cbd69463be41c2e73b4fd4eb33946193c4

View File

@ -176,6 +176,7 @@ int sqlite3OsOpenReadOnly(const char*, OsFile*);
int sqlite3OsOpenDirectory(const char*, OsFile*);
int sqlite3OsSyncDirectory(const char*);
int sqlite3OsTempFileName(char*);
int sqlite3OsIsDirWritable(char*);
int sqlite3OsClose(OsFile*);
int sqlite3OsRead(OsFile*, void*, int amt);
int sqlite3OsWrite(OsFile*, const void*, int amt);

View File

@ -272,6 +272,22 @@ int sqlite3OsTempFileName(char *zBuf){
return SQLITE_OK;
}
/*
** If the following global variable points to a string which is the
** name of a directory, then that directory will be used to store
** temporary files.
*/
char *sqlite3_temp_directory = 0;
/*
** Check that a given pathname is a directory and is writable
** Just return false, as module is deprecated.
*/
int sqlite3OsIsDirWritable(char *zBuf){
return 0;
}
/*
** Close a file.
*/

View File

@ -574,7 +574,7 @@ int sqlite3OsOpenDirectory(
** name of a directory, then that directory will be used to store
** temporary files.
*/
const char *sqlite3_temp_directory = 0;
char *sqlite3_temp_directory = 0;
/*
** Create a temporary file name in zBuf. zBuf must be big enough to
@ -616,6 +616,20 @@ int sqlite3OsTempFileName(char *zBuf){
return SQLITE_OK;
}
/*
** Check that a given pathname is a directory and is writable
**
*/
int sqlite3OsIsDirWritable(char *zBuf){
struct stat buf;
if( zBuf==0 ) return 0;
if( strlen(zBuf)==0 ) return 0;
if( stat(zBuf, &buf) ) return 0;
if( !S_ISDIR(buf.st_mode) ) return 0;
if( access(zBuf, 07) ) return 0;
return 1;
}
/*
** Read data from a file into a buffer. Return SQLITE_OK if all
** bytes were read successfully and SQLITE_IOERR if anything goes

View File

@ -202,7 +202,7 @@ int sqlite3OsOpenDirectory(
** name of a directory, then that directory will be used to store
** temporary files.
*/
const char *sqlite3_temp_directory = 0;
char *sqlite3_temp_directory = 0;
/*
** Create a temporary file name in zBuf. zBuf must be big enough to
@ -409,6 +409,21 @@ static int unlockReadLock(OsFile *id){
return res;
}
/*
** Check that a given pathname is a directory and is writable
**
*/
int sqlite3OsIsDirWritable(char *zBuf){
int fileAttr;
if(! zBuf ) return 0;
if(! isNT() && strlen(zBuf) > MAX_PATH ) return 0;
fileAttr = GetFileAttributesA(zBuf);
if( fileAttr == 0xffffffff ) return 0;
if( (fileAttr & FILE_ATTRIBUTE_DIRECTORY) != FILE_ATTRIBUTE_DIRECTORY ) return 0;
return 1;
}
/*
** Lock the file with the lock specified by parameter locktype - one
** of the following:

View File

@ -11,7 +11,7 @@
*************************************************************************
** This file contains code used to implement the PRAGMA command.
**
** $Id: pragma.c,v 1.79 2004/11/22 19:12:21 drh Exp $
** $Id: pragma.c,v 1.80 2004/12/20 19:01:33 tpoindex Exp $
*/
#include "sqliteInt.h"
#include <ctype.h>
@ -79,14 +79,11 @@ static int getTempStore(const char *z){
}
/*
** If the TEMP database is open, close it and mark the database schema
** as needing reloading. This must be done when using the TEMP_STORE
** or DEFAULT_TEMP_STORE pragmas.
** Invalidate temp storage, either when the temp storage is changed
** from default, or when 'file' and the temp_store_directory has changed
*/
static int changeTempStorage(Parse *pParse, const char *zStorageType){
int ts = getTempStore(zStorageType);
static int invalidateTempStorage(Parse *pParse){
sqlite3 *db = pParse->db;
if( db->temp_store==ts ) return SQLITE_OK;
if( db->aDb[1].pBt!=0 ){
if( db->flags & SQLITE_InTrans ){
sqlite3ErrorMsg(pParse, "temporary storage cannot be changed "
@ -97,6 +94,21 @@ static int changeTempStorage(Parse *pParse, const char *zStorageType){
db->aDb[1].pBt = 0;
sqlite3ResetInternalSchema(db, 0);
}
return SQLITE_OK;
}
/*
** If the TEMP database is open, close it and mark the database schema
** as needing reloading. This must be done when using the TEMP_STORE
** or DEFAULT_TEMP_STORE pragmas.
*/
static int changeTempStorage(Parse *pParse, const char *zStorageType){
int ts = getTempStore(zStorageType);
sqlite3 *db = pParse->db;
if( db->temp_store==ts ) return SQLITE_OK;
if( invalidateTempStorage( pParse ) != SQLITE_OK ){
return SQLITE_ERROR;
}
db->temp_store = ts;
return SQLITE_OK;
}
@ -342,6 +354,68 @@ void sqlite3Pragma(
}
}else
/*
** PRAGMA temp_store_directory
** PRAGMA temp_store_directory = ""|"directory_name"
**
** Return or set the local value of the temp_store_directory flag. Changing
** the value sets a specific directory to be used for temporary files.
** Setting to a null string reverts to the default temporary directory search.
** If temporary directory is changed, then invalidateTempStorage.
**
*/
if( sqlite3StrICmp(zLeft, "temp_store_directory")==0 ){
if( !zRight ){
if( sqlite3_temp_directory ){
sqlite3VdbeSetNumCols(v, 1);
sqlite3VdbeSetColName(v, 0, "temp_store_directory", P3_STATIC);
sqlite3VdbeOp3(v, OP_String8, 0, 0, sqlite3_temp_directory, 0);
sqlite3VdbeAddOp(v, OP_Callback, 1, 0);
}
}else{
if( strlen(zRight)==0 ){
/* empty path, set to default. allows os_{unix,win}.c to choose directory */
if( sqlite3_temp_directory ){
/* previous temp_store_directory defined, free and invalidate */
sqlite3FreeX(sqlite3_temp_directory);
if( db->temp_store==1 ) {
/* temp storage is "file", so invalidate temp */
invalidateTempStorage( pParse );
}
}
sqlite3_temp_directory = 0;
}else{
/* check if previous directory defined, free and alloc if needed */
if( sqlite3_temp_directory ){
if( strlen(sqlite3_temp_directory) < strlen(zRight) + 1){
sqlite3FreeX(sqlite3_temp_directory);
sqlite3_temp_directory = sqlite3Malloc( strlen(zRight) + 1 );
if( sqlite3_temp_directory==0 ){
goto pragma_out;
}
sqlite3_temp_directory[0] = '\0';
}
}else{
sqlite3_temp_directory = sqlite3Malloc( strlen(zRight) + 1 );
if( sqlite3_temp_directory==0 ){
goto pragma_out;
}
sqlite3_temp_directory[0] = '\0';
}
/* check that directory exists and is writable */
if( sqlite3OsIsDirWritable( zRight ) ){
strcpy(sqlite3_temp_directory, zRight);
if( db->temp_store==1 ) {
/* temp storage is "file", so invalidate temp */
invalidateTempStorage( pParse );
}
}else{
sqlite3ErrorMsg(pParse, "not a directory, or not writable");
}
}
}
}else
/*
** PRAGMA [database.]synchronous
** PRAGMA [database.]synchronous=OFF|ON|NORMAL|FULL

View File

@ -12,7 +12,7 @@
** This header file defines the interface that the SQLite library
** presents to client programs.
**
** @(#) $Id: sqlite.h.in,v 1.125 2004/12/07 02:14:51 drh Exp $
** @(#) $Id: sqlite.h.in,v 1.126 2004/12/20 19:01:33 tpoindex Exp $
*/
#ifndef _SQLITE3_H_
#define _SQLITE3_H_
@ -1155,17 +1155,16 @@ int sqlite3_rekey(
);
/*
** If the following global variable is made to point to a constant
** If the following global variable is made to point to a
** string which is the name of a directory, then all temporary files
** created by SQLite will be placed in that directory. If this variable
** is NULL pointer, then SQLite does a search for an appropriate temporary
** file directory.
**
** This variable should only be changed when there are no open databases.
** Once sqlite3_open() has been called, this variable should not be changed
** until all database connections are closed.
** Once sqlite3_open() has been called, changing this variable will invalidate the
** current temporary database, if any.
*/
extern const char *sqlite3_temp_directory;
extern char *sqlite3_temp_directory;
#ifdef __cplusplus
} /* End of the 'extern "C"' block */

View File

@ -12,7 +12,7 @@
#
# This file implements tests for the PRAGMA command.
#
# $Id: pragma.test,v 1.27 2004/11/23 11:16:42 danielk1977 Exp $
# $Id: pragma.test,v 1.28 2004/12/20 19:01:33 tpoindex Exp $
set testdir [file dirname $argv0]
source $testdir/tester.tcl
@ -25,6 +25,7 @@ source $testdir/tester.tcl
# pragma-4.*: Test cache_size and default_cache_size on attached db.
# pragma-5.*: Test that pragma synchronous may not be used inside of a
# transaction.
# pragma-9.*: Test temp_store and temp_store_directory.
#
# Delete the preexisting database to avoid the special setup
@ -586,6 +587,80 @@ do_test pragma-8.2.15 {
}
} {-450}
# Test temp_store and temp_store_directory pragmas
#
do_test pragma-9.1 {
db close
sqlite3 db test.db
execsql {
PRAGMA temp_store;
}
} {0}
do_test pragma-9.2 {
execsql {
PRAGMA temp_store=file;
PRAGMA temp_store;
}
} {1}
do_test pragma-9.3 {
execsql {
PRAGMA temp_store=memory;
PRAGMA temp_store;
}
} {2}
do_test pragma-9.4 {
execsql {
PRAGMA temp_store_directory;
}
} {}
do_test pragma-9.5 {
execsql " \
PRAGMA temp_store_directory='[pwd]'; \
"
} {}
do_test pragma-9.6 {
execsql {
PRAGMA temp_store_directory;
}
} [pwd]
do_test pragma-9.7 {
set result ""
catch {
execsql {
PRAGMA temp_store_directory='/NON/EXISTENT/PATH/FOOBAR';
}
} result
set result
} {not a directory, or not writable}
do_test pragma-9.8 {
execsql {
PRAGMA temp_store_directory='';
}
} {}
do_test pragma-9.9 {
execsql {
PRAGMA temp_store_directory;
PRAGMA temp_store=FILE;
CREATE TEMP TABLE temp_store_directory_test(a integer);
INSERT INTO temp_store_directory_test values (2);
SELECT * FROM temp_store_directory_test;
}
} {2}
do_test pragma-9.10 {
set result ""
catch {
execsql " \
PRAGMA temp_store_directory='[pwd]'; \
SELECT * FROM temp_store_directory_test;
"
} result
set result
} {no such table: temp_store_directory_test}
} ; # ifcapable schema_version
finish_test

View File

@ -1,7 +1,7 @@
#
# Run this Tcl script to generate the pragma.html file.
#
set rcsid {$Id: pragma.tcl,v 1.6 2004/11/20 08:17:18 danielk1977 Exp $}
set rcsid {$Id: pragma.tcl,v 1.7 2004/12/20 19:01:34 tpoindex Exp $}
source common.tcl
header {Pragma statements supported by SQLite}
@ -211,12 +211,51 @@ puts {
is closed and reopened. For additional information on the temp_store
flag, see the description of the <a href="#pragma_default_temp_store">
<b>default_temp_store</b></a> pragma. Note that it is possible for
the library compile-time options to override this setting. </p>
the library compile-time options to override this setting. See
PRAGMA <a href="#pragma_temp_store_directory">temp_store_directory</a>
for further temporary storage options when <b>FILE</b> is specified.</p>
<p>When the temp_store setting is changed, all existing temporary
tables, indices, triggers, and viewers are immediately deleted.
</p>
</li>
<a name="pragma_temp_store_directory"></a>
<li><p><b>PRAGMA temp_store_directory;
<br>PRAGMA temp_store_directory = 'directory-name';</b></p>
<p>Query or change the setting of the "temp_store_directory" flag affecting
the database for the duration of the current database connection.
The temp_store_directory flag reverts to its default value when the database
is closed and reopened. Setting temp_store_directory allows control of the
placement of temporary files created by SQLite when PRAGMA
<a href="#pragma_temp_store">temp_store</a> is <b>FILE</b> (1),
or when the compile time default temporary store is FILE.
Otherwise, when the temp_store (or default) setting is
<b>MEMORY</b> (2), setting temp_store_directory has no effect.</p>
<p>When the temp_store_directory setting is changed, all existing temporary
tables, indices, triggers, and viewers are immediately deleted. In
practice, temp_store_directory should be set immediately after the
database is opened. </p>
<p>The value <i>directory-name</i> should be enclosed in single quotes.
To revert the directory to the default, set the <i>directory-name</i> to
a null string, e.g., <i>PRAGMA temp_store_directory = ''</i>. An
error is raised if <i>directory-name</i> is not found or is not
writable. </p>
<p>The default directory for temporary files depends on the OS. For
Unix/Linux/OSX, the default is the is the first writable directory found
in the list of: <b>/var/tmp, /usr/tmp, /tmp,</b> and <b>
<i>current-directory</i></b>. For Windows NT, the default
directory is determined by Windows, generally
<b>C:\Documents and Settings\<i>user-name</i>\Local Settings\Temp\</b>.
Temporary files created by SQLite are unlinked immediately after
opening, so that the operating system can automatically delete the
files when the SQLite process exits. Thus, temporary files are not
normally visible through <i>ls</i> or <i>dir</i> commands.</p>
</li>
</ul>
}