track 3.7.13
This commit is contained in:
parent
35a66a5caa
commit
de4f34b64d
13
Makefile.in
13
Makefile.in
|
@ -165,8 +165,9 @@ LIBOBJS0 = alter.lo analyze.lo attach.lo auth.lo \
|
|||
backup.lo bitvec.lo btmutex.lo btree.lo build.lo \
|
||||
callback.lo complete.lo ctime.lo date.lo delete.lo \
|
||||
expr.lo fault.lo fkey.lo \
|
||||
fts3.lo fts3_aux.lo fts3_expr.lo fts3_hash.lo fts3_icu.lo fts3_porter.lo \
|
||||
fts3_snippet.lo fts3_tokenizer.lo fts3_tokenizer1.lo fts3_write.lo \
|
||||
fts3.lo fts3_aux.lo fts3_expr.lo fts3_hash.lo fts3_icu.lo \
|
||||
fts3_porter.lo fts3_snippet.lo fts3_tokenizer.lo fts3_tokenizer1.lo \
|
||||
fts3_unicode.lo fts3_unicode2.lo fts3_write.lo \
|
||||
func.lo global.lo hash.lo \
|
||||
icu.lo insert.lo journal.lo legacy.lo loadext.lo \
|
||||
main.lo malloc.lo mem0.lo mem1.lo mem2.lo mem3.lo mem5.lo \
|
||||
|
@ -317,6 +318,8 @@ SRC += \
|
|||
$(TOP)/ext/fts3/fts3_tokenizer.h \
|
||||
$(TOP)/ext/fts3/fts3_tokenizer.c \
|
||||
$(TOP)/ext/fts3/fts3_tokenizer1.c \
|
||||
$(TOP)/ext/fts3/fts3_unicode.c \
|
||||
$(TOP)/ext/fts3/fts3_unicode2.c \
|
||||
$(TOP)/ext/fts3/fts3_write.c
|
||||
SRC += \
|
||||
$(TOP)/ext/icu/sqliteicu.h \
|
||||
|
@ -856,6 +859,12 @@ fts3_tokenizer.lo: $(TOP)/ext/fts3/fts3_tokenizer.c $(HDR) $(EXTHDR)
|
|||
fts3_tokenizer1.lo: $(TOP)/ext/fts3/fts3_tokenizer1.c $(HDR) $(EXTHDR)
|
||||
$(LTCOMPILE) -DSQLITE_CORE -c $(TOP)/ext/fts3/fts3_tokenizer1.c
|
||||
|
||||
fts3_unicode.lo: $(TOP)/ext/fts3/fts3_unicode.c $(HDR) $(EXTHDR)
|
||||
$(LTCOMPILE) -DSQLITE_CORE -c $(TOP)/ext/fts3/fts3_unicode.c
|
||||
|
||||
fts3_unicode2.lo: $(TOP)/ext/fts3/fts3_unicode2.c $(HDR) $(EXTHDR)
|
||||
$(LTCOMPILE) -DSQLITE_CORE -c $(TOP)/ext/fts3/fts3_unicode2.c
|
||||
|
||||
fts3_write.lo: $(TOP)/ext/fts3/fts3_write.c $(HDR) $(EXTHDR)
|
||||
$(LTCOMPILE) -DSQLITE_CORE -c $(TOP)/ext/fts3/fts3_write.c
|
||||
|
||||
|
|
58
Makefile.msc
58
Makefile.msc
|
@ -15,6 +15,12 @@ USE_AMALGAMATION = 1
|
|||
#
|
||||
USE_ICU = 0
|
||||
|
||||
# Set this non-0 to compile binaries suitable for the WinRT environment.
|
||||
# This setting does not apply to any binaries that require Tcl to operate
|
||||
# properly (i.e. the text fixture, etc).
|
||||
#
|
||||
FOR_WINRT = 0
|
||||
|
||||
# Set this to non-0 to create and use PDBs.
|
||||
#
|
||||
SYMBOLS = 1
|
||||
|
@ -32,16 +38,10 @@ SYMBOLS = 1
|
|||
#
|
||||
DEBUG = 0
|
||||
|
||||
# Version numbers and release number for the SQLite being compiled.
|
||||
#
|
||||
VERSION = 3.7
|
||||
VERSION_NUMBER = 3007009
|
||||
RELEASE = 3.7.9
|
||||
|
||||
# C Compiler and options for use in building executables that
|
||||
# will run on the platform that is doing the build.
|
||||
#
|
||||
BCC = cl.exe
|
||||
BCC = cl.exe -W3
|
||||
|
||||
# C Compile and options for use in building executables that
|
||||
# will run on the target platform. (BCC and TCC are usually the
|
||||
|
@ -49,7 +49,18 @@ BCC = cl.exe
|
|||
#
|
||||
TCC = cl.exe -W3 -DSQLITE_OS_WIN=1 -I. -I$(TOP)\src -fp:precise
|
||||
|
||||
# The mksqlite3c.tcl and mksqlite3h.tcl scripts will pull in
|
||||
# When compiling the library for use in the WinRT environment,
|
||||
# the following compile-time options must be used as well to
|
||||
# disable use of Win32 APIs that are not available and to enable
|
||||
# use of Win32 APIs that are specific to Windows 8 and/or WinRT.
|
||||
# Also, we need to dynamically link to the MSVC runtime when
|
||||
# compiling for WinRT.
|
||||
#
|
||||
!IF $(FOR_WINRT)!=0
|
||||
TCC = $(TCC) -DSQLITE_OS_WINRT=1 -MD
|
||||
!ENDIF
|
||||
|
||||
# The mksqlite3c.tcl and mksqlite3h.tcl scripts will pull in
|
||||
# any extension header files by default. For non-amalgamation
|
||||
# builds, we need to make sure the compiler can find these.
|
||||
#
|
||||
|
@ -64,6 +75,7 @@ TCC = $(TCC) -I$(TOP)\ext\rtree
|
|||
#
|
||||
!IF $(DEBUG)==0
|
||||
TCC = $(TCC) -DNDEBUG
|
||||
BCC = $(BCC) -DNDEBUG
|
||||
!ENDIF
|
||||
|
||||
!IF $(DEBUG)>1
|
||||
|
@ -82,6 +94,7 @@ TCC = $(TCC) -DSQLITE_ENABLE_IOTRACE
|
|||
# Prevent warnings about "insecure" runtime library functions being used.
|
||||
#
|
||||
TCC = $(TCC) -D_CRT_SECURE_NO_DEPRECATE -D_CRT_SECURE_NO_WARNINGS
|
||||
BCC = $(BCC) -D_CRT_SECURE_NO_DEPRECATE -D_CRT_SECURE_NO_WARNINGS
|
||||
|
||||
#
|
||||
# Use native Win32 heap instead of malloc/free?
|
||||
|
@ -194,12 +207,15 @@ TCC = $(TCC) $(OPTS)
|
|||
# If debugging is enabled, disable all optimizations and enable PDBs.
|
||||
!IF $(DEBUG)>0
|
||||
TCC = $(TCC) -Od -D_DEBUG
|
||||
BCC = $(BCC) -Od -D_DEBUG
|
||||
!ELSE
|
||||
TCC = $(TCC) -O2
|
||||
BCC = $(BCC) -O2
|
||||
!ENDIF
|
||||
|
||||
!IF $(DEBUG)>0 || $(SYMBOLS)!=0
|
||||
TCC = $(TCC) -Zi
|
||||
BCC = $(BCC) -Zi
|
||||
!ENDIF
|
||||
|
||||
# If ICU support is enabled, add the compiler options for it.
|
||||
|
@ -223,9 +239,18 @@ LTLINKOPTS = /MACHINE:$(PLATFORM)
|
|||
LTLIBOPTS = /MACHINE:$(PLATFORM)
|
||||
!ENDIF
|
||||
|
||||
# If debugging is enabled, enable PDBs.
|
||||
# When compiling for use in the WinRT environment, the following
|
||||
# linker option must be used to mark the executable as runnable
|
||||
# only in the context of an application container.
|
||||
#
|
||||
!IF $(FOR_WINRT)!=0
|
||||
LTLINKOPTS = $(LTLINKOPTS) /APPCONTAINER
|
||||
!ENDIF
|
||||
|
||||
# If either debugging or symbols are enabled, enable PDBs.
|
||||
!IF $(DEBUG)>0 || $(SYMBOLS)!=0
|
||||
LTLINKOPTS = $(LTLINKOPTS) /DEBUG
|
||||
BCC = $(BCC) /DEBUG
|
||||
!ENDIF
|
||||
|
||||
# Start with the Tcl related linker options.
|
||||
|
@ -250,8 +275,9 @@ LIBOBJS0 = alter.lo analyze.lo attach.lo auth.lo \
|
|||
backup.lo bitvec.lo btmutex.lo btree.lo build.lo \
|
||||
callback.lo complete.lo ctime.lo date.lo delete.lo \
|
||||
expr.lo fault.lo fkey.lo \
|
||||
fts3.lo fts3_aux.lo fts3_expr.lo fts3_hash.lo fts3_icu.lo fts3_porter.lo \
|
||||
fts3_snippet.lo fts3_tokenizer.lo fts3_tokenizer1.lo fts3_write.lo \
|
||||
fts3.lo fts3_aux.lo fts3_expr.lo fts3_hash.lo fts3_icu.lo \
|
||||
fts3_porter.lo fts3_snippet.lo fts3_tokenizer.lo fts3_tokenizer1.lo \
|
||||
fts3_unicode.lo fts3_unicode2.lo fts3_write.lo \
|
||||
func.lo global.lo hash.lo \
|
||||
icu.lo insert.lo journal.lo legacy.lo loadext.lo \
|
||||
main.lo malloc.lo mem0.lo mem1.lo mem2.lo mem3.lo mem5.lo \
|
||||
|
@ -405,6 +431,8 @@ SRC = $(SRC) \
|
|||
$(TOP)\ext\fts3\fts3_tokenizer.h \
|
||||
$(TOP)\ext\fts3\fts3_tokenizer.c \
|
||||
$(TOP)\ext\fts3\fts3_tokenizer1.c \
|
||||
$(TOP)\ext\fts3\fts3_unicode.c \
|
||||
$(TOP)\ext\fts3\fts3_unicode2.c \
|
||||
$(TOP)\ext\fts3\fts3_write.c
|
||||
SRC = $(SRC) \
|
||||
$(TOP)\ext\icu\sqliteicu.h \
|
||||
|
@ -512,6 +540,8 @@ TESTSRC2 = \
|
|||
$(TOP)\ext\fts3\fts3_aux.c \
|
||||
$(TOP)\ext\fts3\fts3_expr.c \
|
||||
$(TOP)\ext\fts3\fts3_tokenizer.c \
|
||||
$(TOP)\ext\fts3\fts3_unicode.c \
|
||||
$(TOP)\ext\fts3\fts3_unicode2.c \
|
||||
$(TOP)\ext\fts3\fts3_write.c \
|
||||
$(TOP)\ext\async\sqlite3async.c
|
||||
|
||||
|
@ -926,6 +956,12 @@ fts3_tokenizer.lo: $(TOP)\ext\fts3\fts3_tokenizer.c $(HDR) $(EXTHDR)
|
|||
fts3_tokenizer1.lo: $(TOP)\ext\fts3\fts3_tokenizer1.c $(HDR) $(EXTHDR)
|
||||
$(LTCOMPILE) -DSQLITE_CORE -c $(TOP)\ext\fts3\fts3_tokenizer1.c
|
||||
|
||||
fts3_unicode.lo: $(TOP)\ext\fts3\fts3_unicode.c $(HDR) $(EXTHDR)
|
||||
$(LTCOMPILE) -DSQLITE_CORE -c $(TOP)\ext\fts3\fts3_unicode.c
|
||||
|
||||
fts3_unicode2.lo: $(TOP)\ext\fts3\fts3_unicode2.c $(HDR) $(EXTHDR)
|
||||
$(LTCOMPILE) -DSQLITE_CORE -c $(TOP)\ext\fts3\fts3_unicode2.c
|
||||
|
||||
fts3_write.lo: $(TOP)\ext\fts3\fts3_write.c $(HDR) $(EXTHDR)
|
||||
$(LTCOMPILE) -DSQLITE_CORE -c $(TOP)\ext\fts3\fts3_write.c
|
||||
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
#! /bin/sh
|
||||
# Guess values for system-dependent variables and create Makefiles.
|
||||
# Generated by GNU Autoconf 2.62 for sqlite 3.7.12.1.
|
||||
# Generated by GNU Autoconf 2.62 for sqlite 3.7.13.
|
||||
#
|
||||
# Copyright (C) 1992, 1993, 1994, 1995, 1996, 1998, 1999, 2000, 2001,
|
||||
# 2002, 2003, 2004, 2005, 2006, 2007, 2008 Free Software Foundation, Inc.
|
||||
|
@ -743,8 +743,8 @@ SHELL=${CONFIG_SHELL-/bin/sh}
|
|||
# Identity of this package.
|
||||
PACKAGE_NAME='sqlite'
|
||||
PACKAGE_TARNAME='sqlite'
|
||||
PACKAGE_VERSION='3.7.12.1'
|
||||
PACKAGE_STRING='sqlite 3.7.12.1'
|
||||
PACKAGE_VERSION='3.7.13'
|
||||
PACKAGE_STRING='sqlite 3.7.13'
|
||||
PACKAGE_BUGREPORT=''
|
||||
|
||||
# Factoring default headers for most tests.
|
||||
|
@ -1485,7 +1485,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.7.12.1 to adapt to many kinds of systems.
|
||||
\`configure' configures sqlite 3.7.13 to adapt to many kinds of systems.
|
||||
|
||||
Usage: $0 [OPTION]... [VAR=VALUE]...
|
||||
|
||||
|
@ -1550,7 +1550,7 @@ fi
|
|||
|
||||
if test -n "$ac_init_help"; then
|
||||
case $ac_init_help in
|
||||
short | recursive ) echo "Configuration of sqlite 3.7.12.1:";;
|
||||
short | recursive ) echo "Configuration of sqlite 3.7.13:";;
|
||||
esac
|
||||
cat <<\_ACEOF
|
||||
|
||||
|
@ -1666,7 +1666,7 @@ fi
|
|||
test -n "$ac_init_help" && exit $ac_status
|
||||
if $ac_init_version; then
|
||||
cat <<\_ACEOF
|
||||
sqlite configure 3.7.12.1
|
||||
sqlite configure 3.7.13
|
||||
generated by GNU Autoconf 2.62
|
||||
|
||||
Copyright (C) 1992, 1993, 1994, 1995, 1996, 1998, 1999, 2000, 2001,
|
||||
|
@ -1680,7 +1680,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.7.12.1, which was
|
||||
It was created by sqlite $as_me 3.7.13, which was
|
||||
generated by GNU Autoconf 2.62. Invocation command line was
|
||||
|
||||
$ $0 $@
|
||||
|
@ -14032,7 +14032,7 @@ exec 6>&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.7.12.1, which was
|
||||
This file was extended by sqlite $as_me 3.7.13, which was
|
||||
generated by GNU Autoconf 2.62. Invocation command line was
|
||||
|
||||
CONFIG_FILES = $CONFIG_FILES
|
||||
|
@ -14085,7 +14085,7 @@ Report bugs to <bug-autoconf@gnu.org>."
|
|||
_ACEOF
|
||||
cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
|
||||
ac_cs_version="\\
|
||||
sqlite config.status 3.7.12.1
|
||||
sqlite config.status 3.7.13
|
||||
configured by $0, generated by GNU Autoconf 2.62,
|
||||
with options \\"`$as_echo "$ac_configure_args" | sed 's/^ //; s/[\\""\`\$]/\\\\&/g'`\\"
|
||||
|
||||
|
|
|
@ -11,7 +11,7 @@
|
|||
);
|
||||
|
||||
The built-in tokenizers (valid values to pass as <tokenizer name>) are
|
||||
"simple" and "porter".
|
||||
"simple", "porter" and "unicode".
|
||||
|
||||
<tokenizer-args> should consist of zero or more white-space separated
|
||||
arguments to pass to the selected tokenizer implementation. The
|
||||
|
|
|
@ -3554,6 +3554,9 @@ static void hashDestroy(void *p){
|
|||
*/
|
||||
void sqlite3Fts3SimpleTokenizerModule(sqlite3_tokenizer_module const**ppModule);
|
||||
void sqlite3Fts3PorterTokenizerModule(sqlite3_tokenizer_module const**ppModule);
|
||||
#ifdef SQLITE_ENABLE_FTS4_UNICODE61
|
||||
void sqlite3Fts3UnicodeTokenizer(sqlite3_tokenizer_module const**ppModule);
|
||||
#endif
|
||||
#ifdef SQLITE_ENABLE_ICU
|
||||
void sqlite3Fts3IcuTokenizerModule(sqlite3_tokenizer_module const**ppModule);
|
||||
#endif
|
||||
|
@ -3569,12 +3572,19 @@ int sqlite3Fts3Init(sqlite3 *db){
|
|||
Fts3Hash *pHash = 0;
|
||||
const sqlite3_tokenizer_module *pSimple = 0;
|
||||
const sqlite3_tokenizer_module *pPorter = 0;
|
||||
#ifdef SQLITE_ENABLE_FTS4_UNICODE61
|
||||
const sqlite3_tokenizer_module *pUnicode = 0;
|
||||
#endif
|
||||
|
||||
#ifdef SQLITE_ENABLE_ICU
|
||||
const sqlite3_tokenizer_module *pIcu = 0;
|
||||
sqlite3Fts3IcuTokenizerModule(&pIcu);
|
||||
#endif
|
||||
|
||||
#ifdef SQLITE_ENABLE_FTS4_UNICODE61
|
||||
sqlite3Fts3UnicodeTokenizer(&pUnicode);
|
||||
#endif
|
||||
|
||||
#ifdef SQLITE_TEST
|
||||
rc = sqlite3Fts3InitTerm(db);
|
||||
if( rc!=SQLITE_OK ) return rc;
|
||||
|
@ -3598,6 +3608,10 @@ int sqlite3Fts3Init(sqlite3 *db){
|
|||
if( rc==SQLITE_OK ){
|
||||
if( sqlite3Fts3HashInsert(pHash, "simple", 7, (void *)pSimple)
|
||||
|| sqlite3Fts3HashInsert(pHash, "porter", 7, (void *)pPorter)
|
||||
|
||||
#ifdef SQLITE_ENABLE_FTS4_UNICODE61
|
||||
|| sqlite3Fts3HashInsert(pHash, "unicode61", 10, (void *)pUnicode)
|
||||
#endif
|
||||
#ifdef SQLITE_ENABLE_ICU
|
||||
|| (pIcu && sqlite3Fts3HashInsert(pHash, "icu", 4, (void *)pIcu))
|
||||
#endif
|
||||
|
|
|
@ -541,5 +541,12 @@ int sqlite3Fts3MsrIncrRestart(Fts3MultiSegReader *pCsr);
|
|||
|
||||
int sqlite3Fts3DeferredTokenList(Fts3DeferredToken *, char **, int *);
|
||||
|
||||
/* fts3_unicode2.c (functions generated by parsing unicode text files) */
|
||||
#ifdef SQLITE_ENABLE_FTS4_UNICODE61
|
||||
int sqlite3FtsUnicodeFold(int, int);
|
||||
int sqlite3FtsUnicodeIsalnum(int);
|
||||
int sqlite3FtsUnicodeIsdiacritic(int);
|
||||
#endif
|
||||
|
||||
#endif /* !SQLITE_CORE || SQLITE_ENABLE_FTS3 */
|
||||
#endif /* _FTSINT_H */
|
||||
|
|
|
@ -209,10 +209,9 @@ int sqlite3Fts3InitTokenizer(
|
|||
/*
|
||||
** Implementation of a special SQL scalar function for testing tokenizers
|
||||
** designed to be used in concert with the Tcl testing framework. This
|
||||
** function must be called with two arguments:
|
||||
** function must be called with two or more arguments:
|
||||
**
|
||||
** SELECT <function-name>(<key-name>, <input-string>);
|
||||
** SELECT <function-name>(<key-name>, <pointer>);
|
||||
** SELECT <function-name>(<key-name>, ..., <input-string>);
|
||||
**
|
||||
** where <function-name> is the name passed as the second argument
|
||||
** to the sqlite3Fts3InitHashTable() function (e.g. 'fts3_tokenizer')
|
||||
|
@ -249,27 +248,27 @@ static void testFunc(
|
|||
const char *zInput;
|
||||
int nInput;
|
||||
|
||||
const char *zArg = 0;
|
||||
const char *azArg[64];
|
||||
|
||||
const char *zToken;
|
||||
int nToken;
|
||||
int iStart;
|
||||
int iEnd;
|
||||
int iPos;
|
||||
int i;
|
||||
|
||||
Tcl_Obj *pRet;
|
||||
|
||||
assert( argc==2 || argc==3 );
|
||||
if( argc<2 ){
|
||||
sqlite3_result_error(context, "insufficient arguments", -1);
|
||||
return;
|
||||
}
|
||||
|
||||
nName = sqlite3_value_bytes(argv[0]);
|
||||
zName = (const char *)sqlite3_value_text(argv[0]);
|
||||
nInput = sqlite3_value_bytes(argv[argc-1]);
|
||||
zInput = (const char *)sqlite3_value_text(argv[argc-1]);
|
||||
|
||||
if( argc==3 ){
|
||||
zArg = (const char *)sqlite3_value_text(argv[1]);
|
||||
}
|
||||
|
||||
pHash = (Fts3Hash *)sqlite3_user_data(context);
|
||||
p = (sqlite3_tokenizer_module *)sqlite3Fts3HashFind(pHash, zName, nName+1);
|
||||
|
||||
|
@ -283,7 +282,11 @@ static void testFunc(
|
|||
pRet = Tcl_NewObj();
|
||||
Tcl_IncrRefCount(pRet);
|
||||
|
||||
if( SQLITE_OK!=p->xCreate(zArg ? 1 : 0, &zArg, &pTokenizer) ){
|
||||
for(i=1; i<argc-1; i++){
|
||||
azArg[i-1] = (const char *)sqlite3_value_text(argv[i]);
|
||||
}
|
||||
|
||||
if( SQLITE_OK!=p->xCreate(argc-2, azArg, &pTokenizer) ){
|
||||
zErr = "error in xCreate()";
|
||||
goto finish;
|
||||
}
|
||||
|
@ -467,10 +470,7 @@ int sqlite3Fts3InitHashTable(
|
|||
}
|
||||
#ifdef SQLITE_TEST
|
||||
if( SQLITE_OK==rc ){
|
||||
rc = sqlite3_create_function(db, zTest, 2, any, p, testFunc, 0, 0);
|
||||
}
|
||||
if( SQLITE_OK==rc ){
|
||||
rc = sqlite3_create_function(db, zTest, 3, any, p, testFunc, 0, 0);
|
||||
rc = sqlite3_create_function(db, zTest, -1, any, p, testFunc, 0, 0);
|
||||
}
|
||||
if( SQLITE_OK==rc ){
|
||||
rc = sqlite3_create_function(db, zTest2, 0, any, pdb, intTestFunc, 0, 0);
|
||||
|
|
|
@ -0,0 +1,393 @@
|
|||
/*
|
||||
** 2012 May 24
|
||||
**
|
||||
** 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.
|
||||
**
|
||||
******************************************************************************
|
||||
**
|
||||
** Implementation of the "unicode" full-text-search tokenizer.
|
||||
*/
|
||||
|
||||
#ifdef SQLITE_ENABLE_FTS4_UNICODE61
|
||||
|
||||
#include "fts3Int.h"
|
||||
#if !defined(SQLITE_CORE) || defined(SQLITE_ENABLE_FTS3)
|
||||
|
||||
#include <assert.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "fts3_tokenizer.h"
|
||||
|
||||
/*
|
||||
** The following two macros - READ_UTF8 and WRITE_UTF8 - have been copied
|
||||
** from the sqlite3 source file utf.c. If this file is compiled as part
|
||||
** of the amalgamation, they are not required.
|
||||
*/
|
||||
#ifndef SQLITE_AMALGAMATION
|
||||
|
||||
static const unsigned char sqlite3Utf8Trans1[] = {
|
||||
0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
|
||||
0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
|
||||
0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
|
||||
0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f,
|
||||
0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
|
||||
0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
|
||||
0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
|
||||
0x00, 0x01, 0x02, 0x03, 0x00, 0x01, 0x00, 0x00,
|
||||
};
|
||||
|
||||
#define READ_UTF8(zIn, zTerm, c) \
|
||||
c = *(zIn++); \
|
||||
if( c>=0xc0 ){ \
|
||||
c = sqlite3Utf8Trans1[c-0xc0]; \
|
||||
while( zIn!=zTerm && (*zIn & 0xc0)==0x80 ){ \
|
||||
c = (c<<6) + (0x3f & *(zIn++)); \
|
||||
} \
|
||||
if( c<0x80 \
|
||||
|| (c&0xFFFFF800)==0xD800 \
|
||||
|| (c&0xFFFFFFFE)==0xFFFE ){ c = 0xFFFD; } \
|
||||
}
|
||||
|
||||
#define WRITE_UTF8(zOut, c) { \
|
||||
if( c<0x00080 ){ \
|
||||
*zOut++ = (u8)(c&0xFF); \
|
||||
} \
|
||||
else if( c<0x00800 ){ \
|
||||
*zOut++ = 0xC0 + (u8)((c>>6)&0x1F); \
|
||||
*zOut++ = 0x80 + (u8)(c & 0x3F); \
|
||||
} \
|
||||
else if( c<0x10000 ){ \
|
||||
*zOut++ = 0xE0 + (u8)((c>>12)&0x0F); \
|
||||
*zOut++ = 0x80 + (u8)((c>>6) & 0x3F); \
|
||||
*zOut++ = 0x80 + (u8)(c & 0x3F); \
|
||||
}else{ \
|
||||
*zOut++ = 0xF0 + (u8)((c>>18) & 0x07); \
|
||||
*zOut++ = 0x80 + (u8)((c>>12) & 0x3F); \
|
||||
*zOut++ = 0x80 + (u8)((c>>6) & 0x3F); \
|
||||
*zOut++ = 0x80 + (u8)(c & 0x3F); \
|
||||
} \
|
||||
}
|
||||
|
||||
#endif /* ifndef SQLITE_AMALGAMATION */
|
||||
|
||||
typedef struct unicode_tokenizer unicode_tokenizer;
|
||||
typedef struct unicode_cursor unicode_cursor;
|
||||
|
||||
struct unicode_tokenizer {
|
||||
sqlite3_tokenizer base;
|
||||
int bRemoveDiacritic;
|
||||
int nException;
|
||||
int *aiException;
|
||||
};
|
||||
|
||||
struct unicode_cursor {
|
||||
sqlite3_tokenizer_cursor base;
|
||||
const unsigned char *aInput; /* Input text being tokenized */
|
||||
int nInput; /* Size of aInput[] in bytes */
|
||||
int iOff; /* Current offset within aInput[] */
|
||||
int iToken; /* Index of next token to be returned */
|
||||
char *zToken; /* storage for current token */
|
||||
int nAlloc; /* space allocated at zToken */
|
||||
};
|
||||
|
||||
|
||||
/*
|
||||
** Destroy a tokenizer allocated by unicodeCreate().
|
||||
*/
|
||||
static int unicodeDestroy(sqlite3_tokenizer *pTokenizer){
|
||||
if( pTokenizer ){
|
||||
unicode_tokenizer *p = (unicode_tokenizer *)pTokenizer;
|
||||
sqlite3_free(p->aiException);
|
||||
sqlite3_free(p);
|
||||
}
|
||||
return SQLITE_OK;
|
||||
}
|
||||
|
||||
/*
|
||||
** As part of a tokenchars= or separators= option, the CREATE VIRTUAL TABLE
|
||||
** statement has specified that the tokenizer for this table shall consider
|
||||
** all characters in string zIn/nIn to be separators (if bAlnum==0) or
|
||||
** token characters (if bAlnum==1).
|
||||
**
|
||||
** For each codepoint in the zIn/nIn string, this function checks if the
|
||||
** sqlite3FtsUnicodeIsalnum() function already returns the desired result.
|
||||
** If so, no action is taken. Otherwise, the codepoint is added to the
|
||||
** unicode_tokenizer.aiException[] array. For the purposes of tokenization,
|
||||
** the return value of sqlite3FtsUnicodeIsalnum() is inverted for all
|
||||
** codepoints in the aiException[] array.
|
||||
**
|
||||
** If a standalone diacritic mark (one that sqlite3FtsUnicodeIsdiacritic()
|
||||
** identifies as a diacritic) occurs in the zIn/nIn string it is ignored.
|
||||
** It is not possible to change the behaviour of the tokenizer with respect
|
||||
** to these codepoints.
|
||||
*/
|
||||
static int unicodeAddExceptions(
|
||||
unicode_tokenizer *p, /* Tokenizer to add exceptions to */
|
||||
int bAlnum, /* Replace Isalnum() return value with this */
|
||||
const char *zIn, /* Array of characters to make exceptions */
|
||||
int nIn /* Length of z in bytes */
|
||||
){
|
||||
const unsigned char *z = (const unsigned char *)zIn;
|
||||
const unsigned char *zTerm = &z[nIn];
|
||||
int iCode;
|
||||
int nEntry = 0;
|
||||
|
||||
assert( bAlnum==0 || bAlnum==1 );
|
||||
|
||||
while( z<zTerm ){
|
||||
READ_UTF8(z, zTerm, iCode);
|
||||
assert( (sqlite3FtsUnicodeIsalnum(iCode) & 0xFFFFFFFE)==0 );
|
||||
if( sqlite3FtsUnicodeIsalnum(iCode)!=bAlnum
|
||||
&& sqlite3FtsUnicodeIsdiacritic(iCode)==0
|
||||
){
|
||||
nEntry++;
|
||||
}
|
||||
}
|
||||
|
||||
if( nEntry ){
|
||||
int *aNew; /* New aiException[] array */
|
||||
int nNew; /* Number of valid entries in array aNew[] */
|
||||
|
||||
aNew = sqlite3_realloc(p->aiException, (p->nException+nEntry)*sizeof(int));
|
||||
if( aNew==0 ) return SQLITE_NOMEM;
|
||||
nNew = p->nException;
|
||||
|
||||
z = (const unsigned char *)zIn;
|
||||
while( z<zTerm ){
|
||||
READ_UTF8(z, zTerm, iCode);
|
||||
if( sqlite3FtsUnicodeIsalnum(iCode)!=bAlnum
|
||||
&& sqlite3FtsUnicodeIsdiacritic(iCode)==0
|
||||
){
|
||||
int i, j;
|
||||
for(i=0; i<nNew && aNew[i]<iCode; i++);
|
||||
for(j=nNew; j>i; j--) aNew[j] = aNew[j-1];
|
||||
aNew[i] = iCode;
|
||||
nNew++;
|
||||
}
|
||||
}
|
||||
p->aiException = aNew;
|
||||
p->nException = nNew;
|
||||
}
|
||||
|
||||
return SQLITE_OK;
|
||||
}
|
||||
|
||||
/*
|
||||
** Return true if the p->aiException[] array contains the value iCode.
|
||||
*/
|
||||
static int unicodeIsException(unicode_tokenizer *p, int iCode){
|
||||
if( p->nException>0 ){
|
||||
int *a = p->aiException;
|
||||
int iLo = 0;
|
||||
int iHi = p->nException-1;
|
||||
|
||||
while( iHi>=iLo ){
|
||||
int iTest = (iHi + iLo) / 2;
|
||||
if( iCode==a[iTest] ){
|
||||
return 1;
|
||||
}else if( iCode>a[iTest] ){
|
||||
iLo = iTest+1;
|
||||
}else{
|
||||
iHi = iTest-1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
** Return true if, for the purposes of tokenization, codepoint iCode is
|
||||
** considered a token character (not a separator).
|
||||
*/
|
||||
static int unicodeIsAlnum(unicode_tokenizer *p, int iCode){
|
||||
assert( (sqlite3FtsUnicodeIsalnum(iCode) & 0xFFFFFFFE)==0 );
|
||||
return sqlite3FtsUnicodeIsalnum(iCode) ^ unicodeIsException(p, iCode);
|
||||
}
|
||||
|
||||
/*
|
||||
** Create a new tokenizer instance.
|
||||
*/
|
||||
static int unicodeCreate(
|
||||
int nArg, /* Size of array argv[] */
|
||||
const char * const *azArg, /* Tokenizer creation arguments */
|
||||
sqlite3_tokenizer **pp /* OUT: New tokenizer handle */
|
||||
){
|
||||
unicode_tokenizer *pNew; /* New tokenizer object */
|
||||
int i;
|
||||
int rc = SQLITE_OK;
|
||||
|
||||
pNew = (unicode_tokenizer *) sqlite3_malloc(sizeof(unicode_tokenizer));
|
||||
if( pNew==NULL ) return SQLITE_NOMEM;
|
||||
memset(pNew, 0, sizeof(unicode_tokenizer));
|
||||
pNew->bRemoveDiacritic = 1;
|
||||
|
||||
for(i=0; rc==SQLITE_OK && i<nArg; i++){
|
||||
const char *z = azArg[i];
|
||||
int n = strlen(z);
|
||||
|
||||
if( n==19 && memcmp("remove_diacritics=1", z, 19)==0 ){
|
||||
pNew->bRemoveDiacritic = 1;
|
||||
}
|
||||
else if( n==19 && memcmp("remove_diacritics=0", z, 19)==0 ){
|
||||
pNew->bRemoveDiacritic = 0;
|
||||
}
|
||||
else if( n>=11 && memcmp("tokenchars=", z, 11)==0 ){
|
||||
rc = unicodeAddExceptions(pNew, 1, &z[11], n-11);
|
||||
}
|
||||
else if( n>=11 && memcmp("separators=", z, 11)==0 ){
|
||||
rc = unicodeAddExceptions(pNew, 0, &z[11], n-11);
|
||||
}
|
||||
else{
|
||||
/* Unrecognized argument */
|
||||
rc = SQLITE_ERROR;
|
||||
}
|
||||
}
|
||||
|
||||
if( rc!=SQLITE_OK ){
|
||||
unicodeDestroy((sqlite3_tokenizer *)pNew);
|
||||
pNew = 0;
|
||||
}
|
||||
*pp = (sqlite3_tokenizer *)pNew;
|
||||
return rc;
|
||||
}
|
||||
|
||||
/*
|
||||
** Prepare to begin tokenizing a particular string. The input
|
||||
** string to be tokenized is pInput[0..nBytes-1]. A cursor
|
||||
** used to incrementally tokenize this string is returned in
|
||||
** *ppCursor.
|
||||
*/
|
||||
static int unicodeOpen(
|
||||
sqlite3_tokenizer *p, /* The tokenizer */
|
||||
const char *aInput, /* Input string */
|
||||
int nInput, /* Size of string aInput in bytes */
|
||||
sqlite3_tokenizer_cursor **pp /* OUT: New cursor object */
|
||||
){
|
||||
unicode_cursor *pCsr;
|
||||
|
||||
pCsr = (unicode_cursor *)sqlite3_malloc(sizeof(unicode_cursor));
|
||||
if( pCsr==0 ){
|
||||
return SQLITE_NOMEM;
|
||||
}
|
||||
memset(pCsr, 0, sizeof(unicode_cursor));
|
||||
|
||||
pCsr->aInput = (const unsigned char *)aInput;
|
||||
if( aInput==0 ){
|
||||
pCsr->nInput = 0;
|
||||
}else if( nInput<0 ){
|
||||
pCsr->nInput = (int)strlen(aInput);
|
||||
}else{
|
||||
pCsr->nInput = nInput;
|
||||
}
|
||||
|
||||
*pp = &pCsr->base;
|
||||
UNUSED_PARAMETER(p);
|
||||
return SQLITE_OK;
|
||||
}
|
||||
|
||||
/*
|
||||
** Close a tokenization cursor previously opened by a call to
|
||||
** simpleOpen() above.
|
||||
*/
|
||||
static int unicodeClose(sqlite3_tokenizer_cursor *pCursor){
|
||||
unicode_cursor *pCsr = (unicode_cursor *) pCursor;
|
||||
sqlite3_free(pCsr->zToken);
|
||||
sqlite3_free(pCsr);
|
||||
return SQLITE_OK;
|
||||
}
|
||||
|
||||
/*
|
||||
** Extract the next token from a tokenization cursor. The cursor must
|
||||
** have been opened by a prior call to simpleOpen().
|
||||
*/
|
||||
static int unicodeNext(
|
||||
sqlite3_tokenizer_cursor *pC, /* Cursor returned by simpleOpen */
|
||||
const char **paToken, /* OUT: Token text */
|
||||
int *pnToken, /* OUT: Number of bytes at *paToken */
|
||||
int *piStart, /* OUT: Starting offset of token */
|
||||
int *piEnd, /* OUT: Ending offset of token */
|
||||
int *piPos /* OUT: Position integer of token */
|
||||
){
|
||||
unicode_cursor *pCsr = (unicode_cursor *)pC;
|
||||
unicode_tokenizer *p = ((unicode_tokenizer *)pCsr->base.pTokenizer);
|
||||
int iCode;
|
||||
char *zOut;
|
||||
const unsigned char *z = &pCsr->aInput[pCsr->iOff];
|
||||
const unsigned char *zStart = z;
|
||||
const unsigned char *zEnd;
|
||||
const unsigned char *zTerm = &pCsr->aInput[pCsr->nInput];
|
||||
|
||||
/* Scan past any delimiter characters before the start of the next token.
|
||||
** Return SQLITE_DONE early if this takes us all the way to the end of
|
||||
** the input. */
|
||||
while( z<zTerm ){
|
||||
READ_UTF8(z, zTerm, iCode);
|
||||
if( unicodeIsAlnum(p, iCode) ) break;
|
||||
zStart = z;
|
||||
}
|
||||
if( zStart>=zTerm ) return SQLITE_DONE;
|
||||
|
||||
zOut = pCsr->zToken;
|
||||
do {
|
||||
int iOut;
|
||||
|
||||
/* Grow the output buffer if required. */
|
||||
if( (zOut-pCsr->zToken)>=(pCsr->nAlloc-4) ){
|
||||
char *zNew = sqlite3_realloc(pCsr->zToken, pCsr->nAlloc+64);
|
||||
if( !zNew ) return SQLITE_NOMEM;
|
||||
zOut = &zNew[zOut - pCsr->zToken];
|
||||
pCsr->zToken = zNew;
|
||||
pCsr->nAlloc += 64;
|
||||
}
|
||||
|
||||
/* Write the folded case of the last character read to the output */
|
||||
zEnd = z;
|
||||
iOut = sqlite3FtsUnicodeFold(iCode, p->bRemoveDiacritic);
|
||||
if( iOut ){
|
||||
WRITE_UTF8(zOut, iOut);
|
||||
}
|
||||
|
||||
/* If the cursor is not at EOF, read the next character */
|
||||
if( z>=zTerm ) break;
|
||||
READ_UTF8(z, zTerm, iCode);
|
||||
}while( unicodeIsAlnum(p, iCode)
|
||||
|| sqlite3FtsUnicodeIsdiacritic(iCode)
|
||||
);
|
||||
|
||||
/* Set the output variables and return. */
|
||||
pCsr->iOff = (z - pCsr->aInput);
|
||||
*paToken = pCsr->zToken;
|
||||
*pnToken = zOut - pCsr->zToken;
|
||||
*piStart = (zStart - pCsr->aInput);
|
||||
*piEnd = (zEnd - pCsr->aInput);
|
||||
*piPos = pCsr->iToken++;
|
||||
return SQLITE_OK;
|
||||
}
|
||||
|
||||
/*
|
||||
** Set *ppModule to a pointer to the sqlite3_tokenizer_module
|
||||
** structure for the unicode tokenizer.
|
||||
*/
|
||||
void sqlite3Fts3UnicodeTokenizer(sqlite3_tokenizer_module const **ppModule){
|
||||
static const sqlite3_tokenizer_module module = {
|
||||
0,
|
||||
unicodeCreate,
|
||||
unicodeDestroy,
|
||||
unicodeOpen,
|
||||
unicodeClose,
|
||||
unicodeNext,
|
||||
0,
|
||||
};
|
||||
*ppModule = &module;
|
||||
}
|
||||
|
||||
#endif /* !defined(SQLITE_CORE) || defined(SQLITE_ENABLE_FTS3) */
|
||||
#endif /* ifndef SQLITE_ENABLE_FTS4_UNICODE61 */
|
|
@ -0,0 +1,366 @@
|
|||
/*
|
||||
** 2012 May 25
|
||||
**
|
||||
** 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.
|
||||
**
|
||||
******************************************************************************
|
||||
*/
|
||||
|
||||
/*
|
||||
** DO NOT EDIT THIS MACHINE GENERATED FILE.
|
||||
*/
|
||||
|
||||
#if defined(SQLITE_ENABLE_FTS4_UNICODE61)
|
||||
#if defined(SQLITE_ENABLE_FTS3) || defined(SQLITE_ENABLE_FTS4)
|
||||
|
||||
#include <assert.h>
|
||||
|
||||
/*
|
||||
** Return true if the argument corresponds to a unicode codepoint
|
||||
** classified as either a letter or a number. Otherwise false.
|
||||
**
|
||||
** The results are undefined if the value passed to this function
|
||||
** is less than zero.
|
||||
*/
|
||||
int sqlite3FtsUnicodeIsalnum(int c){
|
||||
/* Each unsigned integer in the following array corresponds to a contiguous
|
||||
** range of unicode codepoints that are not either letters or numbers (i.e.
|
||||
** codepoints for which this function should return 0).
|
||||
**
|
||||
** The most significant 22 bits in each 32-bit value contain the first
|
||||
** codepoint in the range. The least significant 10 bits are used to store
|
||||
** the size of the range (always at least 1). In other words, the value
|
||||
** ((C<<22) + N) represents a range of N codepoints starting with codepoint
|
||||
** C. It is not possible to represent a range larger than 1023 codepoints
|
||||
** using this format.
|
||||
*/
|
||||
const static unsigned int aEntry[] = {
|
||||
0x00000030, 0x0000E807, 0x00016C06, 0x0001EC2F, 0x0002AC07,
|
||||
0x0002D001, 0x0002D803, 0x0002EC01, 0x0002FC01, 0x00035C01,
|
||||
0x0003DC01, 0x000B0804, 0x000B480E, 0x000B9407, 0x000BB401,
|
||||
0x000BBC81, 0x000DD401, 0x000DF801, 0x000E1002, 0x000E1C01,
|
||||
0x000FD801, 0x00120808, 0x00156806, 0x00162402, 0x00163C01,
|
||||
0x00164437, 0x0017CC02, 0x00180005, 0x00181816, 0x00187802,
|
||||
0x00192C15, 0x0019A804, 0x0019C001, 0x001B5001, 0x001B580F,
|
||||
0x001B9C07, 0x001BF402, 0x001C000E, 0x001C3C01, 0x001C4401,
|
||||
0x001CC01B, 0x001E980B, 0x001FAC09, 0x001FD804, 0x00205804,
|
||||
0x00206C09, 0x00209403, 0x0020A405, 0x0020C00F, 0x00216403,
|
||||
0x00217801, 0x0023901B, 0x00240004, 0x0024E803, 0x0024F812,
|
||||
0x00254407, 0x00258804, 0x0025C001, 0x00260403, 0x0026F001,
|
||||
0x0026F807, 0x00271C02, 0x00272C03, 0x00275C01, 0x00278802,
|
||||
0x0027C802, 0x0027E802, 0x00280403, 0x0028F001, 0x0028F805,
|
||||
0x00291C02, 0x00292C03, 0x00294401, 0x0029C002, 0x0029D401,
|
||||
0x002A0403, 0x002AF001, 0x002AF808, 0x002B1C03, 0x002B2C03,
|
||||
0x002B8802, 0x002BC002, 0x002C0403, 0x002CF001, 0x002CF807,
|
||||
0x002D1C02, 0x002D2C03, 0x002D5802, 0x002D8802, 0x002DC001,
|
||||
0x002E0801, 0x002EF805, 0x002F1803, 0x002F2804, 0x002F5C01,
|
||||
0x002FCC08, 0x00300403, 0x0030F807, 0x00311803, 0x00312804,
|
||||
0x00315402, 0x00318802, 0x0031FC01, 0x00320802, 0x0032F001,
|
||||
0x0032F807, 0x00331803, 0x00332804, 0x00335402, 0x00338802,
|
||||
0x00340802, 0x0034F807, 0x00351803, 0x00352804, 0x00355C01,
|
||||
0x00358802, 0x0035E401, 0x00360802, 0x00372801, 0x00373C06,
|
||||
0x00375801, 0x00376008, 0x0037C803, 0x0038C401, 0x0038D007,
|
||||
0x0038FC01, 0x00391C09, 0x00396802, 0x003AC401, 0x003AD006,
|
||||
0x003AEC02, 0x003B2006, 0x003C041F, 0x003CD00C, 0x003DC417,
|
||||
0x003E340B, 0x003E6424, 0x003EF80F, 0x003F380D, 0x0040AC14,
|
||||
0x00412806, 0x00415804, 0x00417803, 0x00418803, 0x00419C07,
|
||||
0x0041C404, 0x0042080C, 0x00423C01, 0x00426806, 0x0043EC01,
|
||||
0x004D740C, 0x004E400A, 0x00500001, 0x0059B402, 0x005A0001,
|
||||
0x005A6C02, 0x005BAC03, 0x005C4803, 0x005CC805, 0x005D4802,
|
||||
0x005DC802, 0x005ED023, 0x005F6004, 0x005F7401, 0x0060000F,
|
||||
0x0062A401, 0x0064800C, 0x0064C00C, 0x00650001, 0x00651002,
|
||||
0x0066C011, 0x00672002, 0x00677822, 0x00685C05, 0x00687802,
|
||||
0x0069540A, 0x0069801D, 0x0069FC01, 0x006A8007, 0x006AA006,
|
||||
0x006C0005, 0x006CD011, 0x006D6823, 0x006E0003, 0x006E840D,
|
||||
0x006F980E, 0x006FF004, 0x00709014, 0x0070EC05, 0x0071F802,
|
||||
0x00730008, 0x00734019, 0x0073B401, 0x0073C803, 0x00770027,
|
||||
0x0077F004, 0x007EF401, 0x007EFC03, 0x007F3403, 0x007F7403,
|
||||
0x007FB403, 0x007FF402, 0x00800065, 0x0081A806, 0x0081E805,
|
||||
0x00822805, 0x0082801A, 0x00834021, 0x00840002, 0x00840C04,
|
||||
0x00842002, 0x00845001, 0x00845803, 0x00847806, 0x00849401,
|
||||
0x00849C01, 0x0084A401, 0x0084B801, 0x0084E802, 0x00850005,
|
||||
0x00852804, 0x00853C01, 0x00864264, 0x00900027, 0x0091000B,
|
||||
0x0092704E, 0x00940200, 0x009C0475, 0x009E53B9, 0x00AD400A,
|
||||
0x00B39406, 0x00B3BC03, 0x00B3E404, 0x00B3F802, 0x00B5C001,
|
||||
0x00B5FC01, 0x00B7804F, 0x00B8C00C, 0x00BA001A, 0x00BA6C59,
|
||||
0x00BC00D6, 0x00BFC00C, 0x00C00005, 0x00C02019, 0x00C0A807,
|
||||
0x00C0D802, 0x00C0F403, 0x00C26404, 0x00C28001, 0x00C3EC01,
|
||||
0x00C64002, 0x00C6580A, 0x00C70024, 0x00C8001F, 0x00C8A81E,
|
||||
0x00C94001, 0x00C98020, 0x00CA2827, 0x00CB003F, 0x00CC0100,
|
||||
0x01370040, 0x02924037, 0x0293F802, 0x02983403, 0x0299BC10,
|
||||
0x029A7C01, 0x029BC008, 0x029C0017, 0x029C8002, 0x029E2402,
|
||||
0x02A00801, 0x02A01801, 0x02A02C01, 0x02A08C09, 0x02A0D804,
|
||||
0x02A1D004, 0x02A20002, 0x02A2D011, 0x02A33802, 0x02A38012,
|
||||
0x02A3E003, 0x02A4980A, 0x02A51C0D, 0x02A57C01, 0x02A60004,
|
||||
0x02A6CC1B, 0x02A77802, 0x02A8A40E, 0x02A90C01, 0x02A93002,
|
||||
0x02A97004, 0x02A9DC03, 0x02A9EC01, 0x02AAC001, 0x02AAC803,
|
||||
0x02AADC02, 0x02AAF802, 0x02AB0401, 0x02AB7802, 0x02ABAC07,
|
||||
0x02ABD402, 0x02AF8C0B, 0x03600001, 0x036DFC02, 0x036FFC02,
|
||||
0x037FFC02, 0x03E3FC01, 0x03EC7801, 0x03ECA401, 0x03EEC810,
|
||||
0x03F4F802, 0x03F7F002, 0x03F8001A, 0x03F88007, 0x03F8C023,
|
||||
0x03F95013, 0x03F9A004, 0x03FBFC01, 0x03FC040F, 0x03FC6807,
|
||||
0x03FCEC06, 0x03FD6C0B, 0x03FF8007, 0x03FFA007, 0x03FFE405,
|
||||
0x04040003, 0x0404DC09, 0x0405E411, 0x0406400C, 0x0407402E,
|
||||
0x040E7C01, 0x040F4001, 0x04215C01, 0x04247C01, 0x0424FC01,
|
||||
0x04280403, 0x04281402, 0x04283004, 0x0428E003, 0x0428FC01,
|
||||
0x04294009, 0x0429FC01, 0x042CE407, 0x04400003, 0x0440E016,
|
||||
0x04420003, 0x0442C012, 0x04440003, 0x04449C0E, 0x04450004,
|
||||
0x04460003, 0x0446CC0E, 0x04471404, 0x045AAC0D, 0x0491C004,
|
||||
0x05BD442E, 0x05BE3C04, 0x074000F6, 0x07440027, 0x0744A4B5,
|
||||
0x07480046, 0x074C0057, 0x075B0401, 0x075B6C01, 0x075BEC01,
|
||||
0x075C5401, 0x075CD401, 0x075D3C01, 0x075DBC01, 0x075E2401,
|
||||
0x075EA401, 0x075F0C01, 0x07BBC002, 0x07C0002C, 0x07C0C064,
|
||||
0x07C2800F, 0x07C2C40E, 0x07C3040F, 0x07C3440F, 0x07C4401F,
|
||||
0x07C4C03C, 0x07C5C02B, 0x07C7981D, 0x07C8402B, 0x07C90009,
|
||||
0x07C94002, 0x07CC0021, 0x07CCC006, 0x07CCDC46, 0x07CE0014,
|
||||
0x07CE8025, 0x07CF1805, 0x07CF8011, 0x07D0003F, 0x07D10001,
|
||||
0x07D108B6, 0x07D3E404, 0x07D4003E, 0x07D50004, 0x07D54018,
|
||||
0x07D7EC46, 0x07D9140B, 0x07DA0046, 0x07DC0074, 0x38000401,
|
||||
0x38008060, 0x380400F0, 0x3C000001, 0x3FFFF401, 0x40000001,
|
||||
0x43FFF401,
|
||||
};
|
||||
static const unsigned int aAscii[4] = {
|
||||
0xFFFFFFFF, 0xFC00FFFF, 0xF8000001, 0xF8000001,
|
||||
};
|
||||
|
||||
if( c<128 ){
|
||||
return ( (aAscii[c >> 5] & (1 << (c & 0x001F)))==0 );
|
||||
}else if( c<(1<<22) ){
|
||||
unsigned int key = (((unsigned int)c)<<10) | 0x000003FF;
|
||||
int iRes;
|
||||
int iHi = sizeof(aEntry)/sizeof(aEntry[0]) - 1;
|
||||
int iLo = 0;
|
||||
while( iHi>=iLo ){
|
||||
int iTest = (iHi + iLo) / 2;
|
||||
if( key >= aEntry[iTest] ){
|
||||
iRes = iTest;
|
||||
iLo = iTest+1;
|
||||
}else{
|
||||
iHi = iTest-1;
|
||||
}
|
||||
}
|
||||
assert( aEntry[0]<key );
|
||||
assert( key>=aEntry[iRes] );
|
||||
return (c >= ((aEntry[iRes]>>10) + (aEntry[iRes]&0x3FF)));
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
** If the argument is a codepoint corresponding to a lowercase letter
|
||||
** in the ASCII range with a diacritic added, return the codepoint
|
||||
** of the ASCII letter only. For example, if passed 235 - "LATIN
|
||||
** SMALL LETTER E WITH DIAERESIS" - return 65 ("LATIN SMALL LETTER
|
||||
** E"). The resuls of passing a codepoint that corresponds to an
|
||||
** uppercase letter are undefined.
|
||||
*/
|
||||
static int remove_diacritic(int c){
|
||||
unsigned short aDia[] = {
|
||||
0, 1797, 1848, 1859, 1891, 1928, 1940, 1995,
|
||||
2024, 2040, 2060, 2110, 2168, 2206, 2264, 2286,
|
||||
2344, 2383, 2472, 2488, 2516, 2596, 2668, 2732,
|
||||
2782, 2842, 2894, 2954, 2984, 3000, 3028, 3336,
|
||||
3456, 3696, 3712, 3728, 3744, 3896, 3912, 3928,
|
||||
3968, 4008, 4040, 4106, 4138, 4170, 4202, 4234,
|
||||
4266, 4296, 4312, 4344, 4408, 4424, 4472, 4504,
|
||||
6148, 6198, 6264, 6280, 6360, 6429, 6505, 6529,
|
||||
61448, 61468, 61534, 61592, 61642, 61688, 61704, 61726,
|
||||
61784, 61800, 61836, 61880, 61914, 61948, 61998, 62122,
|
||||
62154, 62200, 62218, 62302, 62364, 62442, 62478, 62536,
|
||||
62554, 62584, 62604, 62640, 62648, 62656, 62664, 62730,
|
||||
62924, 63050, 63082, 63274, 63390,
|
||||
};
|
||||
char aChar[] = {
|
||||
'\0', 'a', 'c', 'e', 'i', 'n', 'o', 'u', 'y', 'y', 'a', 'c',
|
||||
'd', 'e', 'e', 'g', 'h', 'i', 'j', 'k', 'l', 'n', 'o', 'r',
|
||||
's', 't', 'u', 'u', 'w', 'y', 'z', 'o', 'u', 'a', 'i', 'o',
|
||||
'u', 'g', 'k', 'o', 'j', 'g', 'n', 'a', 'e', 'i', 'o', 'r',
|
||||
'u', 's', 't', 'h', 'a', 'e', 'o', 'y', '\0', '\0', '\0', '\0',
|
||||
'\0', '\0', '\0', '\0', 'a', 'b', 'd', 'd', 'e', 'f', 'g', 'h',
|
||||
'h', 'i', 'k', 'l', 'l', 'm', 'n', 'p', 'r', 'r', 's', 't',
|
||||
'u', 'v', 'w', 'w', 'x', 'y', 'z', 'h', 't', 'w', 'y', 'a',
|
||||
'e', 'i', 'o', 'u', 'y',
|
||||
};
|
||||
|
||||
unsigned int key = (((unsigned int)c)<<3) | 0x00000007;
|
||||
int iRes = 0;
|
||||
int iHi = sizeof(aDia)/sizeof(aDia[0]) - 1;
|
||||
int iLo = 0;
|
||||
while( iHi>=iLo ){
|
||||
int iTest = (iHi + iLo) / 2;
|
||||
if( key >= aDia[iTest] ){
|
||||
iRes = iTest;
|
||||
iLo = iTest+1;
|
||||
}else{
|
||||
iHi = iTest-1;
|
||||
}
|
||||
}
|
||||
assert( key>=aDia[iRes] );
|
||||
return ((c > (aDia[iRes]>>3) + (aDia[iRes]&0x07)) ? c : (int)aChar[iRes]);
|
||||
};
|
||||
|
||||
|
||||
/*
|
||||
** Return true if the argument interpreted as a unicode codepoint
|
||||
** is a diacritical modifier character.
|
||||
*/
|
||||
int sqlite3FtsUnicodeIsdiacritic(int c){
|
||||
unsigned int mask0 = 0x08029FDF;
|
||||
unsigned int mask1 = 0x000361F8;
|
||||
if( c<768 || c>817 ) return 0;
|
||||
return (c < 768+32) ?
|
||||
(mask0 & (1 << (c-768))) :
|
||||
(mask1 & (1 << (c-768-32)));
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
** Interpret the argument as a unicode codepoint. If the codepoint
|
||||
** is an upper case character that has a lower case equivalent,
|
||||
** return the codepoint corresponding to the lower case version.
|
||||
** Otherwise, return a copy of the argument.
|
||||
**
|
||||
** The results are undefined if the value passed to this function
|
||||
** is less than zero.
|
||||
*/
|
||||
int sqlite3FtsUnicodeFold(int c, int bRemoveDiacritic){
|
||||
/* Each entry in the following array defines a rule for folding a range
|
||||
** of codepoints to lower case. The rule applies to a range of nRange
|
||||
** codepoints starting at codepoint iCode.
|
||||
**
|
||||
** If the least significant bit in flags is clear, then the rule applies
|
||||
** to all nRange codepoints (i.e. all nRange codepoints are upper case and
|
||||
** need to be folded). Or, if it is set, then the rule only applies to
|
||||
** every second codepoint in the range, starting with codepoint C.
|
||||
**
|
||||
** The 7 most significant bits in flags are an index into the aiOff[]
|
||||
** array. If a specific codepoint C does require folding, then its lower
|
||||
** case equivalent is ((C + aiOff[flags>>1]) & 0xFFFF).
|
||||
**
|
||||
** The contents of this array are generated by parsing the CaseFolding.txt
|
||||
** file distributed as part of the "Unicode Character Database". See
|
||||
** http://www.unicode.org for details.
|
||||
*/
|
||||
static const struct TableEntry {
|
||||
unsigned short iCode;
|
||||
unsigned char flags;
|
||||
unsigned char nRange;
|
||||
} aEntry[] = {
|
||||
{65, 14, 26}, {181, 64, 1}, {192, 14, 23},
|
||||
{216, 14, 7}, {256, 1, 48}, {306, 1, 6},
|
||||
{313, 1, 16}, {330, 1, 46}, {376, 116, 1},
|
||||
{377, 1, 6}, {383, 104, 1}, {385, 50, 1},
|
||||
{386, 1, 4}, {390, 44, 1}, {391, 0, 1},
|
||||
{393, 42, 2}, {395, 0, 1}, {398, 32, 1},
|
||||
{399, 38, 1}, {400, 40, 1}, {401, 0, 1},
|
||||
{403, 42, 1}, {404, 46, 1}, {406, 52, 1},
|
||||
{407, 48, 1}, {408, 0, 1}, {412, 52, 1},
|
||||
{413, 54, 1}, {415, 56, 1}, {416, 1, 6},
|
||||
{422, 60, 1}, {423, 0, 1}, {425, 60, 1},
|
||||
{428, 0, 1}, {430, 60, 1}, {431, 0, 1},
|
||||
{433, 58, 2}, {435, 1, 4}, {439, 62, 1},
|
||||
{440, 0, 1}, {444, 0, 1}, {452, 2, 1},
|
||||
{453, 0, 1}, {455, 2, 1}, {456, 0, 1},
|
||||
{458, 2, 1}, {459, 1, 18}, {478, 1, 18},
|
||||
{497, 2, 1}, {498, 1, 4}, {502, 122, 1},
|
||||
{503, 134, 1}, {504, 1, 40}, {544, 110, 1},
|
||||
{546, 1, 18}, {570, 70, 1}, {571, 0, 1},
|
||||
{573, 108, 1}, {574, 68, 1}, {577, 0, 1},
|
||||
{579, 106, 1}, {580, 28, 1}, {581, 30, 1},
|
||||
{582, 1, 10}, {837, 36, 1}, {880, 1, 4},
|
||||
{886, 0, 1}, {902, 18, 1}, {904, 16, 3},
|
||||
{908, 26, 1}, {910, 24, 2}, {913, 14, 17},
|
||||
{931, 14, 9}, {962, 0, 1}, {975, 4, 1},
|
||||
{976, 140, 1}, {977, 142, 1}, {981, 146, 1},
|
||||
{982, 144, 1}, {984, 1, 24}, {1008, 136, 1},
|
||||
{1009, 138, 1}, {1012, 130, 1}, {1013, 128, 1},
|
||||
{1015, 0, 1}, {1017, 152, 1}, {1018, 0, 1},
|
||||
{1021, 110, 3}, {1024, 34, 16}, {1040, 14, 32},
|
||||
{1120, 1, 34}, {1162, 1, 54}, {1216, 6, 1},
|
||||
{1217, 1, 14}, {1232, 1, 88}, {1329, 22, 38},
|
||||
{4256, 66, 38}, {4295, 66, 1}, {4301, 66, 1},
|
||||
{7680, 1, 150}, {7835, 132, 1}, {7838, 96, 1},
|
||||
{7840, 1, 96}, {7944, 150, 8}, {7960, 150, 6},
|
||||
{7976, 150, 8}, {7992, 150, 8}, {8008, 150, 6},
|
||||
{8025, 151, 8}, {8040, 150, 8}, {8072, 150, 8},
|
||||
{8088, 150, 8}, {8104, 150, 8}, {8120, 150, 2},
|
||||
{8122, 126, 2}, {8124, 148, 1}, {8126, 100, 1},
|
||||
{8136, 124, 4}, {8140, 148, 1}, {8152, 150, 2},
|
||||
{8154, 120, 2}, {8168, 150, 2}, {8170, 118, 2},
|
||||
{8172, 152, 1}, {8184, 112, 2}, {8186, 114, 2},
|
||||
{8188, 148, 1}, {8486, 98, 1}, {8490, 92, 1},
|
||||
{8491, 94, 1}, {8498, 12, 1}, {8544, 8, 16},
|
||||
{8579, 0, 1}, {9398, 10, 26}, {11264, 22, 47},
|
||||
{11360, 0, 1}, {11362, 88, 1}, {11363, 102, 1},
|
||||
{11364, 90, 1}, {11367, 1, 6}, {11373, 84, 1},
|
||||
{11374, 86, 1}, {11375, 80, 1}, {11376, 82, 1},
|
||||
{11378, 0, 1}, {11381, 0, 1}, {11390, 78, 2},
|
||||
{11392, 1, 100}, {11499, 1, 4}, {11506, 0, 1},
|
||||
{42560, 1, 46}, {42624, 1, 24}, {42786, 1, 14},
|
||||
{42802, 1, 62}, {42873, 1, 4}, {42877, 76, 1},
|
||||
{42878, 1, 10}, {42891, 0, 1}, {42893, 74, 1},
|
||||
{42896, 1, 4}, {42912, 1, 10}, {42922, 72, 1},
|
||||
{65313, 14, 26},
|
||||
};
|
||||
static const unsigned short aiOff[] = {
|
||||
1, 2, 8, 15, 16, 26, 28, 32,
|
||||
37, 38, 40, 48, 63, 64, 69, 71,
|
||||
79, 80, 116, 202, 203, 205, 206, 207,
|
||||
209, 210, 211, 213, 214, 217, 218, 219,
|
||||
775, 7264, 10792, 10795, 23228, 23256, 30204, 54721,
|
||||
54753, 54754, 54756, 54787, 54793, 54809, 57153, 57274,
|
||||
57921, 58019, 58363, 61722, 65268, 65341, 65373, 65406,
|
||||
65408, 65410, 65415, 65424, 65436, 65439, 65450, 65462,
|
||||
65472, 65476, 65478, 65480, 65482, 65488, 65506, 65511,
|
||||
65514, 65521, 65527, 65528, 65529,
|
||||
};
|
||||
|
||||
int ret = c;
|
||||
|
||||
assert( c>=0 );
|
||||
assert( sizeof(unsigned short)==2 && sizeof(unsigned char)==1 );
|
||||
|
||||
if( c<128 ){
|
||||
if( c>='A' && c<='Z' ) ret = c + ('a' - 'A');
|
||||
}else if( c<65536 ){
|
||||
int iHi = sizeof(aEntry)/sizeof(aEntry[0]) - 1;
|
||||
int iLo = 0;
|
||||
int iRes = -1;
|
||||
|
||||
while( iHi>=iLo ){
|
||||
int iTest = (iHi + iLo) / 2;
|
||||
int cmp = (c - aEntry[iTest].iCode);
|
||||
if( cmp>=0 ){
|
||||
iRes = iTest;
|
||||
iLo = iTest+1;
|
||||
}else{
|
||||
iHi = iTest-1;
|
||||
}
|
||||
}
|
||||
assert( iRes<0 || c>=aEntry[iRes].iCode );
|
||||
|
||||
if( iRes>=0 ){
|
||||
const struct TableEntry *p = &aEntry[iRes];
|
||||
if( c<(p->iCode + p->nRange) && 0==(0x01 & p->flags & (p->iCode ^ c)) ){
|
||||
ret = (c + (aiOff[p->flags>>1])) & 0x0000FFFF;
|
||||
assert( ret>0 );
|
||||
}
|
||||
}
|
||||
|
||||
if( bRemoveDiacritic ) ret = remove_diacritic(ret);
|
||||
}
|
||||
|
||||
else if( c>=66560 && c<66600 ){
|
||||
ret = c + 40;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
#endif /* defined(SQLITE_ENABLE_FTS3) || defined(SQLITE_ENABLE_FTS4) */
|
||||
#endif /* !defined(SQLITE_ENABLE_FTS4_UNICODE61) */
|
|
@ -136,7 +136,8 @@ struct Fts3DeferredToken {
|
|||
*/
|
||||
struct Fts3SegReader {
|
||||
int iIdx; /* Index within level, or 0x7FFFFFFF for PT */
|
||||
int bLookup; /* True for a lookup only */
|
||||
u8 bLookup; /* True for a lookup only */
|
||||
u8 rootOnly; /* True for a root-only reader */
|
||||
|
||||
sqlite3_int64 iStartBlock; /* Rowid of first leaf block to traverse */
|
||||
sqlite3_int64 iLeafEndBlock; /* Rowid of final leaf block to traverse */
|
||||
|
@ -170,7 +171,7 @@ struct Fts3SegReader {
|
|||
};
|
||||
|
||||
#define fts3SegReaderIsPending(p) ((p)->ppNextElem!=0)
|
||||
#define fts3SegReaderIsRootOnly(p) ((p)->aNode==(char *)&(p)[1])
|
||||
#define fts3SegReaderIsRootOnly(p) ((p)->rootOnly!=0)
|
||||
|
||||
/*
|
||||
** An instance of this structure is used to create a segment b-tree in the
|
||||
|
@ -1581,7 +1582,7 @@ int sqlite3Fts3SegReaderNew(
|
|||
}
|
||||
memset(pReader, 0, sizeof(Fts3SegReader));
|
||||
pReader->iIdx = iAge;
|
||||
pReader->bLookup = bLookup;
|
||||
pReader->bLookup = bLookup!=0;
|
||||
pReader->iStartBlock = iStartLeaf;
|
||||
pReader->iLeafEndBlock = iEndLeaf;
|
||||
pReader->iEndBlock = iEndBlock;
|
||||
|
@ -1589,6 +1590,7 @@ int sqlite3Fts3SegReaderNew(
|
|||
if( nExtra ){
|
||||
/* The entire segment is stored in the root node. */
|
||||
pReader->aNode = (char *)&pReader[1];
|
||||
pReader->rootOnly = 1;
|
||||
pReader->nNode = nRoot;
|
||||
memcpy(pReader->aNode, zRoot, nRoot);
|
||||
memset(&pReader->aNode[nRoot], 0, FTS3_NODE_PADDING);
|
||||
|
@ -3174,7 +3176,12 @@ static void fts3UpdateDocTotals(
|
|||
}else{
|
||||
memset(a, 0, sizeof(u32)*(nStat) );
|
||||
}
|
||||
sqlite3_reset(pStmt);
|
||||
rc = sqlite3_reset(pStmt);
|
||||
if( rc!=SQLITE_OK ){
|
||||
sqlite3_free(a);
|
||||
*pRC = rc;
|
||||
return;
|
||||
}
|
||||
if( nChng<0 && a[0]<(u32)(-nChng) ){
|
||||
a[0] = 0;
|
||||
}else{
|
||||
|
|
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,808 @@
|
|||
|
||||
#
|
||||
# Parameter $zName must be a path to the file UnicodeData.txt. This command
|
||||
# reads the file and returns a list of mappings required to remove all
|
||||
# diacritical marks from a unicode string. Each mapping is itself a list
|
||||
# consisting of two elements - the unicode codepoint and the single ASCII
|
||||
# character that it should be replaced with, or an empty string if the
|
||||
# codepoint should simply be removed from the input. Examples:
|
||||
#
|
||||
# { 224 a } (replace codepoint 224 to "a")
|
||||
# { 769 "" } (remove codepoint 769 from input)
|
||||
#
|
||||
# Mappings are only returned for non-upper case codepoints. It is assumed
|
||||
# that the input has already been folded to lower case.
|
||||
#
|
||||
proc rd_load_unicodedata_text {zName} {
|
||||
global tl_lookup_table
|
||||
|
||||
set fd [open $zName]
|
||||
set lField {
|
||||
code
|
||||
character_name
|
||||
general_category
|
||||
canonical_combining_classes
|
||||
bidirectional_category
|
||||
character_decomposition_mapping
|
||||
decimal_digit_value
|
||||
digit_value
|
||||
numeric_value
|
||||
mirrored
|
||||
unicode_1_name
|
||||
iso10646_comment_field
|
||||
uppercase_mapping
|
||||
lowercase_mapping
|
||||
titlecase_mapping
|
||||
}
|
||||
set lRet [list]
|
||||
|
||||
while { ![eof $fd] } {
|
||||
set line [gets $fd]
|
||||
if {$line == ""} continue
|
||||
|
||||
set fields [split $line ";"]
|
||||
if {[llength $fields] != [llength $lField]} { error "parse error: $line" }
|
||||
foreach $lField $fields {}
|
||||
if { [llength $character_decomposition_mapping]!=2
|
||||
|| [string is xdigit [lindex $character_decomposition_mapping 0]]==0
|
||||
} {
|
||||
continue
|
||||
}
|
||||
|
||||
set iCode [expr "0x$code"]
|
||||
set iAscii [expr "0x[lindex $character_decomposition_mapping 0]"]
|
||||
set iDia [expr "0x[lindex $character_decomposition_mapping 1]"]
|
||||
|
||||
if {[info exists tl_lookup_table($iCode)]} continue
|
||||
|
||||
if { ($iAscii >= 97 && $iAscii <= 122)
|
||||
|| ($iAscii >= 65 && $iAscii <= 90)
|
||||
} {
|
||||
lappend lRet [list $iCode [string tolower [format %c $iAscii]]]
|
||||
set dia($iDia) 1
|
||||
}
|
||||
}
|
||||
|
||||
foreach d [array names dia] {
|
||||
lappend lRet [list $d ""]
|
||||
}
|
||||
set lRet [lsort -integer -index 0 $lRet]
|
||||
|
||||
close $fd
|
||||
set lRet
|
||||
}
|
||||
|
||||
|
||||
proc print_rd {map} {
|
||||
global tl_lookup_table
|
||||
set aChar [list]
|
||||
set lRange [list]
|
||||
|
||||
set nRange 1
|
||||
set iFirst [lindex $map 0 0]
|
||||
set cPrev [lindex $map 0 1]
|
||||
|
||||
foreach m [lrange $map 1 end] {
|
||||
foreach {i c} $m {}
|
||||
|
||||
if {$cPrev == $c} {
|
||||
for {set j [expr $iFirst+$nRange]} {$j<$i} {incr j} {
|
||||
if {[info exists tl_lookup_table($j)]==0} break
|
||||
}
|
||||
|
||||
if {$j==$i} {
|
||||
set nNew [expr {(1 + $i - $iFirst)}]
|
||||
if {$nNew<=8} {
|
||||
set nRange $nNew
|
||||
continue
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
lappend lRange [list $iFirst $nRange]
|
||||
lappend aChar $cPrev
|
||||
|
||||
set iFirst $i
|
||||
set cPrev $c
|
||||
set nRange 1
|
||||
}
|
||||
lappend lRange [list $iFirst $nRange]
|
||||
lappend aChar $cPrev
|
||||
|
||||
puts "/*"
|
||||
puts "** If the argument is a codepoint corresponding to a lowercase letter"
|
||||
puts "** in the ASCII range with a diacritic added, return the codepoint"
|
||||
puts "** of the ASCII letter only. For example, if passed 235 - \"LATIN"
|
||||
puts "** SMALL LETTER E WITH DIAERESIS\" - return 65 (\"LATIN SMALL LETTER"
|
||||
puts "** E\"). The resuls of passing a codepoint that corresponds to an"
|
||||
puts "** uppercase letter are undefined."
|
||||
puts "*/"
|
||||
puts "static int remove_diacritic(int c)\{"
|
||||
puts " unsigned short aDia\[\] = \{"
|
||||
puts -nonewline " 0, "
|
||||
set i 1
|
||||
foreach r $lRange {
|
||||
foreach {iCode nRange} $r {}
|
||||
if {($i % 8)==0} {puts "" ; puts -nonewline " " }
|
||||
incr i
|
||||
|
||||
puts -nonewline [format "%5d" [expr ($iCode<<3) + $nRange-1]]
|
||||
puts -nonewline ", "
|
||||
}
|
||||
puts ""
|
||||
puts " \};"
|
||||
puts " char aChar\[\] = \{"
|
||||
puts -nonewline " '\\0', "
|
||||
set i 1
|
||||
foreach c $aChar {
|
||||
set str "'$c', "
|
||||
if {$c == ""} { set str "'\\0', " }
|
||||
|
||||
if {($i % 12)==0} {puts "" ; puts -nonewline " " }
|
||||
incr i
|
||||
puts -nonewline "$str"
|
||||
}
|
||||
puts ""
|
||||
puts " \};"
|
||||
puts {
|
||||
unsigned int key = (((unsigned int)c)<<3) | 0x00000007;
|
||||
int iRes = 0;
|
||||
int iHi = sizeof(aDia)/sizeof(aDia[0]) - 1;
|
||||
int iLo = 0;
|
||||
while( iHi>=iLo ){
|
||||
int iTest = (iHi + iLo) / 2;
|
||||
if( key >= aDia[iTest] ){
|
||||
iRes = iTest;
|
||||
iLo = iTest+1;
|
||||
}else{
|
||||
iHi = iTest-1;
|
||||
}
|
||||
}
|
||||
assert( key>=aDia[iRes] );
|
||||
return ((c > (aDia[iRes]>>3) + (aDia[iRes]&0x07)) ? c : (int)aChar[iRes]);}
|
||||
puts "\};"
|
||||
}
|
||||
|
||||
proc print_isdiacritic {zFunc map} {
|
||||
|
||||
set lCode [list]
|
||||
foreach m $map {
|
||||
foreach {code char} $m {}
|
||||
if {$code && $char == ""} { lappend lCode $code }
|
||||
}
|
||||
set lCode [lsort -integer $lCode]
|
||||
set iFirst [lindex $lCode 0]
|
||||
set iLast [lindex $lCode end]
|
||||
|
||||
set i1 0
|
||||
set i2 0
|
||||
|
||||
foreach c $lCode {
|
||||
set i [expr $c - $iFirst]
|
||||
if {$i < 32} {
|
||||
set i1 [expr {$i1 | (1<<$i)}]
|
||||
} else {
|
||||
set i2 [expr {$i2 | (1<<($i-32))}]
|
||||
}
|
||||
}
|
||||
|
||||
puts "/*"
|
||||
puts "** Return true if the argument interpreted as a unicode codepoint"
|
||||
puts "** is a diacritical modifier character."
|
||||
puts "*/"
|
||||
puts "int ${zFunc}\(int c)\{"
|
||||
puts " unsigned int mask0 = [format "0x%08X" $i1];"
|
||||
puts " unsigned int mask1 = [format "0x%08X" $i2];"
|
||||
|
||||
puts " if( c<$iFirst || c>$iLast ) return 0;"
|
||||
puts " return (c < $iFirst+32) ?"
|
||||
puts " (mask0 & (1 << (c-$iFirst))) :"
|
||||
puts " (mask1 & (1 << (c-$iFirst-32)));"
|
||||
puts "\}"
|
||||
}
|
||||
|
||||
|
||||
#-------------------------------------------------------------------------
|
||||
|
||||
# Parameter $zName must be a path to the file UnicodeData.txt. This command
|
||||
# reads the file and returns a list of codepoints (integers). The list
|
||||
# contains all codepoints in the UnicodeData.txt assigned to any "General
|
||||
# Category" that is not a "Letter" or "Number".
|
||||
#
|
||||
proc an_load_unicodedata_text {zName} {
|
||||
set fd [open $zName]
|
||||
set lField {
|
||||
code
|
||||
character_name
|
||||
general_category
|
||||
canonical_combining_classes
|
||||
bidirectional_category
|
||||
character_decomposition_mapping
|
||||
decimal_digit_value
|
||||
digit_value
|
||||
numeric_value
|
||||
mirrored
|
||||
unicode_1_name
|
||||
iso10646_comment_field
|
||||
uppercase_mapping
|
||||
lowercase_mapping
|
||||
titlecase_mapping
|
||||
}
|
||||
set lRet [list]
|
||||
|
||||
while { ![eof $fd] } {
|
||||
set line [gets $fd]
|
||||
if {$line == ""} continue
|
||||
|
||||
set fields [split $line ";"]
|
||||
if {[llength $fields] != [llength $lField]} { error "parse error: $line" }
|
||||
foreach $lField $fields {}
|
||||
|
||||
set iCode [expr "0x$code"]
|
||||
set bAlnum [expr {[lsearch {L N} [string range $general_category 0 0]]>=0}]
|
||||
|
||||
if { !$bAlnum } { lappend lRet $iCode }
|
||||
}
|
||||
|
||||
close $fd
|
||||
set lRet
|
||||
}
|
||||
|
||||
proc an_load_separator_ranges {} {
|
||||
global unicodedata.txt
|
||||
set lSep [an_load_unicodedata_text ${unicodedata.txt}]
|
||||
unset -nocomplain iFirst
|
||||
unset -nocomplain nRange
|
||||
set lRange [list]
|
||||
foreach sep $lSep {
|
||||
if {0==[info exists iFirst]} {
|
||||
set iFirst $sep
|
||||
set nRange 1
|
||||
} elseif { $sep == ($iFirst+$nRange) } {
|
||||
incr nRange
|
||||
} else {
|
||||
lappend lRange [list $iFirst $nRange]
|
||||
set iFirst $sep
|
||||
set nRange 1
|
||||
}
|
||||
}
|
||||
lappend lRange [list $iFirst $nRange]
|
||||
set lRange
|
||||
}
|
||||
|
||||
proc an_print_range_array {lRange} {
|
||||
set iFirstMax 0
|
||||
set nRangeMax 0
|
||||
foreach range $lRange {
|
||||
foreach {iFirst nRange} $range {}
|
||||
if {$iFirst > $iFirstMax} {set iFirstMax $iFirst}
|
||||
if {$nRange > $nRangeMax} {set nRangeMax $nRange}
|
||||
}
|
||||
if {$iFirstMax >= (1<<22)} {error "first-max is too large for format"}
|
||||
if {$nRangeMax >= (1<<10)} {error "range-max is too large for format"}
|
||||
|
||||
puts -nonewline " "
|
||||
puts [string trim {
|
||||
/* Each unsigned integer in the following array corresponds to a contiguous
|
||||
** range of unicode codepoints that are not either letters or numbers (i.e.
|
||||
** codepoints for which this function should return 0).
|
||||
**
|
||||
** The most significant 22 bits in each 32-bit value contain the first
|
||||
** codepoint in the range. The least significant 10 bits are used to store
|
||||
** the size of the range (always at least 1). In other words, the value
|
||||
** ((C<<22) + N) represents a range of N codepoints starting with codepoint
|
||||
** C. It is not possible to represent a range larger than 1023 codepoints
|
||||
** using this format.
|
||||
*/
|
||||
}]
|
||||
puts -nonewline " const static unsigned int aEntry\[\] = \{"
|
||||
set i 0
|
||||
foreach range $lRange {
|
||||
foreach {iFirst nRange} $range {}
|
||||
set u32 [format "0x%08X" [expr ($iFirst<<10) + $nRange]]
|
||||
|
||||
if {($i % 5)==0} {puts "" ; puts -nonewline " "}
|
||||
puts -nonewline " $u32,"
|
||||
incr i
|
||||
}
|
||||
puts ""
|
||||
puts " \};"
|
||||
}
|
||||
|
||||
proc an_print_ascii_bitmap {lRange} {
|
||||
foreach range $lRange {
|
||||
foreach {iFirst nRange} $range {}
|
||||
for {set i $iFirst} {$i < ($iFirst+$nRange)} {incr i} {
|
||||
if {$i<=127} { set a($i) 1 }
|
||||
}
|
||||
}
|
||||
|
||||
set aAscii [list 0 0 0 0]
|
||||
foreach key [array names a] {
|
||||
set idx [expr $key >> 5]
|
||||
lset aAscii $idx [expr [lindex $aAscii $idx] | (1 << ($key&0x001F))]
|
||||
}
|
||||
|
||||
puts " static const unsigned int aAscii\[4\] = \{"
|
||||
puts -nonewline " "
|
||||
foreach v $aAscii { puts -nonewline [format " 0x%08X," $v] }
|
||||
puts ""
|
||||
puts " \};"
|
||||
}
|
||||
|
||||
proc print_isalnum {zFunc lRange} {
|
||||
puts "/*"
|
||||
puts "** Return true if the argument corresponds to a unicode codepoint"
|
||||
puts "** classified as either a letter or a number. Otherwise false."
|
||||
puts "**"
|
||||
puts "** The results are undefined if the value passed to this function"
|
||||
puts "** is less than zero."
|
||||
puts "*/"
|
||||
puts "int ${zFunc}\(int c)\{"
|
||||
an_print_range_array $lRange
|
||||
an_print_ascii_bitmap $lRange
|
||||
puts {
|
||||
if( c<128 ){
|
||||
return ( (aAscii[c >> 5] & (1 << (c & 0x001F)))==0 );
|
||||
}else if( c<(1<<22) ){
|
||||
unsigned int key = (((unsigned int)c)<<10) | 0x000003FF;
|
||||
int iRes;
|
||||
int iHi = sizeof(aEntry)/sizeof(aEntry[0]) - 1;
|
||||
int iLo = 0;
|
||||
while( iHi>=iLo ){
|
||||
int iTest = (iHi + iLo) / 2;
|
||||
if( key >= aEntry[iTest] ){
|
||||
iRes = iTest;
|
||||
iLo = iTest+1;
|
||||
}else{
|
||||
iHi = iTest-1;
|
||||
}
|
||||
}
|
||||
assert( aEntry[0]<key );
|
||||
assert( key>=aEntry[iRes] );
|
||||
return (c >= ((aEntry[iRes]>>10) + (aEntry[iRes]&0x3FF)));
|
||||
}
|
||||
return 1;}
|
||||
puts "\}"
|
||||
}
|
||||
|
||||
proc print_test_isalnum {zFunc lRange} {
|
||||
foreach range $lRange {
|
||||
foreach {iFirst nRange} $range {}
|
||||
for {set i $iFirst} {$i < ($iFirst+$nRange)} {incr i} { set a($i) 1 }
|
||||
}
|
||||
|
||||
puts "static int isalnum_test(int *piCode)\{"
|
||||
puts -nonewline " unsigned char aAlnum\[\] = \{"
|
||||
for {set i 0} {$i < 70000} {incr i} {
|
||||
if {($i % 32)==0} { puts "" ; puts -nonewline " " }
|
||||
set bFlag [expr ![info exists a($i)]]
|
||||
puts -nonewline "${bFlag},"
|
||||
}
|
||||
puts ""
|
||||
puts " \};"
|
||||
|
||||
puts -nonewline " int aLargeSep\[\] = \{"
|
||||
set i 0
|
||||
foreach iSep [lsort -integer [array names a]] {
|
||||
if {$iSep<70000} continue
|
||||
if {($i % 8)==0} { puts "" ; puts -nonewline " " }
|
||||
puts -nonewline " $iSep,"
|
||||
incr i
|
||||
}
|
||||
puts ""
|
||||
puts " \};"
|
||||
puts -nonewline " int aLargeOther\[\] = \{"
|
||||
set i 0
|
||||
foreach iSep [lsort -integer [array names a]] {
|
||||
if {$iSep<70000} continue
|
||||
if {[info exists a([expr $iSep-1])]==0} {
|
||||
if {($i % 8)==0} { puts "" ; puts -nonewline " " }
|
||||
puts -nonewline " [expr $iSep-1],"
|
||||
incr i
|
||||
}
|
||||
if {[info exists a([expr $iSep+1])]==0} {
|
||||
if {($i % 8)==0} { puts "" ; puts -nonewline " " }
|
||||
puts -nonewline " [expr $iSep+1],"
|
||||
incr i
|
||||
}
|
||||
}
|
||||
puts ""
|
||||
puts " \};"
|
||||
|
||||
puts [subst -nocommands {
|
||||
int i;
|
||||
for(i=0; i<sizeof(aAlnum)/sizeof(aAlnum[0]); i++){
|
||||
if( ${zFunc}(i)!=aAlnum[i] ){
|
||||
*piCode = i;
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
for(i=0; i<sizeof(aLargeSep)/sizeof(aLargeSep[0]); i++){
|
||||
if( ${zFunc}(aLargeSep[i])!=0 ){
|
||||
*piCode = aLargeSep[i];
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
for(i=0; i<sizeof(aLargeOther)/sizeof(aLargeOther[0]); i++){
|
||||
if( ${zFunc}(aLargeOther[i])!=1 ){
|
||||
*piCode = aLargeOther[i];
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
}]
|
||||
puts " return 0;"
|
||||
puts "\}"
|
||||
}
|
||||
|
||||
#-------------------------------------------------------------------------
|
||||
|
||||
proc tl_load_casefolding_txt {zName} {
|
||||
global tl_lookup_table
|
||||
|
||||
set fd [open $zName]
|
||||
while { ![eof $fd] } {
|
||||
set line [gets $fd]
|
||||
if {[string range $line 0 0] == "#"} continue
|
||||
if {$line == ""} continue
|
||||
|
||||
foreach x {a b c d} {unset -nocomplain $x}
|
||||
foreach {a b c d} [split $line ";"] {}
|
||||
|
||||
set a2 [list]
|
||||
set c2 [list]
|
||||
foreach elem $a { lappend a2 [expr "0x[string trim $elem]"] }
|
||||
foreach elem $c { lappend c2 [expr "0x[string trim $elem]"] }
|
||||
set b [string trim $b]
|
||||
set d [string trim $d]
|
||||
|
||||
if {$b=="C" || $b=="S"} { set tl_lookup_table($a2) $c2 }
|
||||
}
|
||||
}
|
||||
|
||||
proc tl_create_records {} {
|
||||
global tl_lookup_table
|
||||
|
||||
set iFirst ""
|
||||
set nOff 0
|
||||
set nRange 0
|
||||
set nIncr 0
|
||||
|
||||
set lRecord [list]
|
||||
foreach code [lsort -integer [array names tl_lookup_table]] {
|
||||
set mapping $tl_lookup_table($code)
|
||||
if {$iFirst == ""} {
|
||||
set iFirst $code
|
||||
set nOff [expr $mapping - $code]
|
||||
set nRange 1
|
||||
set nIncr 1
|
||||
} else {
|
||||
set diff [expr $code - ($iFirst + ($nIncr * ($nRange - 1)))]
|
||||
if { $nRange==1 && ($diff==1 || $diff==2) } {
|
||||
set nIncr $diff
|
||||
}
|
||||
|
||||
if {$diff != $nIncr || ($mapping - $code)!=$nOff} {
|
||||
if { $nRange==1 } {set nIncr 1}
|
||||
lappend lRecord [list $iFirst $nIncr $nRange $nOff]
|
||||
set iFirst $code
|
||||
set nOff [expr $mapping - $code]
|
||||
set nRange 1
|
||||
set nIncr 1
|
||||
} else {
|
||||
incr nRange
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
lappend lRecord [list $iFirst $nIncr $nRange $nOff]
|
||||
|
||||
set lRecord
|
||||
}
|
||||
|
||||
proc tl_print_table_header {} {
|
||||
puts -nonewline " "
|
||||
puts [string trim {
|
||||
/* Each entry in the following array defines a rule for folding a range
|
||||
** of codepoints to lower case. The rule applies to a range of nRange
|
||||
** codepoints starting at codepoint iCode.
|
||||
**
|
||||
** If the least significant bit in flags is clear, then the rule applies
|
||||
** to all nRange codepoints (i.e. all nRange codepoints are upper case and
|
||||
** need to be folded). Or, if it is set, then the rule only applies to
|
||||
** every second codepoint in the range, starting with codepoint C.
|
||||
**
|
||||
** The 7 most significant bits in flags are an index into the aiOff[]
|
||||
** array. If a specific codepoint C does require folding, then its lower
|
||||
** case equivalent is ((C + aiOff[flags>>1]) & 0xFFFF).
|
||||
**
|
||||
** The contents of this array are generated by parsing the CaseFolding.txt
|
||||
** file distributed as part of the "Unicode Character Database". See
|
||||
** http://www.unicode.org for details.
|
||||
*/
|
||||
}]
|
||||
puts " static const struct TableEntry \{"
|
||||
puts " unsigned short iCode;"
|
||||
puts " unsigned char flags;"
|
||||
puts " unsigned char nRange;"
|
||||
puts " \} aEntry\[\] = \{"
|
||||
}
|
||||
|
||||
proc tl_print_table_entry {togglevar entry liOff} {
|
||||
upvar $togglevar t
|
||||
foreach {iFirst nIncr nRange nOff} $entry {}
|
||||
|
||||
if {$iFirst > (1<<16)} { return 1 }
|
||||
|
||||
if {[info exists t]==0} {set t 0}
|
||||
if {$t==0} { puts -nonewline " " }
|
||||
|
||||
set flags 0
|
||||
if {$nIncr==2} { set flags 1 ; set nRange [expr $nRange * 2]}
|
||||
if {$nOff<0} { incr nOff [expr (1<<16)] }
|
||||
|
||||
set idx [lsearch $liOff $nOff]
|
||||
if {$idx<0} {error "malfunction generating aiOff"}
|
||||
set flags [expr $flags + $idx*2]
|
||||
|
||||
set txt "{$iFirst, $flags, $nRange},"
|
||||
if {$t==2} {
|
||||
puts $txt
|
||||
} else {
|
||||
puts -nonewline [format "% -23s" $txt]
|
||||
}
|
||||
set t [expr ($t+1)%3]
|
||||
|
||||
return 0
|
||||
}
|
||||
|
||||
proc tl_print_table_footer {togglevar} {
|
||||
upvar $togglevar t
|
||||
if {$t!=0} {puts ""}
|
||||
puts " \};"
|
||||
}
|
||||
|
||||
proc tl_print_if_entry {entry} {
|
||||
foreach {iFirst nIncr nRange nOff} $entry {}
|
||||
if {$nIncr==2} {error "tl_print_if_entry needs improvement!"}
|
||||
|
||||
puts " else if( c>=$iFirst && c<[expr $iFirst+$nRange] )\{"
|
||||
puts " ret = c + $nOff;"
|
||||
puts " \}"
|
||||
}
|
||||
|
||||
proc tl_generate_ioff_table {lRecord} {
|
||||
foreach entry $lRecord {
|
||||
foreach {iFirst nIncr nRange iOff} $entry {}
|
||||
if {$iOff<0} { incr iOff [expr (1<<16)] }
|
||||
if {[info exists a($iOff)]} continue
|
||||
set a($iOff) 1
|
||||
}
|
||||
|
||||
set liOff [lsort -integer [array names a]]
|
||||
if {[llength $liOff]>128} { error "Too many distinct ioffs" }
|
||||
return $liOff
|
||||
}
|
||||
|
||||
proc tl_print_ioff_table {liOff} {
|
||||
puts -nonewline " static const unsigned short aiOff\[\] = \{"
|
||||
set i 0
|
||||
foreach off $liOff {
|
||||
if {($i % 8)==0} {puts "" ; puts -nonewline " "}
|
||||
puts -nonewline [format "% -7s" "$off,"]
|
||||
incr i
|
||||
}
|
||||
puts ""
|
||||
puts " \};"
|
||||
|
||||
}
|
||||
|
||||
proc print_fold {zFunc} {
|
||||
|
||||
set lRecord [tl_create_records]
|
||||
|
||||
set lHigh [list]
|
||||
puts "/*"
|
||||
puts "** Interpret the argument as a unicode codepoint. If the codepoint"
|
||||
puts "** is an upper case character that has a lower case equivalent,"
|
||||
puts "** return the codepoint corresponding to the lower case version."
|
||||
puts "** Otherwise, return a copy of the argument."
|
||||
puts "**"
|
||||
puts "** The results are undefined if the value passed to this function"
|
||||
puts "** is less than zero."
|
||||
puts "*/"
|
||||
puts "int ${zFunc}\(int c, int bRemoveDiacritic)\{"
|
||||
|
||||
set liOff [tl_generate_ioff_table $lRecord]
|
||||
tl_print_table_header
|
||||
foreach entry $lRecord {
|
||||
if {[tl_print_table_entry toggle $entry $liOff]} {
|
||||
lappend lHigh $entry
|
||||
}
|
||||
}
|
||||
tl_print_table_footer toggle
|
||||
tl_print_ioff_table $liOff
|
||||
|
||||
puts {
|
||||
int ret = c;
|
||||
|
||||
assert( c>=0 );
|
||||
assert( sizeof(unsigned short)==2 && sizeof(unsigned char)==1 );
|
||||
|
||||
if( c<128 ){
|
||||
if( c>='A' && c<='Z' ) ret = c + ('a' - 'A');
|
||||
}else if( c<65536 ){
|
||||
int iHi = sizeof(aEntry)/sizeof(aEntry[0]) - 1;
|
||||
int iLo = 0;
|
||||
int iRes = -1;
|
||||
|
||||
while( iHi>=iLo ){
|
||||
int iTest = (iHi + iLo) / 2;
|
||||
int cmp = (c - aEntry[iTest].iCode);
|
||||
if( cmp>=0 ){
|
||||
iRes = iTest;
|
||||
iLo = iTest+1;
|
||||
}else{
|
||||
iHi = iTest-1;
|
||||
}
|
||||
}
|
||||
assert( iRes<0 || c>=aEntry[iRes].iCode );
|
||||
|
||||
if( iRes>=0 ){
|
||||
const struct TableEntry *p = &aEntry[iRes];
|
||||
if( c<(p->iCode + p->nRange) && 0==(0x01 & p->flags & (p->iCode ^ c)) ){
|
||||
ret = (c + (aiOff[p->flags>>1])) & 0x0000FFFF;
|
||||
assert( ret>0 );
|
||||
}
|
||||
}
|
||||
|
||||
if( bRemoveDiacritic ) ret = remove_diacritic(ret);
|
||||
}
|
||||
}
|
||||
|
||||
foreach entry $lHigh {
|
||||
tl_print_if_entry $entry
|
||||
}
|
||||
|
||||
puts ""
|
||||
puts " return ret;"
|
||||
puts "\}"
|
||||
}
|
||||
|
||||
proc print_fold_test {zFunc mappings} {
|
||||
global tl_lookup_table
|
||||
|
||||
foreach m $mappings {
|
||||
set c [lindex $m 1]
|
||||
if {$c == ""} {
|
||||
set extra([lindex $m 0]) 0
|
||||
} else {
|
||||
scan $c %c i
|
||||
set extra([lindex $m 0]) $i
|
||||
}
|
||||
}
|
||||
|
||||
puts "static int fold_test(int *piCode)\{"
|
||||
puts -nonewline " static int aLookup\[\] = \{"
|
||||
for {set i 0} {$i < 70000} {incr i} {
|
||||
|
||||
set expected $i
|
||||
catch { set expected $tl_lookup_table($i) }
|
||||
set expected2 $expected
|
||||
catch { set expected2 $extra($expected2) }
|
||||
|
||||
if {($i % 4)==0} { puts "" ; puts -nonewline " " }
|
||||
puts -nonewline "$expected, $expected2, "
|
||||
}
|
||||
puts " \};"
|
||||
puts " int i;"
|
||||
puts " for(i=0; i<sizeof(aLookup)/sizeof(aLookup\[0\]); i++)\{"
|
||||
puts " int iCode = (i/2);"
|
||||
puts " int bFlag = i & 0x0001;"
|
||||
puts " if( ${zFunc}\(iCode, bFlag)!=aLookup\[i\] )\{"
|
||||
puts " *piCode = iCode;"
|
||||
puts " return 1;"
|
||||
puts " \}"
|
||||
puts " \}"
|
||||
puts " return 0;"
|
||||
puts "\}"
|
||||
}
|
||||
|
||||
|
||||
proc print_fileheader {} {
|
||||
puts [string trim {
|
||||
/*
|
||||
** 2012 May 25
|
||||
**
|
||||
** 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.
|
||||
**
|
||||
******************************************************************************
|
||||
*/
|
||||
|
||||
/*
|
||||
** DO NOT EDIT THIS MACHINE GENERATED FILE.
|
||||
*/
|
||||
}]
|
||||
puts ""
|
||||
puts "#if !defined(SQLITE_DISABLE_FTS3_UNICODE)"
|
||||
puts "#if defined(SQLITE_ENABLE_FTS3) || defined(SQLITE_ENABLE_FTS4)"
|
||||
puts ""
|
||||
puts "#include <assert.h>"
|
||||
puts ""
|
||||
}
|
||||
|
||||
proc print_test_main {} {
|
||||
puts ""
|
||||
puts "#include <stdio.h>"
|
||||
puts ""
|
||||
puts "int main(int argc, char **argv)\{"
|
||||
puts " int r1, r2;"
|
||||
puts " int code;"
|
||||
puts " r1 = isalnum_test(&code);"
|
||||
puts " if( r1 ) printf(\"isalnum(): Problem with code %d\\n\",code);"
|
||||
puts " else printf(\"isalnum(): test passed\\n\");"
|
||||
puts " r2 = fold_test(&code);"
|
||||
puts " if( r2 ) printf(\"fold(): Problem with code %d\\n\",code);"
|
||||
puts " else printf(\"fold(): test passed\\n\");"
|
||||
puts " return (r1 || r2);"
|
||||
puts "\}"
|
||||
}
|
||||
|
||||
# Proces the command line arguments. Exit early if they are not to
|
||||
# our liking.
|
||||
#
|
||||
proc usage {} {
|
||||
puts -nonewline stderr "Usage: $::argv0 ?-test? "
|
||||
puts stderr "<CaseFolding.txt file> <UnicodeData.txt file>"
|
||||
exit 1
|
||||
}
|
||||
if {[llength $argv]!=2 && [llength $argv]!=3} usage
|
||||
if {[llength $argv]==3 && [lindex $argv 0]!="-test"} usage
|
||||
set unicodedata.txt [lindex $argv end]
|
||||
set casefolding.txt [lindex $argv end-1]
|
||||
set generate_test_code [expr {[llength $argv]==3}]
|
||||
|
||||
print_fileheader
|
||||
|
||||
# Print the isalnum() function to stdout.
|
||||
#
|
||||
set lRange [an_load_separator_ranges]
|
||||
print_isalnum sqlite3FtsUnicodeIsalnum $lRange
|
||||
|
||||
# Leave a gap between the two generated C functions.
|
||||
#
|
||||
puts ""
|
||||
puts ""
|
||||
|
||||
# Load the fold data. This is used by the [rd_XXX] commands
|
||||
# as well as [print_fold].
|
||||
tl_load_casefolding_txt ${casefolding.txt}
|
||||
|
||||
set mappings [rd_load_unicodedata_text ${unicodedata.txt}]
|
||||
print_rd $mappings
|
||||
puts ""
|
||||
puts ""
|
||||
print_isdiacritic sqlite3FtsUnicodeIsdiacritic $mappings
|
||||
puts ""
|
||||
puts ""
|
||||
|
||||
# Print the fold() function to stdout.
|
||||
#
|
||||
print_fold sqlite3FtsUnicodeFold
|
||||
|
||||
# Print the test routines and main() function to stdout, if -test
|
||||
# was specified.
|
||||
#
|
||||
if {$::generate_test_code} {
|
||||
print_test_isalnum sqlite3FtsUnicodeIsalnum $lRange
|
||||
print_fold_test sqlite3FtsUnicodeFold $mappings
|
||||
print_test_main
|
||||
}
|
||||
|
||||
puts "#endif /* defined(SQLITE_ENABLE_FTS3) || defined(SQLITE_ENABLE_FTS4) */"
|
||||
puts "#endif /* !defined(SQLITE_DISABLE_FTS3_UNICODE) */"
|
|
@ -2739,6 +2739,36 @@ static int rtreeDeleteRowid(Rtree *pRtree, sqlite3_int64 iDelete){
|
|||
return rc;
|
||||
}
|
||||
|
||||
/*
|
||||
** Rounding constants for float->double conversion.
|
||||
*/
|
||||
#define RNDTOWARDS (1.0 - 1.0/8388608.0) /* Round towards zero */
|
||||
#define RNDAWAY (1.0 + 1.0/8388608.0) /* Round away from zero */
|
||||
|
||||
#if !defined(SQLITE_RTREE_INT_ONLY)
|
||||
/*
|
||||
** Convert an sqlite3_value into an RtreeValue (presumably a float)
|
||||
** while taking care to round toward negative or positive, respectively.
|
||||
*/
|
||||
static RtreeValue rtreeValueDown(sqlite3_value *v){
|
||||
double d = sqlite3_value_double(v);
|
||||
float f = (float)d;
|
||||
if( f>d ){
|
||||
f = (float)(d*(d<0 ? RNDAWAY : RNDTOWARDS));
|
||||
}
|
||||
return f;
|
||||
}
|
||||
static RtreeValue rtreeValueUp(sqlite3_value *v){
|
||||
double d = sqlite3_value_double(v);
|
||||
float f = (float)d;
|
||||
if( f<d ){
|
||||
f = (float)(d*(d<0 ? RNDTOWARDS : RNDAWAY));
|
||||
}
|
||||
return f;
|
||||
}
|
||||
#endif /* !defined(SQLITE_RTREE_INT_ONLY) */
|
||||
|
||||
|
||||
/*
|
||||
** The xUpdate method for rtree module virtual tables.
|
||||
*/
|
||||
|
@ -2775,8 +2805,8 @@ static int rtreeUpdate(
|
|||
#ifndef SQLITE_RTREE_INT_ONLY
|
||||
if( pRtree->eCoordType==RTREE_COORD_REAL32 ){
|
||||
for(ii=0; ii<(pRtree->nDim*2); ii+=2){
|
||||
cell.aCoord[ii].f = (RtreeValue)sqlite3_value_double(azData[ii+3]);
|
||||
cell.aCoord[ii+1].f = (RtreeValue)sqlite3_value_double(azData[ii+4]);
|
||||
cell.aCoord[ii].f = rtreeValueDown(azData[ii+3]);
|
||||
cell.aCoord[ii+1].f = rtreeValueUp(azData[ii+4]);
|
||||
if( cell.aCoord[ii].f>cell.aCoord[ii+1].f ){
|
||||
rc = SQLITE_CONSTRAINT;
|
||||
goto constraint;
|
||||
|
|
9
main.mk
9
main.mk
|
@ -55,6 +55,7 @@ LIBOBJ+= alter.o analyze.o attach.o auth.o \
|
|||
callback.o complete.o ctime.o date.o delete.o expr.o fault.o fkey.o \
|
||||
fts3.o fts3_aux.o fts3_expr.o fts3_hash.o fts3_icu.o fts3_porter.o \
|
||||
fts3_snippet.o fts3_tokenizer.o fts3_tokenizer1.o \
|
||||
fts3_unicode.o fts3_unicode2.o \
|
||||
fts3_write.o func.o global.o hash.o \
|
||||
icu.o insert.o journal.o legacy.o loadext.o \
|
||||
main.o malloc.o mem0.o mem1.o mem2.o mem3.o mem5.o \
|
||||
|
@ -198,6 +199,8 @@ SRC += \
|
|||
$(TOP)/ext/fts3/fts3_tokenizer.h \
|
||||
$(TOP)/ext/fts3/fts3_tokenizer.c \
|
||||
$(TOP)/ext/fts3/fts3_tokenizer1.c \
|
||||
$(TOP)/ext/fts3/fts3_unicode.c \
|
||||
$(TOP)/ext/fts3/fts3_unicode2.c \
|
||||
$(TOP)/ext/fts3/fts3_write.c
|
||||
SRC += \
|
||||
$(TOP)/ext/icu/sqliteicu.h \
|
||||
|
@ -508,6 +511,12 @@ fts3_tokenizer.o: $(TOP)/ext/fts3/fts3_tokenizer.c $(HDR) $(EXTHDR)
|
|||
fts3_tokenizer1.o: $(TOP)/ext/fts3/fts3_tokenizer1.c $(HDR) $(EXTHDR)
|
||||
$(TCCX) -DSQLITE_CORE -c $(TOP)/ext/fts3/fts3_tokenizer1.c
|
||||
|
||||
fts3_unicode.o: $(TOP)/ext/fts3/fts3_unicode.c $(HDR) $(EXTHDR)
|
||||
$(TCCX) -DSQLITE_CORE -c $(TOP)/ext/fts3/fts3_unicode.c
|
||||
|
||||
fts3_unicode2.o: $(TOP)/ext/fts3/fts3_unicode2.c $(HDR) $(EXTHDR)
|
||||
$(TCCX) -DSQLITE_CORE -c $(TOP)/ext/fts3/fts3_unicode2.c
|
||||
|
||||
fts3_write.o: $(TOP)/ext/fts3/fts3_write.c $(HDR) $(EXTHDR)
|
||||
$(TCCX) -DSQLITE_CORE -c $(TOP)/ext/fts3/fts3_write.c
|
||||
|
||||
|
|
133
manifest
133
manifest
|
@ -1,12 +1,12 @@
|
|||
C Version\s3.7.12.1
|
||||
D 2012-05-22T02:45:53.459
|
||||
C Version\s3.7.13
|
||||
D 2012-06-11T02:05:22.539
|
||||
F Makefile.arm-wince-mingw32ce-gcc d6df77f1f48d690bd73162294bbba7f59507c72f
|
||||
F Makefile.in 2f37e468503dbe79d35c9f6dffcf3fae1ae9ec20
|
||||
F Makefile.in d17fddaa4e81f93a7c9c7c0808aacb3fc95f79f4
|
||||
F Makefile.linux-gcc 91d710bdc4998cb015f39edf3cb314ec4f4d7e23
|
||||
F Makefile.msc 7849a871b6cdb20fd51baee6bbe5965a03326be4
|
||||
F Makefile.msc fd86027849a59a2f621b791b79eabf3f8ffbd684
|
||||
F Makefile.vxworks 3b7fe7a0571fdadc61363ebc1b23732d2d6363ca
|
||||
F README cd04a36fbc7ea56932a4052d7d0b7f09f27c33d6
|
||||
F VERSION 1e25ebddd2ed5811c10bdabe914cd46d2dc38af8
|
||||
F VERSION 3e857b9b826e818eec9411eafe2c3fa22c1dbb8a
|
||||
F aclocal.m4 a5c22d164aff7ed549d53a90fa56d56955281f50
|
||||
F addopcodes.awk 17dc593f791f874d2c23a0f9360850ded0286531
|
||||
F art/sqlite370.eps aa97a671332b432a54e1d74ff5e8775be34200c2
|
||||
|
@ -15,7 +15,7 @@ F art/sqlite370.jpg d512473dae7e378a67e28ff96a34da7cb331def2
|
|||
F config.guess 226d9a188c6196f3033ffc651cbc9dcee1a42977
|
||||
F config.h.in 0921066a13130082764ab4ab6456f7b5bebe56de
|
||||
F config.sub 9ebe4c3b3dab6431ece34f16828b594fb420da55
|
||||
F configure faa04198b719ec9cb2166aa0b163558e9b8ddd77 x
|
||||
F configure 79405675c313ce4a5e94afac6ec880bb3e27b4f1 x
|
||||
F configure.ac 9ee886c21c095b3272137b1553ae416c8b8c8557
|
||||
F contrib/sqlitecon.tcl 210a913ad63f9f991070821e599d600bd913e0ad
|
||||
F doc/lemon.html 3091574143dd3415669b6745843ff8d011d33549
|
||||
|
@ -53,11 +53,11 @@ F ext/fts2/fts2_tokenizer1.c 0123d21078e053bd98fd6186c5c6dc6d67969f2e
|
|||
F ext/fts2/mkfts2amal.tcl 974d5d438cb3f7c4a652639262f82418c1e4cff0
|
||||
F ext/fts3/README.content fdc666a70d5257a64fee209f97cf89e0e6e32b51
|
||||
F ext/fts3/README.syntax a19711dc5458c20734b8e485e75fb1981ec2427a
|
||||
F ext/fts3/README.tokenizers 998756696647400de63d5ba60e9655036cb966e9
|
||||
F ext/fts3/README.tokenizers e0a8b81383ea60d0334d274fadf305ea14a8c314
|
||||
F ext/fts3/README.txt 8c18f41574404623b76917b9da66fcb0ab38328d
|
||||
F ext/fts3/fts3.c a7adf6747d1fdd627ecd421c1709996741ca6693
|
||||
F ext/fts3/fts3.c bb3107c0e420ea2e26e57050e84cdf0aeaafcd4f
|
||||
F ext/fts3/fts3.h 3a10a0af180d502cecc50df77b1b22df142817fe
|
||||
F ext/fts3/fts3Int.h aca752b99c15ee738f5bcf0910eafb9e4aeb1b97
|
||||
F ext/fts3/fts3Int.h 81115435f79248ac09017bc665aae27b410d651f
|
||||
F ext/fts3/fts3_aux.c 5205182bd8f372782597888156404766edf5781e
|
||||
F ext/fts3/fts3_expr.c dbc7ba4c3a6061adde0f38ed8e9b349568299551
|
||||
F ext/fts3/fts3_hash.c 8dd2d06b66c72c628c2732555a32bc0943114914
|
||||
|
@ -67,18 +67,23 @@ F ext/fts3/fts3_porter.c a465b49fcb8249a755792f87516eff182efa42b3
|
|||
F ext/fts3/fts3_snippet.c bf67520ae9d2352a65368ed101729ff701c08808
|
||||
F ext/fts3/fts3_term.c a521f75132f9a495bdca1bdd45949b3191c52763
|
||||
F ext/fts3/fts3_test.c 348f7d08cae05285794e23dc4fe8b8fdf66e264a
|
||||
F ext/fts3/fts3_tokenizer.c 3da7254a9881f7e270ab28e2004e0d22b3212bce
|
||||
F ext/fts3/fts3_tokenizer.c e94a8b901066031437ccfe4769fc76370257cede
|
||||
F ext/fts3/fts3_tokenizer.h 66dec98e365854b6cd2d54f1a96bb6d428fc5a68
|
||||
F ext/fts3/fts3_tokenizer1.c 5c98225a53705e5ee34824087478cf477bdb7004
|
||||
F ext/fts3/fts3_write.c cd4af00b3b0512b4d76177a267fcaafab44cbce4
|
||||
F ext/fts3/fts3_unicode.c 49e36e6ba59f79e6bd6a8bfe434570fe48d20559
|
||||
F ext/fts3/fts3_unicode2.c 2965d217c37079f1dbbdbd2c58f843be285d73f2
|
||||
F ext/fts3/fts3_write.c 794438f904cdf4516b258e530c0065efadb7b9b5
|
||||
F ext/fts3/fts3speed.tcl b54caf6a18d38174f1a6e84219950d85e98bb1e9
|
||||
F ext/fts3/mkfts3amal.tcl 252ecb7fe6467854f2aa237bf2c390b74e71f100
|
||||
F ext/fts3/tool/fts3view.c 6cfc5b67a5f0e09c0d698f9fd012c784bfaa9197
|
||||
F ext/fts3/unicode/CaseFolding.txt 8c678ca52ecc95e16bc7afc2dbf6fc9ffa05db8c
|
||||
F ext/fts3/unicode/UnicodeData.txt cd07314edb62d49fde34debdaf92fa2aa69011e7
|
||||
F ext/fts3/unicode/mkunicode.tcl 7a9bc018e2962abb79563c5a39fe581fcbf2f675
|
||||
F ext/icu/README.txt bf8461d8cdc6b8f514c080e4e10dc3b2bbdfefa9
|
||||
F ext/icu/icu.c eb9ae1d79046bd7871aa97ee6da51eb770134b5a
|
||||
F ext/icu/sqliteicu.h 728867a802baa5a96de7495e9689a8e01715ef37
|
||||
F ext/rtree/README 6315c0d73ebf0ec40dedb5aa0e942bc8b54e3761
|
||||
F ext/rtree/rtree.c 73502e5336162fdc8f5d1c4bdd4ec6b1299c2f2a
|
||||
F ext/rtree/rtree.c d17aecb7a92762efa7b1f5d5fd7c88fd77d70827
|
||||
F ext/rtree/rtree.h 834dbcb82dc85b2481cde6a07cdadfddc99e9b9e
|
||||
F ext/rtree/rtree1.test e474a2b5eff231496dbd073fe67e5fbaf7f444c9
|
||||
F ext/rtree/rtree2.test acbb3a4ce0f4fbc2c304d2b4b784cfa161856bba
|
||||
|
@ -98,7 +103,7 @@ F ext/rtree/tkt3363.test 142ab96eded44a3615ec79fba98c7bde7d0f96de
|
|||
F ext/rtree/viewrtree.tcl eea6224b3553599ae665b239bd827e182b466024
|
||||
F install-sh 9d4de14ab9fb0facae2f48780b874848cbf2f895 x
|
||||
F ltmain.sh 3ff0879076df340d2e23ae905484d8c15d5fdea8
|
||||
F main.mk a80771d44176a0c744d9d4e048497e7ed0b4040d
|
||||
F main.mk 84ed9c324cf0b8f4eb6f276553d1fd092b5ae0f4
|
||||
F mkdll.sh 7d09b23c05d56532e9d44a50868eb4b12ff4f74a
|
||||
F mkextu.sh 416f9b7089d80e5590a29692c9d9280a10dbad9f
|
||||
F mkextw.sh 4123480947681d9b434a5e7b1ee08135abe409ac
|
||||
|
@ -113,18 +118,18 @@ F sqlite3.1 6be1ad09113570e1fc8dcaff84c9b0b337db5ffc
|
|||
F sqlite3.pc.in ae6f59a76e862f5c561eb32a380228a02afc3cad
|
||||
F src/alter.c 149cc80d9257971b0bff34e58fb2263e01998289
|
||||
F src/analyze.c 70c46504c0d2543ea5cdca01140b2cd3e1d886e7
|
||||
F src/attach.c 12c6957996908edc31c96d7c68d4942c2474405f
|
||||
F src/attach.c 577bf5675b0c50495fc28549f2fcbdb1bac71143
|
||||
F src/auth.c 523da7fb4979469955d822ff9298352d6b31de34
|
||||
F src/backup.c 6be23a344d3301ae38e92fddb3a33b91c309fce4
|
||||
F src/backup.c d7fb4c6d2ad3fe51a4ce1a897fde7b00f4de5fef
|
||||
F src/bitvec.c af50f1c8c0ff54d6bdb7a80e2fceca5a93670bef
|
||||
F src/btmutex.c 976f45a12e37293e32cae0281b15a21d48a8aaa7
|
||||
F src/btree.c df800f10896bc2ddaa1125c532d6e7a7b9efc532
|
||||
F src/btree.c f0b71054103cb77eb5e782088c16998ec4f06624
|
||||
F src/btree.h 48a013f8964f12d944d90e4700df47b72dd6d923
|
||||
F src/btreeInt.h 38a639c0542c29fe8331a221c4aed0cb8686249e
|
||||
F src/build.c 2bb2163bb1e69f59e9f36a9413079ead42fa1d2c
|
||||
F src/build.c 47c4506afe4bcb4ed1f4b5357582d1cb3402f8ad
|
||||
F src/callback.c 0cb4228cdcd827dcc5def98fb099edcc9142dbcd
|
||||
F src/complete.c dc1d136c0feee03c2f7550bafc0d29075e36deac
|
||||
F src/ctime.c a9c26822515f81ec21588cbb482ca6724be02e33
|
||||
F src/ctime.c 500d019da966631ad957c37705642be87524463b
|
||||
F src/date.c 067a81c9942c497aafd2c260e13add8a7d0c7dd4
|
||||
F src/delete.c 4c20ea4f6213b3bc1c6a510586864b679946e05e
|
||||
F src/expr.c 06a7733d19dc725dc46ba51afd9feadb4b85d991
|
||||
|
@ -140,7 +145,7 @@ F src/journal.c 552839e54d1bf76fb8f7abe51868b66acacf6a0e
|
|||
F src/legacy.c a199d7683d60cef73089e892409113e69c23a99f
|
||||
F src/lempar.c 0ee69fca0be54cd93939df98d2aca4ca46f44416
|
||||
F src/loadext.c f20382fbaeec832438a1ba7797bee3d3c8a6d51d
|
||||
F src/main.c 91458c713e9b7f8dbc98d79e78f1150f0ca9c2a1
|
||||
F src/main.c 07e05ba330b5994fa20d3b2e8c1c146133587d68
|
||||
F src/malloc.c fe085aa851b666b7c375c1ff957643dc20a04bf6
|
||||
F src/mem0.c 6a55ebe57c46ca1a7d98da93aaa07f99f1059645
|
||||
F src/mem1.c b3677415e69603d6a0e7c5410a1b3731d55beda1
|
||||
|
@ -153,49 +158,49 @@ F src/mutex.h 2a79e0c10c26412546b501ee0f3d92b42decf63e
|
|||
F src/mutex_noop.c 7682796b7d8d39bf1c138248858efcd10c9e1553
|
||||
F src/mutex_os2.c 882d735098c07c8c6a5472b8dd66e19675fe117f
|
||||
F src/mutex_unix.c c3a4e00f96ba068a8dbef34084465979aaf369cc
|
||||
F src/mutex_w32.c 5e54f3ba275bcb5d00248b8c23107df2e2f73e33
|
||||
F src/mutex_w32.c db8970270841e2385a43602477e84c4b19aff1db
|
||||
F src/notify.c 976dd0f6171d4588e89e874fcc765e92914b6d30
|
||||
F src/os.c e1acdc09ff3ac2412945cca9766e2dcf4675f31c
|
||||
F src/os.h 59beba555b65a450bd1d804220532971d4299f60
|
||||
F src/os.h 38aabd5e3ecd4162332076f55bb09cec02165cca
|
||||
F src/os_common.h 92815ed65f805560b66166e3583470ff94478f04
|
||||
F src/os_os2.c 4a75888ba3dfc820ad5e8177025972d74d7f2440
|
||||
F src/os_unix.c 424d46e0edab969293c2223f09923b2178171f47
|
||||
F src/os_win.c 412d6434133c7c81dc48b7702f3ea5e61c309e5c
|
||||
F src/pager.c bb5635dde0b152797836d1c72275284724bb563c
|
||||
F src/pager.h ef1eaf8593e78f73885c1dfac27ad83bee23bdc5
|
||||
F src/os_unix.c d7c96b5d140f550f07345870112fae5d7ef99757
|
||||
F src/os_win.c e3d3d3e26b65a35d4293d753137a58510bd3299b
|
||||
F src/pager.c e381c118b77dc22021a1a59d3fec24815e91df78
|
||||
F src/pager.h 8b8c9bc065a3c66769df8724dfdf492ee1aab3c5
|
||||
F src/parse.y f29df90bd3adc64b33114ab1de9fb7768fcf2099
|
||||
F src/pcache.c f8043b433a57aba85384a531e3937a804432a346
|
||||
F src/pcache.h 1b5dcc3dc8103d03e625b177023ee67764fa6b7c
|
||||
F src/pcache1.c b30b1c35908346ecc43d8d9d17f2ddf6817f8f60
|
||||
F src/pragma.c e708b3bb5704605816f617e0b1d63a5488060715
|
||||
F src/prepare.c 9a00a9612ebf80203fbb41f8a29ab8cb27a05f40
|
||||
F src/pcache1.c 2234d84f9c003d800a57f00f8535c91667fa4f6c
|
||||
F src/pragma.c eee3e3161f82a1e06f632a8d2a82b29ba3c45889
|
||||
F src/prepare.c 33291b83cca285718048d219c67b8298501fa3a5
|
||||
F src/printf.c 7ffb4ebb8b341f67e049695ba031da717b3d2699
|
||||
F src/random.c cd4a67b3953b88019f8cd4ccd81394a8ddfaba50
|
||||
F src/resolve.c b3c70ab28cac60de33684c9aa9e5138dcf71d6dd
|
||||
F src/rowset.c f6a49f3e9579428024662f6e2931832511f831a1
|
||||
F src/select.c f6c4833c4d8e94714761d99013d74f381e084f1d
|
||||
F src/shell.c c16f72e34f611f060546709564c121a67cb2b31b
|
||||
F src/sqlite.h.in 4f4d4792f6fb00387c877af013cb09d955643f12
|
||||
F src/sqlite.h.in 39f041ce71a0d994e2487014fc9e8721595f5bc0
|
||||
F src/sqlite3ext.h 6904f4aadf976f95241311fbffb00823075d9477
|
||||
F src/sqliteInt.h 97ccae71ae0a4e924dcb9fab14eb4fc4839790da
|
||||
F src/sqliteInt.h 29b5348f0056d9b46d0bb94d4853db21568afde9
|
||||
F src/sqliteLimit.h 164b0e6749d31e0daa1a4589a169d31c0dec7b3d
|
||||
F src/status.c 35939e7e03abf1b7577ce311f48f682c40de3208
|
||||
F src/table.c 2cd62736f845d82200acfa1287e33feb3c15d62e
|
||||
F src/tclsqlite.c fe5406573e1527957e00dcaf51edd9d8bd31b918
|
||||
F src/test1.c a808bfa548a501b513579bdbaf83901c98e059c9
|
||||
F src/test1.c fc2acf0a2db517c8d19e5e55bda8e1237db77378
|
||||
F src/test2.c 4178056dd1e7d70f954ad8a1e3edb71a2a784daf
|
||||
F src/test3.c 3c3c2407fa6ec7a19e24ae23f7cb439d0275a60d
|
||||
F src/test4.c d1e5a5e904d4b444cf572391fdcb017638e36ff7
|
||||
F src/test5.c a6d1ac55ac054d0b2b8f37b5e655b6c92645a013
|
||||
F src/test6.c 417e1e214734393c24a8ee80b41485a9c4169123
|
||||
F src/test7.c 2e0781754905c8adc3268d8f0967e7633af58843
|
||||
F src/test8.c 5ecbffe6712da81d5d10454e9d77d6c5bac95fe8
|
||||
F src/test8.c 235f1d19716fa768c46fc461ccbf529b2c9e4399
|
||||
F src/test9.c bea1e8cf52aa93695487badedd6e1886c321ea60
|
||||
F src/test_async.c 0612a752896fad42d55c3999a5122af10dcf22ad
|
||||
F src/test_autoext.c 30e7bd98ab6d70a62bb9ba572e4c7df347fe645e
|
||||
F src/test_backup.c c129c91127e9b46e335715ae2e75756e25ba27de
|
||||
F src/test_btree.c 47cd771250f09cdc6e12dda5bc71bc0b3abc96e2
|
||||
F src/test_config.c 0de329e736eb4aa5845069bed630e5c72f012264
|
||||
F src/test_btree.c 5b89601dcb42a33ba8b820a6b763cc9cb48bac16
|
||||
F src/test_config.c 4f7b8030287d62fe56a1d99e68b41760feae381a
|
||||
F src/test_demovfs.c 20a4975127993f4959890016ae9ce5535a880094
|
||||
F src/test_devsym.c e7498904e72ba7491d142d5c83b476c4e76993bc
|
||||
F src/test_func.c 090f2c3339e85c2c964435f99aed6f3da9d59525
|
||||
|
@ -213,8 +218,8 @@ F src/test_mutex.c a6bd7b9cf6e19d989e31392b06ac8d189f0d573e
|
|||
F src/test_onefile.c 0396f220561f3b4eedc450cef26d40c593c69a25
|
||||
F src/test_osinst.c 90a845c8183013d80eccb1f29e8805608516edba
|
||||
F src/test_pcache.c a5cd24730cb43c5b18629043314548c9169abb00
|
||||
F src/test_quota.c 47cb7b606160ce8f603a7d47143dd1f74de09058
|
||||
F src/test_quota.h ee5da2ae7f84d1c8e0e0e2ab33f01d69f10259b5
|
||||
F src/test_quota.c 0af3e1e9a1f22bc5f431dd3efcc32762f4109f58
|
||||
F src/test_quota.h 8761e463b25e75ebc078bd67d70e39b9c817a0cb
|
||||
F src/test_rtree.c aba603c949766c4193f1068b91c787f57274e0d9
|
||||
F src/test_schema.c 8c06ef9ddb240c7a0fcd31bc221a6a2aade58bf0
|
||||
F src/test_server.c 2f99eb2837dfa06a4aacf24af24c6affdf66a84f
|
||||
|
@ -233,8 +238,8 @@ F src/trigger.c ee7e178fb9188f44b532cebd449a7c1df90fb684
|
|||
F src/update.c d3076782c887c10e882996550345da9c4c9f9dea
|
||||
F src/utf.c 890c67dcfcc7a74623c95baac7535aadfe265e84
|
||||
F src/util.c 4f6cfad661b2e3454b0cdd5b1b9d39a54942d0e3
|
||||
F src/vacuum.c bfd53f9bd20a8fdb70b0fa8e77182b866875c0d8
|
||||
F src/vdbe.c e1d26b98288889c22f00cf4851ec351ee67ad8b9
|
||||
F src/vacuum.c 587a52bb8833d7ac15af8916f25437e2575028bd
|
||||
F src/vdbe.c f5ad3c06dc3fe647097065829c013f3f1b9eadca
|
||||
F src/vdbe.h 18f581cac1f4339ec3299f3e0cc6e11aec654cdb
|
||||
F src/vdbeInt.h 6ff4180a05683566a8835d12f7ec504b22932c82
|
||||
F src/vdbeapi.c 3662b6a468a2a4605a15dfab313baa6dff81ad91
|
||||
|
@ -243,7 +248,7 @@ F src/vdbeblob.c 32f2a4899d67f69634ea4dd93e3f651936d732cb
|
|||
F src/vdbemem.c cb55e84b8e2c15704968ee05f0fae25883299b74
|
||||
F src/vdbesort.c b25814d385895544ebc8118245c8311ded7f81c9
|
||||
F src/vdbetrace.c 79059ebd17b3c8545fab2a24253713e77e4ab392
|
||||
F src/vtab.c ae657b1c22cff43863458e768a44f915c07bc0e4
|
||||
F src/vtab.c bb8ea3a26608bb1357538a5d2fc72beba6638998
|
||||
F src/wal.c 7bb3ad807afc7973406c805d5157ec7a2f65e146
|
||||
F src/wal.h 29c197540b19044e6cd73487017e5e47a1d3dac6
|
||||
F src/walker.c 3112bb3afe1d85dc52317cb1d752055e9a781f8f
|
||||
|
@ -291,8 +296,8 @@ F test/badutf.test d5360fc31f643d37a973ab0d8b4fb85799c3169f
|
|||
F test/badutf2.test f5bc7f2d280670ecd79b9cf4f0f1760c607fe51f
|
||||
F test/bc_common.tcl 5c8689cc6d2fb44b7c0968ae4f85eb26d50022fa
|
||||
F test/between.test 16b1776c6323faadb097a52d673e8e3d8be7d070
|
||||
F test/bigfile.test 82dfe93ee7eb9e2e05641afa2b39ffd947a92ff1
|
||||
F test/bigfile2.test 852f948cb492aadab45b58f4d2f3b0832a115cb0
|
||||
F test/bigfile.test 8f88b5ef065e31c615c49d725ede94155fbe9609
|
||||
F test/bigfile2.test 8a3c242c3c3481e7cde5a6ef2a66fdc367a095f7
|
||||
F test/bigrow.test f0aeb7573dcb8caaafea76454be3ade29b7fc747
|
||||
F test/bind.test 3c7b320969000c441a70952b0b15938fbb66237c
|
||||
F test/bindxfer.test efecd12c580c14df5f4ad3b3e83c667744a4f7e0
|
||||
|
@ -309,9 +314,9 @@ F test/boundary4.test 89e02fa66397b8a325d5eb102b5806f961f8ec4b
|
|||
F test/busy.test 76b4887f8b9160ba903c1ac22e8ff406ad6ae2f0
|
||||
F test/cache.test f64136b0893c293d0b910ed057b3b711249099a7
|
||||
F test/capi2.test 835d4cee9f542ea50fa8d01f3fe6de80b0627360
|
||||
F test/capi3.test 8dedb0050610e9ff95cd9d487beb0ce5f33a31ee
|
||||
F test/capi3.test 56ab450125ead38846cbae7e5b6a216686c3cffa
|
||||
F test/capi3b.test efb2b9cfd127efa84433cd7a2d72ce0454ae0dc4
|
||||
F test/capi3c.test 01f197d73f4d4d66316483662f475cab7ab5bd60
|
||||
F test/capi3c.test 93d24621c9ff84da9da060f30431e0453db1cdb0
|
||||
F test/capi3d.test 17b57ca28be3e37e14c2ba8f787d292d84b724a1
|
||||
F test/capi3e.test f7408dda65c92b9056199fdc180f893015f83dde
|
||||
F test/cast.test 4c275cbdc8202d6f9c54a3596701719868ac7dc3
|
||||
|
@ -384,7 +389,7 @@ F test/e_resolve.test dcce9308fb13b934ce29591105d031d3e14fbba6
|
|||
F test/e_select.test f5d4b81205701deacfae42051ae200969c41d2c0
|
||||
F test/e_select2.test 5c3d3da19c7b3e90ae444579db2b70098599ab92
|
||||
F test/e_update.test 161d5dc6a3ed9dd08f5264d13e20735d7a89f00c
|
||||
F test/e_uri.test e8b894474fdfe7b18b0c9cb2d911270de2ad64ce
|
||||
F test/e_uri.test 9e190ca799d9190eec6e43f2aadf1d10c06a57a3
|
||||
F test/e_vacuum.test 331da289ae186656cf5f2eb27f577a89c0c221af
|
||||
F test/enc.test e54531cd6bf941ee6760be041dff19a104c7acea
|
||||
F test/enc2.test 796c59832e2b9a52842f382ffda8f3e989db03ad
|
||||
|
@ -477,7 +482,7 @@ F test/fts3e.test 1f6c6ac9cc8b772ca256e6b22aaeed50c9350851
|
|||
F test/fts3expr.test 5e745b2b6348499d9ef8d59015de3182072c564c
|
||||
F test/fts3expr2.test 18da930352e5693eaa163a3eacf96233b7290d1a
|
||||
F test/fts3fault.test cb72dccb0a3b9f730f16c5240f3fcb9303eb1660
|
||||
F test/fts3fault2.test b62a2bc843c20414405f80e5eeb78e39bc68fe53
|
||||
F test/fts3fault2.test 3198eef2804deea7cac8403e771d9cbcb752d887
|
||||
F test/fts3first.test dbdedd20914c8d539aa3206c9b34a23775644641
|
||||
F test/fts3malloc.test b86ea33db9e8c58c0c2f8027a9fcadaf6a1568be
|
||||
F test/fts3matchinfo.test 6507fe1c342e542300d65ea637d4110eccf894e6
|
||||
|
@ -496,6 +501,7 @@ F test/fts4langid.test 24a6e41063b416bbdf371ff6b4476fa41c194aa7
|
|||
F test/fts4merge.test c424309743fdd203f8e56a1f1cd7872cd66cc0ee
|
||||
F test/fts4merge2.test 5faa558d1b672f82b847d2a337465fa745e46891
|
||||
F test/fts4merge3.test aab02a09f50fe6baaddc2e159c3eabc116d45fc7
|
||||
F test/fts4unicode.test 247e6c64563b5f930aec0f89a5b01ed6b4b129cd
|
||||
F test/func.test 9809b7622d721904a8cc33c1ffb87f46d506ed01
|
||||
F test/func2.test 772d66227e4e6684b86053302e2d74a2500e1e0f
|
||||
F test/func3.test 001021e5b88bd02a3b365a5c5fd8f6f49d39744a
|
||||
|
@ -605,7 +611,7 @@ F test/minmax.test 722d80816f7e096bf2c04f4111f1a6c1ba65453d
|
|||
F test/minmax2.test 33504c01a03bd99226144e4b03f7631a274d66e0
|
||||
F test/minmax3.test cc1e8b010136db0d01a6f2a29ba5a9f321034354
|
||||
F test/minmax4.test 536a3360470633a177e42fbc19660d146b51daef
|
||||
F test/misc1.test 55cb2bfbf4a8cd61f4be1effc30426ad41696bff
|
||||
F test/misc1.test 889b40722442380a2f6575f30831b32b2372d70e
|
||||
F test/misc2.test 00d7de54eda90e237fc9a38b9e5ccc769ebf6d4d
|
||||
F test/misc3.test fe55130a43e444ee75e2156ff75dc96e964b5738
|
||||
F test/misc4.test 9c078510fbfff05a9869a0b6d8b86a623ad2c4f6
|
||||
|
@ -626,7 +632,7 @@ F test/notnull.test cc7c78340328e6112a13c3e311a9ab3127114347
|
|||
F test/null.test a8b09b8ed87852742343b33441a9240022108993
|
||||
F test/openv2.test 0d3040974bf402e19b7df4b783e447289d7ab394
|
||||
F test/oserror.test 50417780d0e0d7cd23cf12a8277bb44024765df3
|
||||
F test/pager1.test 31fef8ff6d5cbb4643f430e31756312d361ecfdf
|
||||
F test/pager1.test 2163c6ef119f497a71a84137c957c63763e640ab
|
||||
F test/pager2.test 745b911dde3d1f24ae0870bd433dfa83d7c658c1
|
||||
F test/pager3.test 3856d9c80839be0668efee1b74811b1b7f7fc95f
|
||||
F test/pagerfault.test 452f2cc23e3bfcfa935f4442aec1da4fe1dc0442
|
||||
|
@ -636,16 +642,16 @@ F test/pageropt.test 9191867ed19a2b3db6c42d1b36b6fbc657cd1ab0
|
|||
F test/pagesize.test 1dd51367e752e742f58e861e65ed7390603827a0
|
||||
F test/pcache.test 065aa286e722ab24f2e51792c1f093bf60656b16
|
||||
F test/pcache2.test a83efe2dec0d392f814bfc998def1d1833942025
|
||||
F test/permutations.test dbda172249564f43ec556108a704581044c57dbd
|
||||
F test/pragma.test c51c148defe32bf4a419a522f95d26838d5cf677
|
||||
F test/permutations.test 2af90e00cea9e7e7c0a6b16d34727cb5bbae14dd
|
||||
F test/pragma.test cb736bcc75b8b629af21ac0ad83ba1d054a2107b
|
||||
F test/pragma2.test 3a55f82b954242c642f8342b17dffc8b47472947
|
||||
F test/printf.test ec9870c4dce8686a37818e0bf1aba6e6a1863552
|
||||
F test/progress.test 5b075c3c790c7b2a61419bc199db87aaf48b8301
|
||||
F test/ptrchng.test ef1aa72d6cf35a2bbd0869a649b744e9d84977fc
|
||||
F test/quick.test 1681febc928d686362d50057c642f77a02c62e57
|
||||
F test/quota-glob.test 32901e9eed6705d68ca3faee2a06b73b57cb3c26
|
||||
F test/quota.test c2f778dab4c7fb07bcfa962cc5c762f36d8061dc
|
||||
F test/quota2.test bc9fdb2e46aace691c1a01a9cc8d097bd4d7c1ab
|
||||
F test/quota.test b5b3eec55a059e0fe493c66c6e27bd2c07676cfd
|
||||
F test/quota2.test 6d2bd57e8a4da28817f46db9da18551211cd325f
|
||||
F test/quote.test 215897dbe8de1a6f701265836d6601cc6ed103e6
|
||||
F test/randexpr1.tcl 40dec52119ed3a2b8b2a773bce24b63a3a746459
|
||||
F test/randexpr1.test eda062a97e60f9c38ae8d806b03b0ddf23d796df
|
||||
|
@ -683,15 +689,16 @@ F test/selectA.test 06d1032fa9009314c95394f2ca2e60d9f7ae8532
|
|||
F test/selectB.test 954e4e49cf1f896d61794e440669e03a27ceea25
|
||||
F test/selectC.test 871fb55d884d3de5943c4057ebd22c2459e71977
|
||||
F test/server1.test 46803bd3fe8b99b30dbc5ff38ffc756f5c13a118
|
||||
F test/shared.test 34945a516532b11182c3eb26e31247eee3c9ae48
|
||||
F test/shared.test 1da9dbad400cee0d93f252ccf76e1ae007a63746
|
||||
F test/shared2.test 03eb4a8d372e290107d34b6ce1809919a698e879
|
||||
F test/shared3.test ebf77f023f4bdaa8f74f65822b559e86ce5c6257
|
||||
F test/shared4.test 72d90821e8d2fc918a08f16d32880868d8ee8e9d
|
||||
F test/shared6.test 866bb4982c45ce216c61ded5e8fde4e7e2f3ffa9
|
||||
F test/shared7.test 960760bc8d03e1419e70dea69cf41db62853616e
|
||||
F test/shared8.test b27befbefbe7f4517f1d6b7ff8f64a41ec74165d
|
||||
F test/shared_err.test 91e26ec4f3fbe07951967955585137e2f18993de
|
||||
F test/sharedlock.test ffa0a3c4ac192145b310f1254f8afca4d553eabf
|
||||
F test/shell1.test 6e3013bc50e2b73f00d17e491f776decc82a71c8
|
||||
F test/shell1.test 9895ee3013742a02e5afd8d77793729967ffd195
|
||||
F test/shell2.test 037d6ad16e873354195d30bb2dc4b5321788154a
|
||||
F test/shell3.test 9196c42772d575685e722c92b4b39053c6ebba59
|
||||
F test/shell4.test aa4eef8118b412d1a01477a53426ece169ea86a9
|
||||
|
@ -727,7 +734,7 @@ F test/tclsqlite.test 1597d353308531527583481d14d9da52ea8ed0af
|
|||
F test/tempdb.test 19d0f66e2e3eeffd68661a11c83ba5e6ace9128c
|
||||
F test/temptable.test 51edd31c65ed1560dd600b1796e8325df96318e2
|
||||
F test/temptrigger.test 26670ed7a39cf2296a7f0a9e0a1d7bdb7abe936d
|
||||
F test/tester.tcl a55e066251bc05e26f9da00e76644ab649b26f3c
|
||||
F test/tester.tcl 2665f64c9ce71944b4d41269114e658fb81bda05
|
||||
F test/thread001.test 7cc2ce08f9cde95964736d11e91f9ab610f82f91
|
||||
F test/thread002.test e630504f8a06c00bf8bbe68528774dd96aeb2e58
|
||||
F test/thread003.test ee4c9efc3b86a6a2767516a37bd64251272560a7
|
||||
|
@ -891,7 +898,7 @@ F test/unique.test 083c7fff74695bcc27a71d75699deba3595bc9c2
|
|||
F test/unixexcl.test a9870e46cc6f8390a494513d4f2bf55b5a8b3e46
|
||||
F test/unordered.test f53095cee37851bf30130fa1bf299a8845e837bb
|
||||
F test/update.test 8bc86fd7ef1a00014f76dc6a6a7c974df4aef172
|
||||
F test/uri.test 78e869db1ff6331157b08ef089b1b3e65819c74c
|
||||
F test/uri.test 63e03df051620a18f794b4f4adcdefb3c23b6751
|
||||
F test/utf16align.test 54cd35a27c005a9b6e7815d887718780b6a462ae
|
||||
F test/vacuum.test ce91c39f7f91a4273bf620efad21086b5aa6ef1d
|
||||
F test/vacuum2.test af432e6e3bfc0ea20a80cb86a03c7d9876d38324
|
||||
|
@ -900,7 +907,7 @@ F test/vacuum4.test d3f8ecff345f166911568f397d2432c16d2867d9
|
|||
F test/varint.test ab7b110089a08b9926ed7390e7e97bdefeb74102
|
||||
F test/veryquick.test 7701bb609fe8bf6535514e8b849a309e8f00573b
|
||||
F test/view.test b182a67ec43f490b156b5a710827a341be83dd17
|
||||
F test/vtab1.test e429a6835faa3870016c55d1178dcfead85f936a
|
||||
F test/vtab1.test 10fb9e656fe4b318cd82ff1616a340acc01aac4b
|
||||
F test/vtab2.test 7bcffc050da5c68f4f312e49e443063e2d391c0d
|
||||
F test/vtab3.test baad99fd27217f5d6db10660522e0b7192446de1
|
||||
F test/vtab4.test 942f8b8280b3ea8a41dae20e7822d065ca1cb275
|
||||
|
@ -918,7 +925,7 @@ F test/vtabF.test fd5ad376f5a34fe0891df1f3cddb4fe7c3eb077e
|
|||
F test/vtab_alter.test 9e374885248f69e251bdaacf480b04a197f125e5
|
||||
F test/vtab_err.test 0d4d8eb4def1d053ac7c5050df3024fd47a3fbd8
|
||||
F test/vtab_shared.test 82f463886e18d7f8395a4b6167c91815efe54839
|
||||
F test/wal.test b3d28d655371bf3f6500c679f526e9860544fe70
|
||||
F test/wal.test a040047d7f2b9f34bc4d597964e5e7c09609c635
|
||||
F test/wal2.test d5021064bebfc717fe2bf4db2536ea030b76a773
|
||||
F test/wal3.test 6504bbf348b2d6dfade64a064f1050fd617e8706
|
||||
F test/wal4.test 4744e155cd6299c6bd99d3eab1c82f77db9cdb3c
|
||||
|
@ -972,7 +979,7 @@ F tool/mkkeywordhash.c bb52064aa614e1426445e4b2b9b00eeecd23cc79
|
|||
F tool/mkopts.tcl 66ac10d240cc6e86abd37dc908d50382f84ff46e
|
||||
F tool/mkspeedsql.tcl a1a334d288f7adfe6e996f2e712becf076745c97
|
||||
F tool/mksqlite3c-noext.tcl 105023aa86f696a74b1d6a4929d1e1c3baf9471c
|
||||
F tool/mksqlite3c.tcl 9fbac513cd9d5ac95ad55630f49bb16c5347ab75
|
||||
F tool/mksqlite3c.tcl f289ba51f74f45c71a80c13e6c74a6dd92763253
|
||||
F tool/mksqlite3h.tcl 78013ad79a5e492e5f764f3c7a8ef834255061f8
|
||||
F tool/mksqlite3internalh.tcl 7b43894e21bcb1bb39e11547ce7e38a063357e87
|
||||
F tool/offsets.c fe4262fdfa378e8f5499a42136d17bf3b98f6091
|
||||
|
@ -996,12 +1003,12 @@ F tool/symbols-mingw.sh 4dbcea7e74768305384c9fd2ed2b41bbf9f0414d
|
|||
F tool/symbols.sh fec58532668296d7c7dc48be9c87f75ccdb5814f
|
||||
F tool/tostr.awk e75472c2f98dd76e06b8c9c1367f4ab07e122d06
|
||||
F tool/vdbe-compress.tcl d70ea6d8a19e3571d7ab8c9b75cba86d1173ff0f
|
||||
F tool/warnings-clang.sh a8a0a3babda96dfb1ff51adda3cbbf3dfb7266c2
|
||||
F tool/warnings-clang.sh f6aa929dc20ef1f856af04a730772f59283631d4
|
||||
F tool/warnings.sh fbc018d67fd7395f440c28f33ef0f94420226381
|
||||
P 5519cc5ef471e32a59995a34be811b46478dca1e
|
||||
R f9f0e59804fa7e60869ace7ace22bd3d
|
||||
P 0ae0ce630a2e11f81dca50a9cfb04c4a41c03b2d
|
||||
R 45dae5fdb66a9a88c8595b45bd7db627
|
||||
T +bgcolor * #d0c0ff
|
||||
T +sym-release *
|
||||
T +sym-version-3.7.12.1 *
|
||||
T +sym-version-3.7.13 *
|
||||
U drh
|
||||
Z a30e57621f706278c1c64a3624297cbb
|
||||
Z c0babe9c1caac24f66a10b2544a508b6
|
||||
|
|
|
@ -1 +1 @@
|
|||
6d326d44fd1d626aae0e8456e5fa2049f1ce0789
|
||||
f5b5a13f7394dc143aa136f1d4faba6839eaa6dc
|
||||
|
|
|
@ -216,7 +216,7 @@ static void attachFunc(
|
|||
db->aDb[iDb].pBt = 0;
|
||||
db->aDb[iDb].pSchema = 0;
|
||||
}
|
||||
sqlite3ResetInternalSchema(db, -1);
|
||||
sqlite3ResetAllSchemasOfConnection(db);
|
||||
db->nDb = iDb;
|
||||
if( rc==SQLITE_NOMEM || rc==SQLITE_IOERR_NOMEM ){
|
||||
db->mallocFailed = 1;
|
||||
|
@ -288,7 +288,7 @@ static void detachFunc(
|
|||
sqlite3BtreeClose(pDb->pBt);
|
||||
pDb->pBt = 0;
|
||||
pDb->pSchema = 0;
|
||||
sqlite3ResetInternalSchema(db, -1);
|
||||
sqlite3ResetAllSchemasOfConnection(db);
|
||||
return;
|
||||
|
||||
detach_error:
|
||||
|
|
|
@ -414,7 +414,7 @@ int sqlite3_backup_step(sqlite3_backup *p, int nPage){
|
|||
rc = sqlite3BtreeUpdateMeta(p->pDest,1,p->iDestSchema+1);
|
||||
if( rc==SQLITE_OK ){
|
||||
if( p->pDestDb ){
|
||||
sqlite3ResetInternalSchema(p->pDestDb, -1);
|
||||
sqlite3ResetAllSchemasOfConnection(p->pDestDb);
|
||||
}
|
||||
if( destMode==PAGER_JOURNALMODE_WAL ){
|
||||
rc = sqlite3BtreeSetVersion(p->pDest, 2);
|
||||
|
|
27
src/btree.c
27
src/btree.c
|
@ -1721,7 +1721,8 @@ int sqlite3BtreeOpen(
|
|||
const int isMemdb = 0;
|
||||
#else
|
||||
const int isMemdb = (zFilename && strcmp(zFilename, ":memory:")==0)
|
||||
|| (isTempDb && sqlite3TempInMemory(db));
|
||||
|| (isTempDb && sqlite3TempInMemory(db))
|
||||
|| (vfsFlags & SQLITE_OPEN_MEMORY)!=0;
|
||||
#endif
|
||||
|
||||
assert( db!=0 );
|
||||
|
@ -1757,7 +1758,7 @@ int sqlite3BtreeOpen(
|
|||
** If this Btree is a candidate for shared cache, try to find an
|
||||
** existing BtShared object that we can share with
|
||||
*/
|
||||
if( isMemdb==0 && isTempDb==0 ){
|
||||
if( isTempDb==0 && (isMemdb==0 || (vfsFlags&SQLITE_OPEN_URI)!=0) ){
|
||||
if( vfsFlags & SQLITE_OPEN_SHAREDCACHE ){
|
||||
int nFullPathname = pVfs->mxPathname+1;
|
||||
char *zFullPathname = sqlite3Malloc(nFullPathname);
|
||||
|
@ -1767,11 +1768,16 @@ int sqlite3BtreeOpen(
|
|||
sqlite3_free(p);
|
||||
return SQLITE_NOMEM;
|
||||
}
|
||||
rc = sqlite3OsFullPathname(pVfs, zFilename, nFullPathname, zFullPathname);
|
||||
if( rc ){
|
||||
sqlite3_free(zFullPathname);
|
||||
sqlite3_free(p);
|
||||
return rc;
|
||||
if( isMemdb ){
|
||||
memcpy(zFullPathname, zFilename, sqlite3Strlen30(zFilename)+1);
|
||||
}else{
|
||||
rc = sqlite3OsFullPathname(pVfs, zFilename,
|
||||
nFullPathname, zFullPathname);
|
||||
if( rc ){
|
||||
sqlite3_free(zFullPathname);
|
||||
sqlite3_free(p);
|
||||
return rc;
|
||||
}
|
||||
}
|
||||
#if SQLITE_THREADSAFE
|
||||
mutexOpen = sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_OPEN);
|
||||
|
@ -1781,7 +1787,7 @@ int sqlite3BtreeOpen(
|
|||
#endif
|
||||
for(pBt=GLOBAL(BtShared*,sqlite3SharedCacheList); pBt; pBt=pBt->pNext){
|
||||
assert( pBt->nRef>0 );
|
||||
if( 0==strcmp(zFullPathname, sqlite3PagerFilename(pBt->pPager))
|
||||
if( 0==strcmp(zFullPathname, sqlite3PagerFilename(pBt->pPager, 0))
|
||||
&& sqlite3PagerVfs(pBt->pPager)==pVfs ){
|
||||
int iDb;
|
||||
for(iDb=db->nDb-1; iDb>=0; iDb--){
|
||||
|
@ -8046,14 +8052,15 @@ char *sqlite3BtreeIntegrityCheck(
|
|||
#endif /* SQLITE_OMIT_INTEGRITY_CHECK */
|
||||
|
||||
/*
|
||||
** Return the full pathname of the underlying database file.
|
||||
** Return the full pathname of the underlying database file. Return
|
||||
** an empty string if the database is in-memory or a TEMP database.
|
||||
**
|
||||
** The pager filename is invariant as long as the pager is
|
||||
** open so it is safe to access without the BtShared mutex.
|
||||
*/
|
||||
const char *sqlite3BtreeGetFilename(Btree *p){
|
||||
assert( p->pBt->pPager!=0 );
|
||||
return sqlite3PagerFilename(p->pBt->pPager);
|
||||
return sqlite3PagerFilename(p->pBt->pPager, 1);
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
102
src/build.c
102
src/build.c
|
@ -394,58 +394,15 @@ void sqlite3UnlinkAndDeleteIndex(sqlite3 *db, int iDb, const char *zIdxName){
|
|||
}
|
||||
|
||||
/*
|
||||
** Erase all schema information from the in-memory hash tables of
|
||||
** a single database. This routine is called to reclaim memory
|
||||
** before the database closes. It is also called during a rollback
|
||||
** if there were schema changes during the transaction or if a
|
||||
** schema-cookie mismatch occurs.
|
||||
** Look through the list of open database files in db->aDb[] and if
|
||||
** any have been closed, remove them from the list. Reallocate the
|
||||
** db->aDb[] structure to a smaller size, if possible.
|
||||
**
|
||||
** If iDb<0 then reset the internal schema tables for all database
|
||||
** files. If iDb>=0 then reset the internal schema for only the
|
||||
** single file indicated.
|
||||
** Entry 0 (the "main" database) and entry 1 (the "temp" database)
|
||||
** are never candidates for being collapsed.
|
||||
*/
|
||||
void sqlite3ResetInternalSchema(sqlite3 *db, int iDb){
|
||||
void sqlite3CollapseDatabaseArray(sqlite3 *db){
|
||||
int i, j;
|
||||
assert( iDb<db->nDb );
|
||||
|
||||
if( iDb>=0 ){
|
||||
/* Case 1: Reset the single schema identified by iDb */
|
||||
Db *pDb = &db->aDb[iDb];
|
||||
assert( sqlite3SchemaMutexHeld(db, iDb, 0) );
|
||||
assert( pDb->pSchema!=0 );
|
||||
sqlite3SchemaClear(pDb->pSchema);
|
||||
|
||||
/* If any database other than TEMP is reset, then also reset TEMP
|
||||
** since TEMP might be holding triggers that reference tables in the
|
||||
** other database.
|
||||
*/
|
||||
if( iDb!=1 ){
|
||||
pDb = &db->aDb[1];
|
||||
assert( pDb->pSchema!=0 );
|
||||
sqlite3SchemaClear(pDb->pSchema);
|
||||
}
|
||||
return;
|
||||
}
|
||||
/* Case 2 (from here to the end): Reset all schemas for all attached
|
||||
** databases. */
|
||||
assert( iDb<0 );
|
||||
sqlite3BtreeEnterAll(db);
|
||||
for(i=0; i<db->nDb; i++){
|
||||
Db *pDb = &db->aDb[i];
|
||||
if( pDb->pSchema ){
|
||||
sqlite3SchemaClear(pDb->pSchema);
|
||||
}
|
||||
}
|
||||
db->flags &= ~SQLITE_InternChanges;
|
||||
sqlite3VtabUnlockList(db);
|
||||
sqlite3BtreeLeaveAll(db);
|
||||
|
||||
/* If one or more of the auxiliary database files has been closed,
|
||||
** then remove them from the auxiliary database list. We take the
|
||||
** opportunity to do this here since we have just deleted all of the
|
||||
** schema hash tables and therefore do not have to make any changes
|
||||
** to any of those tables.
|
||||
*/
|
||||
for(i=j=2; i<db->nDb; i++){
|
||||
struct Db *pDb = &db->aDb[i];
|
||||
if( pDb->pBt==0 ){
|
||||
|
@ -467,6 +424,51 @@ void sqlite3ResetInternalSchema(sqlite3 *db, int iDb){
|
|||
}
|
||||
}
|
||||
|
||||
/*
|
||||
** Reset the schema for the database at index iDb. Also reset the
|
||||
** TEMP schema.
|
||||
*/
|
||||
void sqlite3ResetOneSchema(sqlite3 *db, int iDb){
|
||||
Db *pDb;
|
||||
assert( iDb<db->nDb );
|
||||
|
||||
/* Case 1: Reset the single schema identified by iDb */
|
||||
pDb = &db->aDb[iDb];
|
||||
assert( sqlite3SchemaMutexHeld(db, iDb, 0) );
|
||||
assert( pDb->pSchema!=0 );
|
||||
sqlite3SchemaClear(pDb->pSchema);
|
||||
|
||||
/* If any database other than TEMP is reset, then also reset TEMP
|
||||
** since TEMP might be holding triggers that reference tables in the
|
||||
** other database.
|
||||
*/
|
||||
if( iDb!=1 ){
|
||||
pDb = &db->aDb[1];
|
||||
assert( pDb->pSchema!=0 );
|
||||
sqlite3SchemaClear(pDb->pSchema);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
/*
|
||||
** Erase all schema information from all attached databases (including
|
||||
** "main" and "temp") for a single database connection.
|
||||
*/
|
||||
void sqlite3ResetAllSchemasOfConnection(sqlite3 *db){
|
||||
int i;
|
||||
sqlite3BtreeEnterAll(db);
|
||||
for(i=0; i<db->nDb; i++){
|
||||
Db *pDb = &db->aDb[i];
|
||||
if( pDb->pSchema ){
|
||||
sqlite3SchemaClear(pDb->pSchema);
|
||||
}
|
||||
}
|
||||
db->flags &= ~SQLITE_InternChanges;
|
||||
sqlite3VtabUnlockList(db);
|
||||
sqlite3BtreeLeaveAll(db);
|
||||
sqlite3CollapseDatabaseArray(db);
|
||||
}
|
||||
|
||||
/*
|
||||
** This routine is called when a commit occurs.
|
||||
*/
|
||||
|
@ -2763,7 +2765,7 @@ Index *sqlite3CreateIndex(
|
|||
}else{
|
||||
zColl = pTab->aCol[j].zColl;
|
||||
if( !zColl ){
|
||||
zColl = db->pDfltColl->zName;
|
||||
zColl = "BINARY";
|
||||
}
|
||||
}
|
||||
if( !db->init.busy && !sqlite3LocateCollSeq(pParse, zColl) ){
|
||||
|
|
|
@ -48,6 +48,9 @@ static const char * const azCompileOpt[] = {
|
|||
#ifdef SQLITE_COVERAGE_TEST
|
||||
"COVERAGE_TEST",
|
||||
#endif
|
||||
#ifdef SQLITE_CURDIR
|
||||
"CURDIR",
|
||||
#endif
|
||||
#ifdef SQLITE_DEBUG
|
||||
"DEBUG",
|
||||
#endif
|
||||
|
|
74
src/main.c
74
src/main.c
|
@ -74,6 +74,15 @@ void (*sqlite3IoTrace)(const char*, ...) = 0;
|
|||
*/
|
||||
char *sqlite3_temp_directory = 0;
|
||||
|
||||
/*
|
||||
** If the following global variable points to a string which is the
|
||||
** name of a directory, then that directory will be used to store
|
||||
** all database files specified with a relative pathname.
|
||||
**
|
||||
** See also the "PRAGMA data_store_directory" SQL command.
|
||||
*/
|
||||
char *sqlite3_data_directory = 0;
|
||||
|
||||
/*
|
||||
** Initialize SQLite.
|
||||
**
|
||||
|
@ -272,6 +281,18 @@ int sqlite3_shutdown(void){
|
|||
if( sqlite3GlobalConfig.isMallocInit ){
|
||||
sqlite3MallocEnd();
|
||||
sqlite3GlobalConfig.isMallocInit = 0;
|
||||
|
||||
#ifndef SQLITE_OMIT_SHUTDOWN_DIRECTORIES
|
||||
/* The heap subsystem has now been shutdown and these values are supposed
|
||||
** to be NULL or point to memory that was obtained from sqlite3_malloc(),
|
||||
** which would rely on that heap subsystem; therefore, make sure these
|
||||
** values cannot refer to heap memory that was just invalidated when the
|
||||
** heap subsystem was shutdown. This is only done if the current call to
|
||||
** this function resulted in the heap subsystem actually being shutdown.
|
||||
*/
|
||||
sqlite3_data_directory = 0;
|
||||
sqlite3_temp_directory = 0;
|
||||
#endif
|
||||
}
|
||||
if( sqlite3GlobalConfig.isMutexInit ){
|
||||
sqlite3MutexEnd();
|
||||
|
@ -720,6 +741,30 @@ static void functionDestroy(sqlite3 *db, FuncDef *p){
|
|||
}
|
||||
}
|
||||
|
||||
/*
|
||||
** Disconnect all sqlite3_vtab objects that belong to database connection
|
||||
** db. This is called when db is being closed.
|
||||
*/
|
||||
static void disconnectAllVtab(sqlite3 *db){
|
||||
#ifndef SQLITE_OMIT_VIRTUALTABLE
|
||||
int i;
|
||||
sqlite3BtreeEnterAll(db);
|
||||
for(i=0; i<db->nDb; i++){
|
||||
Schema *pSchema = db->aDb[i].pSchema;
|
||||
if( db->aDb[i].pSchema ){
|
||||
HashElem *p;
|
||||
for(p=sqliteHashFirst(&pSchema->tblHash); p; p=sqliteHashNext(p)){
|
||||
Table *pTab = (Table *)sqliteHashData(p);
|
||||
if( IsVirtual(pTab) ) sqlite3VtabDisconnect(db, pTab);
|
||||
}
|
||||
}
|
||||
}
|
||||
sqlite3BtreeLeaveAll(db);
|
||||
#else
|
||||
UNUSED_PARAMETER(db);
|
||||
#endif
|
||||
}
|
||||
|
||||
/*
|
||||
** Close an existing SQLite database
|
||||
*/
|
||||
|
@ -735,10 +780,10 @@ int sqlite3_close(sqlite3 *db){
|
|||
}
|
||||
sqlite3_mutex_enter(db->mutex);
|
||||
|
||||
/* Force xDestroy calls on all virtual tables */
|
||||
sqlite3ResetInternalSchema(db, -1);
|
||||
/* Force xDisconnect calls on all virtual tables */
|
||||
disconnectAllVtab(db);
|
||||
|
||||
/* If a transaction is open, the ResetInternalSchema() call above
|
||||
/* If a transaction is open, the disconnectAllVtab() call above
|
||||
** will not have called the xDisconnect() method on any virtual
|
||||
** tables in the db->aVTrans[] array. The following sqlite3VtabRollback()
|
||||
** call will do so. We need to do this before the check for active
|
||||
|
@ -769,6 +814,7 @@ int sqlite3_close(sqlite3 *db){
|
|||
/* Free any outstanding Savepoint structures. */
|
||||
sqlite3CloseSavepoints(db);
|
||||
|
||||
/* Close all database connections */
|
||||
for(j=0; j<db->nDb; j++){
|
||||
struct Db *pDb = &db->aDb[j];
|
||||
if( pDb->pBt ){
|
||||
|
@ -779,15 +825,22 @@ int sqlite3_close(sqlite3 *db){
|
|||
}
|
||||
}
|
||||
}
|
||||
sqlite3ResetInternalSchema(db, -1);
|
||||
/* Clear the TEMP schema separately and last */
|
||||
if( db->aDb[1].pSchema ){
|
||||
sqlite3SchemaClear(db->aDb[1].pSchema);
|
||||
}
|
||||
sqlite3VtabUnlockList(db);
|
||||
|
||||
/* Free up the array of auxiliary databases */
|
||||
sqlite3CollapseDatabaseArray(db);
|
||||
assert( db->nDb<=2 );
|
||||
assert( db->aDb==db->aDbStatic );
|
||||
|
||||
/* Tell the code in notify.c that the connection no longer holds any
|
||||
** locks and does not require any further unlock-notify callbacks.
|
||||
*/
|
||||
sqlite3ConnectionClosed(db);
|
||||
|
||||
assert( db->nDb<=2 );
|
||||
assert( db->aDb==db->aDbStatic );
|
||||
for(j=0; j<ArraySize(db->aFunc.a); j++){
|
||||
FuncDef *pNext, *pHash, *p;
|
||||
for(p=db->aFunc.a[j]; p; p=pHash){
|
||||
|
@ -874,7 +927,7 @@ void sqlite3RollbackAll(sqlite3 *db, int tripCode){
|
|||
|
||||
if( db->flags&SQLITE_InternChanges ){
|
||||
sqlite3ExpirePreparedStatements(db);
|
||||
sqlite3ResetInternalSchema(db, -1);
|
||||
sqlite3ResetAllSchemasOfConnection(db);
|
||||
}
|
||||
|
||||
/* Any deferred constraint violations have now been resolved. */
|
||||
|
@ -2012,10 +2065,12 @@ int sqlite3ParseUri(
|
|||
{ "ro", SQLITE_OPEN_READONLY },
|
||||
{ "rw", SQLITE_OPEN_READWRITE },
|
||||
{ "rwc", SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE },
|
||||
{ "memory", SQLITE_OPEN_MEMORY },
|
||||
{ 0, 0 }
|
||||
};
|
||||
|
||||
mask = SQLITE_OPEN_READONLY|SQLITE_OPEN_READWRITE|SQLITE_OPEN_CREATE;
|
||||
mask = SQLITE_OPEN_READONLY | SQLITE_OPEN_READWRITE
|
||||
| SQLITE_OPEN_CREATE | SQLITE_OPEN_MEMORY;
|
||||
aMode = aOpenMode;
|
||||
limit = mask & flags;
|
||||
zModeType = "access";
|
||||
|
@ -2036,7 +2091,7 @@ int sqlite3ParseUri(
|
|||
rc = SQLITE_ERROR;
|
||||
goto parse_uri_out;
|
||||
}
|
||||
if( mode>limit ){
|
||||
if( (mode & ~SQLITE_OPEN_MEMORY)>limit ){
|
||||
*pzErrMsg = sqlite3_mprintf("%s mode not allowed: %s",
|
||||
zModeType, zVal);
|
||||
rc = SQLITE_PERM;
|
||||
|
@ -2055,6 +2110,7 @@ int sqlite3ParseUri(
|
|||
memcpy(zFile, zUri, nUri);
|
||||
zFile[nUri] = '\0';
|
||||
zFile[nUri+1] = '\0';
|
||||
flags &= ~SQLITE_OPEN_URI;
|
||||
}
|
||||
|
||||
*ppVfs = sqlite3_vfs_find(zVfs);
|
||||
|
|
|
@ -56,7 +56,7 @@ struct sqlite3_mutex {
|
|||
** this out as well.
|
||||
*/
|
||||
#if 0
|
||||
#if SQLITE_OS_WINCE
|
||||
#if SQLITE_OS_WINCE || SQLITE_OS_WINRT
|
||||
# define mutexIsNT() (1)
|
||||
#else
|
||||
static int mutexIsNT(void){
|
||||
|
@ -109,18 +109,24 @@ static int winMutex_isInit = 0;
|
|||
*/
|
||||
static long winMutex_lock = 0;
|
||||
|
||||
extern void sqlite3_win32_sleep(DWORD milliseconds); /* os_win.c */
|
||||
|
||||
static int winMutexInit(void){
|
||||
/* The first to increment to 1 does actual initialization */
|
||||
if( InterlockedCompareExchange(&winMutex_lock, 1, 0)==0 ){
|
||||
int i;
|
||||
for(i=0; i<ArraySize(winMutex_staticMutexes); i++){
|
||||
#if SQLITE_OS_WINRT
|
||||
InitializeCriticalSectionEx(&winMutex_staticMutexes[i].mutex, 0, 0);
|
||||
#else
|
||||
InitializeCriticalSection(&winMutex_staticMutexes[i].mutex);
|
||||
#endif
|
||||
}
|
||||
winMutex_isInit = 1;
|
||||
}else{
|
||||
/* Someone else is in the process of initing the static mutexes */
|
||||
while( !winMutex_isInit ){
|
||||
Sleep(1);
|
||||
sqlite3_win32_sleep(1);
|
||||
}
|
||||
}
|
||||
return SQLITE_OK;
|
||||
|
@ -194,7 +200,11 @@ static sqlite3_mutex *winMutexAlloc(int iType){
|
|||
#ifdef SQLITE_DEBUG
|
||||
p->id = iType;
|
||||
#endif
|
||||
#if SQLITE_OS_WINRT
|
||||
InitializeCriticalSectionEx(&p->mutex, 0, 0);
|
||||
#else
|
||||
InitializeCriticalSection(&p->mutex);
|
||||
#endif
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
|
27
src/os.h
27
src/os.h
|
@ -65,13 +65,11 @@
|
|||
# endif
|
||||
#endif
|
||||
|
||||
/*
|
||||
** Define the maximum size of a temporary filename
|
||||
*/
|
||||
#if SQLITE_OS_WIN
|
||||
# include <windows.h>
|
||||
# define SQLITE_TEMPNAME_SIZE (MAX_PATH+50)
|
||||
#elif SQLITE_OS_OS2
|
||||
#endif
|
||||
|
||||
#if SQLITE_OS_OS2
|
||||
# if (__GNUC__ > 3 || __GNUC__ == 3 && __GNUC_MINOR__ >= 3) && defined(OS2_HIGH_MEMORY)
|
||||
# include <os2safe.h> /* has to be included before os2.h for linking to work */
|
||||
# endif
|
||||
|
@ -84,9 +82,6 @@
|
|||
# define INCL_DOSSEMAPHORES
|
||||
# include <os2.h>
|
||||
# include <uconv.h>
|
||||
# define SQLITE_TEMPNAME_SIZE (CCHMAXPATHCOMP)
|
||||
#else
|
||||
# define SQLITE_TEMPNAME_SIZE 200
|
||||
#endif
|
||||
|
||||
/*
|
||||
|
@ -120,6 +115,22 @@
|
|||
# define SQLITE_OS_WINCE 0
|
||||
#endif
|
||||
|
||||
/*
|
||||
** Determine if we are dealing with WindowsRT (Metro) as this has a different and
|
||||
** incompatible API from win32.
|
||||
*/
|
||||
#if !defined(SQLITE_OS_WINRT)
|
||||
# define SQLITE_OS_WINRT 0
|
||||
#endif
|
||||
|
||||
/*
|
||||
** When compiled for WinCE or WinRT, there is no concept of the current
|
||||
** directory.
|
||||
*/
|
||||
#if !SQLITE_OS_WINCE && !SQLITE_OS_WINRT
|
||||
# define SQLITE_CURDIR 1
|
||||
#endif
|
||||
|
||||
/* If the SET_FULLSYNC macro is not defined above, then make it
|
||||
** a no-op
|
||||
*/
|
||||
|
|
|
@ -227,7 +227,7 @@ struct unixFile {
|
|||
#if OS_VXWORKS
|
||||
struct vxworksFileId *pId; /* Unique file ID */
|
||||
#endif
|
||||
#ifndef NDEBUG
|
||||
#ifdef SQLITE_DEBUG
|
||||
/* The next group of variables are used to track whether or not the
|
||||
** transaction counter in bytes 24-27 of database files are updated
|
||||
** whenever any part of the database changes. An assertion fault will
|
||||
|
@ -262,7 +262,6 @@ struct unixFile {
|
|||
#define UNIXFILE_DELETE 0x20 /* Delete on close */
|
||||
#define UNIXFILE_URI 0x40 /* Filename might have query parameters */
|
||||
#define UNIXFILE_NOLOCK 0x80 /* Do no file locking */
|
||||
#define UNIXFILE_CHOWN 0x100 /* File ownership was changed */
|
||||
|
||||
/*
|
||||
** Include code that is common to all os_*.c files
|
||||
|
@ -308,6 +307,15 @@ static int posixOpen(const char *zFile, int flags, int mode){
|
|||
return open(zFile, flags, mode);
|
||||
}
|
||||
|
||||
/*
|
||||
** On some systems, calls to fchown() will trigger a message in a security
|
||||
** log if they come from non-root processes. So avoid calling fchown() if
|
||||
** we are not running as root.
|
||||
*/
|
||||
static int posixFchown(int fd, uid_t uid, gid_t gid){
|
||||
return geteuid() ? 0 : fchown(fd,uid,gid);
|
||||
}
|
||||
|
||||
/* Forward reference */
|
||||
static int openDirectory(const char*, int*);
|
||||
|
||||
|
@ -419,7 +427,7 @@ static struct unix_syscall {
|
|||
{ "rmdir", (sqlite3_syscall_ptr)rmdir, 0 },
|
||||
#define osRmdir ((int(*)(const char*))aSyscall[19].pCurrent)
|
||||
|
||||
{ "fchown", (sqlite3_syscall_ptr)fchown, 0 },
|
||||
{ "fchown", (sqlite3_syscall_ptr)posixFchown, 0 },
|
||||
#define osFchown ((int(*)(int,uid_t,gid_t))aSyscall[20].pCurrent)
|
||||
|
||||
{ "umask", (sqlite3_syscall_ptr)umask, 0 },
|
||||
|
@ -1563,7 +1571,7 @@ static int unixLock(sqlite3_file *id, int eFileLock){
|
|||
}
|
||||
|
||||
|
||||
#ifndef NDEBUG
|
||||
#ifdef SQLITE_DEBUG
|
||||
/* Set up the transaction-counter change checking flags when
|
||||
** transitioning from a SHARED to a RESERVED lock. The change
|
||||
** from SHARED to RESERVED marks the beginning of a normal
|
||||
|
@ -1642,7 +1650,7 @@ static int posixUnlock(sqlite3_file *id, int eFileLock, int handleNFSUnlock){
|
|||
if( pFile->eFileLock>SHARED_LOCK ){
|
||||
assert( pInode->eFileLock==pFile->eFileLock );
|
||||
|
||||
#ifndef NDEBUG
|
||||
#ifdef SQLITE_DEBUG
|
||||
/* When reducing a lock such that other processes can start
|
||||
** reading the database file again, make sure that the
|
||||
** transaction counter was updated if any part of the database
|
||||
|
@ -2841,7 +2849,7 @@ static int afpUnlock(sqlite3_file *id, int eFileLock) {
|
|||
SimulateIOError( h=(-1) )
|
||||
SimulateIOErrorBenign(0);
|
||||
|
||||
#ifndef NDEBUG
|
||||
#ifdef SQLITE_DEBUG
|
||||
/* When reducing a lock such that other processes can start
|
||||
** reading the database file again, make sure that the
|
||||
** transaction counter was updated if any part of the database
|
||||
|
@ -3145,7 +3153,7 @@ static int unixWrite(
|
|||
);
|
||||
#endif
|
||||
|
||||
#ifndef NDEBUG
|
||||
#ifdef SQLITE_DEBUG
|
||||
/* If we are doing a normal write to a database file (as opposed to
|
||||
** doing a hot-journal rollback or a write to some file other than a
|
||||
** normal database file) then record the fact that the database
|
||||
|
@ -3436,7 +3444,7 @@ static int unixTruncate(sqlite3_file *id, i64 nByte){
|
|||
pFile->lastErrno = errno;
|
||||
return unixLogError(SQLITE_IOERR_TRUNCATE, "ftruncate", pFile->zPath);
|
||||
}else{
|
||||
#ifndef NDEBUG
|
||||
#ifdef SQLITE_DEBUG
|
||||
/* If we are doing a normal write to a database file (as opposed to
|
||||
** doing a hot-journal rollback or a write to some file other than a
|
||||
** normal database file) and we truncate the file to zero length,
|
||||
|
@ -3593,7 +3601,7 @@ static int unixFileControl(sqlite3_file *id, int op, void *pArg){
|
|||
*(char**)pArg = sqlite3_mprintf("%s", pFile->pVfs->zName);
|
||||
return SQLITE_OK;
|
||||
}
|
||||
#ifndef NDEBUG
|
||||
#ifdef SQLITE_DEBUG
|
||||
/* The pager calls this method to signal that it has done
|
||||
** a rollback and that the database is therefore unchanged and
|
||||
** it hence it is OK for the transaction change counter to be
|
||||
|
@ -3944,14 +3952,9 @@ static int unixOpenSharedMemory(unixFile *pDbFd){
|
|||
|
||||
/* If this process is running as root, make sure that the SHM file
|
||||
** is owned by the same user that owns the original database. Otherwise,
|
||||
** the original owner will not be able to connect. If this process is
|
||||
** not root, the following fchown() will fail, but we don't care. The
|
||||
** if(){..} and the UNIXFILE_CHOWN flag are purely to silence compiler
|
||||
** warnings.
|
||||
** the original owner will not be able to connect.
|
||||
*/
|
||||
if( osFchown(pShmNode->h, sStat.st_uid, sStat.st_gid)==0 ){
|
||||
pDbFd->ctrlFlags |= UNIXFILE_CHOWN;
|
||||
}
|
||||
osFchown(pShmNode->h, sStat.st_uid, sStat.st_gid);
|
||||
|
||||
/* Check to see if another process is holding the dead-man switch.
|
||||
** If not, truncate the file to zero length.
|
||||
|
@ -5157,13 +5160,10 @@ static int unixOpen(
|
|||
|
||||
/* If this process is running as root and if creating a new rollback
|
||||
** journal or WAL file, set the ownership of the journal or WAL to be
|
||||
** the same as the original database. If we are not running as root,
|
||||
** then the fchown() call will fail, but that's ok. The "if(){}" and
|
||||
** the setting of the UNIXFILE_CHOWN flag are purely to silence compiler
|
||||
** warnings from gcc.
|
||||
** the same as the original database.
|
||||
*/
|
||||
if( flags & (SQLITE_OPEN_WAL|SQLITE_OPEN_MAIN_JOURNAL) ){
|
||||
if( osFchown(fd, uid, gid)==0 ){ p->ctrlFlags |= UNIXFILE_CHOWN; }
|
||||
osFchown(fd, uid, gid);
|
||||
}
|
||||
}
|
||||
assert( fd>=0 );
|
||||
|
|
1032
src/os_win.c
1032
src/os_win.c
File diff suppressed because it is too large
Load Diff
28
src/pager.c
28
src/pager.c
|
@ -4360,7 +4360,12 @@ int sqlite3PagerOpen(
|
|||
#ifndef SQLITE_OMIT_MEMORYDB
|
||||
if( flags & PAGER_MEMORY ){
|
||||
memDb = 1;
|
||||
zFilename = 0;
|
||||
if( zFilename && zFilename[0] ){
|
||||
zPathname = sqlite3DbStrDup(0, zFilename);
|
||||
if( zPathname==0 ) return SQLITE_NOMEM;
|
||||
nPathname = sqlite3Strlen30(zPathname);
|
||||
zFilename = 0;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
|
@ -4371,7 +4376,7 @@ int sqlite3PagerOpen(
|
|||
if( zFilename && zFilename[0] ){
|
||||
const char *z;
|
||||
nPathname = pVfs->mxPathname+1;
|
||||
zPathname = sqlite3Malloc(nPathname*2);
|
||||
zPathname = sqlite3DbMallocRaw(0, nPathname*2);
|
||||
if( zPathname==0 ){
|
||||
return SQLITE_NOMEM;
|
||||
}
|
||||
|
@ -4395,7 +4400,7 @@ int sqlite3PagerOpen(
|
|||
rc = SQLITE_CANTOPEN_BKPT;
|
||||
}
|
||||
if( rc!=SQLITE_OK ){
|
||||
sqlite3_free(zPathname);
|
||||
sqlite3DbFree(0, zPathname);
|
||||
return rc;
|
||||
}
|
||||
}
|
||||
|
@ -4425,7 +4430,7 @@ int sqlite3PagerOpen(
|
|||
);
|
||||
assert( EIGHT_BYTE_ALIGNMENT(SQLITE_INT_TO_PTR(journalFileSize)) );
|
||||
if( !pPtr ){
|
||||
sqlite3_free(zPathname);
|
||||
sqlite3DbFree(0, zPathname);
|
||||
return SQLITE_NOMEM;
|
||||
}
|
||||
pPager = (Pager*)(pPtr);
|
||||
|
@ -4441,7 +4446,7 @@ int sqlite3PagerOpen(
|
|||
assert( nPathname>0 );
|
||||
pPager->zJournal = (char*)(pPtr += nPathname + 1 + nUri);
|
||||
memcpy(pPager->zFilename, zPathname, nPathname);
|
||||
memcpy(&pPager->zFilename[nPathname+1], zUri, nUri);
|
||||
if( nUri ) memcpy(&pPager->zFilename[nPathname+1], zUri, nUri);
|
||||
memcpy(pPager->zJournal, zPathname, nPathname);
|
||||
memcpy(&pPager->zJournal[nPathname], "-journal\000", 8+1);
|
||||
sqlite3FileSuffix3(pPager->zFilename, pPager->zJournal);
|
||||
|
@ -4451,7 +4456,7 @@ int sqlite3PagerOpen(
|
|||
memcpy(&pPager->zWal[nPathname], "-wal\000", 4+1);
|
||||
sqlite3FileSuffix3(pPager->zFilename, pPager->zWal);
|
||||
#endif
|
||||
sqlite3_free(zPathname);
|
||||
sqlite3DbFree(0, zPathname);
|
||||
}
|
||||
pPager->pVfs = pVfs;
|
||||
pPager->vfsFlags = vfsFlags;
|
||||
|
@ -6296,9 +6301,16 @@ int sqlite3PagerSavepoint(Pager *pPager, int op, int iSavepoint){
|
|||
|
||||
/*
|
||||
** Return the full pathname of the database file.
|
||||
**
|
||||
** Except, if the pager is in-memory only, then return an empty string if
|
||||
** nullIfMemDb is true. This routine is called with nullIfMemDb==1 when
|
||||
** used to report the filename to the user, for compatibility with legacy
|
||||
** behavior. But when the Btree needs to know the filename for matching to
|
||||
** shared cache, it uses nullIfMemDb==0 so that in-memory databases can
|
||||
** participate in shared-cache.
|
||||
*/
|
||||
const char *sqlite3PagerFilename(Pager *pPager){
|
||||
return pPager->zFilename;
|
||||
const char *sqlite3PagerFilename(Pager *pPager, int nullIfMemDb){
|
||||
return (nullIfMemDb && pPager->memDb) ? "" : pPager->zFilename;
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
|
@ -151,7 +151,7 @@ int sqlite3PagerCloseWal(Pager *pPager);
|
|||
u8 sqlite3PagerIsreadonly(Pager*);
|
||||
int sqlite3PagerRefcount(Pager*);
|
||||
int sqlite3PagerMemUsed(Pager*);
|
||||
const char *sqlite3PagerFilename(Pager*);
|
||||
const char *sqlite3PagerFilename(Pager*, int);
|
||||
const sqlite3_vfs *sqlite3PagerVfs(Pager*);
|
||||
sqlite3_file *sqlite3PagerFile(Pager*);
|
||||
const char *sqlite3PagerJournalname(Pager*);
|
||||
|
|
|
@ -212,12 +212,14 @@ static void *pcache1Alloc(int nByte){
|
|||
** it from sqlite3Malloc instead.
|
||||
*/
|
||||
p = sqlite3Malloc(nByte);
|
||||
#ifndef SQLITE_DISABLE_PAGECACHE_OVERFLOW_STATS
|
||||
if( p ){
|
||||
int sz = sqlite3MallocSize(p);
|
||||
sqlite3_mutex_enter(pcache1.mutex);
|
||||
sqlite3StatusAdd(SQLITE_STATUS_PAGECACHE_OVERFLOW, sz);
|
||||
sqlite3_mutex_leave(pcache1.mutex);
|
||||
}
|
||||
#endif
|
||||
sqlite3MemdebugSetType(p, MEMTYPE_PCACHE);
|
||||
}
|
||||
return p;
|
||||
|
@ -244,9 +246,11 @@ static int pcache1Free(void *p){
|
|||
assert( sqlite3MemdebugHasType(p, MEMTYPE_PCACHE) );
|
||||
sqlite3MemdebugSetType(p, MEMTYPE_HEAP);
|
||||
nFreed = sqlite3MallocSize(p);
|
||||
#ifndef SQLITE_DISABLE_PAGECACHE_OVERFLOW_STATS
|
||||
sqlite3_mutex_enter(pcache1.mutex);
|
||||
sqlite3StatusAdd(SQLITE_STATUS_PAGECACHE_OVERFLOW, -nFreed);
|
||||
sqlite3_mutex_leave(pcache1.mutex);
|
||||
#endif
|
||||
sqlite3_free(p);
|
||||
}
|
||||
return nFreed;
|
||||
|
|
46
src/pragma.c
46
src/pragma.c
|
@ -118,7 +118,7 @@ static int invalidateTempStorage(Parse *pParse){
|
|||
}
|
||||
sqlite3BtreeClose(db->aDb[1].pBt);
|
||||
db->aDb[1].pBt = 0;
|
||||
sqlite3ResetInternalSchema(db, -1);
|
||||
sqlite3ResetAllSchemasOfConnection(db);
|
||||
}
|
||||
return SQLITE_OK;
|
||||
}
|
||||
|
@ -804,6 +804,50 @@ void sqlite3Pragma(
|
|||
}
|
||||
}else
|
||||
|
||||
#if SQLITE_OS_WIN
|
||||
/*
|
||||
** PRAGMA data_store_directory
|
||||
** PRAGMA data_store_directory = ""|"directory_name"
|
||||
**
|
||||
** Return or set the local value of the data_store_directory flag. Changing
|
||||
** the value sets a specific directory to be used for database files that
|
||||
** were specified with a relative pathname. Setting to a null string reverts
|
||||
** to the default database directory, which for database files specified with
|
||||
** a relative path will probably be based on the current directory for the
|
||||
** process. Database file specified with an absolute path are not impacted
|
||||
** by this setting, regardless of its value.
|
||||
**
|
||||
*/
|
||||
if( sqlite3StrICmp(zLeft, "data_store_directory")==0 ){
|
||||
if( !zRight ){
|
||||
if( sqlite3_data_directory ){
|
||||
sqlite3VdbeSetNumCols(v, 1);
|
||||
sqlite3VdbeSetColName(v, 0, COLNAME_NAME,
|
||||
"data_store_directory", SQLITE_STATIC);
|
||||
sqlite3VdbeAddOp4(v, OP_String8, 0, 1, 0, sqlite3_data_directory, 0);
|
||||
sqlite3VdbeAddOp2(v, OP_ResultRow, 1, 1);
|
||||
}
|
||||
}else{
|
||||
#ifndef SQLITE_OMIT_WSD
|
||||
if( zRight[0] ){
|
||||
int res;
|
||||
rc = sqlite3OsAccess(db->pVfs, zRight, SQLITE_ACCESS_READWRITE, &res);
|
||||
if( rc!=SQLITE_OK || res==0 ){
|
||||
sqlite3ErrorMsg(pParse, "not a writable directory");
|
||||
goto pragma_out;
|
||||
}
|
||||
}
|
||||
sqlite3_free(sqlite3_data_directory);
|
||||
if( zRight[0] ){
|
||||
sqlite3_data_directory = sqlite3_mprintf("%s", zRight);
|
||||
}else{
|
||||
sqlite3_data_directory = 0;
|
||||
}
|
||||
#endif /* SQLITE_OMIT_WSD */
|
||||
}
|
||||
}else
|
||||
#endif
|
||||
|
||||
#if !defined(SQLITE_ENABLE_LOCKING_STYLE)
|
||||
# if defined(__APPLE__)
|
||||
# define SQLITE_ENABLE_LOCKING_STYLE 1
|
||||
|
|
|
@ -262,7 +262,6 @@ static int sqlite3InitOne(sqlite3 *db, int iDb, char **pzErrMsg){
|
|||
encoding = (u8)meta[BTREE_TEXT_ENCODING-1] & 3;
|
||||
if( encoding==0 ) encoding = SQLITE_UTF8;
|
||||
ENC(db) = encoding;
|
||||
db->pDfltColl = sqlite3FindCollSeq(db, SQLITE_UTF8, "BINARY", 0);
|
||||
}else{
|
||||
/* If opening an attached database, the encoding much match ENC(db) */
|
||||
if( meta[BTREE_TEXT_ENCODING-1]!=ENC(db) ){
|
||||
|
@ -342,7 +341,7 @@ static int sqlite3InitOne(sqlite3 *db, int iDb, char **pzErrMsg){
|
|||
}
|
||||
if( db->mallocFailed ){
|
||||
rc = SQLITE_NOMEM;
|
||||
sqlite3ResetInternalSchema(db, -1);
|
||||
sqlite3ResetAllSchemasOfConnection(db);
|
||||
}
|
||||
if( rc==SQLITE_OK || (db->flags&SQLITE_RecoveryMode)){
|
||||
/* Black magic: If the SQLITE_RecoveryMode flag is set, then consider
|
||||
|
@ -395,7 +394,7 @@ int sqlite3Init(sqlite3 *db, char **pzErrMsg){
|
|||
if( DbHasProperty(db, i, DB_SchemaLoaded) || i==1 ) continue;
|
||||
rc = sqlite3InitOne(db, i, pzErrMsg);
|
||||
if( rc ){
|
||||
sqlite3ResetInternalSchema(db, i);
|
||||
sqlite3ResetOneSchema(db, i);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -408,7 +407,7 @@ int sqlite3Init(sqlite3 *db, char **pzErrMsg){
|
|||
&& !DbHasProperty(db, 1, DB_SchemaLoaded) ){
|
||||
rc = sqlite3InitOne(db, 1, pzErrMsg);
|
||||
if( rc ){
|
||||
sqlite3ResetInternalSchema(db, 1);
|
||||
sqlite3ResetOneSchema(db, 1);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
@ -476,7 +475,7 @@ static void schemaIsValid(Parse *pParse){
|
|||
sqlite3BtreeGetMeta(pBt, BTREE_SCHEMA_VERSION, (u32 *)&cookie);
|
||||
assert( sqlite3SchemaMutexHeld(db, iDb, 0) );
|
||||
if( cookie!=db->aDb[iDb].pSchema->schema_cookie ){
|
||||
sqlite3ResetInternalSchema(db, iDb);
|
||||
sqlite3ResetOneSchema(db, iDb);
|
||||
pParse->rc = SQLITE_SCHEMA;
|
||||
}
|
||||
|
||||
|
|
|
@ -473,6 +473,7 @@ int sqlite3_exec(
|
|||
#define SQLITE_OPEN_EXCLUSIVE 0x00000010 /* VFS only */
|
||||
#define SQLITE_OPEN_AUTOPROXY 0x00000020 /* VFS only */
|
||||
#define SQLITE_OPEN_URI 0x00000040 /* Ok for sqlite3_open_v2() */
|
||||
#define SQLITE_OPEN_MEMORY 0x00000080 /* Ok for sqlite3_open_v2() */
|
||||
#define SQLITE_OPEN_MAIN_DB 0x00000100 /* VFS only */
|
||||
#define SQLITE_OPEN_TEMP_DB 0x00000200 /* VFS only */
|
||||
#define SQLITE_OPEN_TRANSIENT_DB 0x00000400 /* VFS only */
|
||||
|
@ -2164,12 +2165,12 @@ char *sqlite3_vsnprintf(int,char*,const char*, va_list);
|
|||
** implementation of these routines to be omitted. That capability
|
||||
** is no longer provided. Only built-in memory allocators can be used.
|
||||
**
|
||||
** The Windows OS interface layer calls
|
||||
** Prior to SQLite version 3.7.10, the Windows OS interface layer called
|
||||
** the system malloc() and free() directly when converting
|
||||
** filenames between the UTF-8 encoding used by SQLite
|
||||
** and whatever filename encoding is used by the particular Windows
|
||||
** installation. Memory allocation errors are detected, but
|
||||
** they are reported back as [SQLITE_CANTOPEN] or
|
||||
** installation. Memory allocation errors were detected, but
|
||||
** they were reported back as [SQLITE_CANTOPEN] or
|
||||
** [SQLITE_IOERR] rather than [SQLITE_NOMEM].
|
||||
**
|
||||
** The pointer arguments to [sqlite3_free()] and [sqlite3_realloc()]
|
||||
|
@ -2570,18 +2571,20 @@ void sqlite3_progress_handler(sqlite3*, int, int(*)(void*), void*);
|
|||
** present, then the VFS specified by the option takes precedence over
|
||||
** the value passed as the fourth parameter to sqlite3_open_v2().
|
||||
**
|
||||
** <li> <b>mode</b>: ^(The mode parameter may be set to either "ro", "rw" or
|
||||
** "rwc". Attempting to set it to any other value is an error)^.
|
||||
** <li> <b>mode</b>: ^(The mode parameter may be set to either "ro", "rw",
|
||||
** "rwc", or "memory". Attempting to set it to any other value is
|
||||
** an error)^.
|
||||
** ^If "ro" is specified, then the database is opened for read-only
|
||||
** access, just as if the [SQLITE_OPEN_READONLY] flag had been set in the
|
||||
** third argument to sqlite3_prepare_v2(). ^If the mode option is set to
|
||||
** "rw", then the database is opened for read-write (but not create)
|
||||
** access, as if SQLITE_OPEN_READWRITE (but not SQLITE_OPEN_CREATE) had
|
||||
** been set. ^Value "rwc" is equivalent to setting both
|
||||
** SQLITE_OPEN_READWRITE and SQLITE_OPEN_CREATE. ^If sqlite3_open_v2() is
|
||||
** used, it is an error to specify a value for the mode parameter that is
|
||||
** less restrictive than that specified by the flags passed as the third
|
||||
** parameter.
|
||||
** SQLITE_OPEN_READWRITE and SQLITE_OPEN_CREATE. ^If the mode option is
|
||||
** set to "memory" then a pure [in-memory database] that never reads
|
||||
** or writes from disk is used. ^It is an error to specify a value for
|
||||
** the mode parameter that is less restrictive than that specified by
|
||||
** the flags passed in the third parameter to sqlite3_open_v2().
|
||||
**
|
||||
** <li> <b>cache</b>: ^The cache parameter may be set to either "shared" or
|
||||
** "private". ^Setting it to "shared" is equivalent to setting the
|
||||
|
@ -4444,6 +4447,43 @@ int sqlite3_sleep(int);
|
|||
*/
|
||||
SQLITE_EXTERN char *sqlite3_temp_directory;
|
||||
|
||||
/*
|
||||
** CAPI3REF: Name Of The Folder Holding Database Files
|
||||
**
|
||||
** ^(If this global variable is made to point to a string which is
|
||||
** the name of a folder (a.k.a. directory), then all database files
|
||||
** specified with a relative pathname and created or accessed by
|
||||
** SQLite when using a built-in windows [sqlite3_vfs | VFS] will be assumed
|
||||
** to be relative to that directory.)^ ^If this variable is a NULL
|
||||
** pointer, then SQLite assumes that all database files specified
|
||||
** with a relative pathname are relative to the current directory
|
||||
** for the process. Only the windows VFS makes use of this global
|
||||
** variable; it is ignored by the unix VFS.
|
||||
**
|
||||
** Changing the value of this variable while a database connection is
|
||||
** open can result in a corrupt database.
|
||||
**
|
||||
** It is not safe to read or modify this variable in more than one
|
||||
** thread at a time. It is not safe to read or modify this variable
|
||||
** if a [database connection] is being used at the same time in a separate
|
||||
** thread.
|
||||
** It is intended that this variable be set once
|
||||
** as part of process initialization and before any SQLite interface
|
||||
** routines have been called and that this variable remain unchanged
|
||||
** thereafter.
|
||||
**
|
||||
** ^The [data_store_directory pragma] may modify this variable and cause
|
||||
** it to point to memory obtained from [sqlite3_malloc]. ^Furthermore,
|
||||
** the [data_store_directory pragma] always assumes that any string
|
||||
** that this variable points to is held in memory obtained from
|
||||
** [sqlite3_malloc] and the pragma may attempt to free that memory
|
||||
** using [sqlite3_free].
|
||||
** Hence, if this variable is modified directly, either it should be
|
||||
** made NULL or made to point to memory obtained from [sqlite3_malloc]
|
||||
** or else the use of the [data_store_directory pragma] should be avoided.
|
||||
*/
|
||||
SQLITE_EXTERN char *sqlite3_data_directory;
|
||||
|
||||
/*
|
||||
** CAPI3REF: Test For Auto-Commit Mode
|
||||
** KEYWORDS: {autocommit mode}
|
||||
|
@ -4622,7 +4662,6 @@ void *sqlite3_update_hook(
|
|||
|
||||
/*
|
||||
** CAPI3REF: Enable Or Disable Shared Pager Cache
|
||||
** KEYWORDS: {shared cache}
|
||||
**
|
||||
** ^(This routine enables or disables the sharing of the database cache
|
||||
** and schema data structures between [database connection | connections]
|
||||
|
|
|
@ -203,15 +203,22 @@
|
|||
#endif
|
||||
|
||||
/*
|
||||
** Many people are failing to set -DNDEBUG=1 when compiling SQLite.
|
||||
** Setting NDEBUG makes the code smaller and run faster. So the following
|
||||
** lines are added to automatically set NDEBUG unless the -DSQLITE_DEBUG=1
|
||||
** option is set. Thus NDEBUG becomes an opt-in rather than an opt-out
|
||||
** NDEBUG and SQLITE_DEBUG are opposites. It should always be true that
|
||||
** defined(NDEBUG)==!defined(SQLITE_DEBUG). If this is not currently true,
|
||||
** make it true by defining or undefining NDEBUG.
|
||||
**
|
||||
** Setting NDEBUG makes the code smaller and run faster by disabling the
|
||||
** number assert() statements in the code. So we want the default action
|
||||
** to be for NDEBUG to be set and NDEBUG to be undefined only if SQLITE_DEBUG
|
||||
** is set. Thus NDEBUG becomes an opt-in rather than an opt-out
|
||||
** feature.
|
||||
*/
|
||||
#if !defined(NDEBUG) && !defined(SQLITE_DEBUG)
|
||||
# define NDEBUG 1
|
||||
#endif
|
||||
#if defined(NDEBUG) && defined(SQLITE_DEBUG)
|
||||
# undef NDEBUG
|
||||
#endif
|
||||
|
||||
/*
|
||||
** The testcase() macro is used to aid in coverage testing. When
|
||||
|
@ -2702,7 +2709,9 @@ void sqlite3ExprListDelete(sqlite3*, ExprList*);
|
|||
int sqlite3Init(sqlite3*, char**);
|
||||
int sqlite3InitCallback(void*, int, char**, char**);
|
||||
void sqlite3Pragma(Parse*,Token*,Token*,Token*,int);
|
||||
void sqlite3ResetInternalSchema(sqlite3*, int);
|
||||
void sqlite3ResetAllSchemasOfConnection(sqlite3*);
|
||||
void sqlite3ResetOneSchema(sqlite3*,int);
|
||||
void sqlite3CollapseDatabaseArray(sqlite3*);
|
||||
void sqlite3BeginParse(Parse*,int);
|
||||
void sqlite3CommitInternalChanges(sqlite3*);
|
||||
Table *sqlite3ResultSetOfSelect(Parse*,Select*);
|
||||
|
@ -3107,6 +3116,7 @@ void sqlite3AutoLoadExtensions(sqlite3*);
|
|||
# define sqlite3GetVTable(X,Y) ((VTable*)0)
|
||||
#else
|
||||
void sqlite3VtabClear(sqlite3 *db, Table*);
|
||||
void sqlite3VtabDisconnect(sqlite3 *db, Table *p);
|
||||
int sqlite3VtabSync(sqlite3 *db, char **);
|
||||
int sqlite3VtabRollback(sqlite3 *db);
|
||||
int sqlite3VtabCommit(sqlite3 *db);
|
||||
|
|
|
@ -6287,6 +6287,8 @@ int Sqlitetest1_Init(Tcl_Interp *interp){
|
|||
(char*)&sqlite_static_bind_nbyte, TCL_LINK_INT);
|
||||
Tcl_LinkVar(interp, "sqlite_temp_directory",
|
||||
(char*)&sqlite3_temp_directory, TCL_LINK_STRING);
|
||||
Tcl_LinkVar(interp, "sqlite_data_directory",
|
||||
(char*)&sqlite3_data_directory, TCL_LINK_STRING);
|
||||
Tcl_LinkVar(interp, "bitmask_size",
|
||||
(char*)&bitmask_size, TCL_LINK_INT|TCL_LINK_READ_ONLY);
|
||||
Tcl_LinkVar(interp, "sqlite_sync_count",
|
||||
|
|
20
src/test8.c
20
src/test8.c
|
@ -1300,6 +1300,7 @@ static sqlite3_module echoModuleV2 = {
|
|||
** Decode a pointer to an sqlite3 object.
|
||||
*/
|
||||
extern int getDbPointer(Tcl_Interp *interp, const char *zA, sqlite3 **ppDb);
|
||||
extern const char *sqlite3TestErrorName(int rc);
|
||||
|
||||
static void moduleDestroy(void *p){
|
||||
sqlite3_free(p);
|
||||
|
@ -1314,6 +1315,7 @@ static int register_echo_module(
|
|||
int objc, /* Number of arguments */
|
||||
Tcl_Obj *CONST objv[] /* Command arguments */
|
||||
){
|
||||
int rc;
|
||||
sqlite3 *db;
|
||||
EchoModule *pMod;
|
||||
if( objc!=2 ){
|
||||
|
@ -1325,14 +1327,20 @@ static int register_echo_module(
|
|||
/* Virtual table module "echo" */
|
||||
pMod = sqlite3_malloc(sizeof(EchoModule));
|
||||
pMod->interp = interp;
|
||||
sqlite3_create_module_v2(db, "echo", &echoModule, (void*)pMod, moduleDestroy);
|
||||
rc = sqlite3_create_module_v2(
|
||||
db, "echo", &echoModule, (void*)pMod, moduleDestroy
|
||||
);
|
||||
|
||||
/* Virtual table module "echo_v2" */
|
||||
pMod = sqlite3_malloc(sizeof(EchoModule));
|
||||
pMod->interp = interp;
|
||||
sqlite3_create_module_v2(db, "echo_v2",
|
||||
&echoModuleV2, (void*)pMod, moduleDestroy
|
||||
);
|
||||
if( rc==SQLITE_OK ){
|
||||
pMod = sqlite3_malloc(sizeof(EchoModule));
|
||||
pMod->interp = interp;
|
||||
rc = sqlite3_create_module_v2(db, "echo_v2",
|
||||
&echoModuleV2, (void*)pMod, moduleDestroy
|
||||
);
|
||||
}
|
||||
|
||||
Tcl_SetResult(interp, (char *)sqlite3TestErrorName(rc), TCL_STATIC);
|
||||
return TCL_OK;
|
||||
}
|
||||
|
||||
|
|
|
@ -33,7 +33,7 @@ int sqlite3BtreeSharedCacheReport(
|
|||
BtShared *pBt;
|
||||
Tcl_Obj *pRet = Tcl_NewObj();
|
||||
for(pBt=GLOBAL(BtShared*,sqlite3SharedCacheList); pBt; pBt=pBt->pNext){
|
||||
const char *zFile = sqlite3PagerFilename(pBt->pPager);
|
||||
const char *zFile = sqlite3PagerFilename(pBt->pPager, 1);
|
||||
Tcl_ListObjAppendElement(interp, pRet, Tcl_NewStringObj(zFile, -1));
|
||||
Tcl_ListObjAppendElement(interp, pRet, Tcl_NewIntObj(pBt->nRef));
|
||||
}
|
||||
|
|
|
@ -57,6 +57,12 @@ static void set_options(Tcl_Interp *interp){
|
|||
Tcl_SetVar2(interp, "sqlite_options","casesensitivelike","0",TCL_GLOBAL_ONLY);
|
||||
#endif
|
||||
|
||||
#ifdef SQLITE_CURDIR
|
||||
Tcl_SetVar2(interp, "sqlite_options", "curdir", "1", TCL_GLOBAL_ONLY);
|
||||
#else
|
||||
Tcl_SetVar2(interp, "sqlite_options", "curdir", "0", TCL_GLOBAL_ONLY);
|
||||
#endif
|
||||
|
||||
#ifdef SQLITE_DEBUG
|
||||
Tcl_SetVar2(interp, "sqlite_options", "debug", "1", TCL_GLOBAL_ONLY);
|
||||
#else
|
||||
|
@ -307,6 +313,12 @@ static void set_options(Tcl_Interp *interp){
|
|||
Tcl_SetVar2(interp, "sqlite_options", "fts3", "0", TCL_GLOBAL_ONLY);
|
||||
#endif
|
||||
|
||||
#if defined(SQLITE_ENABLE_FTS3) && defined(SQLITE_ENABLE_FTS4_UNICODE61)
|
||||
Tcl_SetVar2(interp, "sqlite_options", "fts3_unicode", "1", TCL_GLOBAL_ONLY);
|
||||
#else
|
||||
Tcl_SetVar2(interp, "sqlite_options", "fts3_unicode", "0", TCL_GLOBAL_ONLY);
|
||||
#endif
|
||||
|
||||
#ifdef SQLITE_OMIT_GET_TABLE
|
||||
Tcl_SetVar2(interp, "sqlite_options", "gettable", "0", TCL_GLOBAL_ONLY);
|
||||
#else
|
||||
|
|
|
@ -1042,7 +1042,7 @@ size_t sqlite3_quota_fread(
|
|||
** the write if we exceed quota.
|
||||
*/
|
||||
size_t sqlite3_quota_fwrite(
|
||||
void *pBuf, /* Take content to write from here */
|
||||
const void *pBuf, /* Take content to write from here */
|
||||
size_t size, /* Size of each element */
|
||||
size_t nmemb, /* Number of elements */
|
||||
quota_FILE *p /* Write to this quota_FILE objecct */
|
||||
|
@ -1052,7 +1052,7 @@ size_t sqlite3_quota_fwrite(
|
|||
sqlite3_int64 szNew;
|
||||
quotaFile *pFile;
|
||||
size_t rc;
|
||||
|
||||
|
||||
iOfst = ftell(p->f);
|
||||
iEnd = iOfst + size*nmemb;
|
||||
pFile = p->pFile;
|
||||
|
@ -1091,7 +1091,7 @@ size_t sqlite3_quota_fwrite(
|
|||
pFile->iSize = iNewEnd;
|
||||
quotaLeave();
|
||||
}
|
||||
return rc;
|
||||
return rc;
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -1160,6 +1160,13 @@ long sqlite3_quota_ftell(quota_FILE *p){
|
|||
return ftell(p->f);
|
||||
}
|
||||
|
||||
/*
|
||||
** Test the error indicator for the given file.
|
||||
*/
|
||||
int sqlite3_quota_ferror(quota_FILE *p){
|
||||
return ferror(p->f);
|
||||
}
|
||||
|
||||
/*
|
||||
** Truncate a file to szNew bytes.
|
||||
*/
|
||||
|
@ -1236,6 +1243,25 @@ sqlite3_int64 sqlite3_quota_file_truesize(quota_FILE *p){
|
|||
sqlite3_int64 sqlite3_quota_file_size(quota_FILE *p){
|
||||
return p->pFile ? p->pFile->iSize : -1;
|
||||
}
|
||||
|
||||
/*
|
||||
** Determine the amount of data in bytes available for reading
|
||||
** in the given file.
|
||||
*/
|
||||
long sqlite3_quota_file_available(quota_FILE *p){
|
||||
FILE* f = p->f;
|
||||
long pos1, pos2;
|
||||
int rc;
|
||||
pos1 = ftell(f);
|
||||
if ( pos1 < 0 ) return -1;
|
||||
rc = fseek(f, 0, SEEK_END);
|
||||
if ( rc != 0 ) return -1;
|
||||
pos2 = ftell(f);
|
||||
if ( pos2 < 0 ) return -1;
|
||||
rc = fseek(f, pos1, SEEK_SET);
|
||||
if ( rc != 0 ) return -1;
|
||||
return pos2 - pos1;
|
||||
}
|
||||
|
||||
/*
|
||||
** Remove a managed file. Update quotas accordingly.
|
||||
|
@ -1895,6 +1921,53 @@ static int test_quota_glob(
|
|||
return TCL_OK;
|
||||
}
|
||||
|
||||
/*
|
||||
** tclcmd: sqlite3_quota_file_available HANDLE
|
||||
**
|
||||
** Return the number of bytes from the current file point to the end of
|
||||
** the file.
|
||||
*/
|
||||
static int test_quota_file_available(
|
||||
void * clientData,
|
||||
Tcl_Interp *interp,
|
||||
int objc,
|
||||
Tcl_Obj *CONST objv[]
|
||||
){
|
||||
quota_FILE *p;
|
||||
sqlite3_int64 x;
|
||||
if( objc!=2 ){
|
||||
Tcl_WrongNumArgs(interp, 1, objv, "HANDLE");
|
||||
return TCL_ERROR;
|
||||
}
|
||||
p = sqlite3TestTextToPtr(Tcl_GetString(objv[1]));
|
||||
x = sqlite3_quota_file_available(p);
|
||||
Tcl_SetObjResult(interp, Tcl_NewWideIntObj(x));
|
||||
return TCL_OK;
|
||||
}
|
||||
|
||||
/*
|
||||
** tclcmd: sqlite3_quota_ferror HANDLE
|
||||
**
|
||||
** Return true if the file handle is in the error state.
|
||||
*/
|
||||
static int test_quota_ferror(
|
||||
void * clientData,
|
||||
Tcl_Interp *interp,
|
||||
int objc,
|
||||
Tcl_Obj *CONST objv[]
|
||||
){
|
||||
quota_FILE *p;
|
||||
int x;
|
||||
if( objc!=2 ){
|
||||
Tcl_WrongNumArgs(interp, 1, objv, "HANDLE");
|
||||
return TCL_ERROR;
|
||||
}
|
||||
p = sqlite3TestTextToPtr(Tcl_GetString(objv[1]));
|
||||
x = sqlite3_quota_ferror(p);
|
||||
Tcl_SetObjResult(interp, Tcl_NewIntObj(x));
|
||||
return TCL_OK;
|
||||
}
|
||||
|
||||
/*
|
||||
** This routine registers the custom TCL commands defined in this
|
||||
** module. This should be the only procedure visible from outside
|
||||
|
@ -1924,6 +1997,8 @@ int Sqlitequota_Init(Tcl_Interp *interp){
|
|||
{ "sqlite3_quota_file_mtime", test_quota_file_mtime },
|
||||
{ "sqlite3_quota_remove", test_quota_remove },
|
||||
{ "sqlite3_quota_glob", test_quota_glob },
|
||||
{ "sqlite3_quota_file_available",test_quota_file_available },
|
||||
{ "sqlite3_quota_ferror", test_quota_ferror },
|
||||
};
|
||||
int i;
|
||||
|
||||
|
|
|
@ -162,7 +162,7 @@ quota_FILE *sqlite3_quota_fopen(const char *zFilename, const char *zMode);
|
|||
** the sum of sizes of all files from going over quota.
|
||||
*/
|
||||
size_t sqlite3_quota_fread(void*, size_t, size_t, quota_FILE*);
|
||||
size_t sqlite3_quota_fwrite(void*, size_t, size_t, quota_FILE*);
|
||||
size_t sqlite3_quota_fwrite(const void*, size_t, size_t, quota_FILE*);
|
||||
|
||||
/*
|
||||
** Flush all written content held in memory buffers out to disk.
|
||||
|
@ -190,6 +190,13 @@ int sqlite3_quota_fseek(quota_FILE*, long, int);
|
|||
void sqlite3_quota_rewind(quota_FILE*);
|
||||
long sqlite3_quota_ftell(quota_FILE*);
|
||||
|
||||
/*
|
||||
** Test the error indicator for the given file.
|
||||
**
|
||||
** Return non-zero if the error indicator is set.
|
||||
*/
|
||||
int sqlite3_quota_ferror(quota_FILE*);
|
||||
|
||||
/*
|
||||
** Truncate a file previously opened by sqlite3_quota_fopen(). Return
|
||||
** zero on success and non-zero on any kind of failure.
|
||||
|
@ -198,7 +205,7 @@ long sqlite3_quota_ftell(quota_FILE*);
|
|||
** Any attempt to "truncate" a file to a larger size results in
|
||||
** undefined behavior.
|
||||
*/
|
||||
int sqlite3_quota_ftrunate(quota_FILE*, sqlite3_int64 newSize);
|
||||
int sqlite3_quota_ftruncate(quota_FILE*, sqlite3_int64 newSize);
|
||||
|
||||
/*
|
||||
** Return the last modification time of the opened file, in seconds
|
||||
|
@ -232,6 +239,14 @@ sqlite3_int64 sqlite3_quota_file_size(quota_FILE*);
|
|||
*/
|
||||
sqlite3_int64 sqlite3_quota_file_truesize(quota_FILE*);
|
||||
|
||||
/*
|
||||
** Determine the amount of data in bytes available for reading
|
||||
** in the given file.
|
||||
**
|
||||
** Return -1 if the amount cannot be determined for some reason.
|
||||
*/
|
||||
long sqlite3_quota_file_available(quota_FILE*);
|
||||
|
||||
/*
|
||||
** Delete a file from the disk, if that file is under quota management.
|
||||
** Adjust quotas accordingly.
|
||||
|
|
|
@ -339,7 +339,7 @@ end_of_vacuum:
|
|||
|
||||
/* This both clears the schemas and reduces the size of the db->aDb[]
|
||||
** array. */
|
||||
sqlite3ResetInternalSchema(db, -1);
|
||||
sqlite3ResetAllSchemasOfConnection(db);
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
|
11
src/vdbe.c
11
src/vdbe.c
|
@ -2747,7 +2747,7 @@ case OP_Savepoint: {
|
|||
}
|
||||
if( p1==SAVEPOINT_ROLLBACK && (db->flags&SQLITE_InternChanges)!=0 ){
|
||||
sqlite3ExpirePreparedStatements(db);
|
||||
sqlite3ResetInternalSchema(db, -1);
|
||||
sqlite3ResetAllSchemasOfConnection(db);
|
||||
db->flags = (db->flags | SQLITE_InternChanges);
|
||||
}
|
||||
}
|
||||
|
@ -3051,7 +3051,7 @@ case OP_VerifyCookie: {
|
|||
** a v-table method.
|
||||
*/
|
||||
if( db->aDb[pOp->p1].pSchema->schema_cookie!=iMeta ){
|
||||
sqlite3ResetInternalSchema(db, pOp->p1);
|
||||
sqlite3ResetOneSchema(db, pOp->p1);
|
||||
}
|
||||
|
||||
p->expired = 1;
|
||||
|
@ -4214,7 +4214,6 @@ case OP_RowData: {
|
|||
assert( pC!=0 );
|
||||
assert( pC->nullRow==0 );
|
||||
assert( pC->pseudoTableReg==0 );
|
||||
assert( !pC->isSorter );
|
||||
assert( pC->pCursor!=0 );
|
||||
pCrsr = pC->pCursor;
|
||||
assert( sqlite3BtreeCursorIsValid(pCrsr) );
|
||||
|
@ -4864,7 +4863,7 @@ case OP_ParseSchema: {
|
|||
db->init.busy = 0;
|
||||
}
|
||||
}
|
||||
if( rc ) sqlite3ResetInternalSchema(db, -1);
|
||||
if( rc ) sqlite3ResetAllSchemasOfConnection(db);
|
||||
if( rc==SQLITE_NOMEM ){
|
||||
goto no_mem;
|
||||
}
|
||||
|
@ -5511,7 +5510,7 @@ case OP_JournalMode: { /* out2-prerelease */
|
|||
if( !sqlite3PagerOkToChangeJournalMode(pPager) ) eNew = eOld;
|
||||
|
||||
#ifndef SQLITE_OMIT_WAL
|
||||
zFilename = sqlite3PagerFilename(pPager);
|
||||
zFilename = sqlite3PagerFilename(pPager, 1);
|
||||
|
||||
/* Do not allow a transition to journal_mode=WAL for a database
|
||||
** in temporary storage or if the VFS does not support shared memory
|
||||
|
@ -6159,7 +6158,7 @@ vdbe_error_halt:
|
|||
if( rc==SQLITE_IOERR_NOMEM ) db->mallocFailed = 1;
|
||||
rc = SQLITE_ERROR;
|
||||
if( resetSchemaOnFault>0 ){
|
||||
sqlite3ResetInternalSchema(db, resetSchemaOnFault-1);
|
||||
sqlite3ResetOneSchema(db, resetSchemaOnFault-1);
|
||||
}
|
||||
|
||||
/* This is the only way out of this procedure. We have to
|
||||
|
|
75
src/vtab.c
75
src/vtab.c
|
@ -22,8 +22,8 @@
|
|||
** are invoked only from within xCreate and xConnect methods.
|
||||
*/
|
||||
struct VtabCtx {
|
||||
Table *pTab;
|
||||
VTable *pVTable;
|
||||
VTable *pVTable; /* The virtual table being constructed */
|
||||
Table *pTab; /* The Table object to which the virtual table belongs */
|
||||
};
|
||||
|
||||
/*
|
||||
|
@ -38,33 +38,35 @@ static int createModule(
|
|||
void *pAux, /* Context pointer for xCreate/xConnect */
|
||||
void (*xDestroy)(void *) /* Module destructor function */
|
||||
){
|
||||
int rc, nName;
|
||||
Module *pMod;
|
||||
int rc = SQLITE_OK;
|
||||
int nName;
|
||||
|
||||
sqlite3_mutex_enter(db->mutex);
|
||||
nName = sqlite3Strlen30(zName);
|
||||
pMod = (Module *)sqlite3DbMallocRaw(db, sizeof(Module) + nName + 1);
|
||||
if( pMod ){
|
||||
Module *pDel;
|
||||
char *zCopy = (char *)(&pMod[1]);
|
||||
memcpy(zCopy, zName, nName+1);
|
||||
pMod->zName = zCopy;
|
||||
pMod->pModule = pModule;
|
||||
pMod->pAux = pAux;
|
||||
pMod->xDestroy = xDestroy;
|
||||
pDel = (Module *)sqlite3HashInsert(&db->aModule, zCopy, nName, (void*)pMod);
|
||||
if( pDel && pDel->xDestroy ){
|
||||
sqlite3ResetInternalSchema(db, -1);
|
||||
pDel->xDestroy(pDel->pAux);
|
||||
if( sqlite3HashFind(&db->aModule, zName, nName) ){
|
||||
rc = SQLITE_MISUSE_BKPT;
|
||||
}else{
|
||||
Module *pMod;
|
||||
pMod = (Module *)sqlite3DbMallocRaw(db, sizeof(Module) + nName + 1);
|
||||
if( pMod ){
|
||||
Module *pDel;
|
||||
char *zCopy = (char *)(&pMod[1]);
|
||||
memcpy(zCopy, zName, nName+1);
|
||||
pMod->zName = zCopy;
|
||||
pMod->pModule = pModule;
|
||||
pMod->pAux = pAux;
|
||||
pMod->xDestroy = xDestroy;
|
||||
pDel = (Module *)sqlite3HashInsert(&db->aModule,zCopy,nName,(void*)pMod);
|
||||
assert( pDel==0 || pDel==pMod );
|
||||
if( pDel ){
|
||||
db->mallocFailed = 1;
|
||||
sqlite3DbFree(db, pDel);
|
||||
}
|
||||
}
|
||||
sqlite3DbFree(db, pDel);
|
||||
if( pDel==pMod ){
|
||||
db->mallocFailed = 1;
|
||||
}
|
||||
}else if( xDestroy ){
|
||||
xDestroy(pAux);
|
||||
}
|
||||
rc = sqlite3ApiExit(db, SQLITE_OK);
|
||||
rc = sqlite3ApiExit(db, rc);
|
||||
if( rc!=SQLITE_OK && xDestroy ) xDestroy(pAux);
|
||||
|
||||
sqlite3_mutex_leave(db->mutex);
|
||||
return rc;
|
||||
}
|
||||
|
@ -180,6 +182,31 @@ static VTable *vtabDisconnectAll(sqlite3 *db, Table *p){
|
|||
return pRet;
|
||||
}
|
||||
|
||||
/*
|
||||
** Table *p is a virtual table. This function removes the VTable object
|
||||
** for table *p associated with database connection db from the linked
|
||||
** list in p->pVTab. It also decrements the VTable ref count. This is
|
||||
** used when closing database connection db to free all of its VTable
|
||||
** objects without disturbing the rest of the Schema object (which may
|
||||
** be being used by other shared-cache connections).
|
||||
*/
|
||||
void sqlite3VtabDisconnect(sqlite3 *db, Table *p){
|
||||
VTable **ppVTab;
|
||||
|
||||
assert( IsVirtual(p) );
|
||||
assert( sqlite3BtreeHoldsAllMutexes(db) );
|
||||
assert( sqlite3_mutex_held(db->mutex) );
|
||||
|
||||
for(ppVTab=&p->pVTable; *ppVTab; ppVTab=&(*ppVTab)->pNext){
|
||||
if( (*ppVTab)->db==db ){
|
||||
VTable *pVTab = *ppVTab;
|
||||
*ppVTab = pVTab->pNext;
|
||||
sqlite3VtabUnlock(pVTab);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
** Disconnect all the virtual table objects in the sqlite3.pDisconnect list.
|
||||
|
|
|
@ -15,6 +15,8 @@
|
|||
# $Id: bigfile.test,v 1.12 2009/03/05 04:27:08 shane Exp $
|
||||
#
|
||||
|
||||
if {[file exists skip-big-file]} return
|
||||
|
||||
set testdir [file dirname $argv0]
|
||||
source $testdir/tester.tcl
|
||||
|
||||
|
|
|
@ -13,6 +13,8 @@
|
|||
# files larger than 4GB.
|
||||
#
|
||||
|
||||
if {[file exists skip-big-file]} return
|
||||
|
||||
set testdir [file dirname $argv0]
|
||||
source $testdir/tester.tcl
|
||||
set testprefix bigfile2
|
||||
|
|
|
@ -649,13 +649,18 @@ do_test capi3-6.1 {
|
|||
db cache flush
|
||||
sqlite3_close $DB
|
||||
} {SQLITE_BUSY}
|
||||
|
||||
# 6.2 and 6.3 used to return SQLITE_ERROR and SQLITE_SCHEMA, respectively.
|
||||
# But since attempting to close a connection no longer resets the internal
|
||||
# schema and expires all statements, this is no longer the case.
|
||||
do_test capi3-6.2 {
|
||||
sqlite3_step $STMT
|
||||
} {SQLITE_ERROR}
|
||||
} {SQLITE_ROW}
|
||||
#check_data $STMT capi3-6.3 {INTEGER} {1} {1.0} {1}
|
||||
do_test capi3-6.3 {
|
||||
sqlite3_finalize $STMT
|
||||
} {SQLITE_SCHEMA}
|
||||
} {SQLITE_OK}
|
||||
|
||||
do_test capi3-6.4-misuse {
|
||||
db cache flush
|
||||
sqlite3_close $DB
|
||||
|
@ -778,6 +783,7 @@ foreach {code english} $code2english {
|
|||
}
|
||||
|
||||
# Test the error message when a "real" out of memory occurs.
|
||||
if { [permutation] != "nofaultsim" } {
|
||||
ifcapable memdebug {
|
||||
do_test capi3-10-1 {
|
||||
sqlite3 db test.db
|
||||
|
@ -816,6 +822,7 @@ ifcapable memdebug {
|
|||
db close
|
||||
sqlite3_memdebug_fail -1
|
||||
}
|
||||
}
|
||||
|
||||
# The following tests - capi3-11.* - test that a COMMIT or ROLLBACK
|
||||
# statement issued while there are still outstanding VMs that are part of
|
||||
|
|
|
@ -751,6 +751,7 @@ foreach {code english} $code2english {
|
|||
}
|
||||
|
||||
# Test the error message when a "real" out of memory occurs.
|
||||
if { [permutation] != "nofaultsim" } {
|
||||
ifcapable memdebug {
|
||||
do_test capi3c-10-1 {
|
||||
sqlite3 db test.db
|
||||
|
@ -771,6 +772,7 @@ ifcapable memdebug {
|
|||
db close
|
||||
sqlite3_memdebug_fail -1
|
||||
}
|
||||
}
|
||||
|
||||
# The following tests - capi3c-11.* - test that a COMMIT or ROLLBACK
|
||||
# statement issued while there are still outstanding VMs that are part of
|
||||
|
|
|
@ -131,10 +131,10 @@ sqlite3_config_uri 1
|
|||
if {$tcl_platform(platform) == "unix"} {
|
||||
set flags [list SQLITE_OPEN_READWRITE SQLITE_OPEN_CREATE SQLITE_OPEN_URI]
|
||||
foreach {tn uri error} "
|
||||
1 {file://localhost[get_pwd]/test.db} {not an error}
|
||||
2 {file://[get_pwd]/test.db} {not an error}
|
||||
3 {file://x[get_pwd]/test.db} {invalid uri authority: x}
|
||||
4 {file://invalid[get_pwd]/test.db} {invalid uri authority: invalid}
|
||||
1 {file://localhost[test_pwd /]test.db} {not an error}
|
||||
2 {file://[test_pwd /]test.db} {not an error}
|
||||
3 {file://x[test_pwd /]test.db} {invalid uri authority: x}
|
||||
4 {file://invalid[test_pwd /]test.db} {invalid uri authority: invalid}
|
||||
" {
|
||||
do_test 2.$tn {
|
||||
set DB [sqlite3_open_v2 $uri $flags ""]
|
||||
|
@ -153,9 +153,9 @@ if {$tcl_platform(platform) == "unix"} {
|
|||
# parameters passed through to the VFS xOpen() methods.
|
||||
#
|
||||
foreach {tn uri parse} "
|
||||
1 {file:test.db#abc} {[get_pwd]/test.db {}}
|
||||
2 {file:test.db?a=b#abc} {[get_pwd]/test.db {a b}}
|
||||
3 {file:test.db?a=b#?c=d} {[get_pwd]/test.db {a b}}
|
||||
1 {file:test.db#abc} {[test_pwd / {}]test.db {}}
|
||||
2 {file:test.db?a=b#abc} {[test_pwd / {}]test.db {a b}}
|
||||
3 {file:test.db?a=b#?c=d} {[test_pwd / {}]test.db {a b}}
|
||||
" {
|
||||
do_filepath_test 3.$tn { parse_uri $uri } $parse
|
||||
}
|
||||
|
@ -171,7 +171,7 @@ foreach {tn uri parse} "
|
|||
# path is interpreted as a relative path.
|
||||
#
|
||||
foreach {tn uri parse} "
|
||||
1 {file:test.db} {[get_pwd]/test.db {}}
|
||||
1 {file:test.db} {[test_pwd / {}]test.db {}}
|
||||
2 {file:/test.db} {/test.db {}}
|
||||
3 {file:///test.db} {/test.db {}}
|
||||
4 {file://localhost/test.db} {/test.db {}}
|
||||
|
@ -241,9 +241,9 @@ do_test 6.1 {
|
|||
} {no such vfs: nosuchvfs}
|
||||
|
||||
|
||||
# EVIDENCE-OF: R-60479-64270 The mode parameter may be set to either
|
||||
# "ro", "rw" or "rwc". Attempting to set it to any other value is an
|
||||
# error
|
||||
# EVIDENCE-OF: R-44013-13102 The mode parameter may be set to either
|
||||
# "ro", "rw", "rwc", or "memory". Attempting to set it to any other
|
||||
# value is an error
|
||||
#
|
||||
sqlite3 db test.db
|
||||
db close
|
||||
|
@ -254,6 +254,8 @@ foreach {tn uri error} "
|
|||
4 {file:test.db?mode=Ro} {no such access mode: Ro}
|
||||
5 {file:test.db?mode=Rw} {no such access mode: Rw}
|
||||
6 {file:test.db?mode=Rwc} {no such access mode: Rwc}
|
||||
7 {file:test.db?mode=memory} {not an error}
|
||||
8 {file:test.db?mode=MEMORY} {no such access mode: MEMORY}
|
||||
" {
|
||||
do_test 7.$tn { open_uri_error $uri } $error
|
||||
}
|
||||
|
@ -306,10 +308,9 @@ foreach {tn uri read write create} {
|
|||
catch {db close}
|
||||
}
|
||||
|
||||
# EVIDENCE-OF: R-56032-32287 If sqlite3_open_v2() is used, it is an
|
||||
# error to specify a value for the mode parameter that is less
|
||||
# restrictive than that specified by the flags passed as the third
|
||||
# parameter.
|
||||
# EVIDENCE-OF: R-20590-08726 It is an error to specify a value for the
|
||||
# mode parameter that is less restrictive than that specified by the
|
||||
# flags passed in the third parameter to sqlite3_open_v2().
|
||||
#
|
||||
forcedelete test.db
|
||||
sqlite3 db test.db
|
||||
|
|
|
@ -131,4 +131,28 @@ do_faultsim_test 4.1 -prep {
|
|||
faultsim_test_result {0 {}}
|
||||
}
|
||||
|
||||
ifcapable fts3_unicode {
|
||||
do_test 5.0 {
|
||||
faultsim_delete_and_reopen
|
||||
execsql {
|
||||
CREATE VIRTUAL TABLE ft USING fts4(a, tokenize=unicode61);
|
||||
}
|
||||
faultsim_save_and_close
|
||||
} {}
|
||||
|
||||
do_faultsim_test 5.1 -faults oom* -prep {
|
||||
faultsim_restore_and_reopen
|
||||
db eval {SELECT * FROM sqlite_master}
|
||||
} -body {
|
||||
execsql { INSERT INTO ft VALUES('the quick brown fox'); }
|
||||
execsql { INSERT INTO ft VALUES(
|
||||
'theunusuallylongtokenthatjustdragsonandonandonandthendragsonsomemoreeof'
|
||||
);
|
||||
}
|
||||
execsql { SELECT docid FROM ft WHERE ft MATCH 'th*' }
|
||||
} -test {
|
||||
faultsim_test_result {0 {1 2}}
|
||||
}
|
||||
}
|
||||
|
||||
finish_test
|
||||
|
|
|
@ -0,0 +1,330 @@
|
|||
# 2012 May 25
|
||||
#
|
||||
# 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.
|
||||
#
|
||||
#*************************************************************************
|
||||
#
|
||||
# The tests in this file focus on testing the "unicode" FTS tokenizer.
|
||||
#
|
||||
|
||||
set testdir [file dirname $argv0]
|
||||
source $testdir/tester.tcl
|
||||
ifcapable !fts3_unicode { finish_test ; return }
|
||||
set ::testprefix fts4unicode
|
||||
|
||||
proc do_unicode_token_test {tn input res} {
|
||||
set input [string map {' ''} $input]
|
||||
uplevel [list do_execsql_test $tn "
|
||||
SELECT fts3_tokenizer_test('unicode61', 'remove_diacritics=0', '$input');
|
||||
" [list [list {*}$res]]]
|
||||
}
|
||||
|
||||
proc do_unicode_token_test2 {tn input res} {
|
||||
set input [string map {' ''} $input]
|
||||
uplevel [list do_execsql_test $tn "
|
||||
SELECT fts3_tokenizer_test('unicode61', '$input');
|
||||
" [list [list {*}$res]]]
|
||||
}
|
||||
|
||||
proc do_unicode_token_test3 {tn args} {
|
||||
set res [lindex $args end]
|
||||
set sql "SELECT fts3_tokenizer_test('unicode61'"
|
||||
foreach a [lrange $args 0 end-1] {
|
||||
append sql ", '"
|
||||
append sql [string map {' ''} $a]
|
||||
append sql "'"
|
||||
}
|
||||
append sql ")"
|
||||
uplevel [list do_execsql_test $tn $sql [list [list {*}$res]]]
|
||||
}
|
||||
|
||||
do_unicode_token_test 1.0 {a B c D} {0 a a 1 b B 2 c c 3 d D}
|
||||
do_unicode_token_test 1.1 {Ä Ö Ü} {0 ä Ä 1 ö Ö 2 ü Ü}
|
||||
do_unicode_token_test 1.2 {xÄx xÖx xÜx} {0 xäx xÄx 1 xöx xÖx 2 xüx xÜx}
|
||||
|
||||
# 0x00DF is a small "sharp s". 0x1E9E is a capital sharp s.
|
||||
do_unicode_token_test 1.3 "\uDF" "0 \uDF \uDF"
|
||||
do_unicode_token_test 1.4 "\u1E9E" "0 ß \u1E9E"
|
||||
do_unicode_token_test 1.5 "\u1E9E" "0 \uDF \u1E9E"
|
||||
|
||||
do_unicode_token_test 1.6 "The quick brown fox" {
|
||||
0 the The 1 quick quick 2 brown brown 3 fox fox
|
||||
}
|
||||
do_unicode_token_test 1.7 "The\u00bfquick\u224ebrown\u2263fox" {
|
||||
0 the The 1 quick quick 2 brown brown 3 fox fox
|
||||
}
|
||||
|
||||
do_unicode_token_test2 1.8 {a B c D} {0 a a 1 b B 2 c c 3 d D}
|
||||
do_unicode_token_test2 1.9 {Ä Ö Ü} {0 a Ä 1 o Ö 2 u Ü}
|
||||
do_unicode_token_test2 1.10 {xÄx xÖx xÜx} {0 xax xÄx 1 xox xÖx 2 xux xÜx}
|
||||
|
||||
# Check that diacritics are removed if remove_diacritics=1 is specified.
|
||||
# And that they do not break tokens.
|
||||
do_unicode_token_test2 1.10 "xx\u0301xx" "0 xxxx xx\u301xx"
|
||||
|
||||
#-------------------------------------------------------------------------
|
||||
#
|
||||
set docs [list {
|
||||
Enhance the INSERT syntax to allow multiple rows to be inserted via the
|
||||
VALUES clause.
|
||||
} {
|
||||
Enhance the CREATE VIRTUAL TABLE command to support the IF NOT EXISTS clause.
|
||||
} {
|
||||
Added the sqlite3_stricmp() interface as a counterpart to sqlite3_strnicmp().
|
||||
} {
|
||||
Added the sqlite3_db_readonly() interface.
|
||||
} {
|
||||
Added the SQLITE_FCNTL_PRAGMA file control, giving VFS implementations the
|
||||
ability to add new PRAGMA statements or to override built-in PRAGMAs.
|
||||
} {
|
||||
Queries of the form: "SELECT max(x), y FROM table" returns the value of y on
|
||||
the same row that contains the maximum x value.
|
||||
} {
|
||||
Added support for the FTS4 languageid option.
|
||||
} {
|
||||
Documented support for the FTS4 content option. This feature has actually
|
||||
been in the code since version 3.7.9 but is only now considered to be
|
||||
officially supported.
|
||||
} {
|
||||
Pending statements no longer block ROLLBACK. Instead, the pending statement
|
||||
will return SQLITE_ABORT upon next access after the ROLLBACK.
|
||||
} {
|
||||
Improvements to the handling of CSV inputs in the command-line shell
|
||||
} {
|
||||
Fix a bug introduced in version 3.7.10 that might cause a LEFT JOIN to be
|
||||
incorrectly converted into an INNER JOIN if the WHERE clause indexable terms
|
||||
connected by OR.
|
||||
}]
|
||||
|
||||
set map(a) [list "\u00C4" "\u00E4"] ; # LATIN LETTER A WITH DIAERESIS
|
||||
set map(e) [list "\u00CB" "\u00EB"] ; # LATIN LETTER E WITH DIAERESIS
|
||||
set map(i) [list "\u00CF" "\u00EF"] ; # LATIN LETTER I WITH DIAERESIS
|
||||
set map(o) [list "\u00D6" "\u00F6"] ; # LATIN LETTER O WITH DIAERESIS
|
||||
set map(u) [list "\u00DC" "\u00FC"] ; # LATIN LETTER U WITH DIAERESIS
|
||||
set map(y) [list "\u0178" "\u00FF"] ; # LATIN LETTER Y WITH DIAERESIS
|
||||
set map(h) [list "\u1E26" "\u1E27"] ; # LATIN LETTER H WITH DIAERESIS
|
||||
set map(w) [list "\u1E84" "\u1E85"] ; # LATIN LETTER W WITH DIAERESIS
|
||||
set map(x) [list "\u1E8C" "\u1E8D"] ; # LATIN LETTER X WITH DIAERESIS
|
||||
foreach k [array names map] {
|
||||
lappend mappings [string toupper $k] [lindex $map($k) 0]
|
||||
lappend mappings $k [lindex $map($k) 1]
|
||||
}
|
||||
proc mapdoc {doc} {
|
||||
set doc [regsub -all {[[:space:]]+} $doc " "]
|
||||
string map $::mappings [string trim $doc]
|
||||
}
|
||||
|
||||
do_test 2.0 {
|
||||
execsql { CREATE VIRTUAL TABLE t2 USING fts4(tokenize=unicode61, x); }
|
||||
foreach doc $docs {
|
||||
set d [mapdoc $doc]
|
||||
execsql { INSERT INTO t2 VALUES($d) }
|
||||
}
|
||||
} {}
|
||||
|
||||
do_test 2.1 {
|
||||
set q [mapdoc "row"]
|
||||
execsql { SELECT * FROM t2 WHERE t2 MATCH $q }
|
||||
} [list [mapdoc {
|
||||
Queries of the form: "SELECT max(x), y FROM table" returns the value of y on
|
||||
the same row that contains the maximum x value.
|
||||
}]]
|
||||
|
||||
foreach {tn query snippet} {
|
||||
2 "row" {
|
||||
...returns the value of y on the same [row] that contains
|
||||
the maximum x value.
|
||||
}
|
||||
3 "ROW" {
|
||||
...returns the value of y on the same [row] that contains
|
||||
the maximum x value.
|
||||
}
|
||||
4 "rollback" {
|
||||
...[ROLLBACK]. Instead, the pending statement
|
||||
will return SQLITE_ABORT upon next access after the [ROLLBACK].
|
||||
}
|
||||
5 "rOllback" {
|
||||
...[ROLLBACK]. Instead, the pending statement
|
||||
will return SQLITE_ABORT upon next access after the [ROLLBACK].
|
||||
}
|
||||
6 "lang*" {
|
||||
Added support for the FTS4 [languageid] option.
|
||||
}
|
||||
} {
|
||||
do_test 2.$tn {
|
||||
set q [mapdoc $query]
|
||||
execsql { SELECT snippet(t2, '[', ']', '...') FROM t2 WHERE t2 MATCH $q }
|
||||
} [list [mapdoc $snippet]]
|
||||
}
|
||||
|
||||
#-------------------------------------------------------------------------
|
||||
# Make sure the unicode61 tokenizer does not crash if it is passed a
|
||||
# NULL pointer.
|
||||
reset_db
|
||||
do_execsql_test 3.1 {
|
||||
CREATE VIRTUAL TABLE t1 USING fts4(tokenize=unicode61, x, y);
|
||||
INSERT INTO t1 VALUES(NULL, 'a b c');
|
||||
}
|
||||
|
||||
do_execsql_test 3.2 {
|
||||
SELECT snippet(t1, '[', ']') FROM t1 WHERE t1 MATCH 'b'
|
||||
} {{a [b] c}}
|
||||
|
||||
do_execsql_test 3.3 {
|
||||
BEGIN;
|
||||
DELETE FROM t1;
|
||||
INSERT INTO t1 VALUES('b b b b b b b b b b b', 'b b b b b b b b b b b b b');
|
||||
INSERT INTO t1 SELECT * FROM t1;
|
||||
INSERT INTO t1 SELECT * FROM t1;
|
||||
INSERT INTO t1 SELECT * FROM t1;
|
||||
INSERT INTO t1 SELECT * FROM t1;
|
||||
INSERT INTO t1 SELECT * FROM t1;
|
||||
INSERT INTO t1 SELECT * FROM t1;
|
||||
INSERT INTO t1 SELECT * FROM t1;
|
||||
INSERT INTO t1 SELECT * FROM t1;
|
||||
INSERT INTO t1 SELECT * FROM t1;
|
||||
INSERT INTO t1 SELECT * FROM t1;
|
||||
INSERT INTO t1 SELECT * FROM t1;
|
||||
INSERT INTO t1 SELECT * FROM t1;
|
||||
INSERT INTO t1 SELECT * FROM t1;
|
||||
INSERT INTO t1 SELECT * FROM t1;
|
||||
INSERT INTO t1 SELECT * FROM t1;
|
||||
INSERT INTO t1 SELECT * FROM t1;
|
||||
INSERT INTO t1 VALUES('a b c', NULL);
|
||||
INSERT INTO t1 VALUES('a x c', NULL);
|
||||
COMMIT;
|
||||
}
|
||||
|
||||
do_execsql_test 3.4 {
|
||||
SELECT * FROM t1 WHERE t1 MATCH 'a b';
|
||||
} {{a b c} {}}
|
||||
|
||||
#-------------------------------------------------------------------------
|
||||
#
|
||||
reset_db
|
||||
|
||||
do_test 4.1 {
|
||||
set a "abc\uFFFEdef"
|
||||
set b "abc\uD800def"
|
||||
set c "\uFFFEdef"
|
||||
set d "\uD800def"
|
||||
execsql {
|
||||
CREATE VIRTUAL TABLE t1 USING fts4(tokenize=unicode61, x);
|
||||
INSERT INTO t1 VALUES($a);
|
||||
INSERT INTO t1 VALUES($b);
|
||||
INSERT INTO t1 VALUES($c);
|
||||
INSERT INTO t1 VALUES($d);
|
||||
}
|
||||
} {}
|
||||
|
||||
do_test 4.2 {
|
||||
set a [binary format c* {0x61 0xF7 0xBF 0xBF 0xBF 0x62}]
|
||||
set b [binary format c* {0x61 0xF7 0xBF 0xBF 0xBF 0xBF 0x62}]
|
||||
set c [binary format c* {0x61 0xF7 0xBF 0xBF 0xBF 0xBF 0xBF 0x62}]
|
||||
set d [binary format c* {0x61 0xF7 0xBF 0xBF 0xBF 0xBF 0xBF 0xBF 0x62}]
|
||||
execsql {
|
||||
INSERT INTO t1 VALUES($a);
|
||||
INSERT INTO t1 VALUES($b);
|
||||
INSERT INTO t1 VALUES($c);
|
||||
INSERT INTO t1 VALUES($d);
|
||||
}
|
||||
} {}
|
||||
|
||||
do_test 4.3 {
|
||||
set a [binary format c* {0xF7 0xBF 0xBF 0xBF}]
|
||||
set b [binary format c* {0xF7 0xBF 0xBF 0xBF 0xBF}]
|
||||
set c [binary format c* {0xF7 0xBF 0xBF 0xBF 0xBF 0xBF}]
|
||||
set d [binary format c* {0xF7 0xBF 0xBF 0xBF 0xBF 0xBF 0xBF}]
|
||||
execsql {
|
||||
INSERT INTO t1 VALUES($a);
|
||||
INSERT INTO t1 VALUES($b);
|
||||
INSERT INTO t1 VALUES($c);
|
||||
INSERT INTO t1 VALUES($d);
|
||||
}
|
||||
} {}
|
||||
|
||||
#-------------------------------------------------------------------------
|
||||
|
||||
do_unicode_token_test3 5.1 {tokenchars=} {
|
||||
sqlite3_reset sqlite3_column_int
|
||||
} {
|
||||
0 sqlite3 sqlite3
|
||||
1 reset reset
|
||||
2 sqlite3 sqlite3
|
||||
3 column column
|
||||
4 int int
|
||||
}
|
||||
|
||||
do_unicode_token_test3 5.2 {tokenchars=_} {
|
||||
sqlite3_reset sqlite3_column_int
|
||||
} {
|
||||
0 sqlite3_reset sqlite3_reset
|
||||
1 sqlite3_column_int sqlite3_column_int
|
||||
}
|
||||
|
||||
do_unicode_token_test3 5.3 {separators=xyz} {
|
||||
Laotianxhorseyrunszfast
|
||||
} {
|
||||
0 laotian Laotian
|
||||
1 horse horse
|
||||
2 runs runs
|
||||
3 fast fast
|
||||
}
|
||||
|
||||
do_unicode_token_test3 5.4 {tokenchars=xyz} {
|
||||
Laotianxhorseyrunszfast
|
||||
} {
|
||||
0 laotianxhorseyrunszfast Laotianxhorseyrunszfast
|
||||
}
|
||||
|
||||
do_unicode_token_test3 5.5 {tokenchars=_} {separators=zyx} {
|
||||
sqlite3_resetxsqlite3_column_intyhonda_phantom
|
||||
} {
|
||||
0 sqlite3_reset sqlite3_reset
|
||||
1 sqlite3_column_int sqlite3_column_int
|
||||
2 honda_phantom honda_phantom
|
||||
}
|
||||
|
||||
do_unicode_token_test3 5.6 "separators=\u05D1" "abc\u05D1def" {
|
||||
0 abc abc 1 def def
|
||||
}
|
||||
|
||||
do_unicode_token_test3 5.7 \
|
||||
"tokenchars=\u2444\u2445" \
|
||||
"separators=\u05D0\u05D1\u05D2" \
|
||||
"\u2444fre\u2445sh\u05D0water\u05D2fish.\u2445timer" \
|
||||
[list \
|
||||
0 \u2444fre\u2445sh \u2444fre\u2445sh \
|
||||
1 water water \
|
||||
2 fish fish \
|
||||
3 \u2445timer \u2445timer \
|
||||
]
|
||||
|
||||
# Check that it is not possible to add a standalone diacritic codepoint
|
||||
# to either separators or tokenchars.
|
||||
do_unicode_token_test3 5.8 "separators=\u0301" \
|
||||
"hello\u0301world \u0301helloworld" \
|
||||
"0 helloworld hello\u0301world 1 helloworld helloworld"
|
||||
|
||||
do_unicode_token_test3 5.9 "tokenchars=\u0301" \
|
||||
"hello\u0301world \u0301helloworld" \
|
||||
"0 helloworld hello\u0301world 1 helloworld helloworld"
|
||||
|
||||
do_unicode_token_test3 5.10 "separators=\u0301" \
|
||||
"remove_diacritics=0" \
|
||||
"hello\u0301world \u0301helloworld" \
|
||||
"0 hello\u0301world hello\u0301world 1 helloworld helloworld"
|
||||
|
||||
do_unicode_token_test3 5.11 "tokenchars=\u0301" \
|
||||
"remove_diacritics=0" \
|
||||
"hello\u0301world \u0301helloworld" \
|
||||
"0 hello\u0301world hello\u0301world 1 helloworld helloworld"
|
||||
|
||||
|
||||
finish_test
|
||||
|
|
@ -472,6 +472,11 @@ ifcapable subquery {
|
|||
} {1 2 3 4 5 6 7 8 9 10 11}
|
||||
}
|
||||
|
||||
#
|
||||
# The following tests can only work if the current SQLite VFS has the concept
|
||||
# of a current directory.
|
||||
#
|
||||
ifcapable curdir {
|
||||
# Make sure a database connection still works after changing the
|
||||
# working directory.
|
||||
#
|
||||
|
@ -495,6 +500,7 @@ do_test misc1-14.3 {
|
|||
execsql {COMMIT}
|
||||
file exists ./test.db-journal
|
||||
} {0}
|
||||
}
|
||||
|
||||
# A failed create table should not leave the table in the internal
|
||||
# data structures. Ticket #238.
|
||||
|
|
|
@ -524,18 +524,27 @@ db close
|
|||
# file-system is saved just before the xDelete() call to remove the
|
||||
# master journal file from the file-system.
|
||||
#
|
||||
set pwd [get_pwd]
|
||||
testvfs tv -default 1
|
||||
tv script copy_on_mj_delete
|
||||
set ::mj_filename_length 0
|
||||
proc copy_on_mj_delete {method filename args} {
|
||||
if {[string match *mj* [file tail $filename]]} {
|
||||
set ::mj_filename_length [string length $filename]
|
||||
#
|
||||
# NOTE: Is the file name relative? If so, add the length of the current
|
||||
# directory.
|
||||
#
|
||||
if {[is_relative_file $filename]} {
|
||||
set ::mj_filename_length \
|
||||
[expr {[string length $filename] + [string length $::pwd]}]
|
||||
} else {
|
||||
set ::mj_filename_length [string length $filename]
|
||||
}
|
||||
faultsim_save
|
||||
}
|
||||
return SQLITE_OK
|
||||
}
|
||||
|
||||
set pwd [get_pwd]
|
||||
foreach {tn1 tcl} {
|
||||
1 { set prefix "test.db" }
|
||||
2 {
|
||||
|
@ -1019,8 +1028,17 @@ do_test pager1-5.4.1 {
|
|||
# the master-journal name encoded as utf-8 with no nul term.
|
||||
#
|
||||
set mj_pointer [expr {
|
||||
20 + [string length [get_pwd]] + [string length "/test.db-mjXXXXXX9XX"]
|
||||
20 + [string length "test.db-mjXXXXXX9XX"]
|
||||
}]
|
||||
#
|
||||
# NOTE: For item 3 above, if the current SQLite VFS lacks the concept of a
|
||||
# current directory, the length of the current directory name plus 1
|
||||
# character for the directory separator character are NOT counted as
|
||||
# part of the total size; otherwise, they are.
|
||||
#
|
||||
ifcapable curdir {
|
||||
set mj_pointer [expr {$mj_pointer + [string length [get_pwd]] + 1}]
|
||||
}
|
||||
expr {$::max_journal==(512+2*(1024+8)+$mj_pointer)}
|
||||
} 1
|
||||
do_test pager1-5.4.2 {
|
||||
|
@ -1038,8 +1056,17 @@ do_test pager1-5.4.2 {
|
|||
# written starting at the next (in this case 512 byte) sector boundary.
|
||||
#
|
||||
set mj_pointer [expr {
|
||||
20 + [string length [get_pwd]] + [string length "/test.db-mjXXXXXX9XX"]
|
||||
20 + [string length "test.db-mjXXXXXX9XX"]
|
||||
}]
|
||||
#
|
||||
# NOTE: If the current SQLite VFS lacks the concept of a current directory,
|
||||
# the length of the current directory name plus 1 character for the
|
||||
# directory separator character are NOT counted as part of the total
|
||||
# size; otherwise, they are.
|
||||
#
|
||||
ifcapable curdir {
|
||||
set mj_pointer [expr {$mj_pointer + [string length [get_pwd]] + 1}]
|
||||
}
|
||||
expr {$::max_journal==(((512+2*(1024+8)+511)/512)*512 + $mj_pointer)}
|
||||
} 1
|
||||
db close
|
||||
|
|
|
@ -185,9 +185,24 @@ test_suite "fts3" -prefix "" -description {
|
|||
fts4aa.test fts4content.test
|
||||
fts3conf.test fts3prefix.test fts3fault2.test fts3corrupt.test
|
||||
fts3corrupt2.test fts3first.test fts4langid.test fts4merge.test
|
||||
fts4check.test
|
||||
fts4check.test fts4unicode.test
|
||||
}
|
||||
|
||||
test_suite "nofaultsim" -prefix "" -description {
|
||||
"Very" quick test suite. Runs in less than 5 minutes on a workstation.
|
||||
This test suite is the same as the "quick" tests, except that some files
|
||||
that test malloc and IO errors are omitted.
|
||||
} -files [
|
||||
test_set $allquicktests -exclude *malloc* *ioerr* *fault*
|
||||
] -initialize {
|
||||
catch {db close}
|
||||
sqlite3_shutdown
|
||||
install_malloc_faultsim 0
|
||||
sqlite3_initialize
|
||||
autoinstall_test_functions
|
||||
} -shutdown {
|
||||
unset -nocomplain ::G(valgrind)
|
||||
}
|
||||
|
||||
lappend ::testsuitelist xxx
|
||||
#-------------------------------------------------------------------------
|
||||
|
|
|
@ -40,6 +40,7 @@ do_not_use_codec
|
|||
# pragma-15.*: Test that the value set using the cache_size pragma is not
|
||||
# reset when the schema is reloaded.
|
||||
# pragma-16.*: Test proxy locking
|
||||
# pragma-20.*: Test data_store_directory.
|
||||
#
|
||||
|
||||
ifcapable !pragma {
|
||||
|
@ -1510,5 +1511,47 @@ do_test pragma-19.5 {
|
|||
file tail [lindex [execsql {PRAGMA filename}] 0]
|
||||
} {test.db}
|
||||
|
||||
if {$tcl_platform(platform)=="windows"} {
|
||||
# Test data_store_directory pragma
|
||||
#
|
||||
db close
|
||||
sqlite3 db test.db
|
||||
file mkdir data_dir
|
||||
do_test pragma-20.1 {
|
||||
catchsql {PRAGMA data_store_directory}
|
||||
} {0 {}}
|
||||
do_test pragma-20.2 {
|
||||
set pwd [string map {' ''} [file nativename [get_pwd]]]
|
||||
catchsql "PRAGMA data_store_directory='$pwd';"
|
||||
} {0 {}}
|
||||
do_test pragma-20.3 {
|
||||
catchsql {PRAGMA data_store_directory}
|
||||
} [list 0 [list [file nativename [get_pwd]]]]
|
||||
do_test pragma-20.4 {
|
||||
set pwd [string map {' ''} [file nativename \
|
||||
[file join [get_pwd] data_dir]]]
|
||||
catchsql "PRAGMA data_store_directory='$pwd';"
|
||||
} {0 {}}
|
||||
do_test pragma-20.5 {
|
||||
sqlite3 db2 test2.db
|
||||
catchsql "PRAGMA database_list;" db2
|
||||
} [list 0 [list 0 main [file nativename \
|
||||
[file join [get_pwd] data_dir test2.db]]]]
|
||||
catch {db2 close}
|
||||
do_test pragma-20.6 {
|
||||
sqlite3 db2 [file join [get_pwd] test2.db]
|
||||
catchsql "PRAGMA database_list;" db2
|
||||
} [list 0 [list 0 main [file nativename \
|
||||
[file join [get_pwd] test2.db]]]]
|
||||
catch {db2 close}
|
||||
do_test pragma-20.7 {
|
||||
catchsql "PRAGMA data_store_directory='';"
|
||||
} {0 {}}
|
||||
do_test pragma-20.8 {
|
||||
catchsql {PRAGMA data_store_directory}
|
||||
} {0 {}}
|
||||
|
||||
forcedelete data_dir
|
||||
} ;# endif windows
|
||||
|
||||
finish_test
|
||||
|
|
|
@ -12,6 +12,13 @@
|
|||
|
||||
set testdir [file dirname $argv0]
|
||||
source $testdir/tester.tcl
|
||||
|
||||
# If SQLITE_CURDIR is not defined, omit this file.
|
||||
ifcapable !curdir {
|
||||
finish_test
|
||||
return
|
||||
}
|
||||
|
||||
source $testdir/malloc_common.tcl
|
||||
|
||||
unset -nocomplain defaultVfs
|
||||
|
|
|
@ -12,6 +12,13 @@
|
|||
|
||||
set testdir [file dirname $argv0]
|
||||
source $testdir/tester.tcl
|
||||
|
||||
# If SQLITE_CURDIR is not defined, omit this file.
|
||||
ifcapable !curdir {
|
||||
finish_test
|
||||
return
|
||||
}
|
||||
|
||||
source $testdir/malloc_common.tcl
|
||||
|
||||
db close
|
||||
|
@ -164,11 +171,17 @@ do_test quota2-2.1 {
|
|||
do_test quota2-2.2 {
|
||||
set ::quota
|
||||
} {}
|
||||
do_test quota2-2.3 {
|
||||
do_test quota2-2.3.1 {
|
||||
sqlite3_quota_rewind $::h1
|
||||
sqlite3_quota_file_available $::h1
|
||||
} {7000}
|
||||
do_test quota2-2.3.2 {
|
||||
set ::x [sqlite3_quota_fread $::h1 1001 7]
|
||||
string length $::x
|
||||
} {6006}
|
||||
do_test quota2-2.3.3 {
|
||||
sqlite3_quota_file_available $::h1
|
||||
} {0}
|
||||
do_test quota2-2.4 {
|
||||
string match $::x [string range $::bigtext 0 6005]
|
||||
} {1}
|
||||
|
@ -180,22 +193,40 @@ do_test quota2-2.6 {
|
|||
sqlite3_quota_fseek $::h1 -100 SEEK_END
|
||||
sqlite3_quota_ftell $::h1
|
||||
} {6900}
|
||||
do_test quota2-2.6.1 {
|
||||
sqlite3_quota_file_available $::h1
|
||||
} {100}
|
||||
do_test quota2-2.7 {
|
||||
sqlite3_quota_fseek $::h1 -100 SEEK_CUR
|
||||
sqlite3_quota_ftell $::h1
|
||||
} {6800}
|
||||
do_test quota2-2.7.1 {
|
||||
sqlite3_quota_file_available $::h1
|
||||
} {200}
|
||||
do_test quota2-2.8 {
|
||||
sqlite3_quota_fseek $::h1 50 SEEK_CUR
|
||||
sqlite3_quota_ftell $::h1
|
||||
} {6850}
|
||||
do_test quota2-2.8.1 {
|
||||
sqlite3_quota_file_available $::h1
|
||||
} {150}
|
||||
do_test quota2-2.9 {
|
||||
sqlite3_quota_fseek $::h1 50 SEEK_SET
|
||||
sqlite3_quota_ftell $::h1
|
||||
} {50}
|
||||
do_test quota2-2.9.1 {
|
||||
sqlite3_quota_file_available $::h1
|
||||
} {6950}
|
||||
do_test quota2-2.10 {
|
||||
sqlite3_quota_rewind $::h1
|
||||
sqlite3_quota_ftell $::h1
|
||||
} {0}
|
||||
do_test quota2-2.10.1 {
|
||||
sqlite3_quota_file_available $::h1
|
||||
} {7000}
|
||||
do_test quota2-2.10.2 {
|
||||
sqlite3_quota_ferror $::h1
|
||||
} {0}
|
||||
do_test quota2-2.11 {
|
||||
standard_path [sqlite3_quota_dump]
|
||||
} {{*/quota2b/* 5000 0} {*/quota2a/* 4000 0}}
|
||||
|
|
130
test/shared.test
130
test/shared.test
|
@ -904,9 +904,11 @@ do_test shared-$av.11.8 {
|
|||
set res
|
||||
} {1 4 {} 7}
|
||||
if {[llength [info command sqlite3_shared_cache_report]]==1} {
|
||||
do_test shared-$av.11.9 {
|
||||
string tolower [sqlite3_shared_cache_report]
|
||||
} [string tolower [list [file nativename [file normalize test.db]] 2]]
|
||||
ifcapable curdir {
|
||||
do_test shared-$av.11.9 {
|
||||
string tolower [sqlite3_shared_cache_report]
|
||||
} [string tolower [list [file nativename [file normalize test.db]] 2]]
|
||||
}
|
||||
}
|
||||
|
||||
do_test shared-$av.11.11 {
|
||||
|
@ -1056,7 +1058,127 @@ do_test shared-$av-15.2 {
|
|||
db close
|
||||
db2 close
|
||||
|
||||
}
|
||||
# Shared cache on a :memory: database. This only works for URI filenames.
|
||||
#
|
||||
do_test shared-$av-16.1 {
|
||||
sqlite3 db1 file::memory: -uri 1
|
||||
sqlite3 db2 file::memory: -uri 1
|
||||
db1 eval {
|
||||
CREATE TABLE t1(x); INSERT INTO t1 VALUES(1),(2),(3);
|
||||
}
|
||||
db2 eval {
|
||||
SELECT x FROM t1 ORDER BY x;
|
||||
}
|
||||
} {1 2 3}
|
||||
do_test shared-$av-16.2 {
|
||||
db2 eval {
|
||||
INSERT INTO t1 VALUES(99);
|
||||
DELETE FROM t1 WHERE x=2;
|
||||
}
|
||||
db1 eval {
|
||||
SELECT x FROM t1 ORDER BY x;
|
||||
}
|
||||
} {1 3 99}
|
||||
|
||||
# Verify that there is no cache sharing ordinary (non-URI) filenames are
|
||||
# used.
|
||||
#
|
||||
do_test shared-$av-16.3 {
|
||||
db1 close
|
||||
db2 close
|
||||
sqlite3 db1 :memory:
|
||||
sqlite3 db2 :memory:
|
||||
db1 eval {
|
||||
CREATE TABLE t1(x); INSERT INTO t1 VALUES(4),(5),(6);
|
||||
}
|
||||
catchsql {
|
||||
SELECT * FROM t1;
|
||||
} db2
|
||||
} {1 {no such table: t1}}
|
||||
|
||||
# Shared cache on named memory databases.
|
||||
#
|
||||
do_test shared-$av-16.4 {
|
||||
db1 close
|
||||
db2 close
|
||||
forcedelete test.db test.db-wal test.db-journal
|
||||
sqlite3 db1 file:test.db?mode=memory -uri 1
|
||||
sqlite3 db2 file:test.db?mode=memory -uri 1
|
||||
db1 eval {
|
||||
CREATE TABLE t1(x); INSERT INTO t1 VALUES(1),(2),(3);
|
||||
}
|
||||
db2 eval {
|
||||
SELECT x FROM t1 ORDER BY x;
|
||||
}
|
||||
} {1 2 3}
|
||||
do_test shared-$av-16.5 {
|
||||
db2 eval {
|
||||
INSERT INTO t1 VALUES(99);
|
||||
DELETE FROM t1 WHERE x=2;
|
||||
}
|
||||
db1 eval {
|
||||
SELECT x FROM t1 ORDER BY x;
|
||||
}
|
||||
} {1 3 99}
|
||||
do_test shared-$av-16.6 {
|
||||
file exists test.db
|
||||
} {0} ;# Verify that the database is in-memory
|
||||
|
||||
# Shared cache on named memory databases with different names.
|
||||
#
|
||||
do_test shared-$av-16.7 {
|
||||
db1 close
|
||||
db2 close
|
||||
forcedelete test1.db test2.db
|
||||
sqlite3 db1 file:test1.db?mode=memory -uri 1
|
||||
sqlite3 db2 file:test2.db?mode=memory -uri 1
|
||||
db1 eval {
|
||||
CREATE TABLE t1(x); INSERT INTO t1 VALUES(1),(2),(3);
|
||||
}
|
||||
catchsql {
|
||||
SELECT x FROM t1 ORDER BY x;
|
||||
} db2
|
||||
} {1 {no such table: t1}}
|
||||
do_test shared-$av-16.8 {
|
||||
file exists test1.db
|
||||
} {0} ;# Verify that the database is in-memory
|
||||
|
||||
# Shared cache on named memory databases attached to readonly connections.
|
||||
#
|
||||
do_test shared-$av-16.8.1 {
|
||||
db1 close
|
||||
db2 close
|
||||
|
||||
sqlite3 db test1.db
|
||||
db eval {
|
||||
CREATE TABLE yy(a, b);
|
||||
INSERT INTO yy VALUES(77, 88);
|
||||
}
|
||||
db close
|
||||
|
||||
sqlite3 db1 test1.db -uri 1 -readonly 1
|
||||
sqlite3 db2 test2.db -uri 1
|
||||
|
||||
db1 eval {
|
||||
ATTACH 'file:mem?mode=memory&cache=shared' AS shared;
|
||||
CREATE TABLE shared.xx(a, b);
|
||||
INSERT INTO xx VALUES(55, 66);
|
||||
}
|
||||
db2 eval {
|
||||
ATTACH 'file:mem?mode=memory&cache=shared' AS shared;
|
||||
SELECT * FROM xx;
|
||||
}
|
||||
} {55 66}
|
||||
|
||||
do_test shared-$av-16.8.2 { db1 eval { SELECT * FROM yy } } {77 88}
|
||||
do_test shared-$av-16.8.3 {
|
||||
list [catch {db1 eval { INSERT INTO yy VALUES(1, 2) }} msg] $msg
|
||||
} {1 {attempt to write a readonly database}}
|
||||
|
||||
db1 close
|
||||
db2 close
|
||||
|
||||
} ;# end of autovacuum on/off loop
|
||||
|
||||
sqlite3_enable_shared_cache $::enable_shared_cache
|
||||
finish_test
|
||||
|
|
|
@ -0,0 +1,113 @@
|
|||
# 2012 May 15
|
||||
#
|
||||
# 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.
|
||||
#
|
||||
#***********************************************************************
|
||||
#
|
||||
# The tests in this file are intended to show that closing one database
|
||||
# connection to a shared-cache while there exist other connections (a)
|
||||
# does not cause the schema to be reloaded and (b) does not cause any
|
||||
# other problems.
|
||||
#
|
||||
|
||||
set testdir [file dirname $argv0]
|
||||
source $testdir/tester.tcl
|
||||
ifcapable !shared_cache { finish_test ; return }
|
||||
set testprefix shared8
|
||||
|
||||
db close
|
||||
set ::enable_shared_cache [sqlite3_enable_shared_cache 1]
|
||||
do_test 0.0 { sqlite3_enable_shared_cache } {1}
|
||||
|
||||
proc roman {n} {
|
||||
array set R {1 i 2 ii 3 iii 4 iv 5 v 6 vi 7 vii 8 viii 9 ix 10 x}
|
||||
set R($n)
|
||||
}
|
||||
|
||||
#-------------------------------------------------------------------------
|
||||
# The following tests work as follows:
|
||||
#
|
||||
# 1.0: Open connection [db1] and populate the database.
|
||||
#
|
||||
# 1.1: Using "PRAGMA writable_schema", destroy the database schema on
|
||||
# disk. The schema is still in memory, so it is possible to keep
|
||||
# using it, but any attempt to reload it from disk will fail.
|
||||
#
|
||||
# 1.3-4: Open connection db2. Check that it can see the db schema. Then
|
||||
# close db1 and check that db2 still works. This shows that closing
|
||||
# db1 did not reset the in-memory schema.
|
||||
#
|
||||
# 1.5-7: Similar to 1.3-4.
|
||||
#
|
||||
# 1.8: Close all database connections (deleting the in-memory schema).
|
||||
# Then open a new connection and check that it cannot read the db.
|
||||
#
|
||||
do_test 1.0 {
|
||||
sqlite3 db1 test.db
|
||||
db1 func roman roman
|
||||
execsql {
|
||||
CREATE TABLE t1(a, b);
|
||||
INSERT INTO t1 VALUES(1, 1);
|
||||
INSERT INTO t1 VALUES(2, 2);
|
||||
INSERT INTO t1 VALUES(3, 3);
|
||||
INSERT INTO t1 VALUES(4, 4);
|
||||
CREATE VIEW v1 AS SELECT a, roman(b) FROM t1;
|
||||
SELECT * FROM v1;
|
||||
} db1
|
||||
} {1 i 2 ii 3 iii 4 iv}
|
||||
|
||||
do_test 1.1 {
|
||||
execsql {
|
||||
PRAGMA writable_schema = 1;
|
||||
DELETE FROM sqlite_master WHERE 1;
|
||||
PRAGMA writable_schema = 0;
|
||||
SELECT * FROM sqlite_master;
|
||||
} db1
|
||||
} {}
|
||||
|
||||
do_test 1.2 {
|
||||
execsql { SELECT * FROM v1 } db1
|
||||
} {1 i 2 ii 3 iii 4 iv}
|
||||
|
||||
do_test 1.3 {
|
||||
sqlite3 db2 test.db
|
||||
db2 func roman roman
|
||||
execsql { SELECT * FROM v1 } db2
|
||||
} {1 i 2 ii 3 iii 4 iv}
|
||||
|
||||
do_test 1.4 {
|
||||
db1 close
|
||||
execsql { SELECT * FROM v1 } db2
|
||||
} {1 i 2 ii 3 iii 4 iv}
|
||||
|
||||
do_test 1.5 {
|
||||
sqlite3 db3 test.db
|
||||
db3 func roman roman
|
||||
execsql { SELECT * FROM v1 } db3
|
||||
} {1 i 2 ii 3 iii 4 iv}
|
||||
|
||||
do_test 1.6 {
|
||||
execsql { SELECT * FROM v1 } db2
|
||||
} {1 i 2 ii 3 iii 4 iv}
|
||||
|
||||
do_test 1.7 {
|
||||
db2 close
|
||||
execsql { SELECT * FROM v1 } db3
|
||||
} {1 i 2 ii 3 iii 4 iv}
|
||||
|
||||
do_test 1.8 {
|
||||
db3 close
|
||||
sqlite3 db4 test.db
|
||||
catchsql { SELECT * FROM v1 } db4
|
||||
} {1 {no such table: v1}}
|
||||
|
||||
|
||||
foreach db {db1 db2 db3 db4} { catch { $db close } }
|
||||
sqlite3_enable_shared_cache $::enable_shared_cache
|
||||
finish_test
|
||||
|
|
@ -283,7 +283,7 @@ do_test shell1-3.2.4 {
|
|||
# .databases List names and files of attached databases
|
||||
do_test shell1-3.3.1 {
|
||||
catchcmd "-csv test.db" ".databases"
|
||||
} "/0 +.*main +[string map {/ .} [string range [pwd] 0 10]].*/"
|
||||
} "/0 +.*main +[string map {/ .} [string range [get_pwd] 0 10]].*/"
|
||||
do_test shell1-3.3.2 {
|
||||
# too many arguments
|
||||
catchcmd "test.db" ".databases BAD"
|
||||
|
|
|
@ -19,6 +19,8 @@
|
|||
#
|
||||
# Commands to manipulate the db and the file-system at a high level:
|
||||
#
|
||||
# is_relative_file
|
||||
# test_pwd
|
||||
# get_pwd
|
||||
# copy_file FROM TO
|
||||
# delete_file FILENAME
|
||||
|
@ -212,6 +214,34 @@ proc do_copy_file {force from to} {
|
|||
}
|
||||
}
|
||||
|
||||
# Check if a file name is relative
|
||||
#
|
||||
proc is_relative_file { file } {
|
||||
return [expr {[file pathtype $file] != "absolute"}]
|
||||
}
|
||||
|
||||
# If the VFS supports using the current directory, returns [pwd];
|
||||
# otherwise, it returns only the provided suffix string (which is
|
||||
# empty by default).
|
||||
#
|
||||
proc test_pwd { args } {
|
||||
if {[llength $args] > 0} {
|
||||
set suffix1 [lindex $args 0]
|
||||
if {[llength $args] > 1} {
|
||||
set suffix2 [lindex $args 1]
|
||||
} else {
|
||||
set suffix2 $suffix1
|
||||
}
|
||||
} else {
|
||||
set suffix1 ""; set suffix2 ""
|
||||
}
|
||||
ifcapable curdir {
|
||||
return "[get_pwd]$suffix1"
|
||||
} else {
|
||||
return $suffix2
|
||||
}
|
||||
}
|
||||
|
||||
# Delete a file or directory
|
||||
#
|
||||
proc delete_file {args} {
|
||||
|
|
|
@ -52,11 +52,24 @@ foreach {tn uri file} {
|
|||
16 file://localhostPWD/test.db%3Fhello test.db?hello
|
||||
} {
|
||||
|
||||
|
||||
ifcapable !curdir { if {$tn==3} break }
|
||||
|
||||
if {$tcl_platform(platform)=="windows"} {
|
||||
#
|
||||
# NOTE: Due to limits on legal characters for file names imposed by
|
||||
# Windows, we must skip the final two tests here (i.e. the
|
||||
# question mark is illegal in a file name on Windows).
|
||||
#
|
||||
if {$tn>14} break
|
||||
set uri [string map [list PWD /[get_pwd]] $uri]
|
||||
|
||||
#
|
||||
# NOTE: On Windows, we need to account for the fact that the current
|
||||
# directory does not start with a forward slash.
|
||||
#
|
||||
set uri [string map [list PWD/ /[test_pwd /]] $uri]
|
||||
} else {
|
||||
set uri [string map [list PWD [get_pwd]] $uri]
|
||||
set uri [string map [list PWD/ [test_pwd /]] $uri]
|
||||
}
|
||||
|
||||
if {[file isdir $file]} {error "$file is a directory"}
|
||||
|
|
|
@ -1222,6 +1222,10 @@ do_test vtab1-17.1 {
|
|||
}
|
||||
} {}
|
||||
|
||||
do_test vtab1-17.2 {
|
||||
execsql { DELETE FROM sqlite_master WHERE sql LIKE 'insert%' }
|
||||
} {}
|
||||
|
||||
#-------------------------------------------------------------------------
|
||||
# The following tests - vtab1-18.* - test that the optimization of LIKE
|
||||
# constraints in where.c plays well with virtual tables.
|
||||
|
@ -1275,4 +1279,18 @@ foreach {tn sql res filter} {
|
|||
}
|
||||
do_execsql_test 18.2.x { PRAGMA case_sensitive_like = OFF }
|
||||
|
||||
#-------------------------------------------------------------------------
|
||||
# Test that an existing module may not be overridden.
|
||||
#
|
||||
do_test 19.1 {
|
||||
sqlite3 db2 test.db
|
||||
register_echo_module [sqlite3_connection_pointer db2]
|
||||
} SQLITE_OK
|
||||
do_test 19.2 {
|
||||
register_echo_module [sqlite3_connection_pointer db2]
|
||||
} SQLITE_MISUSE
|
||||
do_test 19.3 {
|
||||
db2 close
|
||||
} {}
|
||||
|
||||
finish_test
|
||||
|
|
|
@ -1478,7 +1478,11 @@ foreach pgsz {512 1024 2048 4096 8192 16384 32768 65536} {
|
|||
# Test that when 1 or more pages are recovered from a WAL file,
|
||||
# sqlite3_log() is invoked to report this to the user.
|
||||
#
|
||||
set walfile [file nativename [file join [get_pwd] test.db-wal]]
|
||||
ifcapable curdir {
|
||||
set walfile [file nativename [file join [get_pwd] test.db-wal]]
|
||||
} else {
|
||||
set walfile test.db-wal
|
||||
}
|
||||
catch {db close}
|
||||
forcedelete test.db
|
||||
do_test wal-23.1 {
|
||||
|
|
|
@ -316,6 +316,8 @@ foreach file {
|
|||
fts3_tokenizer1.c
|
||||
fts3_write.c
|
||||
fts3_snippet.c
|
||||
fts3_unicode.c
|
||||
fts3_unicode2.c
|
||||
|
||||
rtree.c
|
||||
icu.c
|
||||
|
|
|
@ -7,7 +7,7 @@ rm -f sqlite3.c
|
|||
make sqlite3.c
|
||||
echo '************* FTS4 and RTREE ****************'
|
||||
scan-build gcc -c -DHAVE_STDINT_H -DSQLITE_ENABLE_FTS4 -DSQLITE_ENABLE_RTREE \
|
||||
-DSQLITE_DEBUG sqlite3.c 2>&1 | grep -v 'ANALYZE:'
|
||||
-DSQLITE_DEBUG -DSQLITE_ENABLE_STAT3 sqlite3.c 2>&1 | grep -v 'ANALYZE:'
|
||||
echo '********** ENABLE_STAT3. THREADSAFE=0 *******'
|
||||
scan-build gcc -c -I. -DSQLITE_ENABLE_STAT3 -DSQLITE_THREADSAFE=0 \
|
||||
-DSQLITE_DEBUG \
|
||||
|
|
Loading…
Reference in New Issue