Import sqlite3-3.28.0 (3280000)
Security: CVE-2019-9937, CVE-2019-9936
This commit is contained in:
parent
1651db5a41
commit
32335203e0
11
Makefile.msc
11
Makefile.msc
@ -433,9 +433,9 @@ UCRTLIBPATH = $(UCRTLIBPATH:\\=\)
|
||||
# will run on the platform that is doing the build.
|
||||
#
|
||||
!IF $(USE_FULLWARN)!=0
|
||||
BCC = $(NCC) -nologo -W4 $(CCOPTS) $(BCCOPTS)
|
||||
BCC = $(NCC) -nologo -W4 -Fd$*.pdb $(CCOPTS) $(BCCOPTS)
|
||||
!ELSE
|
||||
BCC = $(NCC) -nologo -W3 $(CCOPTS) $(BCCOPTS)
|
||||
BCC = $(NCC) -nologo -W3 -Fd$*.pdb $(CCOPTS) $(BCCOPTS)
|
||||
!ENDIF
|
||||
|
||||
# Check if assembly code listings should be generated for the source
|
||||
@ -808,7 +808,7 @@ BCC = $(BCC) -Zi
|
||||
# Command line prefixes for compiling code, compiling resources,
|
||||
# linking, etc.
|
||||
#
|
||||
LTCOMPILE = $(TCC) -Fo$@
|
||||
LTCOMPILE = $(TCC) -Fo$@ -Fd$*.pdb
|
||||
LTRCOMPILE = $(RCC) -r
|
||||
LTLIB = lib.exe
|
||||
LTLINK = $(TCC) -Fe$@
|
||||
@ -826,6 +826,11 @@ LTLIBS = $(LTLIBS) rpcrt4.lib
|
||||
!IFDEF PLATFORM
|
||||
LTLINKOPTS = /NOLOGO /MACHINE:$(PLATFORM)
|
||||
LTLIBOPTS = /NOLOGO /MACHINE:$(PLATFORM)
|
||||
!ELSEIF "$(VISUALSTUDIOVERSION)"=="12.0" || \
|
||||
"$(VISUALSTUDIOVERSION)"=="14.0" || \
|
||||
"$(VISUALSTUDIOVERSION)"=="15.0"
|
||||
LTLINKOPTS = /NOLOGO /MACHINE:x86
|
||||
LTLIBOPTS = /NOLOGO /MACHINE:x86
|
||||
!ELSE
|
||||
LTLINKOPTS = /NOLOGO
|
||||
LTLIBOPTS = /NOLOGO
|
||||
|
20
configure
vendored
20
configure
vendored
@ -1,6 +1,6 @@
|
||||
#! /bin/sh
|
||||
# Guess values for system-dependent variables and create Makefiles.
|
||||
# Generated by GNU Autoconf 2.69 for sqlite 3.27.2.
|
||||
# Generated by GNU Autoconf 2.69 for sqlite 3.28.0.
|
||||
#
|
||||
# Report bugs to <http://www.sqlite.org>.
|
||||
#
|
||||
@ -590,8 +590,8 @@ MAKEFLAGS=
|
||||
# Identity of this package.
|
||||
PACKAGE_NAME='sqlite'
|
||||
PACKAGE_TARNAME='sqlite'
|
||||
PACKAGE_VERSION='3.27.2'
|
||||
PACKAGE_STRING='sqlite 3.27.2'
|
||||
PACKAGE_VERSION='3.28.0'
|
||||
PACKAGE_STRING='sqlite 3.28.0'
|
||||
PACKAGE_BUGREPORT='http://www.sqlite.org'
|
||||
PACKAGE_URL=''
|
||||
|
||||
@ -1341,7 +1341,7 @@ if test "$ac_init_help" = "long"; then
|
||||
# Omit some internal or obsolete options to make the list less imposing.
|
||||
# This message is too long to be a string in the A/UX 3.1 sh.
|
||||
cat <<_ACEOF
|
||||
\`configure' configures sqlite 3.27.2 to adapt to many kinds of systems.
|
||||
\`configure' configures sqlite 3.28.0 to adapt to many kinds of systems.
|
||||
|
||||
Usage: $0 [OPTION]... [VAR=VALUE]...
|
||||
|
||||
@ -1412,7 +1412,7 @@ fi
|
||||
|
||||
if test -n "$ac_init_help"; then
|
||||
case $ac_init_help in
|
||||
short | recursive ) echo "Configuration of sqlite 3.27.2:";;
|
||||
short | recursive ) echo "Configuration of sqlite 3.28.0:";;
|
||||
esac
|
||||
cat <<\_ACEOF
|
||||
|
||||
@ -1537,7 +1537,7 @@ fi
|
||||
test -n "$ac_init_help" && exit $ac_status
|
||||
if $ac_init_version; then
|
||||
cat <<\_ACEOF
|
||||
sqlite configure 3.27.2
|
||||
sqlite configure 3.28.0
|
||||
generated by GNU Autoconf 2.69
|
||||
|
||||
Copyright (C) 2012 Free Software Foundation, Inc.
|
||||
@ -1952,7 +1952,7 @@ cat >config.log <<_ACEOF
|
||||
This file contains any messages produced by compilers while
|
||||
running configure, to aid debugging if configure makes a mistake.
|
||||
|
||||
It was created by sqlite $as_me 3.27.2, which was
|
||||
It was created by sqlite $as_me 3.28.0, which was
|
||||
generated by GNU Autoconf 2.69. Invocation command line was
|
||||
|
||||
$ $0 $@
|
||||
@ -2818,7 +2818,7 @@ fi
|
||||
|
||||
# Define the identity of the package.
|
||||
PACKAGE='sqlite'
|
||||
VERSION='3.27.2'
|
||||
VERSION='3.28.0'
|
||||
|
||||
|
||||
cat >>confdefs.h <<_ACEOF
|
||||
@ -14438,7 +14438,7 @@ cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1
|
||||
# report actual input values of CONFIG_FILES etc. instead of their
|
||||
# values after options handling.
|
||||
ac_log="
|
||||
This file was extended by sqlite $as_me 3.27.2, which was
|
||||
This file was extended by sqlite $as_me 3.28.0, which was
|
||||
generated by GNU Autoconf 2.69. Invocation command line was
|
||||
|
||||
CONFIG_FILES = $CONFIG_FILES
|
||||
@ -14495,7 +14495,7 @@ _ACEOF
|
||||
cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
|
||||
ac_cs_config="`$as_echo "$ac_configure_args" | sed 's/^ //; s/[\\""\`\$]/\\\\&/g'`"
|
||||
ac_cs_version="\\
|
||||
sqlite config.status 3.27.2
|
||||
sqlite config.status 3.28.0
|
||||
configured by $0, generated by GNU Autoconf 2.69,
|
||||
with options \\"\$ac_cs_config\\"
|
||||
|
||||
|
@ -10,7 +10,7 @@
|
||||
#
|
||||
|
||||
AC_PREREQ(2.61)
|
||||
AC_INIT(sqlite, 3.27.2, http://www.sqlite.org)
|
||||
AC_INIT(sqlite, 3.28.0, http://www.sqlite.org)
|
||||
AC_CONFIG_SRCDIR([sqlite3.c])
|
||||
AC_CONFIG_AUX_DIR([.])
|
||||
|
||||
|
289
shell.c
289
shell.c
@ -2177,13 +2177,13 @@ static void readFileContents(sqlite3_context *ctx, const char *zName){
|
||||
fclose(in);
|
||||
return;
|
||||
}
|
||||
pBuf = sqlite3_malloc64( nIn );
|
||||
pBuf = sqlite3_malloc64( nIn ? nIn : 1 );
|
||||
if( pBuf==0 ){
|
||||
sqlite3_result_error_nomem(ctx);
|
||||
fclose(in);
|
||||
return;
|
||||
}
|
||||
if( 1==fread(pBuf, nIn, 1, in) ){
|
||||
if( nIn==(sqlite3_int64)fread(pBuf, 1, (size_t)nIn, in) ){
|
||||
sqlite3_result_blob64(ctx, pBuf, nIn, sqlite3_free);
|
||||
}else{
|
||||
sqlite3_result_error_code(ctx, SQLITE_IOERR);
|
||||
@ -2318,15 +2318,15 @@ static int fileLinkStat(
|
||||
** Argument zFile is the name of a file that will be created and/or written
|
||||
** by SQL function writefile(). This function ensures that the directory
|
||||
** zFile will be written to exists, creating it if required. The permissions
|
||||
** for any path components created by this function are set to (mode&0777).
|
||||
** for any path components created by this function are set in accordance
|
||||
** with the current umask.
|
||||
**
|
||||
** If an OOM condition is encountered, SQLITE_NOMEM is returned. Otherwise,
|
||||
** SQLITE_OK is returned if the directory is successfully created, or
|
||||
** SQLITE_ERROR otherwise.
|
||||
*/
|
||||
static int makeDirectory(
|
||||
const char *zFile,
|
||||
mode_t mode
|
||||
const char *zFile
|
||||
){
|
||||
char *zCopy = sqlite3_mprintf("%s", zFile);
|
||||
int rc = SQLITE_OK;
|
||||
@ -2347,7 +2347,7 @@ static int makeDirectory(
|
||||
|
||||
rc2 = fileStat(zCopy, &sStat);
|
||||
if( rc2!=0 ){
|
||||
if( mkdir(zCopy, mode & 0777) ) rc = SQLITE_ERROR;
|
||||
if( mkdir(zCopy, 0777) ) rc = SQLITE_ERROR;
|
||||
}else{
|
||||
if( !S_ISDIR(sStat.st_mode) ) rc = SQLITE_ERROR;
|
||||
}
|
||||
@ -2505,7 +2505,7 @@ static void writefileFunc(
|
||||
|
||||
res = writeFile(context, zFile, argv[1], mode, mtime);
|
||||
if( res==1 && errno==ENOENT ){
|
||||
if( makeDirectory(zFile, mode)==SQLITE_OK ){
|
||||
if( makeDirectory(zFile)==SQLITE_OK ){
|
||||
res = writeFile(context, zFile, argv[1], mode, mtime);
|
||||
}
|
||||
}
|
||||
@ -10430,6 +10430,66 @@ static void restore_debug_trace_modes(void){
|
||||
#endif
|
||||
}
|
||||
|
||||
/* Create the TEMP table used to store parameter bindings */
|
||||
static void bind_table_init(ShellState *p){
|
||||
int wrSchema = 0;
|
||||
sqlite3_db_config(p->db, SQLITE_DBCONFIG_WRITABLE_SCHEMA, -1, &wrSchema);
|
||||
sqlite3_db_config(p->db, SQLITE_DBCONFIG_WRITABLE_SCHEMA, 1, 0);
|
||||
sqlite3_exec(p->db,
|
||||
"CREATE TABLE IF NOT EXISTS temp.sqlite_parameters(\n"
|
||||
" key TEXT PRIMARY KEY,\n"
|
||||
" value ANY\n"
|
||||
") WITHOUT ROWID;",
|
||||
0, 0, 0);
|
||||
sqlite3_db_config(p->db, SQLITE_DBCONFIG_WRITABLE_SCHEMA, wrSchema, 0);
|
||||
}
|
||||
|
||||
/*
|
||||
** Bind parameters on a prepared statement.
|
||||
**
|
||||
** Parameter bindings are taken from a TEMP table of the form:
|
||||
**
|
||||
** CREATE TEMP TABLE sqlite_parameters(key TEXT PRIMARY KEY, value)
|
||||
** WITHOUT ROWID;
|
||||
**
|
||||
** No bindings occur if this table does not exist. The special character '$'
|
||||
** is included in the table name to help prevent collisions with actual tables.
|
||||
** The table must be in the TEMP schema.
|
||||
*/
|
||||
static void bind_prepared_stmt(ShellState *pArg, sqlite3_stmt *pStmt){
|
||||
int nVar;
|
||||
int i;
|
||||
int rc;
|
||||
sqlite3_stmt *pQ = 0;
|
||||
|
||||
nVar = sqlite3_bind_parameter_count(pStmt);
|
||||
if( nVar==0 ) return; /* Nothing to do */
|
||||
if( sqlite3_table_column_metadata(pArg->db, "TEMP", "sqlite_parameters",
|
||||
"key", 0, 0, 0, 0, 0)!=SQLITE_OK ){
|
||||
return; /* Parameter table does not exist */
|
||||
}
|
||||
rc = sqlite3_prepare_v2(pArg->db,
|
||||
"SELECT value FROM temp.sqlite_parameters"
|
||||
" WHERE key=?1", -1, &pQ, 0);
|
||||
if( rc || pQ==0 ) return;
|
||||
for(i=1; i<=nVar; i++){
|
||||
char zNum[30];
|
||||
const char *zVar = sqlite3_bind_parameter_name(pStmt, i);
|
||||
if( zVar==0 ){
|
||||
sqlite3_snprintf(sizeof(zNum),zNum,"?%d",i);
|
||||
zVar = zNum;
|
||||
}
|
||||
sqlite3_bind_text(pQ, 1, zVar, -1, SQLITE_STATIC);
|
||||
if( sqlite3_step(pQ)==SQLITE_ROW ){
|
||||
sqlite3_bind_value(pStmt, i, sqlite3_column_value(pQ, 0));
|
||||
}else{
|
||||
sqlite3_bind_null(pStmt, i);
|
||||
}
|
||||
sqlite3_reset(pQ);
|
||||
}
|
||||
sqlite3_finalize(pQ);
|
||||
}
|
||||
|
||||
/*
|
||||
** Run a prepared statement
|
||||
*/
|
||||
@ -10682,7 +10742,7 @@ static int shell_exec(
|
||||
}
|
||||
|
||||
/* Show the EXPLAIN QUERY PLAN if .eqp is on */
|
||||
if( pArg && pArg->autoEQP && sqlite3_strlike("EXPLAIN%",zStmtSql,0)!=0 ){
|
||||
if( pArg && pArg->autoEQP && sqlite3_stmt_isexplain(pStmt)==0 ){
|
||||
sqlite3_stmt *pExplain;
|
||||
char *zEQP;
|
||||
int triggerEQP = 0;
|
||||
@ -10731,13 +10791,10 @@ static int shell_exec(
|
||||
if( pArg ){
|
||||
pArg->cMode = pArg->mode;
|
||||
if( pArg->autoExplain ){
|
||||
if( sqlite3_column_count(pStmt)==8
|
||||
&& sqlite3_strlike("EXPLAIN%", zStmtSql,0)==0
|
||||
){
|
||||
if( sqlite3_stmt_isexplain(pStmt)==1 ){
|
||||
pArg->cMode = MODE_Explain;
|
||||
}
|
||||
if( sqlite3_column_count(pStmt)==4
|
||||
&& sqlite3_strlike("EXPLAIN QUERY PLAN%", zStmtSql,0)==0 ){
|
||||
if( sqlite3_stmt_isexplain(pStmt)==2 ){
|
||||
pArg->cMode = MODE_EQP;
|
||||
}
|
||||
}
|
||||
@ -10749,6 +10806,7 @@ static int shell_exec(
|
||||
}
|
||||
}
|
||||
|
||||
bind_prepared_stmt(pArg, pStmt);
|
||||
exec_prepared_stmt(pArg, pStmt);
|
||||
explain_data_delete(pArg);
|
||||
eqp_render(pArg);
|
||||
@ -11078,7 +11136,8 @@ static const char *(azHelp[]) = {
|
||||
".archive ... Manage SQL archives",
|
||||
" Each command must have exactly one of the following options:",
|
||||
" -c, --create Create a new archive",
|
||||
" -u, --update Update or add files to an existing archive",
|
||||
" -u, --update Add files or update files with changed mtime",
|
||||
" -i, --insert Like -u but always add even if mtime unchanged",
|
||||
" -t, --list List contents of archive",
|
||||
" -x, --extract Extract files from archive",
|
||||
" Optional arguments:",
|
||||
@ -11180,6 +11239,13 @@ static const char *(azHelp[]) = {
|
||||
" --zip FILE is a ZIP archive",
|
||||
".output ?FILE? Send output to FILE or stdout if FILE is omitted",
|
||||
" If FILE begins with '|' then open it as a pipe.",
|
||||
".parameter CMD ... Manage SQL parameter bindings",
|
||||
" clear Erase all bindings",
|
||||
" init Initialize the TEMP table that holds bindings",
|
||||
" list List the current parameter bindings",
|
||||
" set PARAMETER VALUE Given SQL parameter PARAMETER a value of VALUE",
|
||||
" PARAMETER should start with '$', ':', '@', or '?'",
|
||||
" unset PARAMETER Remove PARAMETER from the binding table",
|
||||
".print STRING... Print literal STRING",
|
||||
#ifndef SQLITE_OMIT_PROGRESS_CALLBACK
|
||||
".progress N Invoke progress handler after every N opcodes",
|
||||
@ -12392,7 +12458,7 @@ static int shell_dbinfo_command(ShellState *p, int nArg, char **azArg){
|
||||
{ "schema size:",
|
||||
"SELECT total(length(sql)) FROM %s" },
|
||||
};
|
||||
int i;
|
||||
int i, rc;
|
||||
unsigned iDataVersion;
|
||||
char *zSchemaTab;
|
||||
char *zDb = nArg>=2 ? azArg[1] : "main";
|
||||
@ -12400,8 +12466,19 @@ static int shell_dbinfo_command(ShellState *p, int nArg, char **azArg){
|
||||
unsigned char aHdr[100];
|
||||
open_db(p, 0);
|
||||
if( p->db==0 ) return 1;
|
||||
sqlite3_prepare_v2(p->db,"SELECT data FROM sqlite_dbpage(?1) WHERE pgno=1",
|
||||
-1, &pStmt, 0);
|
||||
rc = sqlite3_prepare_v2(p->db,
|
||||
"SELECT data FROM sqlite_dbpage(?1) WHERE pgno=1",
|
||||
-1, &pStmt, 0);
|
||||
if( rc ){
|
||||
if( !sqlite3_compileoption_used("ENABLE_DBPAGE_VTAB") ){
|
||||
utf8_printf(stderr, "the \".dbinfo\" command requires the "
|
||||
"-DSQLITE_ENABLE_DBPAGE_VTAB compile-time options\n");
|
||||
}else{
|
||||
utf8_printf(stderr, "error: %s\n", sqlite3_errmsg(p->db));
|
||||
}
|
||||
sqlite3_finalize(pStmt);
|
||||
return 1;
|
||||
}
|
||||
sqlite3_bind_text(pStmt, 1, zDb, -1, SQLITE_STATIC);
|
||||
if( sqlite3_step(pStmt)==SQLITE_ROW
|
||||
&& sqlite3_column_bytes(pStmt,0)>100
|
||||
@ -12995,19 +13072,20 @@ static int arErrorMsg(ArCommand *pAr, const char *zFmt, ...){
|
||||
** Values for ArCommand.eCmd.
|
||||
*/
|
||||
#define AR_CMD_CREATE 1
|
||||
#define AR_CMD_EXTRACT 2
|
||||
#define AR_CMD_LIST 3
|
||||
#define AR_CMD_UPDATE 4
|
||||
#define AR_CMD_HELP 5
|
||||
#define AR_CMD_UPDATE 2
|
||||
#define AR_CMD_INSERT 3
|
||||
#define AR_CMD_EXTRACT 4
|
||||
#define AR_CMD_LIST 5
|
||||
#define AR_CMD_HELP 6
|
||||
|
||||
/*
|
||||
** Other (non-command) switches.
|
||||
*/
|
||||
#define AR_SWITCH_VERBOSE 6
|
||||
#define AR_SWITCH_FILE 7
|
||||
#define AR_SWITCH_DIRECTORY 8
|
||||
#define AR_SWITCH_APPEND 9
|
||||
#define AR_SWITCH_DRYRUN 10
|
||||
#define AR_SWITCH_VERBOSE 7
|
||||
#define AR_SWITCH_FILE 8
|
||||
#define AR_SWITCH_DIRECTORY 9
|
||||
#define AR_SWITCH_APPEND 10
|
||||
#define AR_SWITCH_DRYRUN 11
|
||||
|
||||
static int arProcessSwitch(ArCommand *pAr, int eSwitch, const char *zArg){
|
||||
switch( eSwitch ){
|
||||
@ -13015,6 +13093,7 @@ static int arProcessSwitch(ArCommand *pAr, int eSwitch, const char *zArg){
|
||||
case AR_CMD_EXTRACT:
|
||||
case AR_CMD_LIST:
|
||||
case AR_CMD_UPDATE:
|
||||
case AR_CMD_INSERT:
|
||||
case AR_CMD_HELP:
|
||||
if( pAr->eCmd ){
|
||||
return arErrorMsg(pAr, "multiple command options");
|
||||
@ -13061,6 +13140,7 @@ static int arParseCommand(
|
||||
} aSwitch[] = {
|
||||
{ "create", 'c', AR_CMD_CREATE, 0 },
|
||||
{ "extract", 'x', AR_CMD_EXTRACT, 0 },
|
||||
{ "insert", 'i', AR_CMD_INSERT, 0 },
|
||||
{ "list", 't', AR_CMD_LIST, 0 },
|
||||
{ "update", 'u', AR_CMD_UPDATE, 0 },
|
||||
{ "help", 'h', AR_CMD_HELP, 0 },
|
||||
@ -13396,7 +13476,12 @@ static int arExecSql(ArCommand *pAr, const char *zSql){
|
||||
|
||||
|
||||
/*
|
||||
** Implementation of .ar "create" and "update" commands.
|
||||
** Implementation of .ar "create", "insert", and "update" commands.
|
||||
**
|
||||
** create -> Create a new SQL archive
|
||||
** insert -> Insert or reinsert all files listed
|
||||
** update -> Insert files that have changed or that were not
|
||||
** previously in the archive
|
||||
**
|
||||
** Create the "sqlar" table in the database if it does not already exist.
|
||||
** Then add each file in the azFile[] array to the archive. Directories
|
||||
@ -13404,11 +13489,14 @@ static int arExecSql(ArCommand *pAr, const char *zSql){
|
||||
** printed on stdout for each file archived.
|
||||
**
|
||||
** The create command is the same as update, except that it drops
|
||||
** any existing "sqlar" table before beginning.
|
||||
** any existing "sqlar" table before beginning. The "insert" command
|
||||
** always overwrites every file named on the command-line, where as
|
||||
** "update" only overwrites if the size or mtime or mode has changed.
|
||||
*/
|
||||
static int arCreateOrUpdateCommand(
|
||||
ArCommand *pAr, /* Command arguments and options */
|
||||
int bUpdate /* true for a --create. false for --update */
|
||||
int bUpdate, /* true for a --create. */
|
||||
int bOnlyIfChanged /* Only update if file has changed */
|
||||
){
|
||||
const char *zCreate =
|
||||
"CREATE TABLE IF NOT EXISTS sqlar(\n"
|
||||
@ -13430,22 +13518,24 @@ static int arCreateOrUpdateCommand(
|
||||
" WHEN 'd' THEN 0\n"
|
||||
" ELSE -1 END,\n"
|
||||
" sqlar_compress(data)\n"
|
||||
" FROM fsdir(%Q,%Q)\n"
|
||||
" WHERE lsmode(mode) NOT LIKE '?%%';",
|
||||
" FROM fsdir(%Q,%Q) AS disk\n"
|
||||
" WHERE lsmode(mode) NOT LIKE '?%%'%s;"
|
||||
,
|
||||
"REPLACE INTO %s(name,mode,mtime,data)\n"
|
||||
" SELECT\n"
|
||||
" %s,\n"
|
||||
" mode,\n"
|
||||
" mtime,\n"
|
||||
" data\n"
|
||||
" FROM fsdir(%Q,%Q)\n"
|
||||
" WHERE lsmode(mode) NOT LIKE '?%%';"
|
||||
" FROM fsdir(%Q,%Q) AS disk\n"
|
||||
" WHERE lsmode(mode) NOT LIKE '?%%'%s;"
|
||||
};
|
||||
int i; /* For iterating through azFile[] */
|
||||
int rc; /* Return code */
|
||||
const char *zTab = 0; /* SQL table into which to insert */
|
||||
char *zSql;
|
||||
char zTemp[50];
|
||||
char *zExists = 0;
|
||||
|
||||
arExecSql(pAr, "PRAGMA page_size=512");
|
||||
rc = arExecSql(pAr, "SAVEPOINT ar;");
|
||||
@ -13476,10 +13566,21 @@ static int arCreateOrUpdateCommand(
|
||||
}
|
||||
rc = arExecSql(pAr, zCreate);
|
||||
}
|
||||
if( bOnlyIfChanged ){
|
||||
zExists = sqlite3_mprintf(
|
||||
" AND NOT EXISTS("
|
||||
"SELECT 1 FROM %s AS mem"
|
||||
" WHERE mem.name=disk.name"
|
||||
" AND mem.mtime=disk.mtime"
|
||||
" AND mem.mode=disk.mode)", zTab);
|
||||
}else{
|
||||
zExists = sqlite3_mprintf("");
|
||||
}
|
||||
if( zExists==0 ) rc = SQLITE_NOMEM;
|
||||
for(i=0; i<pAr->nArg && rc==SQLITE_OK; i++){
|
||||
char *zSql2 = sqlite3_mprintf(zInsertFmt[pAr->bZip], zTab,
|
||||
pAr->bVerbose ? "shell_putsnl(name)" : "name",
|
||||
pAr->azArg[i], pAr->zDir);
|
||||
pAr->azArg[i], pAr->zDir, zExists);
|
||||
rc = arExecSql(pAr, zSql2);
|
||||
sqlite3_free(zSql2);
|
||||
}
|
||||
@ -13494,6 +13595,7 @@ static int arCreateOrUpdateCommand(
|
||||
sqlite3_free(zSql);
|
||||
}
|
||||
}
|
||||
sqlite3_free(zExists);
|
||||
return rc;
|
||||
}
|
||||
|
||||
@ -13532,7 +13634,8 @@ static int arDotCommand(
|
||||
}else if( cmd.zFile ){
|
||||
int flags;
|
||||
if( cmd.bAppend ) eDbType = SHELL_OPEN_APPENDVFS;
|
||||
if( cmd.eCmd==AR_CMD_CREATE || cmd.eCmd==AR_CMD_UPDATE ){
|
||||
if( cmd.eCmd==AR_CMD_CREATE || cmd.eCmd==AR_CMD_INSERT
|
||||
|| cmd.eCmd==AR_CMD_UPDATE ){
|
||||
flags = SQLITE_OPEN_READWRITE|SQLITE_OPEN_CREATE;
|
||||
}else{
|
||||
flags = SQLITE_OPEN_READONLY;
|
||||
@ -13569,7 +13672,7 @@ static int arDotCommand(
|
||||
|
||||
switch( cmd.eCmd ){
|
||||
case AR_CMD_CREATE:
|
||||
rc = arCreateOrUpdateCommand(&cmd, 0);
|
||||
rc = arCreateOrUpdateCommand(&cmd, 0, 0);
|
||||
break;
|
||||
|
||||
case AR_CMD_EXTRACT:
|
||||
@ -13584,9 +13687,13 @@ static int arDotCommand(
|
||||
arUsage(pState->out);
|
||||
break;
|
||||
|
||||
case AR_CMD_INSERT:
|
||||
rc = arCreateOrUpdateCommand(&cmd, 1, 0);
|
||||
break;
|
||||
|
||||
default:
|
||||
assert( cmd.eCmd==AR_CMD_UPDATE );
|
||||
rc = arCreateOrUpdateCommand(&cmd, 1);
|
||||
rc = arCreateOrUpdateCommand(&cmd, 1, 1);
|
||||
break;
|
||||
}
|
||||
}
|
||||
@ -14711,6 +14818,114 @@ static int do_meta_command(char *zLine, ShellState *p){
|
||||
}
|
||||
}else
|
||||
|
||||
if( c=='p' && n>=3 && strncmp(azArg[0], "parameter", n)==0 ){
|
||||
open_db(p,0);
|
||||
if( nArg<=1 ) goto parameter_syntax_error;
|
||||
|
||||
/* .parameter clear
|
||||
** Clear all bind parameters by dropping the TEMP table that holds them.
|
||||
*/
|
||||
if( nArg==2 && strcmp(azArg[1],"clear")==0 ){
|
||||
int wrSchema = 0;
|
||||
sqlite3_db_config(p->db, SQLITE_DBCONFIG_WRITABLE_SCHEMA, -1, &wrSchema);
|
||||
sqlite3_db_config(p->db, SQLITE_DBCONFIG_WRITABLE_SCHEMA, 1, 0);
|
||||
sqlite3_exec(p->db, "DROP TABLE IF EXISTS temp.sqlite_parameters;",
|
||||
0, 0, 0);
|
||||
sqlite3_db_config(p->db, SQLITE_DBCONFIG_WRITABLE_SCHEMA, wrSchema, 0);
|
||||
}else
|
||||
|
||||
/* .parameter list
|
||||
** List all bind parameters.
|
||||
*/
|
||||
if( nArg==2 && strcmp(azArg[1],"list")==0 ){
|
||||
sqlite3_stmt *pStmt = 0;
|
||||
int rx;
|
||||
int len = 0;
|
||||
rx = sqlite3_prepare_v2(p->db,
|
||||
"SELECT max(length(key)) "
|
||||
"FROM temp.sqlite_parameters;", -1, &pStmt, 0);
|
||||
if( rx==SQLITE_OK && sqlite3_step(pStmt)==SQLITE_ROW ){
|
||||
len = sqlite3_column_int(pStmt, 0);
|
||||
if( len>40 ) len = 40;
|
||||
}
|
||||
sqlite3_finalize(pStmt);
|
||||
pStmt = 0;
|
||||
if( len ){
|
||||
rx = sqlite3_prepare_v2(p->db,
|
||||
"SELECT key, quote(value) "
|
||||
"FROM temp.sqlite_parameters;", -1, &pStmt, 0);
|
||||
while( sqlite3_step(pStmt)==SQLITE_ROW ){
|
||||
utf8_printf(p->out, "%-*s %s\n", len, sqlite3_column_text(pStmt,0),
|
||||
sqlite3_column_text(pStmt,1));
|
||||
}
|
||||
sqlite3_finalize(pStmt);
|
||||
}
|
||||
}else
|
||||
|
||||
/* .parameter init
|
||||
** Make sure the TEMP table used to hold bind parameters exists.
|
||||
** Create it if necessary.
|
||||
*/
|
||||
if( nArg==2 && strcmp(azArg[1],"init")==0 ){
|
||||
bind_table_init(p);
|
||||
}else
|
||||
|
||||
/* .parameter set NAME VALUE
|
||||
** Set or reset a bind parameter. NAME should be the full parameter
|
||||
** name exactly as it appears in the query. (ex: $abc, @def). The
|
||||
** VALUE can be in either SQL literal notation, or if not it will be
|
||||
** understood to be a text string.
|
||||
*/
|
||||
if( nArg==4 && strcmp(azArg[1],"set")==0 ){
|
||||
int rx;
|
||||
char *zSql;
|
||||
sqlite3_stmt *pStmt;
|
||||
const char *zKey = azArg[2];
|
||||
const char *zValue = azArg[3];
|
||||
bind_table_init(p);
|
||||
zSql = sqlite3_mprintf(
|
||||
"REPLACE INTO temp.sqlite_parameters(key,value)"
|
||||
"VALUES(%Q,%s);", zKey, zValue);
|
||||
if( zSql==0 ) shell_out_of_memory();
|
||||
pStmt = 0;
|
||||
rx = sqlite3_prepare_v2(p->db, zSql, -1, &pStmt, 0);
|
||||
sqlite3_free(zSql);
|
||||
if( rx!=SQLITE_OK ){
|
||||
sqlite3_finalize(pStmt);
|
||||
pStmt = 0;
|
||||
zSql = sqlite3_mprintf(
|
||||
"REPLACE INTO temp.sqlite_parameters(key,value)"
|
||||
"VALUES(%Q,%Q);", zKey, zValue);
|
||||
if( zSql==0 ) shell_out_of_memory();
|
||||
rx = sqlite3_prepare_v2(p->db, zSql, -1, &pStmt, 0);
|
||||
sqlite3_free(zSql);
|
||||
if( rx!=SQLITE_OK ){
|
||||
utf8_printf(p->out, "Error: %s\n", sqlite3_errmsg(p->db));
|
||||
sqlite3_finalize(pStmt);
|
||||
pStmt = 0;
|
||||
rc = 1;
|
||||
}
|
||||
}
|
||||
sqlite3_step(pStmt);
|
||||
sqlite3_finalize(pStmt);
|
||||
}else
|
||||
|
||||
/* .parameter unset NAME
|
||||
** Remove the NAME binding from the parameter binding table, if it
|
||||
** exists.
|
||||
*/
|
||||
if( nArg==3 && strcmp(azArg[1],"unset")==0 ){
|
||||
char *zSql = sqlite3_mprintf(
|
||||
"DELETE FROM temp.sqlite_parameters WHERE key=%Q", azArg[2]);
|
||||
if( zSql==0 ) shell_out_of_memory();
|
||||
sqlite3_exec(p->db, zSql, 0, 0, 0);
|
||||
sqlite3_free(zSql);
|
||||
}else
|
||||
/* If no command name matches, show a syntax error */
|
||||
parameter_syntax_error:
|
||||
showHelp(p->out, "parameter");
|
||||
}else
|
||||
|
||||
if( c=='p' && n>=3 && strncmp(azArg[0], "print", n)==0 ){
|
||||
int i;
|
||||
for(i=1; i<nArg; i++){
|
||||
|
59
sqlite3.h
59
sqlite3.h
@ -123,9 +123,9 @@ extern "C" {
|
||||
** [sqlite3_libversion_number()], [sqlite3_sourceid()],
|
||||
** [sqlite_version()] and [sqlite_source_id()].
|
||||
*/
|
||||
#define SQLITE_VERSION "3.27.2"
|
||||
#define SQLITE_VERSION_NUMBER 3027002
|
||||
#define SQLITE_SOURCE_ID "2019-02-25 16:06:06 bd49a8271d650fa89e446b42e513b595a717b9212c91dd384aab871fc1d0f6d7"
|
||||
#define SQLITE_VERSION "3.28.0"
|
||||
#define SQLITE_VERSION_NUMBER 3028000
|
||||
#define SQLITE_SOURCE_ID "2019-04-16 19:49:53 884b4b7e502b4e991677b53971277adfaf0a04a284f8e483e2553d0f83156b50"
|
||||
|
||||
/*
|
||||
** CAPI3REF: Run-Time Library Version Numbers
|
||||
@ -189,6 +189,9 @@ SQLITE_API int sqlite3_libversion_number(void);
|
||||
#ifndef SQLITE_OMIT_COMPILEOPTION_DIAGS
|
||||
SQLITE_API int sqlite3_compileoption_used(const char *zOptName);
|
||||
SQLITE_API const char *sqlite3_compileoption_get(int N);
|
||||
#else
|
||||
# define sqlite3_compileoption_used(X) 0
|
||||
# define sqlite3_compileoption_get(X) ((void*)0)
|
||||
#endif
|
||||
|
||||
/*
|
||||
@ -2086,8 +2089,8 @@ struct sqlite3_mem_methods {
|
||||
**
|
||||
** [[SQLITE_DBCONFIG_ENABLE_FTS3_TOKENIZER]]
|
||||
** <dt>SQLITE_DBCONFIG_ENABLE_FTS3_TOKENIZER</dt>
|
||||
** <dd> ^This option is used to enable or disable the two-argument
|
||||
** version of the [fts3_tokenizer()] function which is part of the
|
||||
** <dd> ^This option is used to enable or disable the
|
||||
** [fts3_tokenizer()] function which is part of the
|
||||
** [FTS3] full-text search engine extension.
|
||||
** There should be two additional arguments.
|
||||
** The first argument is an integer which is 0 to disable fts3_tokenizer() or
|
||||
@ -2199,6 +2202,17 @@ struct sqlite3_mem_methods {
|
||||
** <li> Direct writes to [shadow tables].
|
||||
** </ul>
|
||||
** </dd>
|
||||
**
|
||||
** [[SQLITE_DBCONFIG_WRITABLE_SCHEMA]] <dt>SQLITE_DBCONFIG_WRITABLE_SCHEMA</dt>
|
||||
** <dd>The SQLITE_DBCONFIG_WRITABLE_SCHEMA option activates or deactivates the
|
||||
** "writable_schema" flag. This has the same effect and is logically equivalent
|
||||
** to setting [PRAGMA writable_schema=ON] or [PRAGMA writable_schema=OFF].
|
||||
** The first argument to this setting is an integer which is 0 to disable
|
||||
** the writable_schema, positive to enable writable_schema, or negative to
|
||||
** leave the setting unchanged. The second parameter is a pointer to an
|
||||
** integer into which is written 0 or 1 to indicate whether the writable_schema
|
||||
** is enabled or disabled following this call.
|
||||
** </dd>
|
||||
** </dl>
|
||||
*/
|
||||
#define SQLITE_DBCONFIG_MAINDBNAME 1000 /* const char* */
|
||||
@ -2212,7 +2226,8 @@ struct sqlite3_mem_methods {
|
||||
#define SQLITE_DBCONFIG_TRIGGER_EQP 1008 /* int int* */
|
||||
#define SQLITE_DBCONFIG_RESET_DATABASE 1009 /* int int* */
|
||||
#define SQLITE_DBCONFIG_DEFENSIVE 1010 /* int int* */
|
||||
#define SQLITE_DBCONFIG_MAX 1010 /* Largest DBCONFIG */
|
||||
#define SQLITE_DBCONFIG_WRITABLE_SCHEMA 1011 /* int int* */
|
||||
#define SQLITE_DBCONFIG_MAX 1011 /* Largest DBCONFIG */
|
||||
|
||||
/*
|
||||
** CAPI3REF: Enable Or Disable Extended Result Codes
|
||||
@ -3894,6 +3909,18 @@ SQLITE_API const char *sqlite3_normalized_sql(sqlite3_stmt *pStmt);
|
||||
*/
|
||||
SQLITE_API int sqlite3_stmt_readonly(sqlite3_stmt *pStmt);
|
||||
|
||||
/*
|
||||
** CAPI3REF: Query The EXPLAIN Setting For A Prepared Statement
|
||||
** METHOD: sqlite3_stmt
|
||||
**
|
||||
** ^The sqlite3_stmt_isexplain(S) interface returns 1 if the
|
||||
** prepared statement S is an EXPLAIN statement, or 2 if the
|
||||
** statement S is an EXPLAIN QUERY PLAN.
|
||||
** ^The sqlite3_stmt_isexplain(S) interface returns 0 if S is
|
||||
** an ordinary statement or a NULL pointer.
|
||||
*/
|
||||
SQLITE_API int sqlite3_stmt_isexplain(sqlite3_stmt *pStmt);
|
||||
|
||||
/*
|
||||
** CAPI3REF: Determine If A Prepared Statement Has Been Reset
|
||||
** METHOD: sqlite3_stmt
|
||||
@ -4033,7 +4060,9 @@ typedef struct sqlite3_context sqlite3_context;
|
||||
** ^The fifth argument to the BLOB and string binding interfaces
|
||||
** is a destructor used to dispose of the BLOB or
|
||||
** string after SQLite has finished with it. ^The destructor is called
|
||||
** to dispose of the BLOB or string even if the call to bind API fails.
|
||||
** to dispose of the BLOB or string even if the call to the bind API fails,
|
||||
** except the destructor is not called if the third parameter is a NULL
|
||||
** pointer or the fourth parameter is negative.
|
||||
** ^If the fifth argument is
|
||||
** the special value [SQLITE_STATIC], then SQLite assumes that the
|
||||
** information is in static, unmanaged space and does not need to be freed.
|
||||
@ -4950,6 +4979,8 @@ SQLITE_API SQLITE_DEPRECATED int sqlite3_memory_alarm(void(*)(void*,sqlite3_int6
|
||||
** <tr><td><b>sqlite3_value_nochange </b>
|
||||
** <td>→ <td>True if the column is unchanged in an UPDATE
|
||||
** against a virtual table.
|
||||
** <tr><td><b>sqlite3_value_frombind </b>
|
||||
** <td>→ <td>True if value originated from a [bound parameter]
|
||||
** </table></blockquote>
|
||||
**
|
||||
** <b>Details:</b>
|
||||
@ -5011,6 +5042,11 @@ SQLITE_API SQLITE_DEPRECATED int sqlite3_memory_alarm(void(*)(void*,sqlite3_int6
|
||||
** than within an [xUpdate] method call for an UPDATE statement, then
|
||||
** the return value is arbitrary and meaningless.
|
||||
**
|
||||
** ^The sqlite3_value_frombind(X) interface returns non-zero if the
|
||||
** value X originated from one of the [sqlite3_bind_int|sqlite3_bind()]
|
||||
** interfaces. ^If X comes from an SQL literal value, or a table column,
|
||||
** and expression, then sqlite3_value_frombind(X) returns zero.
|
||||
**
|
||||
** Please pay particular attention to the fact that the pointer returned
|
||||
** from [sqlite3_value_blob()], [sqlite3_value_text()], or
|
||||
** [sqlite3_value_text16()] can be invalidated by a subsequent call to
|
||||
@ -5056,6 +5092,7 @@ SQLITE_API int sqlite3_value_bytes16(sqlite3_value*);
|
||||
SQLITE_API int sqlite3_value_type(sqlite3_value*);
|
||||
SQLITE_API int sqlite3_value_numeric_type(sqlite3_value*);
|
||||
SQLITE_API int sqlite3_value_nochange(sqlite3_value*);
|
||||
SQLITE_API int sqlite3_value_frombind(sqlite3_value*);
|
||||
|
||||
/*
|
||||
** CAPI3REF: Finding The Subtype Of SQL Values
|
||||
@ -5791,7 +5828,7 @@ SQLITE_API sqlite3 *sqlite3_db_handle(sqlite3_stmt*);
|
||||
** associated with database N of connection D. ^The main database file
|
||||
** has the name "main". If there is no attached database N on the database
|
||||
** connection D, or if database N is a temporary or in-memory database, then
|
||||
** a NULL pointer is returned.
|
||||
** this function will return either a NULL pointer or an empty string.
|
||||
**
|
||||
** ^The filename returned by this function is the output of the
|
||||
** xFullPathname method of the [VFS]. ^In other words, the filename
|
||||
@ -10892,7 +10929,7 @@ SQLITE_API int sqlite3rebaser_configure(
|
||||
** in size. This function allocates and populates a buffer with a copy
|
||||
** of the changeset rebased rebased according to the configuration of the
|
||||
** rebaser object passed as the first argument. If successful, (*ppOut)
|
||||
** is set to point to the new buffer containing the rebased changset and
|
||||
** is set to point to the new buffer containing the rebased changeset and
|
||||
** (*pnOut) to its size in bytes and SQLITE_OK returned. It is the
|
||||
** responsibility of the caller to eventually free the new buffer using
|
||||
** sqlite3_free(). Otherwise, if an error occurs, (*ppOut) and (*pnOut)
|
||||
@ -11301,7 +11338,7 @@ struct Fts5PhraseIter {
|
||||
** Save the pointer passed as the second argument as the extension functions
|
||||
** "auxiliary data". The pointer may then be retrieved by the current or any
|
||||
** future invocation of the same fts5 extension function made as part of
|
||||
** of the same MATCH query using the xGetAuxdata() API.
|
||||
** the same MATCH query using the xGetAuxdata() API.
|
||||
**
|
||||
** Each extension function is allocated a single auxiliary data slot for
|
||||
** each FTS query (MATCH expression). If the extension function is invoked
|
||||
@ -11316,7 +11353,7 @@ struct Fts5PhraseIter {
|
||||
** The xDelete callback, if one is specified, is also invoked on the
|
||||
** auxiliary data pointer after the FTS5 query has finished.
|
||||
**
|
||||
** If an error (e.g. an OOM condition) occurs within this function, an
|
||||
** If an error (e.g. an OOM condition) occurs within this function,
|
||||
** the auxiliary data is set to NULL and an error code returned. If the
|
||||
** xDelete parameter was not NULL, it is invoked on the auxiliary data
|
||||
** pointer before returning.
|
||||
|
@ -319,6 +319,9 @@ struct sqlite3_api_routines {
|
||||
void(*xDestroy)(void*));
|
||||
/* Version 3.26.0 and later */
|
||||
const char *(*normalized_sql)(sqlite3_stmt*);
|
||||
/* Version 3.28.0 and later */
|
||||
int (*stmt_isexplain)(sqlite3_stmt*);
|
||||
int (*value_frombind)(sqlite3_value*);
|
||||
};
|
||||
|
||||
/*
|
||||
@ -608,6 +611,9 @@ typedef int (*sqlite3_loadext_entry)(
|
||||
#define sqlite3_create_window_function sqlite3_api->create_window_function
|
||||
/* Version 3.26.0 and later */
|
||||
#define sqlite3_normalized_sql sqlite3_api->normalized_sql
|
||||
/* Version 3.28.0 and later */
|
||||
#define sqlite3_stmt_isexplain sqlite3_api->isexplain
|
||||
#define sqlite3_value_frombind sqlite3_api->frombind
|
||||
#endif /* !defined(SQLITE_CORE) && !defined(SQLITE_OMIT_LOAD_EXTENSION) */
|
||||
|
||||
#if !defined(SQLITE_CORE) && !defined(SQLITE_OMIT_LOAD_EXTENSION)
|
||||
|
18
tea/configure
vendored
18
tea/configure
vendored
@ -1,6 +1,6 @@
|
||||
#! /bin/sh
|
||||
# Guess values for system-dependent variables and create Makefiles.
|
||||
# Generated by GNU Autoconf 2.69 for sqlite 3.27.2.
|
||||
# Generated by GNU Autoconf 2.69 for sqlite 3.28.0.
|
||||
#
|
||||
#
|
||||
# Copyright (C) 1992-1996, 1998-2012 Free Software Foundation, Inc.
|
||||
@ -577,8 +577,8 @@ MAKEFLAGS=
|
||||
# Identity of this package.
|
||||
PACKAGE_NAME='sqlite'
|
||||
PACKAGE_TARNAME='sqlite'
|
||||
PACKAGE_VERSION='3.27.2'
|
||||
PACKAGE_STRING='sqlite 3.27.2'
|
||||
PACKAGE_VERSION='3.28.0'
|
||||
PACKAGE_STRING='sqlite 3.28.0'
|
||||
PACKAGE_BUGREPORT=''
|
||||
PACKAGE_URL=''
|
||||
|
||||
@ -1303,7 +1303,7 @@ if test "$ac_init_help" = "long"; then
|
||||
# Omit some internal or obsolete options to make the list less imposing.
|
||||
# This message is too long to be a string in the A/UX 3.1 sh.
|
||||
cat <<_ACEOF
|
||||
\`configure' configures sqlite 3.27.2 to adapt to many kinds of systems.
|
||||
\`configure' configures sqlite 3.28.0 to adapt to many kinds of systems.
|
||||
|
||||
Usage: $0 [OPTION]... [VAR=VALUE]...
|
||||
|
||||
@ -1365,7 +1365,7 @@ fi
|
||||
|
||||
if test -n "$ac_init_help"; then
|
||||
case $ac_init_help in
|
||||
short | recursive ) echo "Configuration of sqlite 3.27.2:";;
|
||||
short | recursive ) echo "Configuration of sqlite 3.28.0:";;
|
||||
esac
|
||||
cat <<\_ACEOF
|
||||
|
||||
@ -1467,7 +1467,7 @@ fi
|
||||
test -n "$ac_init_help" && exit $ac_status
|
||||
if $ac_init_version; then
|
||||
cat <<\_ACEOF
|
||||
sqlite configure 3.27.2
|
||||
sqlite configure 3.28.0
|
||||
generated by GNU Autoconf 2.69
|
||||
|
||||
Copyright (C) 2012 Free Software Foundation, Inc.
|
||||
@ -1878,7 +1878,7 @@ cat >config.log <<_ACEOF
|
||||
This file contains any messages produced by compilers while
|
||||
running configure, to aid debugging if configure makes a mistake.
|
||||
|
||||
It was created by sqlite $as_me 3.27.2, which was
|
||||
It was created by sqlite $as_me 3.28.0, which was
|
||||
generated by GNU Autoconf 2.69. Invocation command line was
|
||||
|
||||
$ $0 $@
|
||||
@ -9373,7 +9373,7 @@ cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1
|
||||
# report actual input values of CONFIG_FILES etc. instead of their
|
||||
# values after options handling.
|
||||
ac_log="
|
||||
This file was extended by sqlite $as_me 3.27.2, which was
|
||||
This file was extended by sqlite $as_me 3.28.0, which was
|
||||
generated by GNU Autoconf 2.69. Invocation command line was
|
||||
|
||||
CONFIG_FILES = $CONFIG_FILES
|
||||
@ -9426,7 +9426,7 @@ _ACEOF
|
||||
cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
|
||||
ac_cs_config="`$as_echo "$ac_configure_args" | sed 's/^ //; s/[\\""\`\$]/\\\\&/g'`"
|
||||
ac_cs_version="\\
|
||||
sqlite config.status 3.27.2
|
||||
sqlite config.status 3.28.0
|
||||
configured by $0, generated by GNU Autoconf 2.69,
|
||||
with options \\"\$ac_cs_config\\"
|
||||
|
||||
|
@ -19,7 +19,7 @@ dnl to configure the system for the local environment.
|
||||
# so you can encode the package version directly into the source files.
|
||||
#-----------------------------------------------------------------------
|
||||
|
||||
AC_INIT([sqlite], [3.27.2])
|
||||
AC_INIT([sqlite], [3.28.0])
|
||||
|
||||
#--------------------------------------------------------------------
|
||||
# Call TEA_INIT as the first TEA_ macro to set up initial vars.
|
||||
|
@ -98,6 +98,14 @@ typedef struct SqliteDb SqliteDb;
|
||||
/*
|
||||
** New SQL functions can be created as TCL scripts. Each such function
|
||||
** is described by an instance of the following structure.
|
||||
**
|
||||
** Variable eType may be set to SQLITE_INTEGER, SQLITE_FLOAT, SQLITE_TEXT,
|
||||
** SQLITE_BLOB or SQLITE_NULL. If it is SQLITE_NULL, then the implementation
|
||||
** attempts to determine the type of the result based on the Tcl object.
|
||||
** If it is SQLITE_TEXT or SQLITE_BLOB, then a text (sqlite3_result_text())
|
||||
** or blob (sqlite3_result_blob()) is returned. If it is SQLITE_INTEGER
|
||||
** or SQLITE_FLOAT, then an attempt is made to return an integer or float
|
||||
** value, falling back to float and then text if this is not possible.
|
||||
*/
|
||||
typedef struct SqlFunc SqlFunc;
|
||||
struct SqlFunc {
|
||||
@ -105,6 +113,7 @@ struct SqlFunc {
|
||||
Tcl_Obj *pScript; /* The Tcl_Obj representation of the script */
|
||||
SqliteDb *pDb; /* Database connection that owns this function */
|
||||
int useEvalObjv; /* True if it is safe to use Tcl_EvalObjv */
|
||||
int eType; /* Type of value to return */
|
||||
char *zName; /* Name of this function */
|
||||
SqlFunc *pNext; /* Next function on the list of them all */
|
||||
};
|
||||
@ -155,6 +164,7 @@ struct SqliteDb {
|
||||
char *zTraceV2; /* The trace_v2 callback routine */
|
||||
char *zProfile; /* The profile callback routine */
|
||||
char *zProgress; /* The progress callback routine */
|
||||
char *zBindFallback; /* Callback to invoke on a binding miss */
|
||||
char *zAuth; /* The authorization callback routine */
|
||||
int disableAuth; /* Disable the authorizer if it exists */
|
||||
char *zNull; /* Text to substitute for an SQL NULL value */
|
||||
@ -545,6 +555,9 @@ static void SQLITE_TCLAPI DbDeleteCmd(void *db){
|
||||
if( pDb->zProfile ){
|
||||
Tcl_Free(pDb->zProfile);
|
||||
}
|
||||
if( pDb->zBindFallback ){
|
||||
Tcl_Free(pDb->zBindFallback);
|
||||
}
|
||||
if( pDb->zAuth ){
|
||||
Tcl_Free(pDb->zAuth);
|
||||
}
|
||||
@ -1000,27 +1013,54 @@ static void tclSqlFunc(sqlite3_context *context, int argc, sqlite3_value**argv){
|
||||
u8 *data;
|
||||
const char *zType = (pVar->typePtr ? pVar->typePtr->name : "");
|
||||
char c = zType[0];
|
||||
if( c=='b' && strcmp(zType,"bytearray")==0 && pVar->bytes==0 ){
|
||||
/* Only return a BLOB type if the Tcl variable is a bytearray and
|
||||
** has no string representation. */
|
||||
data = Tcl_GetByteArrayFromObj(pVar, &n);
|
||||
sqlite3_result_blob(context, data, n, SQLITE_TRANSIENT);
|
||||
}else if( c=='b' && strcmp(zType,"boolean")==0 ){
|
||||
Tcl_GetIntFromObj(0, pVar, &n);
|
||||
sqlite3_result_int(context, n);
|
||||
}else if( c=='d' && strcmp(zType,"double")==0 ){
|
||||
double r;
|
||||
Tcl_GetDoubleFromObj(0, pVar, &r);
|
||||
sqlite3_result_double(context, r);
|
||||
}else if( (c=='w' && strcmp(zType,"wideInt")==0) ||
|
||||
(c=='i' && strcmp(zType,"int")==0) ){
|
||||
Tcl_WideInt v;
|
||||
Tcl_GetWideIntFromObj(0, pVar, &v);
|
||||
sqlite3_result_int64(context, v);
|
||||
}else{
|
||||
data = (unsigned char *)Tcl_GetStringFromObj(pVar, &n);
|
||||
sqlite3_result_text(context, (char *)data, n, SQLITE_TRANSIENT);
|
||||
int eType = p->eType;
|
||||
|
||||
if( eType==SQLITE_NULL ){
|
||||
if( c=='b' && strcmp(zType,"bytearray")==0 && pVar->bytes==0 ){
|
||||
/* Only return a BLOB type if the Tcl variable is a bytearray and
|
||||
** has no string representation. */
|
||||
eType = SQLITE_BLOB;
|
||||
}else if( (c=='b' && strcmp(zType,"boolean")==0)
|
||||
|| (c=='w' && strcmp(zType,"wideInt")==0)
|
||||
|| (c=='i' && strcmp(zType,"int")==0)
|
||||
){
|
||||
eType = SQLITE_INTEGER;
|
||||
}else if( c=='d' && strcmp(zType,"double")==0 ){
|
||||
eType = SQLITE_FLOAT;
|
||||
}else{
|
||||
eType = SQLITE_TEXT;
|
||||
}
|
||||
}
|
||||
|
||||
switch( eType ){
|
||||
case SQLITE_BLOB: {
|
||||
data = Tcl_GetByteArrayFromObj(pVar, &n);
|
||||
sqlite3_result_blob(context, data, n, SQLITE_TRANSIENT);
|
||||
break;
|
||||
}
|
||||
case SQLITE_INTEGER: {
|
||||
Tcl_WideInt v;
|
||||
if( TCL_OK==Tcl_GetWideIntFromObj(0, pVar, &v) ){
|
||||
sqlite3_result_int64(context, v);
|
||||
break;
|
||||
}
|
||||
/* fall-through */
|
||||
}
|
||||
case SQLITE_FLOAT: {
|
||||
double r;
|
||||
if( TCL_OK==Tcl_GetDoubleFromObj(0, pVar, &r) ){
|
||||
sqlite3_result_double(context, r);
|
||||
break;
|
||||
}
|
||||
/* fall-through */
|
||||
}
|
||||
default: {
|
||||
data = (unsigned char *)Tcl_GetStringFromObj(pVar, &n);
|
||||
sqlite3_result_text(context, (char *)data, n, SQLITE_TRANSIENT);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@ -1270,6 +1310,8 @@ static int dbPrepareAndBind(
|
||||
int iParm = 0; /* Next free entry in apParm */
|
||||
char c;
|
||||
int i;
|
||||
int needResultReset = 0; /* Need to invoke Tcl_ResetResult() */
|
||||
int rc = SQLITE_OK; /* Value to return */
|
||||
Tcl_Interp *interp = pDb->interp;
|
||||
|
||||
*ppPreStmt = 0;
|
||||
@ -1357,6 +1399,25 @@ static int dbPrepareAndBind(
|
||||
const char *zVar = sqlite3_bind_parameter_name(pStmt, i);
|
||||
if( zVar!=0 && (zVar[0]=='$' || zVar[0]==':' || zVar[0]=='@') ){
|
||||
Tcl_Obj *pVar = Tcl_GetVar2Ex(interp, &zVar[1], 0, 0);
|
||||
if( pVar==0 && pDb->zBindFallback!=0 ){
|
||||
Tcl_Obj *pCmd;
|
||||
int rx;
|
||||
pCmd = Tcl_NewStringObj(pDb->zBindFallback, -1);
|
||||
Tcl_IncrRefCount(pCmd);
|
||||
Tcl_ListObjAppendElement(interp, pCmd, Tcl_NewStringObj(zVar,-1));
|
||||
if( needResultReset ) Tcl_ResetResult(interp);
|
||||
needResultReset = 1;
|
||||
rx = Tcl_EvalObjEx(interp, pCmd, TCL_EVAL_DIRECT);
|
||||
Tcl_DecrRefCount(pCmd);
|
||||
if( rx==TCL_OK ){
|
||||
pVar = Tcl_GetObjResult(interp);
|
||||
}else if( rx==TCL_ERROR ){
|
||||
rc = TCL_ERROR;
|
||||
break;
|
||||
}else{
|
||||
pVar = 0;
|
||||
}
|
||||
}
|
||||
if( pVar ){
|
||||
int n;
|
||||
u8 *data;
|
||||
@ -1392,12 +1453,14 @@ static int dbPrepareAndBind(
|
||||
}else{
|
||||
sqlite3_bind_null(pStmt, i);
|
||||
}
|
||||
if( needResultReset ) Tcl_ResetResult(pDb->interp);
|
||||
}
|
||||
}
|
||||
pPreStmt->nParm = iParm;
|
||||
*ppPreStmt = pPreStmt;
|
||||
if( needResultReset && rc==TCL_OK ) Tcl_ResetResult(pDb->interp);
|
||||
|
||||
return TCL_OK;
|
||||
return rc;
|
||||
}
|
||||
|
||||
/*
|
||||
@ -1856,35 +1919,36 @@ static int SQLITE_TCLAPI DbObjCmd(
|
||||
int choice;
|
||||
int rc = TCL_OK;
|
||||
static const char *DB_strs[] = {
|
||||
"authorizer", "backup", "busy",
|
||||
"cache", "changes", "close",
|
||||
"collate", "collation_needed", "commit_hook",
|
||||
"complete", "copy", "deserialize",
|
||||
"enable_load_extension", "errorcode", "eval",
|
||||
"exists", "function", "incrblob",
|
||||
"interrupt", "last_insert_rowid", "nullvalue",
|
||||
"onecolumn", "preupdate", "profile",
|
||||
"progress", "rekey", "restore",
|
||||
"rollback_hook", "serialize", "status",
|
||||
"timeout", "total_changes", "trace",
|
||||
"trace_v2", "transaction", "unlock_notify",
|
||||
"update_hook", "version", "wal_hook",
|
||||
0
|
||||
"authorizer", "backup", "bind_fallback",
|
||||
"busy", "cache", "changes",
|
||||
"close", "collate", "collation_needed",
|
||||
"commit_hook", "complete", "copy",
|
||||
"deserialize", "enable_load_extension", "errorcode",
|
||||
"eval", "exists", "function",
|
||||
"incrblob", "interrupt", "last_insert_rowid",
|
||||
"nullvalue", "onecolumn", "preupdate",
|
||||
"profile", "progress", "rekey",
|
||||
"restore", "rollback_hook", "serialize",
|
||||
"status", "timeout", "total_changes",
|
||||
"trace", "trace_v2", "transaction",
|
||||
"unlock_notify", "update_hook", "version",
|
||||
"wal_hook", 0
|
||||
};
|
||||
enum DB_enum {
|
||||
DB_AUTHORIZER, DB_BACKUP, DB_BUSY,
|
||||
DB_CACHE, DB_CHANGES, DB_CLOSE,
|
||||
DB_COLLATE, DB_COLLATION_NEEDED, DB_COMMIT_HOOK,
|
||||
DB_COMPLETE, DB_COPY, DB_DESERIALIZE,
|
||||
DB_ENABLE_LOAD_EXTENSION, DB_ERRORCODE, DB_EVAL,
|
||||
DB_EXISTS, DB_FUNCTION, DB_INCRBLOB,
|
||||
DB_INTERRUPT, DB_LAST_INSERT_ROWID, DB_NULLVALUE,
|
||||
DB_ONECOLUMN, DB_PREUPDATE, DB_PROFILE,
|
||||
DB_PROGRESS, DB_REKEY, DB_RESTORE,
|
||||
DB_ROLLBACK_HOOK, DB_SERIALIZE, DB_STATUS,
|
||||
DB_TIMEOUT, DB_TOTAL_CHANGES, DB_TRACE,
|
||||
DB_TRACE_V2, DB_TRANSACTION, DB_UNLOCK_NOTIFY,
|
||||
DB_UPDATE_HOOK, DB_VERSION, DB_WAL_HOOK
|
||||
DB_AUTHORIZER, DB_BACKUP, DB_BIND_FALLBACK,
|
||||
DB_BUSY, DB_CACHE, DB_CHANGES,
|
||||
DB_CLOSE, DB_COLLATE, DB_COLLATION_NEEDED,
|
||||
DB_COMMIT_HOOK, DB_COMPLETE, DB_COPY,
|
||||
DB_DESERIALIZE, DB_ENABLE_LOAD_EXTENSION,DB_ERRORCODE,
|
||||
DB_EVAL, DB_EXISTS, DB_FUNCTION,
|
||||
DB_INCRBLOB, DB_INTERRUPT, DB_LAST_INSERT_ROWID,
|
||||
DB_NULLVALUE, DB_ONECOLUMN, DB_PREUPDATE,
|
||||
DB_PROFILE, DB_PROGRESS, DB_REKEY,
|
||||
DB_RESTORE, DB_ROLLBACK_HOOK, DB_SERIALIZE,
|
||||
DB_STATUS, DB_TIMEOUT, DB_TOTAL_CHANGES,
|
||||
DB_TRACE, DB_TRACE_V2, DB_TRANSACTION,
|
||||
DB_UNLOCK_NOTIFY, DB_UPDATE_HOOK, DB_VERSION,
|
||||
DB_WAL_HOOK
|
||||
};
|
||||
/* don't leave trailing commas on DB_enum, it confuses the AIX xlc compiler */
|
||||
|
||||
@ -2006,6 +2070,49 @@ static int SQLITE_TCLAPI DbObjCmd(
|
||||
break;
|
||||
}
|
||||
|
||||
/* $db bind_fallback ?CALLBACK?
|
||||
**
|
||||
** When resolving bind parameters in an SQL statement, if the parameter
|
||||
** cannot be associated with a TCL variable then invoke CALLBACK with a
|
||||
** single argument that is the name of the parameter and use the return
|
||||
** value of the CALLBACK as the binding. If CALLBACK returns something
|
||||
** other than TCL_OK or TCL_ERROR then bind a NULL.
|
||||
**
|
||||
** If CALLBACK is an empty string, then revert to the default behavior
|
||||
** which is to set the binding to NULL.
|
||||
**
|
||||
** If CALLBACK returns an error, that causes the statement execution to
|
||||
** abort. Hence, to configure a connection so that it throws an error
|
||||
** on an attempt to bind an unknown variable, do something like this:
|
||||
**
|
||||
** proc bind_error {name} {error "no such variable: $name"}
|
||||
** db bind_fallback bind_error
|
||||
*/
|
||||
case DB_BIND_FALLBACK: {
|
||||
if( objc>3 ){
|
||||
Tcl_WrongNumArgs(interp, 2, objv, "?CALLBACK?");
|
||||
return TCL_ERROR;
|
||||
}else if( objc==2 ){
|
||||
if( pDb->zBindFallback ){
|
||||
Tcl_AppendResult(interp, pDb->zBindFallback, (char*)0);
|
||||
}
|
||||
}else{
|
||||
char *zCallback;
|
||||
int len;
|
||||
if( pDb->zBindFallback ){
|
||||
Tcl_Free(pDb->zBindFallback);
|
||||
}
|
||||
zCallback = Tcl_GetStringFromObj(objv[2], &len);
|
||||
if( zCallback && len>0 ){
|
||||
pDb->zBindFallback = Tcl_Alloc( len + 1 );
|
||||
memcpy(pDb->zBindFallback, zCallback, len+1);
|
||||
}else{
|
||||
pDb->zBindFallback = 0;
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
/* $db busy ?CALLBACK?
|
||||
**
|
||||
** Invoke the given callback if an SQL statement attempts to open
|
||||
@ -2651,6 +2758,7 @@ static int SQLITE_TCLAPI DbObjCmd(
|
||||
char *zName;
|
||||
int nArg = -1;
|
||||
int i;
|
||||
int eType = SQLITE_NULL;
|
||||
if( objc<4 ){
|
||||
Tcl_WrongNumArgs(interp, 2, objv, "NAME ?SWITCHES? SCRIPT");
|
||||
return TCL_ERROR;
|
||||
@ -2658,7 +2766,7 @@ static int SQLITE_TCLAPI DbObjCmd(
|
||||
for(i=3; i<(objc-1); i++){
|
||||
const char *z = Tcl_GetString(objv[i]);
|
||||
int n = strlen30(z);
|
||||
if( n>2 && strncmp(z, "-argcount",n)==0 ){
|
||||
if( n>1 && strncmp(z, "-argcount",n)==0 ){
|
||||
if( i==(objc-2) ){
|
||||
Tcl_AppendResult(interp, "option requires an argument: ", z,(char*)0);
|
||||
return TCL_ERROR;
|
||||
@ -2671,11 +2779,25 @@ static int SQLITE_TCLAPI DbObjCmd(
|
||||
}
|
||||
i++;
|
||||
}else
|
||||
if( n>2 && strncmp(z, "-deterministic",n)==0 ){
|
||||
if( n>1 && strncmp(z, "-deterministic",n)==0 ){
|
||||
flags |= SQLITE_DETERMINISTIC;
|
||||
}else
|
||||
if( n>1 && strncmp(z, "-returntype", n)==0 ){
|
||||
const char *azType[] = {"integer", "real", "text", "blob", "any", 0};
|
||||
assert( SQLITE_INTEGER==1 && SQLITE_FLOAT==2 && SQLITE_TEXT==3 );
|
||||
assert( SQLITE_BLOB==4 && SQLITE_NULL==5 );
|
||||
if( i==(objc-2) ){
|
||||
Tcl_AppendResult(interp, "option requires an argument: ", z,(char*)0);
|
||||
return TCL_ERROR;
|
||||
}
|
||||
i++;
|
||||
if( Tcl_GetIndexFromObj(interp, objv[i], azType, "type", 0, &eType) ){
|
||||
return TCL_ERROR;
|
||||
}
|
||||
eType++;
|
||||
}else{
|
||||
Tcl_AppendResult(interp, "bad option \"", z,
|
||||
"\": must be -argcount or -deterministic", (char*)0
|
||||
"\": must be -argcount, -deterministic or -returntype", (char*)0
|
||||
);
|
||||
return TCL_ERROR;
|
||||
}
|
||||
@ -2691,6 +2813,7 @@ static int SQLITE_TCLAPI DbObjCmd(
|
||||
pFunc->pScript = pScript;
|
||||
Tcl_IncrRefCount(pScript);
|
||||
pFunc->useEvalObjv = safeToUseEvalObjv(interp, pScript);
|
||||
pFunc->eType = eType;
|
||||
rc = sqlite3_create_function(pDb->db, zName, nArg, flags,
|
||||
pFunc, tclSqlFunc, 0, 0);
|
||||
if( rc!=SQLITE_OK ){
|
||||
|
Loading…
Reference in New Issue
Block a user