mirror of
https://github.com/sqlite/sqlite.git
synced 2025-08-08 14:02:16 +03:00
Merge the latest trunk enhancements into the bedrock branch.
FossilOrigin-Name: c1f616ce802fbb9c3652f8cb43970e4bda18464e765f23fb5f96029721431092
This commit is contained in:
@@ -456,6 +456,7 @@ TESTSRC += \
|
||||
$(TOP)/ext/misc/remember.c \
|
||||
$(TOP)/ext/misc/series.c \
|
||||
$(TOP)/ext/misc/spellfix.c \
|
||||
$(TOP)/ext/misc/stmtrand.c \
|
||||
$(TOP)/ext/misc/totype.c \
|
||||
$(TOP)/ext/misc/unionvtab.c \
|
||||
$(TOP)/ext/misc/wholenumber.c \
|
||||
|
@@ -1597,6 +1597,7 @@ TESTEXT = \
|
||||
$(TOP)\ext\misc\remember.c \
|
||||
$(TOP)\ext\misc\series.c \
|
||||
$(TOP)\ext\misc\spellfix.c \
|
||||
$(TOP)\ext\misc\stmtrand.c \
|
||||
$(TOP)\ext\misc\totype.c \
|
||||
$(TOP)\ext\misc\unionvtab.c \
|
||||
$(TOP)\ext\misc\wholenumber.c \
|
||||
|
@@ -19,7 +19,7 @@ dnl to configure the system for the local environment.
|
||||
# so that we create the export library with the dll.
|
||||
#-----------------------------------------------------------------------
|
||||
|
||||
AC_INIT([sqlite],[3.46.0])
|
||||
AC_INIT([sqlite],[3.47.0])
|
||||
|
||||
#--------------------------------------------------------------------
|
||||
# Call TEA_INIT as the first TEA_ macro to set up initial vars.
|
||||
|
@@ -708,4 +708,3 @@ TK_INCLUDES = -I"$(_TKDIR)\generic" -I"$(_TKDIR)\win" -I"$(_TKDIR)\xlib"
|
||||
!message *** Link options '$(LINKERFLAGS)'
|
||||
|
||||
!endif
|
||||
|
||||
|
40
configure
vendored
40
configure
vendored
@@ -1,6 +1,6 @@
|
||||
#! /bin/sh
|
||||
# Guess values for system-dependent variables and create Makefiles.
|
||||
# Generated by GNU Autoconf 2.69 for sqlite 3.46.0.
|
||||
# Generated by GNU Autoconf 2.69 for sqlite 3.47.0.
|
||||
#
|
||||
#
|
||||
# Copyright (C) 1992-1996, 1998-2012 Free Software Foundation, Inc.
|
||||
@@ -726,8 +726,8 @@ MAKEFLAGS=
|
||||
# Identity of this package.
|
||||
PACKAGE_NAME='sqlite'
|
||||
PACKAGE_TARNAME='sqlite'
|
||||
PACKAGE_VERSION='3.46.0'
|
||||
PACKAGE_STRING='sqlite 3.46.0'
|
||||
PACKAGE_VERSION='3.47.0'
|
||||
PACKAGE_STRING='sqlite 3.47.0'
|
||||
PACKAGE_BUGREPORT=''
|
||||
PACKAGE_URL=''
|
||||
|
||||
@@ -1472,7 +1472,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.46.0 to adapt to many kinds of systems.
|
||||
\`configure' configures sqlite 3.47.0 to adapt to many kinds of systems.
|
||||
|
||||
Usage: $0 [OPTION]... [VAR=VALUE]...
|
||||
|
||||
@@ -1537,7 +1537,7 @@ fi
|
||||
|
||||
if test -n "$ac_init_help"; then
|
||||
case $ac_init_help in
|
||||
short | recursive ) echo "Configuration of sqlite 3.46.0:";;
|
||||
short | recursive ) echo "Configuration of sqlite 3.47.0:";;
|
||||
esac
|
||||
cat <<\_ACEOF
|
||||
|
||||
@@ -1668,7 +1668,7 @@ fi
|
||||
test -n "$ac_init_help" && exit $ac_status
|
||||
if $ac_init_version; then
|
||||
cat <<\_ACEOF
|
||||
sqlite configure 3.46.0
|
||||
sqlite configure 3.47.0
|
||||
generated by GNU Autoconf 2.69
|
||||
|
||||
Copyright (C) 2012 Free Software Foundation, Inc.
|
||||
@@ -2087,7 +2087,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.46.0, which was
|
||||
It was created by sqlite $as_me 3.47.0, which was
|
||||
generated by GNU Autoconf 2.69. Invocation command line was
|
||||
|
||||
$ $0 $@
|
||||
@@ -10318,7 +10318,20 @@ USE_AMALGAMATION=1
|
||||
# if not, then we fall back to plain tclsh.
|
||||
# TODO: try other versions before falling back?
|
||||
#
|
||||
for ac_prog in tclsh8.7 tclsh8.6 tclsh8.5 tclsh
|
||||
if test x"${with_tcl}" != x; then
|
||||
if test ! -r ${with_tcl}/tclConfig.sh; then
|
||||
as_fn_error $? "no tclConfig.sh file found in --with-tcl: ${with_tcl}" "$LINENO" 5
|
||||
else
|
||||
. ${with_tcl}/tclConfig.sh
|
||||
TCLSH_CMD=${TCL_EXEC_PREFIX}/bin/tclsh${TCL_VERSION}
|
||||
if test ! -x ${TCLSH_CMD}; then
|
||||
{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: cannot use tclsh at: ${TCLSH_CMD}" >&5
|
||||
$as_echo "$as_me: WARNING: cannot use tclsh at: ${TCLSH_CMD}" >&2;}
|
||||
TCLSH_CMD=none
|
||||
fi
|
||||
fi
|
||||
else
|
||||
for ac_prog in tclsh8.6 tclsh8.5 tclsh
|
||||
do
|
||||
# Extract the first word of "$ac_prog", so it can be a program name with args.
|
||||
set dummy $ac_prog; ac_word=$2
|
||||
@@ -10361,6 +10374,7 @@ fi
|
||||
done
|
||||
test -n "$TCLSH_CMD" || TCLSH_CMD="none"
|
||||
|
||||
fi
|
||||
if test "$TCLSH_CMD" = "none"; then
|
||||
# If we can't find a local tclsh, then building the amalgamation will fail.
|
||||
# We act as though --disable-amalgamation has been used.
|
||||
@@ -10368,6 +10382,12 @@ if test "$TCLSH_CMD" = "none"; then
|
||||
USE_AMALGAMATION=0
|
||||
TCLSH_CMD="tclsh"
|
||||
fi
|
||||
if test x"$TCLSH_CMD" = x; then
|
||||
as_fn_error $? "cannot find a usable tclsh" "$LINENO" 5
|
||||
else
|
||||
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: using $TCLSH_CMD" >&5
|
||||
$as_echo "using $TCLSH_CMD" >&6; }
|
||||
fi
|
||||
|
||||
|
||||
|
||||
@@ -12481,7 +12501,7 @@ cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1
|
||||
# report actual input values of CONFIG_FILES etc. instead of their
|
||||
# values after options handling.
|
||||
ac_log="
|
||||
This file was extended by sqlite $as_me 3.46.0, which was
|
||||
This file was extended by sqlite $as_me 3.47.0, which was
|
||||
generated by GNU Autoconf 2.69. Invocation command line was
|
||||
|
||||
CONFIG_FILES = $CONFIG_FILES
|
||||
@@ -12547,7 +12567,7 @@ _ACEOF
|
||||
cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
|
||||
ac_cs_config="`$as_echo "$ac_configure_args" | sed 's/^ //; s/[\\""\`\$]/\\\\&/g'`"
|
||||
ac_cs_version="\\
|
||||
sqlite config.status 3.46.0
|
||||
sqlite config.status 3.47.0
|
||||
configured by $0, generated by GNU Autoconf 2.69,
|
||||
with options \\"\$ac_cs_config\\"
|
||||
|
||||
|
20
configure.ac
20
configure.ac
@@ -120,7 +120,20 @@ USE_AMALGAMATION=1
|
||||
# if not, then we fall back to plain tclsh.
|
||||
# TODO: try other versions before falling back?
|
||||
#
|
||||
AC_CHECK_PROGS(TCLSH_CMD, [tclsh8.7 tclsh8.6 tclsh8.5 tclsh], none)
|
||||
if test x"${with_tcl}" != x; then
|
||||
if test ! -r ${with_tcl}/tclConfig.sh; then
|
||||
AC_MSG_ERROR([no tclConfig.sh file found in --with-tcl: ${with_tcl}])
|
||||
else
|
||||
. ${with_tcl}/tclConfig.sh
|
||||
TCLSH_CMD=${TCL_EXEC_PREFIX}/bin/tclsh${TCL_VERSION}
|
||||
if test ! -x ${TCLSH_CMD}; then
|
||||
AC_MSG_WARN([cannot use tclsh at: ${TCLSH_CMD}])
|
||||
TCLSH_CMD=none
|
||||
fi
|
||||
fi
|
||||
else
|
||||
AC_CHECK_PROGS(TCLSH_CMD, [tclsh8.6 tclsh8.5 tclsh], none)
|
||||
fi
|
||||
if test "$TCLSH_CMD" = "none"; then
|
||||
# If we can't find a local tclsh, then building the amalgamation will fail.
|
||||
# We act as though --disable-amalgamation has been used.
|
||||
@@ -128,6 +141,11 @@ if test "$TCLSH_CMD" = "none"; then
|
||||
USE_AMALGAMATION=0
|
||||
TCLSH_CMD="tclsh"
|
||||
fi
|
||||
if test x"$TCLSH_CMD" = x; then
|
||||
AC_MSG_ERROR([cannot find a usable tclsh])
|
||||
else
|
||||
AC_MSG_RESULT([using $TCLSH_CMD])
|
||||
fi
|
||||
AC_SUBST(TCLSH_CMD)
|
||||
|
||||
AC_ARG_VAR([TCLLIBDIR], [Where to install tcl plugin])
|
||||
|
@@ -59,8 +59,16 @@ canonical source on a new Windows 11 PC, as of 2023-11-01:
|
||||
<li> `nmake /f makefile.msc sqlite3.c`
|
||||
<li> `nmake /f makefile.msc devtest`
|
||||
<li> `nmake /f makefile.msc releasetest`
|
||||
<li> `nmake /f makefile.msc sqlite3.exe`
|
||||
</ul>
|
||||
|
||||
7. For a debugging build of the CLI, where the ".treetrace" and ".wheretrace"
|
||||
commands work, add the DEBUG=3 argument to nmake. Like this:
|
||||
<ul>
|
||||
<li> `nmake /f makefile.msc DEBUG=3 clean sqlite3.exe`
|
||||
</ul>
|
||||
|
||||
|
||||
## 32-bit Builds
|
||||
|
||||
Doing a 32-bit build is just like doing a 64-bit build with the
|
||||
|
@@ -16,15 +16,7 @@
|
||||
#include "sqlite3expert.h"
|
||||
#include <assert.h>
|
||||
#include <string.h>
|
||||
|
||||
#if defined(INCLUDE_SQLITE_TCL_H)
|
||||
# include "sqlite_tcl.h"
|
||||
#else
|
||||
# include "tcl.h"
|
||||
# ifndef SQLITE_TCLAPI
|
||||
# define SQLITE_TCLAPI
|
||||
# endif
|
||||
#endif
|
||||
#include "tclsqlite.h"
|
||||
|
||||
#ifndef SQLITE_OMIT_VIRTUALTABLE
|
||||
|
||||
|
@@ -79,6 +79,8 @@ static int fts3termConnectMethod(
|
||||
argc--;
|
||||
}
|
||||
|
||||
*ppVtab = 0;
|
||||
|
||||
/* The user should specify a single argument - the name of an fts3 table. */
|
||||
if( argc!=4 ){
|
||||
sqlite3Fts3ErrMsg(pzErr,
|
||||
@@ -95,12 +97,17 @@ static int fts3termConnectMethod(
|
||||
rc = sqlite3_declare_vtab(db, FTS3_TERMS_SCHEMA);
|
||||
if( rc!=SQLITE_OK ) return rc;
|
||||
|
||||
nByte = sizeof(Fts3termTable) + sizeof(Fts3Table) + nDb + nFts3 + 2;
|
||||
p = (Fts3termTable *)sqlite3_malloc64(nByte);
|
||||
nByte = sizeof(Fts3termTable);
|
||||
p = (Fts3termTable *)sqlite3Fts3MallocZero(nByte);
|
||||
if( !p ) return SQLITE_NOMEM;
|
||||
memset(p, 0, (size_t)nByte);
|
||||
|
||||
p->pFts3Tab = (Fts3Table *)&p[1];
|
||||
p->pFts3Tab = (Fts3Table*)sqlite3Fts3MallocZero(
|
||||
sizeof(Fts3Table) + nDb + nFts3 + 2
|
||||
);
|
||||
if( p->pFts3Tab==0 ){
|
||||
sqlite3_free(p);
|
||||
return SQLITE_NOMEM;
|
||||
}
|
||||
p->pFts3Tab->zDb = (char *)&p->pFts3Tab[1];
|
||||
p->pFts3Tab->zName = &p->pFts3Tab->zDb[nDb+1];
|
||||
p->pFts3Tab->db = db;
|
||||
@@ -130,6 +137,7 @@ static int fts3termDisconnectMethod(sqlite3_vtab *pVtab){
|
||||
sqlite3_finalize(pFts3->aStmt[i]);
|
||||
}
|
||||
sqlite3_free(pFts3->zSegmentsTbl);
|
||||
sqlite3_free(pFts3);
|
||||
sqlite3_free(p);
|
||||
return SQLITE_OK;
|
||||
}
|
||||
|
@@ -18,14 +18,7 @@
|
||||
** that the sqlite3_tokenizer_module.xLanguage() method is invoked correctly.
|
||||
*/
|
||||
|
||||
#if defined(INCLUDE_SQLITE_TCL_H)
|
||||
# include "sqlite_tcl.h"
|
||||
#else
|
||||
# include "tcl.h"
|
||||
# ifndef SQLITE_TCLAPI
|
||||
# define SQLITE_TCLAPI
|
||||
# endif
|
||||
#endif
|
||||
#include "tclsqlite.h"
|
||||
#include <string.h>
|
||||
#include <assert.h>
|
||||
|
||||
@@ -167,7 +160,8 @@ static int SQLITE_TCLAPI fts3_near_match_cmd(
|
||||
Tcl_Obj *pPhrasecount = 0;
|
||||
|
||||
Tcl_Obj **apExprToken;
|
||||
int nExprToken;
|
||||
Tcl_Size nExprToken;
|
||||
Tcl_Size nn;
|
||||
|
||||
UNUSED_PARAMETER(clientData);
|
||||
|
||||
@@ -201,23 +195,25 @@ static int SQLITE_TCLAPI fts3_near_match_cmd(
|
||||
}
|
||||
}
|
||||
|
||||
rc = Tcl_ListObjGetElements(interp, objv[1], &doc.nToken, &apDocToken);
|
||||
rc = Tcl_ListObjGetElements(interp, objv[1], &nn, &apDocToken);
|
||||
doc.nToken = (int)nn;
|
||||
if( rc!=TCL_OK ) goto near_match_out;
|
||||
doc.aToken = (NearToken *)ckalloc(doc.nToken*sizeof(NearToken));
|
||||
for(ii=0; ii<doc.nToken; ii++){
|
||||
doc.aToken[ii].z = Tcl_GetStringFromObj(apDocToken[ii], &doc.aToken[ii].n);
|
||||
doc.aToken[ii].z = Tcl_GetStringFromObj(apDocToken[ii], &nn);
|
||||
doc.aToken[ii].n = (int)nn;
|
||||
}
|
||||
|
||||
rc = Tcl_ListObjGetElements(interp, objv[2], &nExprToken, &apExprToken);
|
||||
if( rc!=TCL_OK ) goto near_match_out;
|
||||
|
||||
nPhrase = (nExprToken + 1) / 2;
|
||||
nPhrase = (int)(nExprToken + 1) / 2;
|
||||
aPhrase = (NearPhrase *)ckalloc(nPhrase * sizeof(NearPhrase));
|
||||
memset(aPhrase, 0, nPhrase * sizeof(NearPhrase));
|
||||
for(ii=0; ii<nPhrase; ii++){
|
||||
Tcl_Obj *pPhrase = apExprToken[ii*2];
|
||||
Tcl_Obj **apToken;
|
||||
int nToken;
|
||||
Tcl_Size nToken;
|
||||
int jj;
|
||||
|
||||
rc = Tcl_ListObjGetElements(interp, pPhrase, &nToken, &apToken);
|
||||
@@ -227,11 +223,12 @@ static int SQLITE_TCLAPI fts3_near_match_cmd(
|
||||
rc = TCL_ERROR;
|
||||
goto near_match_out;
|
||||
}
|
||||
for(jj=0; jj<nToken; jj++){
|
||||
for(jj=0; jj<(int)nToken; jj++){
|
||||
NearToken *pT = &aPhrase[ii].aToken[jj];
|
||||
pT->z = Tcl_GetStringFromObj(apToken[jj], &pT->n);
|
||||
pT->z = Tcl_GetStringFromObj(apToken[jj], &nn);
|
||||
pT->n = (int)nn;
|
||||
}
|
||||
aPhrase[ii].nToken = nToken;
|
||||
aPhrase[ii].nToken = (int)nToken;
|
||||
}
|
||||
for(ii=1; ii<nPhrase; ii++){
|
||||
Tcl_Obj *pNear = apExprToken[2*ii-1];
|
||||
|
@@ -226,11 +226,7 @@ int sqlite3Fts3InitTokenizer(
|
||||
|
||||
#ifdef SQLITE_TEST
|
||||
|
||||
#if defined(INCLUDE_SQLITE_TCL_H)
|
||||
# include "sqlite_tcl.h"
|
||||
#else
|
||||
# include "tcl.h"
|
||||
#endif
|
||||
#include "tclsqlite.h"
|
||||
#include <string.h>
|
||||
|
||||
/*
|
||||
|
@@ -238,6 +238,10 @@ struct Fts5PhraseIter {
|
||||
** (i.e. if it is a contentless table), then this API always iterates
|
||||
** through an empty set (all calls to xPhraseFirst() set iCol to -1).
|
||||
**
|
||||
** In all cases, matches are visited in (column ASC, offset ASC) order.
|
||||
** i.e. all those in column 0, sorted by offset, followed by those in
|
||||
** column 1, etc.
|
||||
**
|
||||
** xPhraseNext()
|
||||
** See xPhraseFirst above.
|
||||
**
|
||||
|
@@ -59,6 +59,22 @@ typedef sqlite3_uint64 u64;
|
||||
# define LARGEST_INT64 (0xffffffff|(((i64)0x7fffffff)<<32))
|
||||
# define SMALLEST_INT64 (((i64)-1) - LARGEST_INT64)
|
||||
|
||||
/* The uptr type is an unsigned integer large enough to hold a pointer
|
||||
*/
|
||||
#if defined(HAVE_STDINT_H)
|
||||
typedef uintptr_t uptr;
|
||||
#elif SQLITE_PTRSIZE==4
|
||||
typedef u32 uptr;
|
||||
#else
|
||||
typedef u64 uptr;
|
||||
#endif
|
||||
|
||||
#ifdef SQLITE_4_BYTE_ALIGNED_MALLOC
|
||||
# define EIGHT_BYTE_ALIGNMENT(X) ((((uptr)(X) - (uptr)0)&3)==0)
|
||||
#else
|
||||
# define EIGHT_BYTE_ALIGNMENT(X) ((((uptr)(X) - (uptr)0)&7)==0)
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
/* Truncate very long tokens to this many bytes. Hard limit is
|
||||
@@ -142,6 +158,15 @@ struct Fts5Colset {
|
||||
*/
|
||||
|
||||
typedef struct Fts5Config Fts5Config;
|
||||
typedef struct Fts5TokenizerConfig Fts5TokenizerConfig;
|
||||
|
||||
struct Fts5TokenizerConfig {
|
||||
Fts5Tokenizer *pTok;
|
||||
fts5_tokenizer *pTokApi;
|
||||
const char **azArg;
|
||||
int nArg;
|
||||
int ePattern; /* FTS_PATTERN_XXX constant */
|
||||
};
|
||||
|
||||
/*
|
||||
** An instance of the following structure encodes all information that can
|
||||
@@ -184,6 +209,7 @@ typedef struct Fts5Config Fts5Config;
|
||||
*/
|
||||
struct Fts5Config {
|
||||
sqlite3 *db; /* Database handle */
|
||||
Fts5Global *pGlobal; /* Global fts5 object for handle db */
|
||||
char *zDb; /* Database holding FTS index (e.g. "main") */
|
||||
char *zName; /* Name of FTS index */
|
||||
int nCol; /* Number of columns */
|
||||
@@ -199,10 +225,8 @@ struct Fts5Config {
|
||||
int bTokendata; /* "tokendata=" option value (dflt==0) */
|
||||
int eDetail; /* FTS5_DETAIL_XXX value */
|
||||
char *zContentExprlist;
|
||||
Fts5Tokenizer *pTok;
|
||||
fts5_tokenizer *pTokApi;
|
||||
Fts5TokenizerConfig t;
|
||||
int bLock; /* True when table is preparing statement */
|
||||
int ePattern; /* FTS_PATTERN_XXX constant */
|
||||
|
||||
/* Values loaded from the %_config table */
|
||||
int iVersion; /* fts5 file format 'version' */
|
||||
@@ -597,13 +621,7 @@ struct Fts5Table {
|
||||
Fts5Index *pIndex; /* Full-text index */
|
||||
};
|
||||
|
||||
int sqlite3Fts5GetTokenizer(
|
||||
Fts5Global*,
|
||||
const char **azArg,
|
||||
int nArg,
|
||||
Fts5Config*,
|
||||
char **pzErr
|
||||
);
|
||||
int sqlite3Fts5LoadTokenizer(Fts5Config *pConfig);
|
||||
|
||||
Fts5Table *sqlite3Fts5TableFromCsrid(Fts5Global*, i64);
|
||||
|
||||
@@ -866,6 +884,7 @@ int sqlite3Fts5TokenizerPattern(
|
||||
int (*xCreate)(void*, const char**, int, Fts5Tokenizer**),
|
||||
Fts5Tokenizer *pTok
|
||||
);
|
||||
int sqlite3Fts5TokenizerPreload(Fts5TokenizerConfig*);
|
||||
/*
|
||||
** End of interface to code in fts5_tokenizer.c.
|
||||
**************************************************************************/
|
||||
|
@@ -234,7 +234,6 @@ static int fts5ConfigSetEnum(
|
||||
** eventually free any such error message using sqlite3_free().
|
||||
*/
|
||||
static int fts5ConfigParseSpecial(
|
||||
Fts5Global *pGlobal,
|
||||
Fts5Config *pConfig, /* Configuration object to update */
|
||||
const char *zCmd, /* Special command to parse */
|
||||
const char *zArg, /* Argument to parse */
|
||||
@@ -298,12 +297,11 @@ static int fts5ConfigParseSpecial(
|
||||
if( sqlite3_strnicmp("tokenize", zCmd, nCmd)==0 ){
|
||||
const char *p = (const char*)zArg;
|
||||
sqlite3_int64 nArg = strlen(zArg) + 1;
|
||||
char **azArg = sqlite3Fts5MallocZero(&rc, sizeof(char*) * nArg);
|
||||
char *pDel = sqlite3Fts5MallocZero(&rc, nArg * 2);
|
||||
char *pSpace = pDel;
|
||||
char **azArg = sqlite3Fts5MallocZero(&rc, (sizeof(char*) + 2) * nArg);
|
||||
|
||||
if( azArg && pSpace ){
|
||||
if( pConfig->pTok ){
|
||||
if( azArg ){
|
||||
char *pSpace = (char*)&azArg[nArg];
|
||||
if( pConfig->t.azArg ){
|
||||
*pzErr = sqlite3_mprintf("multiple tokenize=... directives");
|
||||
rc = SQLITE_ERROR;
|
||||
}else{
|
||||
@@ -326,16 +324,14 @@ static int fts5ConfigParseSpecial(
|
||||
*pzErr = sqlite3_mprintf("parse error in tokenize directive");
|
||||
rc = SQLITE_ERROR;
|
||||
}else{
|
||||
rc = sqlite3Fts5GetTokenizer(pGlobal,
|
||||
(const char**)azArg, (int)nArg, pConfig,
|
||||
pzErr
|
||||
);
|
||||
pConfig->t.azArg = (const char**)azArg;
|
||||
pConfig->t.nArg = nArg;
|
||||
azArg = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
sqlite3_free(azArg);
|
||||
sqlite3_free(pDel);
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
@@ -412,16 +408,6 @@ static int fts5ConfigParseSpecial(
|
||||
return SQLITE_ERROR;
|
||||
}
|
||||
|
||||
/*
|
||||
** Allocate an instance of the default tokenizer ("simple") at
|
||||
** Fts5Config.pTokenizer. Return SQLITE_OK if successful, or an SQLite error
|
||||
** code if an error occurs.
|
||||
*/
|
||||
static int fts5ConfigDefaultTokenizer(Fts5Global *pGlobal, Fts5Config *pConfig){
|
||||
assert( pConfig->pTok==0 && pConfig->pTokApi==0 );
|
||||
return sqlite3Fts5GetTokenizer(pGlobal, 0, 0, pConfig, 0);
|
||||
}
|
||||
|
||||
/*
|
||||
** Gobble up the first bareword or quoted word from the input buffer zIn.
|
||||
** Return a pointer to the character immediately following the last in
|
||||
@@ -554,6 +540,7 @@ int sqlite3Fts5ConfigParse(
|
||||
*ppOut = pRet = (Fts5Config*)sqlite3_malloc(sizeof(Fts5Config));
|
||||
if( pRet==0 ) return SQLITE_NOMEM;
|
||||
memset(pRet, 0, sizeof(Fts5Config));
|
||||
pRet->pGlobal = pGlobal;
|
||||
pRet->db = db;
|
||||
pRet->iCookie = -1;
|
||||
|
||||
@@ -602,7 +589,7 @@ int sqlite3Fts5ConfigParse(
|
||||
rc = SQLITE_ERROR;
|
||||
}else{
|
||||
if( bOption ){
|
||||
rc = fts5ConfigParseSpecial(pGlobal, pRet,
|
||||
rc = fts5ConfigParseSpecial(pRet,
|
||||
ALWAYS(zOne)?zOne:"",
|
||||
zTwo?zTwo:"",
|
||||
pzErr
|
||||
@@ -640,13 +627,6 @@ int sqlite3Fts5ConfigParse(
|
||||
rc = SQLITE_ERROR;
|
||||
}
|
||||
|
||||
/* If a tokenizer= option was successfully parsed, the tokenizer has
|
||||
** already been allocated. Otherwise, allocate an instance of the default
|
||||
** tokenizer (unicode61) now. */
|
||||
if( rc==SQLITE_OK && pRet->pTok==0 ){
|
||||
rc = fts5ConfigDefaultTokenizer(pGlobal, pRet);
|
||||
}
|
||||
|
||||
/* If no zContent option was specified, fill in the default values. */
|
||||
if( rc==SQLITE_OK && pRet->zContent==0 ){
|
||||
const char *zTail = 0;
|
||||
@@ -688,9 +668,10 @@ int sqlite3Fts5ConfigParse(
|
||||
void sqlite3Fts5ConfigFree(Fts5Config *pConfig){
|
||||
if( pConfig ){
|
||||
int i;
|
||||
if( pConfig->pTok ){
|
||||
pConfig->pTokApi->xDelete(pConfig->pTok);
|
||||
if( pConfig->t.pTok ){
|
||||
pConfig->t.pTokApi->xDelete(pConfig->t.pTok);
|
||||
}
|
||||
sqlite3_free((char*)pConfig->t.azArg);
|
||||
sqlite3_free(pConfig->zDb);
|
||||
sqlite3_free(pConfig->zName);
|
||||
for(i=0; i<pConfig->nCol; i++){
|
||||
@@ -765,10 +746,18 @@ int sqlite3Fts5Tokenize(
|
||||
void *pCtx, /* Context passed to xToken() */
|
||||
int (*xToken)(void*, int, const char*, int, int, int) /* Callback */
|
||||
){
|
||||
if( pText==0 ) return SQLITE_OK;
|
||||
return pConfig->pTokApi->xTokenize(
|
||||
pConfig->pTok, pCtx, flags, pText, nText, xToken
|
||||
);
|
||||
int rc = SQLITE_OK;
|
||||
if( pText ){
|
||||
if( pConfig->t.pTok==0 ){
|
||||
rc = sqlite3Fts5LoadTokenizer(pConfig);
|
||||
}
|
||||
if( rc==SQLITE_OK ){
|
||||
rc = pConfig->t.pTokApi->xTokenize(
|
||||
pConfig->t.pTok, pCtx, flags, pText, nText, xToken
|
||||
);
|
||||
}
|
||||
}
|
||||
return rc;
|
||||
}
|
||||
|
||||
/*
|
||||
|
@@ -324,7 +324,11 @@ int sqlite3Fts5ExprNew(
|
||||
}
|
||||
|
||||
sqlite3_free(sParse.apPhrase);
|
||||
*pzErr = sParse.zErr;
|
||||
if( 0==*pzErr ){
|
||||
*pzErr = sParse.zErr;
|
||||
}else{
|
||||
sqlite3_free(sParse.zErr);
|
||||
}
|
||||
return sParse.rc;
|
||||
}
|
||||
|
||||
@@ -1871,6 +1875,7 @@ Fts5ExprPhrase *sqlite3Fts5ParseTerm(
|
||||
}else if( sCtx.pPhrase->nTerm ){
|
||||
sCtx.pPhrase->aTerm[sCtx.pPhrase->nTerm-1].bPrefix = (u8)bPrefix;
|
||||
}
|
||||
assert( pParse->apPhrase!=0 );
|
||||
pParse->apPhrase[pParse->nPhrase-1] = sCtx.pPhrase;
|
||||
}
|
||||
|
||||
@@ -1890,7 +1895,7 @@ int sqlite3Fts5ExprClonePhrase(
|
||||
Fts5ExprPhrase *pOrig = 0; /* The phrase extracted from pExpr */
|
||||
Fts5Expr *pNew = 0; /* Expression to return via *ppNew */
|
||||
TokenCtx sCtx = {0,0,0}; /* Context object for fts5ParseTokenize */
|
||||
if( iPhrase<0 || iPhrase>=pExpr->nPhrase ){
|
||||
if( !pExpr || iPhrase<0 || iPhrase>=pExpr->nPhrase ){
|
||||
rc = SQLITE_RANGE;
|
||||
}else{
|
||||
pOrig = pExpr->apExprPhrase[iPhrase];
|
||||
@@ -2465,6 +2470,8 @@ Fts5ExprNode *sqlite3Fts5ParseImplicitAnd(
|
||||
);
|
||||
|
||||
if( pRight->eType==FTS5_EOF ){
|
||||
assert( pParse->apPhrase!=0 );
|
||||
assert( pParse->nPhrase>0 );
|
||||
assert( pParse->apPhrase[pParse->nPhrase-1]==pRight->pNear->apPhrase[0] );
|
||||
sqlite3Fts5ParseNodeFree(pRight);
|
||||
pRet = pLeft;
|
||||
|
@@ -831,11 +831,12 @@ static Fts5Data *fts5DataRead(Fts5Index *p, i64 iRowid){
|
||||
if( rc==SQLITE_OK ){
|
||||
u8 *aOut = 0; /* Read blob data into this buffer */
|
||||
int nByte = sqlite3_blob_bytes(p->pReader);
|
||||
sqlite3_int64 nAlloc = sizeof(Fts5Data) + nByte + FTS5_DATA_PADDING;
|
||||
int szData = (sizeof(Fts5Data) + 7) & ~7;
|
||||
sqlite3_int64 nAlloc = szData + nByte + FTS5_DATA_PADDING;
|
||||
pRet = (Fts5Data*)sqlite3_malloc64(nAlloc);
|
||||
if( pRet ){
|
||||
pRet->nn = nByte;
|
||||
aOut = pRet->p = (u8*)&pRet[1];
|
||||
aOut = pRet->p = (u8*)pRet + szData;
|
||||
}else{
|
||||
rc = SQLITE_NOMEM;
|
||||
}
|
||||
@@ -858,6 +859,7 @@ static Fts5Data *fts5DataRead(Fts5Index *p, i64 iRowid){
|
||||
}
|
||||
|
||||
assert( (pRet==0)==(p->rc!=SQLITE_OK) );
|
||||
assert( pRet==0 || EIGHT_BYTE_ALIGNMENT( pRet->p ) );
|
||||
return pRet;
|
||||
}
|
||||
|
||||
|
@@ -377,8 +377,12 @@ static int fts5InitVtab(
|
||||
assert( (rc==SQLITE_OK && *pzErr==0) || pConfig==0 );
|
||||
}
|
||||
if( rc==SQLITE_OK ){
|
||||
pConfig->pzErrmsg = pzErr;
|
||||
pTab->p.pConfig = pConfig;
|
||||
pTab->pGlobal = pGlobal;
|
||||
if( bCreate || sqlite3Fts5TokenizerPreload(&pConfig->t) ){
|
||||
rc = sqlite3Fts5LoadTokenizer(pConfig);
|
||||
}
|
||||
}
|
||||
|
||||
/* Open the index sub-system */
|
||||
@@ -400,11 +404,8 @@ static int fts5InitVtab(
|
||||
|
||||
/* Load the initial configuration */
|
||||
if( rc==SQLITE_OK ){
|
||||
assert( pConfig->pzErrmsg==0 );
|
||||
pConfig->pzErrmsg = pzErr;
|
||||
rc = sqlite3Fts5IndexLoadConfig(pTab->p.pIndex);
|
||||
sqlite3Fts5IndexRollback(pTab->p.pIndex);
|
||||
pConfig->pzErrmsg = 0;
|
||||
}
|
||||
|
||||
if( rc==SQLITE_OK && pConfig->eContent==FTS5_CONTENT_NORMAL ){
|
||||
@@ -414,6 +415,7 @@ static int fts5InitVtab(
|
||||
rc = sqlite3_vtab_config(db, SQLITE_VTAB_INNOCUOUS);
|
||||
}
|
||||
|
||||
if( pConfig ) pConfig->pzErrmsg = 0;
|
||||
if( rc!=SQLITE_OK ){
|
||||
fts5FreeVtab(pTab);
|
||||
pTab = 0;
|
||||
@@ -481,10 +483,10 @@ static int fts5UsePatternMatch(
|
||||
){
|
||||
assert( FTS5_PATTERN_GLOB==SQLITE_INDEX_CONSTRAINT_GLOB );
|
||||
assert( FTS5_PATTERN_LIKE==SQLITE_INDEX_CONSTRAINT_LIKE );
|
||||
if( pConfig->ePattern==FTS5_PATTERN_GLOB && p->op==FTS5_PATTERN_GLOB ){
|
||||
if( pConfig->t.ePattern==FTS5_PATTERN_GLOB && p->op==FTS5_PATTERN_GLOB ){
|
||||
return 1;
|
||||
}
|
||||
if( pConfig->ePattern==FTS5_PATTERN_LIKE
|
||||
if( pConfig->t.ePattern==FTS5_PATTERN_LIKE
|
||||
&& (p->op==FTS5_PATTERN_LIKE || p->op==FTS5_PATTERN_GLOB)
|
||||
){
|
||||
return 1;
|
||||
@@ -531,10 +533,10 @@ static int fts5UsePatternMatch(
|
||||
** This function ensures that there is at most one "r" or "=". And that if
|
||||
** there exists an "=" then there is no "<" or ">".
|
||||
**
|
||||
** Costs are assigned as follows:
|
||||
** If an unusable MATCH operator is present in the WHERE clause, then
|
||||
** SQLITE_CONSTRAINT is returned.
|
||||
**
|
||||
** a) If an unusable MATCH operator is present in the WHERE clause, the
|
||||
** cost is unconditionally set to 1e50 (a really big number).
|
||||
** Costs are assigned as follows:
|
||||
**
|
||||
** a) If a MATCH operator is present, the cost depends on the other
|
||||
** constraints also present. As follows:
|
||||
@@ -567,7 +569,7 @@ static int fts5BestIndexMethod(sqlite3_vtab *pVTab, sqlite3_index_info *pInfo){
|
||||
int bSeenEq = 0;
|
||||
int bSeenGt = 0;
|
||||
int bSeenLt = 0;
|
||||
int bSeenMatch = 0;
|
||||
int nSeenMatch = 0;
|
||||
int bSeenRank = 0;
|
||||
|
||||
|
||||
@@ -598,18 +600,15 @@ static int fts5BestIndexMethod(sqlite3_vtab *pVTab, sqlite3_index_info *pInfo){
|
||||
/* A MATCH operator or equivalent */
|
||||
if( p->usable==0 || iCol<0 ){
|
||||
/* As there exists an unusable MATCH constraint this is an
|
||||
** unusable plan. Set a prohibitively high cost. */
|
||||
pInfo->estimatedCost = 1e50;
|
||||
assert( iIdxStr < pInfo->nConstraint*6 + 1 );
|
||||
idxStr[iIdxStr] = 0;
|
||||
return SQLITE_OK;
|
||||
** unusable plan. Return SQLITE_CONSTRAINT. */
|
||||
return SQLITE_CONSTRAINT;
|
||||
}else{
|
||||
if( iCol==nCol+1 ){
|
||||
if( bSeenRank ) continue;
|
||||
idxStr[iIdxStr++] = 'r';
|
||||
bSeenRank = 1;
|
||||
}else if( iCol>=0 ){
|
||||
bSeenMatch = 1;
|
||||
nSeenMatch++;
|
||||
idxStr[iIdxStr++] = 'M';
|
||||
sqlite3_snprintf(6, &idxStr[iIdxStr], "%d", iCol);
|
||||
idxStr += strlen(&idxStr[iIdxStr]);
|
||||
@@ -626,6 +625,7 @@ static int fts5BestIndexMethod(sqlite3_vtab *pVTab, sqlite3_index_info *pInfo){
|
||||
idxStr += strlen(&idxStr[iIdxStr]);
|
||||
pInfo->aConstraintUsage[i].argvIndex = ++iCons;
|
||||
assert( idxStr[iIdxStr]=='\0' );
|
||||
nSeenMatch++;
|
||||
}else if( bSeenEq==0 && p->op==SQLITE_INDEX_CONSTRAINT_EQ && iCol<0 ){
|
||||
idxStr[iIdxStr++] = '=';
|
||||
bSeenEq = 1;
|
||||
@@ -662,7 +662,7 @@ static int fts5BestIndexMethod(sqlite3_vtab *pVTab, sqlite3_index_info *pInfo){
|
||||
*/
|
||||
if( pInfo->nOrderBy==1 ){
|
||||
int iSort = pInfo->aOrderBy[0].iColumn;
|
||||
if( iSort==(pConfig->nCol+1) && bSeenMatch ){
|
||||
if( iSort==(pConfig->nCol+1) && nSeenMatch>0 ){
|
||||
idxFlags |= FTS5_BI_ORDER_RANK;
|
||||
}else if( iSort==-1 && (!pInfo->aOrderBy[0].desc || !pConfig->bTokendata) ){
|
||||
idxFlags |= FTS5_BI_ORDER_ROWID;
|
||||
@@ -677,14 +677,17 @@ static int fts5BestIndexMethod(sqlite3_vtab *pVTab, sqlite3_index_info *pInfo){
|
||||
|
||||
/* Calculate the estimated cost based on the flags set in idxFlags. */
|
||||
if( bSeenEq ){
|
||||
pInfo->estimatedCost = bSeenMatch ? 100.0 : 10.0;
|
||||
if( bSeenMatch==0 ) fts5SetUniqueFlag(pInfo);
|
||||
pInfo->estimatedCost = nSeenMatch ? 1000.0 : 10.0;
|
||||
if( nSeenMatch==0 ) fts5SetUniqueFlag(pInfo);
|
||||
}else if( bSeenLt && bSeenGt ){
|
||||
pInfo->estimatedCost = bSeenMatch ? 500.0 : 250000.0;
|
||||
pInfo->estimatedCost = nSeenMatch ? 5000.0 : 250000.0;
|
||||
}else if( bSeenLt || bSeenGt ){
|
||||
pInfo->estimatedCost = bSeenMatch ? 750.0 : 750000.0;
|
||||
pInfo->estimatedCost = nSeenMatch ? 7500.0 : 750000.0;
|
||||
}else{
|
||||
pInfo->estimatedCost = bSeenMatch ? 1000.0 : 1000000.0;
|
||||
pInfo->estimatedCost = nSeenMatch ? 10000.0 : 1000000.0;
|
||||
}
|
||||
for(i=1; i<nSeenMatch; i++){
|
||||
pInfo->estimatedCost *= 0.4;
|
||||
}
|
||||
|
||||
pInfo->idxNum = idxFlags;
|
||||
@@ -960,6 +963,7 @@ static int fts5NextMethod(sqlite3_vtab_cursor *pCursor){
|
||||
}
|
||||
}else{
|
||||
rc = SQLITE_OK;
|
||||
CsrFlagSet(pCsr, FTS5CSR_REQUIRE_DOCSIZE);
|
||||
}
|
||||
break;
|
||||
}
|
||||
@@ -1213,6 +1217,18 @@ static i64 fts5GetRowidLimit(sqlite3_value *pVal, i64 iDefault){
|
||||
return iDefault;
|
||||
}
|
||||
|
||||
/*
|
||||
** Set the error message on the virtual table passed as the first argument.
|
||||
*/
|
||||
static void fts5SetVtabError(Fts5FullTable *p, const char *zFormat, ...){
|
||||
va_list ap; /* ... printf arguments */
|
||||
va_start(ap, zFormat);
|
||||
sqlite3_free(p->p.base.zErrMsg);
|
||||
p->p.base.zErrMsg = sqlite3_vmprintf(zFormat, ap);
|
||||
va_end(ap);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
** This is the xFilter interface for the virtual table. See
|
||||
** the virtual table xFilter method documentation for additional
|
||||
@@ -1388,9 +1404,7 @@ static int fts5FilterMethod(
|
||||
}
|
||||
}
|
||||
}else if( pConfig->zContent==0 ){
|
||||
*pConfig->pzErrmsg = sqlite3_mprintf(
|
||||
"%s: table does not support scanning", pConfig->zName
|
||||
);
|
||||
fts5SetVtabError(pTab,"%s: table does not support scanning",pConfig->zName);
|
||||
rc = SQLITE_ERROR;
|
||||
}else{
|
||||
/* This is either a full-table scan (ePlan==FTS5_PLAN_SCAN) or a lookup
|
||||
@@ -1433,9 +1447,13 @@ static i64 fts5CursorRowid(Fts5Cursor *pCsr){
|
||||
assert( pCsr->ePlan==FTS5_PLAN_MATCH
|
||||
|| pCsr->ePlan==FTS5_PLAN_SORTED_MATCH
|
||||
|| pCsr->ePlan==FTS5_PLAN_SOURCE
|
||||
|| pCsr->ePlan==FTS5_PLAN_SCAN
|
||||
|| pCsr->ePlan==FTS5_PLAN_ROWID
|
||||
);
|
||||
if( pCsr->pSorter ){
|
||||
return pCsr->pSorter->iRowid;
|
||||
}else if( pCsr->ePlan>=FTS5_PLAN_SCAN ){
|
||||
return sqlite3_column_int64(pCsr->pStmt, 0);
|
||||
}else{
|
||||
return sqlite3Fts5ExprRowid(pCsr->pExpr);
|
||||
}
|
||||
@@ -1452,25 +1470,16 @@ static int fts5RowidMethod(sqlite3_vtab_cursor *pCursor, sqlite_int64 *pRowid){
|
||||
int ePlan = pCsr->ePlan;
|
||||
|
||||
assert( CsrFlagTest(pCsr, FTS5CSR_EOF)==0 );
|
||||
switch( ePlan ){
|
||||
case FTS5_PLAN_SPECIAL:
|
||||
*pRowid = 0;
|
||||
break;
|
||||
|
||||
case FTS5_PLAN_SOURCE:
|
||||
case FTS5_PLAN_MATCH:
|
||||
case FTS5_PLAN_SORTED_MATCH:
|
||||
*pRowid = fts5CursorRowid(pCsr);
|
||||
break;
|
||||
|
||||
default:
|
||||
*pRowid = sqlite3_column_int64(pCsr->pStmt, 0);
|
||||
break;
|
||||
if( ePlan==FTS5_PLAN_SPECIAL ){
|
||||
*pRowid = 0;
|
||||
}else{
|
||||
*pRowid = fts5CursorRowid(pCsr);
|
||||
}
|
||||
|
||||
return SQLITE_OK;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
** If the cursor requires seeking (bSeekRequired flag is set), seek it.
|
||||
** Return SQLITE_OK if no error occurs, or an SQLite error code otherwise.
|
||||
@@ -1507,8 +1516,13 @@ static int fts5SeekCursor(Fts5Cursor *pCsr, int bErrormsg){
|
||||
rc = sqlite3_reset(pCsr->pStmt);
|
||||
if( rc==SQLITE_OK ){
|
||||
rc = FTS5_CORRUPT;
|
||||
fts5SetVtabError((Fts5FullTable*)pTab,
|
||||
"fts5: missing row %lld from content table %s",
|
||||
fts5CursorRowid(pCsr),
|
||||
pTab->pConfig->zContent
|
||||
);
|
||||
}else if( pTab->pConfig->pzErrmsg ){
|
||||
*pTab->pConfig->pzErrmsg = sqlite3_mprintf(
|
||||
fts5SetVtabError((Fts5FullTable*)pTab,
|
||||
"%s", sqlite3_errmsg(pTab->pConfig->db)
|
||||
);
|
||||
}
|
||||
@@ -1517,14 +1531,6 @@ static int fts5SeekCursor(Fts5Cursor *pCsr, int bErrormsg){
|
||||
return rc;
|
||||
}
|
||||
|
||||
static void fts5SetVtabError(Fts5FullTable *p, const char *zFormat, ...){
|
||||
va_list ap; /* ... printf arguments */
|
||||
va_start(ap, zFormat);
|
||||
assert( p->p.base.zErrMsg==0 );
|
||||
p->p.base.zErrMsg = sqlite3_vmprintf(zFormat, ap);
|
||||
va_end(ap);
|
||||
}
|
||||
|
||||
/*
|
||||
** This function is called to handle an FTS INSERT command. In other words,
|
||||
** an INSERT statement of the form:
|
||||
@@ -1700,6 +1706,7 @@ static int fts5UpdateMethod(
|
||||
rc = SQLITE_ERROR;
|
||||
}else{
|
||||
rc = fts5SpecialDelete(pTab, apVal);
|
||||
bUpdateOrDelete = 1;
|
||||
}
|
||||
}else{
|
||||
rc = fts5SpecialInsert(pTab, z, apVal[2 + pConfig->nCol + 1]);
|
||||
@@ -2498,7 +2505,10 @@ static void fts5ApiCallback(
|
||||
sqlite3_result_error(context, zErr, -1);
|
||||
sqlite3_free(zErr);
|
||||
}else{
|
||||
sqlite3_vtab *pTab = pCsr->base.pVtab;
|
||||
fts5ApiInvoke(pAux, pCsr, context, argc-1, &argv[1]);
|
||||
sqlite3_free(pTab->zErrMsg);
|
||||
pTab->zErrMsg = 0;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2861,7 +2871,7 @@ static int fts5FindTokenizer(
|
||||
return rc;
|
||||
}
|
||||
|
||||
int sqlite3Fts5GetTokenizer(
|
||||
int fts5GetTokenizer(
|
||||
Fts5Global *pGlobal,
|
||||
const char **azArg,
|
||||
int nArg,
|
||||
@@ -2875,29 +2885,42 @@ int sqlite3Fts5GetTokenizer(
|
||||
if( pMod==0 ){
|
||||
assert( nArg>0 );
|
||||
rc = SQLITE_ERROR;
|
||||
*pzErr = sqlite3_mprintf("no such tokenizer: %s", azArg[0]);
|
||||
if( pzErr ) *pzErr = sqlite3_mprintf("no such tokenizer: %s", azArg[0]);
|
||||
}else{
|
||||
rc = pMod->x.xCreate(
|
||||
pMod->pUserData, (azArg?&azArg[1]:0), (nArg?nArg-1:0), &pConfig->pTok
|
||||
pMod->pUserData, (azArg?&azArg[1]:0), (nArg?nArg-1:0), &pConfig->t.pTok
|
||||
);
|
||||
pConfig->pTokApi = &pMod->x;
|
||||
pConfig->t.pTokApi = &pMod->x;
|
||||
if( rc!=SQLITE_OK ){
|
||||
if( pzErr ) *pzErr = sqlite3_mprintf("error in tokenizer constructor");
|
||||
if( pzErr && rc!=SQLITE_NOMEM ){
|
||||
*pzErr = sqlite3_mprintf("error in tokenizer constructor");
|
||||
}
|
||||
}else{
|
||||
pConfig->ePattern = sqlite3Fts5TokenizerPattern(
|
||||
pMod->x.xCreate, pConfig->pTok
|
||||
pConfig->t.ePattern = sqlite3Fts5TokenizerPattern(
|
||||
pMod->x.xCreate, pConfig->t.pTok
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
if( rc!=SQLITE_OK ){
|
||||
pConfig->pTokApi = 0;
|
||||
pConfig->pTok = 0;
|
||||
pConfig->t.pTokApi = 0;
|
||||
pConfig->t.pTok = 0;
|
||||
}
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
/*
|
||||
** Attempt to instantiate the tokenizer.
|
||||
*/
|
||||
int sqlite3Fts5LoadTokenizer(Fts5Config *pConfig){
|
||||
return fts5GetTokenizer(
|
||||
pConfig->pGlobal, pConfig->t.azArg, pConfig->t.nArg,
|
||||
pConfig, pConfig->pzErrmsg
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
static void fts5ModuleDestroy(void *pCtx){
|
||||
Fts5TokenizerModule *pTok, *pNextTok;
|
||||
Fts5Auxiliary *pAux, *pNextAux;
|
||||
@@ -2976,17 +2999,23 @@ static int fts5IntegrityMethod(
|
||||
|
||||
assert( pzErr!=0 && *pzErr==0 );
|
||||
UNUSED_PARAM(isQuick);
|
||||
assert( pTab->p.pConfig->pzErrmsg==0 );
|
||||
pTab->p.pConfig->pzErrmsg = pzErr;
|
||||
rc = sqlite3Fts5StorageIntegrity(pTab->pStorage, 0);
|
||||
if( (rc&0xff)==SQLITE_CORRUPT ){
|
||||
*pzErr = sqlite3_mprintf("malformed inverted index for FTS5 table %s.%s",
|
||||
zSchema, zTabname);
|
||||
rc = (*pzErr) ? SQLITE_OK : SQLITE_NOMEM;
|
||||
}else if( rc!=SQLITE_OK ){
|
||||
*pzErr = sqlite3_mprintf("unable to validate the inverted index for"
|
||||
" FTS5 table %s.%s: %s",
|
||||
zSchema, zTabname, sqlite3_errstr(rc));
|
||||
if( *pzErr==0 && rc!=SQLITE_OK ){
|
||||
if( (rc&0xff)==SQLITE_CORRUPT ){
|
||||
*pzErr = sqlite3_mprintf("malformed inverted index for FTS5 table %s.%s",
|
||||
zSchema, zTabname);
|
||||
rc = (*pzErr) ? SQLITE_OK : SQLITE_NOMEM;
|
||||
}else{
|
||||
*pzErr = sqlite3_mprintf("unable to validate the inverted index for"
|
||||
" FTS5 table %s.%s: %s",
|
||||
zSchema, zTabname, sqlite3_errstr(rc));
|
||||
}
|
||||
}
|
||||
|
||||
sqlite3Fts5IndexCloseReader(pTab->p.pIndex);
|
||||
pTab->p.pConfig->pzErrmsg = 0;
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
@@ -447,7 +447,7 @@ static int fts5StorageDeleteFromIndex(
|
||||
zText, nText, (void*)&ctx, fts5StorageInsertCallback
|
||||
);
|
||||
p->aTotalSize[iCol-1] -= (i64)ctx.szCol;
|
||||
if( p->aTotalSize[iCol-1]<0 ){
|
||||
if( p->aTotalSize[iCol-1]<0 && rc==SQLITE_OK ){
|
||||
rc = FTS5_CORRUPT;
|
||||
}
|
||||
}
|
||||
|
@@ -14,14 +14,7 @@
|
||||
|
||||
|
||||
#ifdef SQLITE_TEST
|
||||
#if defined(INCLUDE_SQLITE_TCL_H)
|
||||
# include "sqlite_tcl.h"
|
||||
#else
|
||||
# include "tcl.h"
|
||||
# ifndef SQLITE_TCLAPI
|
||||
# define SQLITE_TCLAPI
|
||||
# endif
|
||||
#endif
|
||||
#include "tclsqlite.h"
|
||||
|
||||
#ifdef SQLITE_ENABLE_FTS5
|
||||
|
||||
@@ -297,12 +290,12 @@ static int SQLITE_TCLAPI xF5tApi(
|
||||
break;
|
||||
}
|
||||
CASE(3, "xTokenize") {
|
||||
int nText;
|
||||
Tcl_Size nText;
|
||||
char *zText = Tcl_GetStringFromObj(objv[2], &nText);
|
||||
F5tFunction ctx;
|
||||
ctx.interp = interp;
|
||||
ctx.pScript = objv[3];
|
||||
rc = p->pApi->xTokenize(p->pFts, zText, nText, &ctx, xTokenizeCb);
|
||||
rc = p->pApi->xTokenize(p->pFts, zText, (int)nText, &ctx, xTokenizeCb);
|
||||
if( rc==SQLITE_OK ){
|
||||
Tcl_ResetResult(interp);
|
||||
}
|
||||
@@ -605,15 +598,16 @@ static void xF5tFunction(
|
||||
sqlite3_result_error(pCtx, Tcl_GetStringResult(p->interp), -1);
|
||||
}else{
|
||||
Tcl_Obj *pVar = Tcl_GetObjResult(p->interp);
|
||||
int n;
|
||||
const char *zType = (pVar->typePtr ? pVar->typePtr->name : "");
|
||||
char c = zType[0];
|
||||
if( c=='b' && strcmp(zType,"bytearray")==0 && pVar->bytes==0 ){
|
||||
/* Only return a BLOB type if the Tcl variable is a bytearray and
|
||||
** has no string representation. */
|
||||
unsigned char *data = Tcl_GetByteArrayFromObj(pVar, &n);
|
||||
sqlite3_result_blob(pCtx, data, n, SQLITE_TRANSIENT);
|
||||
Tcl_Size nn;
|
||||
unsigned char *data = Tcl_GetByteArrayFromObj(pVar, &nn);
|
||||
sqlite3_result_blob(pCtx, data, (int)nn, SQLITE_TRANSIENT);
|
||||
}else if( c=='b' && strcmp(zType,"boolean")==0 ){
|
||||
int n;
|
||||
Tcl_GetIntFromObj(0, pVar, &n);
|
||||
sqlite3_result_int(pCtx, n);
|
||||
}else if( c=='d' && strcmp(zType,"double")==0 ){
|
||||
@@ -626,8 +620,9 @@ static void xF5tFunction(
|
||||
Tcl_GetWideIntFromObj(0, pVar, &v);
|
||||
sqlite3_result_int64(pCtx, v);
|
||||
}else{
|
||||
unsigned char *data = (unsigned char *)Tcl_GetStringFromObj(pVar, &n);
|
||||
sqlite3_result_text(pCtx, (char *)data, n, SQLITE_TRANSIENT);
|
||||
Tcl_Size nn;
|
||||
unsigned char *data = (unsigned char *)Tcl_GetStringFromObj(pVar, &nn);
|
||||
sqlite3_result_text(pCtx, (char*)data, (int)nn, SQLITE_TRANSIENT);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -720,7 +715,7 @@ static int SQLITE_TCLAPI f5tTokenize(
|
||||
Tcl_Obj *CONST objv[]
|
||||
){
|
||||
char *zText;
|
||||
int nText;
|
||||
Tcl_Size nText;
|
||||
sqlite3 *db = 0;
|
||||
fts5_api *pApi = 0;
|
||||
Fts5Tokenizer *pTok = 0;
|
||||
@@ -729,7 +724,7 @@ static int SQLITE_TCLAPI f5tTokenize(
|
||||
void *pUserdata;
|
||||
int rc;
|
||||
|
||||
int nArg;
|
||||
Tcl_Size nArg;
|
||||
const char **azArg;
|
||||
F5tTokenizeCtx ctx;
|
||||
|
||||
@@ -761,7 +756,7 @@ static int SQLITE_TCLAPI f5tTokenize(
|
||||
return TCL_ERROR;
|
||||
}
|
||||
|
||||
rc = tokenizer.xCreate(pUserdata, &azArg[1], nArg-1, &pTok);
|
||||
rc = tokenizer.xCreate(pUserdata, &azArg[1], (int)(nArg-1), &pTok);
|
||||
if( rc!=SQLITE_OK ){
|
||||
Tcl_AppendResult(interp, "error in tokenizer.xCreate()", 0);
|
||||
return TCL_ERROR;
|
||||
@@ -773,7 +768,7 @@ static int SQLITE_TCLAPI f5tTokenize(
|
||||
ctx.pRet = pRet;
|
||||
ctx.zInput = zText;
|
||||
rc = tokenizer.xTokenize(
|
||||
pTok, (void*)&ctx, FTS5_TOKENIZE_DOCUMENT, zText, nText, xTokenizeCb2
|
||||
pTok, (void*)&ctx, FTS5_TOKENIZE_DOCUMENT, zText,(int)nText, xTokenizeCb2
|
||||
);
|
||||
tokenizer.xDelete(pTok);
|
||||
if( rc!=SQLITE_OK ){
|
||||
@@ -928,13 +923,13 @@ static int SQLITE_TCLAPI f5tTokenizerReturn(
|
||||
F5tTokenizerContext *p = (F5tTokenizerContext*)clientData;
|
||||
int iStart;
|
||||
int iEnd;
|
||||
int nToken;
|
||||
Tcl_Size nToken;
|
||||
int tflags = 0;
|
||||
char *zToken;
|
||||
int rc;
|
||||
|
||||
if( objc==5 ){
|
||||
int nArg;
|
||||
Tcl_Size nArg;
|
||||
char *zArg = Tcl_GetStringFromObj(objv[1], &nArg);
|
||||
if( nArg<=10 && nArg>=2 && memcmp("-colocated", zArg, nArg)==0 ){
|
||||
tflags |= FTS5_TOKEN_COLOCATED;
|
||||
@@ -959,7 +954,7 @@ static int SQLITE_TCLAPI f5tTokenizerReturn(
|
||||
return TCL_ERROR;
|
||||
}
|
||||
|
||||
rc = p->xToken(p->pCtx, tflags, zToken, nToken, iStart, iEnd);
|
||||
rc = p->xToken(p->pCtx, tflags, zToken, (int)nToken, iStart, iEnd);
|
||||
Tcl_SetResult(interp, (char*)sqlite3ErrName(rc), TCL_VOLATILE);
|
||||
return rc==SQLITE_OK ? TCL_OK : TCL_ERROR;
|
||||
|
||||
@@ -1083,7 +1078,7 @@ static int SQLITE_TCLAPI f5tTokenHash(
|
||||
Tcl_Obj *CONST objv[]
|
||||
){
|
||||
char *z;
|
||||
int n;
|
||||
Tcl_Size n;
|
||||
unsigned int iVal;
|
||||
int nSlot;
|
||||
|
||||
@@ -1096,7 +1091,7 @@ static int SQLITE_TCLAPI f5tTokenHash(
|
||||
}
|
||||
z = Tcl_GetStringFromObj(objv[2], &n);
|
||||
|
||||
iVal = f5t_fts5HashKey(nSlot, z, n);
|
||||
iVal = f5t_fts5HashKey(nSlot, z, (int)n);
|
||||
Tcl_SetObjResult(interp, Tcl_NewIntObj(iVal));
|
||||
return TCL_OK;
|
||||
}
|
||||
|
@@ -1428,6 +1428,16 @@ int sqlite3Fts5TokenizerPattern(
|
||||
return FTS5_PATTERN_NONE;
|
||||
}
|
||||
|
||||
/*
|
||||
** Return true if the tokenizer described by p->azArg[] is the trigram
|
||||
** tokenizer. This tokenizer needs to be loaded before xBestIndex is
|
||||
** called for the first time in order to correctly handle LIKE/GLOB.
|
||||
*/
|
||||
int sqlite3Fts5TokenizerPreload(Fts5TokenizerConfig *p){
|
||||
return (p->nArg>=1 && 0==sqlite3_stricmp(p->azArg[0], "trigram"));
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
** Register all built-in tokenizers with FTS5.
|
||||
*/
|
||||
|
@@ -64,6 +64,7 @@ struct Fts5VocabCursor {
|
||||
|
||||
int nLeTerm; /* Size of zLeTerm in bytes */
|
||||
char *zLeTerm; /* (term <= $zLeTerm) paramater, or NULL */
|
||||
int colUsed; /* Copy of sqlite3_index_info.colUsed */
|
||||
|
||||
/* These are used by 'col' tables only */
|
||||
int iCol;
|
||||
@@ -90,9 +91,11 @@ struct Fts5VocabCursor {
|
||||
/*
|
||||
** Bits for the mask used as the idxNum value by xBestIndex/xFilter.
|
||||
*/
|
||||
#define FTS5_VOCAB_TERM_EQ 0x01
|
||||
#define FTS5_VOCAB_TERM_GE 0x02
|
||||
#define FTS5_VOCAB_TERM_LE 0x04
|
||||
#define FTS5_VOCAB_TERM_EQ 0x0100
|
||||
#define FTS5_VOCAB_TERM_GE 0x0200
|
||||
#define FTS5_VOCAB_TERM_LE 0x0400
|
||||
|
||||
#define FTS5_VOCAB_COLUSED_MASK 0xFF
|
||||
|
||||
|
||||
/*
|
||||
@@ -269,11 +272,13 @@ static int fts5VocabBestIndexMethod(
|
||||
int iTermEq = -1;
|
||||
int iTermGe = -1;
|
||||
int iTermLe = -1;
|
||||
int idxNum = 0;
|
||||
int idxNum = (int)pInfo->colUsed;
|
||||
int nArg = 0;
|
||||
|
||||
UNUSED_PARAM(pUnused);
|
||||
|
||||
assert( (pInfo->colUsed & FTS5_VOCAB_COLUSED_MASK)==pInfo->colUsed );
|
||||
|
||||
for(i=0; i<pInfo->nConstraint; i++){
|
||||
struct sqlite3_index_constraint *p = &pInfo->aConstraint[i];
|
||||
if( p->usable==0 ) continue;
|
||||
@@ -365,7 +370,7 @@ static int fts5VocabOpenMethod(
|
||||
if( rc==SQLITE_OK ){
|
||||
pVTab->zErrMsg = sqlite3_mprintf(
|
||||
"no such fts5 table: %s.%s", pTab->zFts5Db, pTab->zFts5Tbl
|
||||
);
|
||||
);
|
||||
rc = SQLITE_ERROR;
|
||||
}
|
||||
}else{
|
||||
@@ -525,9 +530,19 @@ static int fts5VocabNextMethod(sqlite3_vtab_cursor *pCursor){
|
||||
|
||||
switch( pTab->eType ){
|
||||
case FTS5_VOCAB_ROW:
|
||||
if( eDetail==FTS5_DETAIL_FULL ){
|
||||
while( 0==sqlite3Fts5PoslistNext64(pPos, nPos, &iOff, &iPos) ){
|
||||
pCsr->aCnt[0]++;
|
||||
/* Do not bother counting the number of instances if the "cnt"
|
||||
** column is not being read (according to colUsed). */
|
||||
if( eDetail==FTS5_DETAIL_FULL && (pCsr->colUsed & 0x04) ){
|
||||
while( iPos<nPos ){
|
||||
u32 ii;
|
||||
fts5FastGetVarint32(pPos, iPos, ii);
|
||||
if( ii==1 ){
|
||||
/* New column in the position list */
|
||||
fts5FastGetVarint32(pPos, iPos, ii);
|
||||
}else{
|
||||
/* An instance - increment pCsr->aCnt[] */
|
||||
pCsr->aCnt[0]++;
|
||||
}
|
||||
}
|
||||
}
|
||||
pCsr->aDoc[0]++;
|
||||
@@ -625,6 +640,7 @@ static int fts5VocabFilterMethod(
|
||||
if( idxNum & FTS5_VOCAB_TERM_EQ ) pEq = apVal[iVal++];
|
||||
if( idxNum & FTS5_VOCAB_TERM_GE ) pGe = apVal[iVal++];
|
||||
if( idxNum & FTS5_VOCAB_TERM_LE ) pLe = apVal[iVal++];
|
||||
pCsr->colUsed = (idxNum & FTS5_VOCAB_COLUSED_MASK);
|
||||
|
||||
if( pEq ){
|
||||
zTerm = (const char *)sqlite3_value_text(pEq);
|
||||
|
@@ -114,6 +114,10 @@ proc fts5_test_rowcount {cmd} {
|
||||
$cmd xRowCount
|
||||
}
|
||||
|
||||
proc fts5_test_rowid {cmd} {
|
||||
$cmd xRowid
|
||||
}
|
||||
|
||||
proc test_queryphrase_cb {cnt cmd} {
|
||||
upvar $cnt L
|
||||
for {set i 0} {$i < [$cmd xInstCount]} {incr i} {
|
||||
@@ -167,6 +171,7 @@ proc fts5_aux_test_functions {db} {
|
||||
fts5_test_collist
|
||||
fts5_test_tokenize
|
||||
fts5_test_rowcount
|
||||
fts5_test_rowid
|
||||
fts5_test_all
|
||||
|
||||
fts5_test_queryphrase
|
||||
|
@@ -440,7 +440,7 @@ do_execsql_test 16.1 {
|
||||
proc funk {} {
|
||||
db eval { UPDATE n1_config SET v=50 WHERE k='version' }
|
||||
set fd [db incrblob main n1_data block 10]
|
||||
fconfigure $fd -encoding binary -translation binary
|
||||
fconfigure $fd -translation binary
|
||||
# puts -nonewline $fd "\x44\x45"
|
||||
close $fd
|
||||
}
|
||||
@@ -453,7 +453,7 @@ db func funk funk
|
||||
# statement no longer fails.
|
||||
#
|
||||
do_catchsql_test 16.2 {
|
||||
SELECT funk(), bm25(n1), funk() FROM n1 WHERE n1 MATCH 'a+b+c+d'
|
||||
SELECT funk(), format('%g',bm25(n1)), funk() FROM n1 WHERE n1 MATCH 'a+b+c+d'
|
||||
} {0 {{} -1e-06 {}}}
|
||||
# {1 {SQL logic error}}
|
||||
|
||||
|
@@ -16,7 +16,7 @@
|
||||
source [file join [file dirname [info script]] fts5_common.tcl]
|
||||
set testprefix fts5ab
|
||||
|
||||
# If SQLITE_ENABLE_FTS5 is defined, omit this file.
|
||||
# If SQLITE_ENABLE_FTS5 is not defined, omit this file.
|
||||
ifcapable !fts5 {
|
||||
finish_test
|
||||
return
|
||||
|
@@ -16,7 +16,7 @@
|
||||
source [file join [file dirname [info script]] fts5_common.tcl]
|
||||
set testprefix fts5ac
|
||||
|
||||
# If SQLITE_ENABLE_FTS5 is defined, omit this file.
|
||||
# If SQLITE_ENABLE_FTS5 is not defined, omit this file.
|
||||
ifcapable !fts5 {
|
||||
finish_test
|
||||
return
|
||||
|
@@ -18,7 +18,7 @@
|
||||
source [file join [file dirname [info script]] fts5_common.tcl]
|
||||
set testprefix fts5ad
|
||||
|
||||
# If SQLITE_ENABLE_FTS5 is defined, omit this file.
|
||||
# If SQLITE_ENABLE_FTS5 is not defined, omit this file.
|
||||
ifcapable !fts5 {
|
||||
finish_test
|
||||
return
|
||||
|
@@ -16,7 +16,7 @@
|
||||
source [file join [file dirname [info script]] fts5_common.tcl]
|
||||
set testprefix fts5ae
|
||||
|
||||
# If SQLITE_ENABLE_FTS5 is defined, omit this file.
|
||||
# If SQLITE_ENABLE_FTS5 is not defined, omit this file.
|
||||
ifcapable !fts5 {
|
||||
finish_test
|
||||
return
|
||||
|
@@ -18,7 +18,7 @@
|
||||
source [file join [file dirname [info script]] fts5_common.tcl]
|
||||
set testprefix fts5af
|
||||
|
||||
# If SQLITE_ENABLE_FTS5 is defined, omit this file.
|
||||
# If SQLITE_ENABLE_FTS5 is not defined, omit this file.
|
||||
ifcapable !fts5 {
|
||||
finish_test
|
||||
return
|
||||
|
@@ -15,7 +15,7 @@
|
||||
source [file join [file dirname [info script]] fts5_common.tcl]
|
||||
set testprefix fts5ag
|
||||
|
||||
# If SQLITE_ENABLE_FTS5 is defined, omit this file.
|
||||
# If SQLITE_ENABLE_FTS5 is not defined, omit this file.
|
||||
ifcapable !fts5 {
|
||||
finish_test
|
||||
return
|
||||
|
@@ -16,7 +16,7 @@
|
||||
source [file join [file dirname [info script]] fts5_common.tcl]
|
||||
set testprefix fts5ah
|
||||
|
||||
# If SQLITE_ENABLE_FTS5 is defined, omit this file.
|
||||
# If SQLITE_ENABLE_FTS5 is not defined, omit this file.
|
||||
ifcapable !fts5 {
|
||||
finish_test
|
||||
return
|
||||
|
@@ -17,7 +17,7 @@
|
||||
source [file join [file dirname [info script]] fts5_common.tcl]
|
||||
set testprefix fts5ai
|
||||
|
||||
# If SQLITE_ENABLE_FTS5 is defined, omit this file.
|
||||
# If SQLITE_ENABLE_FTS5 is not defined, omit this file.
|
||||
ifcapable !fts5 {
|
||||
finish_test
|
||||
return
|
||||
|
@@ -19,7 +19,7 @@
|
||||
source [file join [file dirname [info script]] fts5_common.tcl]
|
||||
set testprefix fts5aj
|
||||
|
||||
# If SQLITE_ENABLE_FTS5 is defined, omit this file.
|
||||
# If SQLITE_ENABLE_FTS5 is not defined, omit this file.
|
||||
ifcapable !fts5 {
|
||||
finish_test
|
||||
return
|
||||
|
@@ -17,7 +17,7 @@
|
||||
source [file join [file dirname [info script]] fts5_common.tcl]
|
||||
set testprefix fts5ak
|
||||
|
||||
# If SQLITE_ENABLE_FTS5 is defined, omit this file.
|
||||
# If SQLITE_ENABLE_FTS5 is not defined, omit this file.
|
||||
ifcapable !fts5 {
|
||||
finish_test
|
||||
return
|
||||
|
@@ -17,7 +17,7 @@
|
||||
source [file join [file dirname [info script]] fts5_common.tcl]
|
||||
set testprefix fts5al
|
||||
|
||||
# If SQLITE_ENABLE_FTS5 is defined, omit this file.
|
||||
# If SQLITE_ENABLE_FTS5 is not defined, omit this file.
|
||||
ifcapable !fts5 {
|
||||
finish_test
|
||||
return
|
||||
|
@@ -16,7 +16,7 @@
|
||||
source [file join [file dirname [info script]] fts5_common.tcl]
|
||||
set testprefix fts5alter
|
||||
|
||||
# If SQLITE_ENABLE_FTS5 is defined, omit this file.
|
||||
# If SQLITE_ENABLE_FTS5 is not defined, omit this file.
|
||||
ifcapable !fts5 {
|
||||
finish_test
|
||||
return
|
||||
|
@@ -16,7 +16,7 @@
|
||||
source [file join [file dirname [info script]] fts5_common.tcl]
|
||||
set testprefix fts5auto
|
||||
|
||||
# If SQLITE_ENABLE_FTS5 is defined, omit this file.
|
||||
# If SQLITE_ENABLE_FTS5 is not defined, omit this file.
|
||||
ifcapable !fts5 {
|
||||
finish_test
|
||||
return
|
||||
|
@@ -15,7 +15,7 @@
|
||||
source [file join [file dirname [info script]] fts5_common.tcl]
|
||||
set testprefix fts5aux
|
||||
|
||||
# If SQLITE_ENABLE_FTS5 is defined, omit this file.
|
||||
# If SQLITE_ENABLE_FTS5 is not defined, omit this file.
|
||||
ifcapable !fts5 {
|
||||
finish_test
|
||||
return
|
||||
@@ -377,4 +377,28 @@ do_catchsql_test 12.3.3 {
|
||||
SELECT fts5_collist(t1, 1) FROM t1('one AND two');
|
||||
} {0 1}
|
||||
|
||||
#-------------------------------------------------------------------------
|
||||
reset_db
|
||||
do_execsql_test 13.1 {
|
||||
CREATE VIRTUAL TABLE t1 USING fts5(a, tokenize=ascii);
|
||||
INSERT INTO t1 VALUES('a b c'), ('d e f');
|
||||
PRAGMA integrity_check;
|
||||
} {ok}
|
||||
|
||||
do_catchsql_test 13.2 {
|
||||
SELECT highlight(t1, 0, '[', ']') FROM t1
|
||||
} {0 {{a b c} {d e f}}}
|
||||
|
||||
do_execsql_test 13.3 {
|
||||
PRAGMA writable_schema = 1;
|
||||
UPDATE sqlite_schema SET sql = 'CREATE VIRTUAL TABLE t1 USING fts5(a, tokenize=blah)'
|
||||
WHERE name = 't1';
|
||||
}
|
||||
|
||||
db close
|
||||
sqlite3 db test.db
|
||||
do_catchsql_test 13.4 {
|
||||
SELECT highlight(t1, 0, '[', ']') FROM t1
|
||||
} {1 {SQL logic error}}
|
||||
|
||||
finish_test
|
||||
|
71
ext/fts5/test/fts5aux2.test
Normal file
71
ext/fts5/test/fts5aux2.test
Normal file
@@ -0,0 +1,71 @@
|
||||
# 2024 June 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.
|
||||
#
|
||||
#***********************************************************************
|
||||
#
|
||||
# Tests focusing on the auxiliary function APIs.
|
||||
#
|
||||
|
||||
source [file join [file dirname [info script]] fts5_common.tcl]
|
||||
set testprefix fts5aux
|
||||
|
||||
# If SQLITE_ENABLE_FTS5 is not defined, omit this file.
|
||||
ifcapable !fts5 {
|
||||
finish_test
|
||||
return
|
||||
}
|
||||
|
||||
do_execsql_test 1.0 {
|
||||
CREATE VIRTUAL TABLE x1 USING fts5(a, b);
|
||||
INSERT INTO x1 VALUES('a b', 'c d');
|
||||
INSERT INTO x1 VALUES('d e', 'a b');
|
||||
INSERT INTO x1 VALUES('a b', 'e f');
|
||||
INSERT INTO x1 VALUES('d e', 'c d');
|
||||
}
|
||||
|
||||
fts5_aux_test_functions db
|
||||
do_execsql_test 1.1 {
|
||||
SELECT fts5_test_all(x1) FROM x1 WHERE rowid=2
|
||||
} [list [list {*}{
|
||||
columnsize {2 2}
|
||||
columntext {{d e} {a b}}
|
||||
columntotalsize {8 8}
|
||||
poslist {}
|
||||
tokenize {{d e} {a b}}
|
||||
rowcount 4
|
||||
}]]
|
||||
|
||||
do_execsql_test 1.2 {
|
||||
SELECT fts5_test_columntext(x1) FROM x1
|
||||
} {
|
||||
{{a b} {c d}}
|
||||
{{d e} {a b}}
|
||||
{{a b} {e f}}
|
||||
{{d e} {c d}}
|
||||
}
|
||||
|
||||
do_execsql_test 1.3 {
|
||||
SELECT fts5_test_rowid(x1) FROM x1
|
||||
} {
|
||||
1 2 3 4
|
||||
}
|
||||
do_execsql_test 1.4 {
|
||||
SELECT fts5_test_phrasecount(x1) FROM x1
|
||||
} {
|
||||
0 0 0 0
|
||||
}
|
||||
do_catchsql_test 1.5 {
|
||||
SELECT fts5_queryphrase(x1, 0) FROM x1
|
||||
} {1 SQLITE_RANGE}
|
||||
do_execsql_test 1.6 {
|
||||
SELECT fts5_test_rowcount(x1) FROM x1
|
||||
} {4 4 4 4}
|
||||
|
||||
|
||||
finish_test
|
@@ -15,7 +15,7 @@
|
||||
source [file join [file dirname [info script]] fts5_common.tcl]
|
||||
set testprefix fts5auxdata
|
||||
|
||||
# If SQLITE_ENABLE_FTS5 is defined, omit this file.
|
||||
# If SQLITE_ENABLE_FTS5 is not defined, omit this file.
|
||||
ifcapable !fts5 {
|
||||
finish_test
|
||||
return
|
||||
|
@@ -17,7 +17,7 @@
|
||||
source [file join [file dirname [info script]] fts5_common.tcl]
|
||||
set testprefix fts5bigpl
|
||||
|
||||
# If SQLITE_ENABLE_FTS5 is defined, omit this file.
|
||||
# If SQLITE_ENABLE_FTS5 is not defined, omit this file.
|
||||
ifcapable !fts5 {
|
||||
finish_test
|
||||
return
|
||||
|
@@ -79,7 +79,7 @@ foreach_detail_mode $::testprefix {
|
||||
|
||||
do_catchsql_test 4.1 {
|
||||
SELECT * FROM t1 WHERE rowid MATCH 'a'
|
||||
} {1 {unable to use function MATCH in the requested context}}
|
||||
} {1 {no query solution}}
|
||||
}
|
||||
|
||||
#-------------------------------------------------------------------------
|
||||
|
@@ -15,7 +15,7 @@
|
||||
source [file join [file dirname [info script]] fts5_common.tcl]
|
||||
set testprefix fts5columnsize
|
||||
|
||||
# If SQLITE_ENABLE_FTS5 is defined, omit this file.
|
||||
# If SQLITE_ENABLE_FTS5 is not defined, omit this file.
|
||||
ifcapable !fts5 {
|
||||
finish_test
|
||||
return
|
||||
|
@@ -16,7 +16,7 @@
|
||||
source [file join [file dirname [info script]] fts5_common.tcl]
|
||||
set testprefix fts5config
|
||||
|
||||
# If SQLITE_ENABLE_FTS5 is defined, omit this file.
|
||||
# If SQLITE_ENABLE_FTS5 is not defined, omit this file.
|
||||
ifcapable !fts5 {
|
||||
finish_test
|
||||
return
|
||||
|
@@ -15,7 +15,7 @@
|
||||
source [file join [file dirname [info script]] fts5_common.tcl]
|
||||
set testprefix fts5content
|
||||
|
||||
# If SQLITE_ENABLE_FTS5 is defined, omit this file.
|
||||
# If SQLITE_ENABLE_FTS5 is not defined, omit this file.
|
||||
ifcapable !fts5 {
|
||||
finish_test
|
||||
return
|
||||
@@ -328,4 +328,41 @@ do_execsql_test 8.3.2 { INSERT INTO t1(t1) VALUES('rebuild') }
|
||||
do_execsql_test 8.3.3 { SELECT * FROM t1 WHERE rowid=1 } {one}
|
||||
do_execsql_test 8.3.4 { SELECT rowid FROM t1('two') } {2}
|
||||
|
||||
#-------------------------------------------------------------------------
|
||||
reset_db
|
||||
do_execsql_test 9.1 {
|
||||
CREATE TABLE t1(a INTEGER PRIMARY KEY, b);
|
||||
INSERT INTO t1 VALUES(1, 'one two three');
|
||||
INSERT INTO t1 VALUES(2, 'one two three');
|
||||
|
||||
CREATE VIRTUAL TABLE ft USING fts5(b, content=t1, content_rowid=a);
|
||||
INSERT INTO ft(ft) VALUES('rebuild');
|
||||
}
|
||||
|
||||
do_execsql_test 9.2 {
|
||||
SELECT rowid, b FROM ft('two');
|
||||
} {
|
||||
1 {one two three}
|
||||
2 {one two three}
|
||||
}
|
||||
|
||||
do_execsql_test 9.3 {
|
||||
DELETE FROM t1 WHERE a=2;
|
||||
}
|
||||
|
||||
do_catchsql_test 9.4 {
|
||||
SELECT rowid FROM ft('two');
|
||||
} {0 {1 2}}
|
||||
|
||||
do_catchsql_test 9.5 {
|
||||
SELECT * FROM ft('two');
|
||||
} {1 {fts5: missing row 2 from content table 'main'.'t1'}}
|
||||
|
||||
fts5_aux_test_functions db
|
||||
|
||||
do_catchsql_test 9.6 {
|
||||
SELECT rowid, fts5_columntext(ft, 0) FROM ft('two');
|
||||
} {1 SQLITE_CORRUPT_VTAB}
|
||||
|
||||
finish_test
|
||||
|
||||
|
@@ -15,7 +15,7 @@
|
||||
source [file join [file dirname [info script]] fts5_common.tcl]
|
||||
set testprefix fts5contentless
|
||||
|
||||
# If SQLITE_ENABLE_FTS5 is defined, omit this file.
|
||||
# If SQLITE_ENABLE_FTS5 is not defined, omit this file.
|
||||
ifcapable !fts5 {
|
||||
finish_test
|
||||
return
|
||||
|
@@ -15,7 +15,7 @@
|
||||
source [file join [file dirname [info script]] fts5_common.tcl]
|
||||
set testprefix fts5contentless2
|
||||
|
||||
# If SQLITE_ENABLE_FTS5 is defined, omit this file.
|
||||
# If SQLITE_ENABLE_FTS5 is not defined, omit this file.
|
||||
ifcapable !fts5 {
|
||||
finish_test
|
||||
return
|
||||
|
@@ -15,7 +15,7 @@
|
||||
source [file join [file dirname [info script]] fts5_common.tcl]
|
||||
set testprefix fts5contentless3
|
||||
|
||||
# If SQLITE_ENABLE_FTS5 is defined, omit this file.
|
||||
# If SQLITE_ENABLE_FTS5 is not defined, omit this file.
|
||||
ifcapable !fts5 {
|
||||
finish_test
|
||||
return
|
||||
|
@@ -15,7 +15,7 @@
|
||||
source [file join [file dirname [info script]] fts5_common.tcl]
|
||||
set testprefix fts5contentless4
|
||||
|
||||
# If SQLITE_ENABLE_FTS5 is defined, omit this file.
|
||||
# If SQLITE_ENABLE_FTS5 is not defined, omit this file.
|
||||
ifcapable !fts5 {
|
||||
finish_test
|
||||
return
|
||||
|
@@ -15,11 +15,12 @@
|
||||
source [file join [file dirname [info script]] fts5_common.tcl]
|
||||
set testprefix fts5contentless5
|
||||
|
||||
# If SQLITE_ENABLE_FTS5 is defined, omit this file.
|
||||
# If SQLITE_ENABLE_FTS5 is not defined, omit this file.
|
||||
ifcapable !fts5 {
|
||||
finish_test
|
||||
return
|
||||
}
|
||||
unset -nocomplain res
|
||||
|
||||
do_execsql_test 1.0 {
|
||||
CREATE VIRTUAL TABLE t1 USING fts5(a, b, c, content='', contentless_delete=1);
|
||||
|
@@ -16,7 +16,7 @@
|
||||
source [file join [file dirname [info script]] fts5_common.tcl]
|
||||
set testprefix fts5corrupt
|
||||
|
||||
# If SQLITE_ENABLE_FTS5 is defined, omit this file.
|
||||
# If SQLITE_ENABLE_FTS5 is not defined, omit this file.
|
||||
ifcapable !fts5 {
|
||||
finish_test
|
||||
return
|
||||
@@ -99,6 +99,6 @@ sqlite3_db_config db DEFENSIVE 0
|
||||
do_catchsql_test 3.1 {
|
||||
DELETE FROM t3_content WHERE rowid = 3;
|
||||
SELECT * FROM t3 WHERE t3 MATCH 'o';
|
||||
} {1 {database disk image is malformed}}
|
||||
} {1 {fts5: missing row 3 from content table 'main'.'t3_content'}}
|
||||
|
||||
finish_test
|
||||
|
@@ -17,7 +17,7 @@
|
||||
source [file join [file dirname [info script]] fts5_common.tcl]
|
||||
set testprefix fts5corrupt2
|
||||
|
||||
# If SQLITE_ENABLE_FTS5 is defined, omit this file.
|
||||
# If SQLITE_ENABLE_FTS5 is not defined, omit this file.
|
||||
ifcapable !fts5 {
|
||||
finish_test
|
||||
return
|
||||
@@ -100,6 +100,7 @@ set lrowid [db one {SELECT max(rowid) FROM t1_data WHERE (rowid & $mask)=0}]
|
||||
set nbyte [db one {SELECT length(block) FROM t1_data WHERE rowid=$lrowid}]
|
||||
set all [db eval {SELECT rowid FROM t1}]
|
||||
sqlite3_db_config db DEFENSIVE 0
|
||||
unset -nocomplain res
|
||||
for {set i [expr $nbyte-2]} {$i>=0} {incr i -1} {
|
||||
do_execsql_test 2.$i.1 {
|
||||
BEGIN;
|
||||
@@ -152,7 +153,7 @@ foreach {tn hdr} {
|
||||
execsql BEGIN
|
||||
|
||||
set fd [db incrblob main x3_data block $rowid]
|
||||
fconfigure $fd -encoding binary -translation binary
|
||||
fconfigure $fd -translation binary
|
||||
set existing [read $fd [string length $hdr]]
|
||||
seek $fd 0
|
||||
puts -nonewline $fd $hdr
|
||||
@@ -238,7 +239,7 @@ foreach {tn hdr} {
|
||||
execsql BEGIN
|
||||
|
||||
set fd [db incrblob main x5_data block $rowid]
|
||||
fconfigure $fd -encoding binary -translation binary
|
||||
fconfigure $fd -translation binary
|
||||
puts -nonewline $fd $hdr
|
||||
close $fd
|
||||
|
||||
|
@@ -17,7 +17,7 @@
|
||||
source [file join [file dirname [info script]] fts5_common.tcl]
|
||||
set testprefix fts5corrupt3
|
||||
|
||||
# If SQLITE_ENABLE_FTS5 is defined, omit this file.
|
||||
# If SQLITE_ENABLE_FTS5 is not defined, omit this file.
|
||||
ifcapable !fts5 {
|
||||
finish_test
|
||||
return
|
||||
@@ -4267,7 +4267,7 @@ do_test 35.0 {
|
||||
|
||||
do_catchsql_test 35.1 {
|
||||
SELECT * FROM t1 WHERE t1 MATCH 'e*';
|
||||
} {1 {database disk image is malformed}}
|
||||
} {1 {fts5: missing row 14 from content table 'main'.'t1_content'}}
|
||||
|
||||
#-------------------------------------------------------------------------
|
||||
reset_db
|
||||
|
@@ -14,7 +14,7 @@
|
||||
source [file join [file dirname [info script]] fts5_common.tcl]
|
||||
set testprefix fts5corrupt4
|
||||
|
||||
# If SQLITE_ENABLE_FTS5 is defined, omit this file.
|
||||
# If SQLITE_ENABLE_FTS5 is not defined, omit this file.
|
||||
ifcapable !fts5 {
|
||||
finish_test
|
||||
return
|
||||
|
@@ -17,7 +17,7 @@
|
||||
source [file join [file dirname [info script]] fts5_common.tcl]
|
||||
set testprefix fts5corrupt5
|
||||
|
||||
# If SQLITE_ENABLE_FTS5 is defined, omit this file.
|
||||
# If SQLITE_ENABLE_FTS5 is not defined, omit this file.
|
||||
ifcapable !fts5 {
|
||||
finish_test
|
||||
return
|
||||
|
@@ -17,7 +17,7 @@
|
||||
source [file join [file dirname [info script]] fts5_common.tcl]
|
||||
set testprefix fts5corrupt6
|
||||
|
||||
# If SQLITE_ENABLE_FTS5 is defined, omit this file.
|
||||
# If SQLITE_ENABLE_FTS5 is not defined, omit this file.
|
||||
ifcapable !fts5 {
|
||||
finish_test
|
||||
return
|
||||
|
@@ -13,7 +13,7 @@
|
||||
source [file join [file dirname [info script]] fts5_common.tcl]
|
||||
set testprefix fts5corrupt7
|
||||
|
||||
# If SQLITE_ENABLE_FTS5 is defined, omit this file.
|
||||
# If SQLITE_ENABLE_FTS5 is not defined, omit this file.
|
||||
ifcapable !fts5 {
|
||||
finish_test
|
||||
return
|
||||
|
@@ -15,7 +15,7 @@
|
||||
source [file join [file dirname [info script]] fts5_common.tcl]
|
||||
set testprefix fts5dlidx
|
||||
|
||||
# If SQLITE_ENABLE_FTS5 is defined, omit this file.
|
||||
# If SQLITE_ENABLE_FTS5 is not defined, omit this file.
|
||||
ifcapable !fts5 {
|
||||
finish_test
|
||||
return
|
||||
|
@@ -15,7 +15,7 @@
|
||||
source [file join [file dirname [info script]] fts5_common.tcl]
|
||||
set testprefix fts5doclist
|
||||
|
||||
# If SQLITE_ENABLE_FTS5 is defined, omit this file.
|
||||
# If SQLITE_ENABLE_FTS5 is not defined, omit this file.
|
||||
ifcapable !fts5 {
|
||||
finish_test
|
||||
return
|
||||
|
@@ -16,7 +16,7 @@
|
||||
source [file join [file dirname [info script]] fts5_common.tcl]
|
||||
set testprefix fts5ea
|
||||
|
||||
# If SQLITE_ENABLE_FTS5 is defined, omit this file.
|
||||
# If SQLITE_ENABLE_FTS5 is not defined, omit this file.
|
||||
ifcapable !fts5 {
|
||||
finish_test
|
||||
return
|
||||
|
@@ -13,7 +13,7 @@
|
||||
source [file join [file dirname [info script]] fts5_common.tcl]
|
||||
set testprefix fts5eb
|
||||
|
||||
# If SQLITE_ENABLE_FTS5 is defined, omit this file.
|
||||
# If SQLITE_ENABLE_FTS5 is not defined, omit this file.
|
||||
ifcapable !fts5 {
|
||||
finish_test
|
||||
return
|
||||
@@ -86,13 +86,13 @@ do_execsql_test 3.0 {
|
||||
INSERT INTO e1 VALUES ('just a few words with a / inside');
|
||||
}
|
||||
do_execsql_test 3.1 {
|
||||
SELECT rowid, bm25(e1) FROM e1 WHERE e1 MATCH '"just"' ORDER BY rank;
|
||||
SELECT rowid, format('%g',bm25(e1)) FROM e1 WHERE e1 MATCH '"just"' ORDER BY rank;
|
||||
} {1 -1e-06}
|
||||
do_execsql_test 3.2 {
|
||||
SELECT rowid FROM e1 WHERE e1 MATCH '"/" OR "just"'
|
||||
} 1
|
||||
do_execsql_test 3.3 {
|
||||
SELECT rowid, bm25(e1) FROM e1 WHERE e1 MATCH '"/" OR "just"' ORDER BY rank;
|
||||
SELECT rowid, format('%g',bm25(e1)) FROM e1 WHERE e1 MATCH '"/" OR "just"' ORDER BY rank;
|
||||
} {1 -1e-06}
|
||||
|
||||
do_execsql_test 3.4 "
|
||||
|
@@ -16,7 +16,7 @@ source [file join [file dirname [info script]] fts5_common.tcl]
|
||||
source $testdir/malloc_common.tcl
|
||||
set testprefix fts5fault6
|
||||
|
||||
# If SQLITE_ENABLE_FTS5 is defined, omit this file.
|
||||
# If SQLITE_ENABLE_FTS5 is not defined, omit this file.
|
||||
ifcapable !fts5 {
|
||||
finish_test
|
||||
return
|
||||
|
@@ -14,7 +14,7 @@ source [file join [file dirname [info script]] fts5_common.tcl]
|
||||
source $testdir/malloc_common.tcl
|
||||
set testprefix fts5faultG
|
||||
|
||||
# If SQLITE_ENABLE_FTS5 is defined, omit this file.
|
||||
# If SQLITE_ENABLE_FTS5 is not defined, omit this file.
|
||||
ifcapable !fts5 {
|
||||
finish_test
|
||||
return
|
||||
|
@@ -14,7 +14,7 @@ source [file join [file dirname [info script]] fts5_common.tcl]
|
||||
source $testdir/malloc_common.tcl
|
||||
set testprefix fts5faultG
|
||||
|
||||
# If SQLITE_ENABLE_FTS5 is defined, omit this file.
|
||||
# If SQLITE_ENABLE_FTS5 is not defined, omit this file.
|
||||
ifcapable !fts5 {
|
||||
finish_test
|
||||
return
|
||||
|
@@ -22,6 +22,7 @@ do_execsql_test 1.0 {
|
||||
CREATE VIRTUAL TABLE x1 USING fts5(a, b);
|
||||
}
|
||||
|
||||
unset -nocomplain res
|
||||
foreach {tn expr ok} {
|
||||
1 {^abc} 1
|
||||
2 {^abc + def} 1
|
||||
|
@@ -17,7 +17,7 @@
|
||||
source [file join [file dirname [info script]] fts5_common.tcl]
|
||||
set testprefix fts5full
|
||||
|
||||
# If SQLITE_ENABLE_FTS5 is defined, omit this file.
|
||||
# If SQLITE_ENABLE_FTS5 is not defined, omit this file.
|
||||
ifcapable !fts5 {
|
||||
finish_test
|
||||
return
|
||||
|
@@ -15,7 +15,7 @@
|
||||
source [file join [file dirname [info script]] fts5_common.tcl]
|
||||
set testprefix fts5hash
|
||||
|
||||
# If SQLITE_ENABLE_FTS5 is defined, omit this file.
|
||||
# If SQLITE_ENABLE_FTS5 is not defined, omit this file.
|
||||
ifcapable !fts5 {
|
||||
finish_test
|
||||
return
|
||||
|
@@ -15,7 +15,7 @@
|
||||
source [file join [file dirname [info script]] fts5_common.tcl]
|
||||
set testprefix fts5integrity
|
||||
|
||||
# If SQLITE_ENABLE_FTS5 is defined, omit this file.
|
||||
# If SQLITE_ENABLE_FTS5 is not defined, omit this file.
|
||||
ifcapable !fts5 {
|
||||
finish_test
|
||||
return
|
||||
@@ -153,6 +153,7 @@ do_execsql_test 5.3 {
|
||||
INSERT INTO gg(gg) VALUES('integrity-check');
|
||||
}
|
||||
|
||||
unset -nocomplain res
|
||||
do_test 5.4.1 {
|
||||
set ok 0
|
||||
for {set i 0} {$i < 10000} {incr i} {
|
||||
@@ -380,5 +381,32 @@ do_execsql_test 12.3 {
|
||||
} {ok}
|
||||
|
||||
|
||||
#-------------------------------------------------------------------
|
||||
reset_db
|
||||
do_execsql_test 13.1 {
|
||||
CREATE VIRTUAL TABLE t1 USING fts5(a, tokenize=ascii);
|
||||
INSERT INTO t1 VALUES('a b c'), ('d e f');
|
||||
PRAGMA integrity_check;
|
||||
} {ok}
|
||||
|
||||
db close
|
||||
sqlite3 db test.db
|
||||
do_catchsql_test 13.2 {
|
||||
PRAGMA integrity_check;
|
||||
} {0 ok}
|
||||
|
||||
do_execsql_test 13.3 {
|
||||
PRAGMA writable_schema = 1;
|
||||
UPDATE sqlite_schema SET sql = 'CREATE VIRTUAL TABLE t1 USING fts5(a, tokenize=blah)'
|
||||
WHERE name = 't1';
|
||||
}
|
||||
|
||||
db close
|
||||
sqlite3 db test.db
|
||||
breakpoint
|
||||
do_catchsql_test 13.4 {
|
||||
PRAGMA integrity_check;
|
||||
} {1 {SQL logic error}}
|
||||
|
||||
|
||||
finish_test
|
||||
|
@@ -33,6 +33,7 @@ proc progress_handler {args} {
|
||||
return 0
|
||||
}
|
||||
|
||||
unset -nocomplain res
|
||||
foreach {tn sql} {
|
||||
1 { INSERT INTO t1(rowid, a) VALUES(0, 'z z z z') }
|
||||
2 { COMMIT }
|
||||
@@ -64,4 +65,3 @@ foreach {tn sql} {
|
||||
}
|
||||
|
||||
finish_test
|
||||
|
||||
|
@@ -15,7 +15,7 @@
|
||||
source [file join [file dirname [info script]] fts5_common.tcl]
|
||||
set testprefix fts5lastrowid
|
||||
|
||||
# If SQLITE_ENABLE_FTS5 is defined, omit this file.
|
||||
# If SQLITE_ENABLE_FTS5 is not defined, omit this file.
|
||||
ifcapable !fts5 {
|
||||
finish_test
|
||||
return
|
||||
|
@@ -517,7 +517,7 @@ fts5_aux_test_functions db
|
||||
do_execsql_test 15.3 {
|
||||
SELECT fts5_test_all(t1) FROM t1 LIMIT 1;
|
||||
} {
|
||||
{columnsize {0 0} columntext {c d} columntotalsize {2 2} poslist {} tokenize {c d} rowcount 2}
|
||||
{columnsize {1 1} columntext {c d} columntotalsize {2 2} poslist {} tokenize {c d} rowcount 2}
|
||||
}
|
||||
|
||||
finish_test
|
||||
|
@@ -15,7 +15,7 @@
|
||||
source [file join [file dirname [info script]] fts5_common.tcl]
|
||||
set testprefix fts5merge
|
||||
|
||||
# If SQLITE_ENABLE_FTS5 is defined, omit this file.
|
||||
# If SQLITE_ENABLE_FTS5 is not defined, omit this file.
|
||||
ifcapable !fts5 {
|
||||
finish_test
|
||||
return
|
||||
|
@@ -535,5 +535,36 @@ do_execsql_test 19.0 {
|
||||
COMMIT;
|
||||
}
|
||||
|
||||
#-------------------------------------------------------------------------
|
||||
reset_db
|
||||
do_execsql_test 20.0 {
|
||||
CREATE VIRTUAL TABLE x1 USING fts5(a);
|
||||
INSERT INTO x1(rowid, a) VALUES
|
||||
(1, 'a b c d'),
|
||||
(2, 'x b c d'),
|
||||
(3, 'x y z d'),
|
||||
(4, 'a y c x');
|
||||
}
|
||||
|
||||
do_execsql_test 20.1 {
|
||||
SELECT rowid FROM x1 WHERE x1 MATCH 'a' AND x1 MATCH 'b';
|
||||
} {1}
|
||||
|
||||
do_execsql_test 20.2 {
|
||||
SELECT rowid FROM x1 WHERE x1 MATCH 'a' AND x1 MATCH 'y';
|
||||
} {4}
|
||||
|
||||
do_execsql_test 20.3 {
|
||||
SELECT rowid FROM x1 WHERE x1 MATCH 'a' OR x1 MATCH 'y';
|
||||
} {1 4 3}
|
||||
|
||||
do_execsql_test 20.4 {
|
||||
SELECT rowid FROM x1 WHERE x1 MATCH 'a' OR (x1 MATCH 'y' AND x1 MATCH 'd');
|
||||
} {1 4 3}
|
||||
|
||||
do_execsql_test 20.5 {
|
||||
SELECT rowid FROM x1 WHERE x1 MATCH 'z' OR (x1 MATCH 'a' AND x1 MATCH 'd');
|
||||
} {3 1}
|
||||
|
||||
finish_test
|
||||
|
||||
|
@@ -15,7 +15,7 @@
|
||||
source [file join [file dirname [info script]] fts5_common.tcl]
|
||||
set testprefix fts5near
|
||||
|
||||
# If SQLITE_ENABLE_FTS5 is defined, omit this file.
|
||||
# If SQLITE_ENABLE_FTS5 is not defined, omit this file.
|
||||
ifcapable !fts5 {
|
||||
finish_test
|
||||
return
|
||||
|
@@ -14,7 +14,7 @@
|
||||
source [file join [file dirname [info script]] fts5_common.tcl]
|
||||
set testprefix fts5optimize
|
||||
|
||||
# If SQLITE_ENABLE_FTS5 is defined, omit this file.
|
||||
# If SQLITE_ENABLE_FTS5 is not defined, omit this file.
|
||||
ifcapable !fts5 {
|
||||
finish_test
|
||||
return
|
||||
|
@@ -15,7 +15,7 @@
|
||||
source [file join [file dirname [info script]] fts5_common.tcl]
|
||||
set testprefix fts5optimize2
|
||||
|
||||
# If SQLITE_ENABLE_FTS5 is defined, omit this file.
|
||||
# If SQLITE_ENABLE_FTS5 is not defined, omit this file.
|
||||
ifcapable !fts5 {
|
||||
finish_test
|
||||
return
|
||||
|
@@ -15,7 +15,7 @@
|
||||
source [file join [file dirname [info script]] fts5_common.tcl]
|
||||
set testprefix fts5optimize2
|
||||
|
||||
# If SQLITE_ENABLE_FTS5 is defined, omit this file.
|
||||
# If SQLITE_ENABLE_FTS5 is not defined, omit this file.
|
||||
ifcapable !fts5 {
|
||||
finish_test
|
||||
return
|
||||
|
@@ -15,7 +15,7 @@
|
||||
source [file join [file dirname [info script]] fts5_common.tcl]
|
||||
set testprefix fts5origintext
|
||||
|
||||
# If SQLITE_ENABLE_FTS5 is defined, omit this file.
|
||||
# If SQLITE_ENABLE_FTS5 is not defined, omit this file.
|
||||
ifcapable !fts5 {
|
||||
finish_test
|
||||
return
|
||||
|
@@ -15,7 +15,7 @@
|
||||
source [file join [file dirname [info script]] fts5_common.tcl]
|
||||
set testprefix fts5origintext2
|
||||
|
||||
# If SQLITE_ENABLE_FTS5 is defined, omit this file.
|
||||
# If SQLITE_ENABLE_FTS5 is not defined, omit this file.
|
||||
ifcapable !fts5 {
|
||||
finish_test
|
||||
return
|
||||
|
@@ -15,7 +15,7 @@
|
||||
source [file join [file dirname [info script]] fts5_common.tcl]
|
||||
set testprefix fts5origintext3
|
||||
|
||||
# If SQLITE_ENABLE_FTS5 is defined, omit this file.
|
||||
# If SQLITE_ENABLE_FTS5 is not defined, omit this file.
|
||||
ifcapable !fts5 {
|
||||
finish_test
|
||||
return
|
||||
|
@@ -15,7 +15,7 @@
|
||||
source [file join [file dirname [info script]] fts5_common.tcl]
|
||||
set testprefix fts5origintext4
|
||||
|
||||
# If SQLITE_ENABLE_FTS5 is defined, omit this file.
|
||||
# If SQLITE_ENABLE_FTS5 is not defined, omit this file.
|
||||
ifcapable !fts5 {
|
||||
finish_test
|
||||
return
|
||||
|
@@ -15,7 +15,7 @@
|
||||
source [file join [file dirname [info script]] fts5_common.tcl]
|
||||
set testprefix fts5origintext
|
||||
|
||||
# If SQLITE_ENABLE_FTS5 is defined, omit this file.
|
||||
# If SQLITE_ENABLE_FTS5 is not defined, omit this file.
|
||||
ifcapable !fts5 {
|
||||
finish_test
|
||||
return
|
||||
|
@@ -15,7 +15,7 @@
|
||||
source [file join [file dirname [info script]] fts5_common.tcl]
|
||||
set testprefix fts5phrase
|
||||
|
||||
# If SQLITE_ENABLE_FTS5 is defined, omit this file.
|
||||
# If SQLITE_ENABLE_FTS5 is not defined, omit this file.
|
||||
ifcapable !fts5 {
|
||||
finish_test
|
||||
return
|
||||
|
@@ -15,7 +15,7 @@
|
||||
source [file join [file dirname [info script]] fts5_common.tcl]
|
||||
set testprefix fts5plan
|
||||
|
||||
# If SQLITE_ENABLE_FTS5 is defined, omit this file.
|
||||
# If SQLITE_ENABLE_FTS5 is not defined, omit this file.
|
||||
ifcapable !fts5 {
|
||||
finish_test
|
||||
return
|
||||
|
@@ -17,7 +17,7 @@
|
||||
source [file join [file dirname [info script]] fts5_common.tcl]
|
||||
set testprefix fts5porter
|
||||
|
||||
# If SQLITE_ENABLE_FTS5 is defined, omit this file.
|
||||
# If SQLITE_ENABLE_FTS5 is not defined, omit this file.
|
||||
ifcapable !fts5 {
|
||||
finish_test
|
||||
return
|
||||
|
@@ -18,7 +18,7 @@
|
||||
source [file join [file dirname [info script]] fts5_common.tcl]
|
||||
set testprefix fts5porter2
|
||||
|
||||
# If SQLITE_ENABLE_FTS5 is defined, omit this file.
|
||||
# If SQLITE_ENABLE_FTS5 is not defined, omit this file.
|
||||
ifcapable !fts5 {
|
||||
finish_test
|
||||
return
|
||||
|
@@ -15,7 +15,7 @@
|
||||
source [file join [file dirname [info script]] fts5_common.tcl]
|
||||
set testprefix fts5prefix
|
||||
|
||||
# If SQLITE_ENABLE_FTS5 is defined, omit this file.
|
||||
# If SQLITE_ENABLE_FTS5 is not defined, omit this file.
|
||||
ifcapable !fts5 {
|
||||
finish_test
|
||||
return
|
||||
|
@@ -15,7 +15,7 @@
|
||||
source [file join [file dirname [info script]] fts5_common.tcl]
|
||||
set testprefix fts5prefix2
|
||||
|
||||
# If SQLITE_ENABLE_FTS5 is defined, omit this file.
|
||||
# If SQLITE_ENABLE_FTS5 is not defined, omit this file.
|
||||
ifcapable !fts5 {
|
||||
finish_test
|
||||
return
|
||||
|
@@ -15,7 +15,7 @@
|
||||
source [file join [file dirname [info script]] fts5_common.tcl]
|
||||
set testprefix fts5query
|
||||
|
||||
# If SQLITE_ENABLE_FTS5 is defined, omit this file.
|
||||
# If SQLITE_ENABLE_FTS5 is not defined, omit this file.
|
||||
ifcapable !fts5 {
|
||||
finish_test
|
||||
return
|
||||
|
@@ -15,7 +15,7 @@
|
||||
source [file join [file dirname [info script]] fts5_common.tcl]
|
||||
set testprefix fts5rank
|
||||
|
||||
# If SQLITE_ENABLE_FTS5 is defined, omit this file.
|
||||
# If SQLITE_ENABLE_FTS5 is not defined, omit this file.
|
||||
ifcapable !fts5 {
|
||||
finish_test
|
||||
return
|
||||
|
@@ -14,7 +14,7 @@
|
||||
source [file join [file dirname [info script]] fts5_common.tcl]
|
||||
set testprefix fts5rebuild
|
||||
|
||||
# If SQLITE_ENABLE_FTS5 is defined, omit this file.
|
||||
# If SQLITE_ENABLE_FTS5 is not defined, omit this file.
|
||||
ifcapable !fts5 {
|
||||
finish_test
|
||||
return
|
||||
|
@@ -15,7 +15,7 @@
|
||||
source [file join [file dirname [info script]] fts5_common.tcl]
|
||||
set testprefix fts5restart
|
||||
|
||||
# If SQLITE_ENABLE_FTS5 is defined, omit this file.
|
||||
# If SQLITE_ENABLE_FTS5 is not defined, omit this file.
|
||||
ifcapable !fts5 {
|
||||
finish_test
|
||||
return
|
||||
@@ -29,6 +29,7 @@ do_execsql_test 1.0 {
|
||||
# Run the 'optimize' command. Check that it does not disturb ongoing
|
||||
# full-text queries.
|
||||
#
|
||||
unset -nocomplain lRowid
|
||||
do_test 1.1 {
|
||||
for {set i 1} {$i < 1000} {incr i} {
|
||||
execsql { INSERT INTO f1 VALUES('a b c d e') }
|
||||
|
@@ -15,7 +15,7 @@
|
||||
source [file join [file dirname [info script]] fts5_common.tcl]
|
||||
set testprefix fts5rowid
|
||||
|
||||
# If SQLITE_ENABLE_FTS5 is defined, omit this file.
|
||||
# If SQLITE_ENABLE_FTS5 is not defined, omit this file.
|
||||
ifcapable !fts5 {
|
||||
finish_test
|
||||
return
|
||||
|
@@ -13,7 +13,7 @@
|
||||
source [file join [file dirname [info script]] fts5_common.tcl]
|
||||
set testprefix fts5savepoint
|
||||
|
||||
# If SQLITE_ENABLE_FTS5 is defined, omit this file.
|
||||
# If SQLITE_ENABLE_FTS5 is not defined, omit this file.
|
||||
ifcapable !fts5 {
|
||||
finish_test
|
||||
return
|
||||
|
@@ -42,6 +42,22 @@ do_execsql_test 1.2 {
|
||||
PRAGMA integrity_check;
|
||||
} {ok}
|
||||
|
||||
do_execsql_test 2.0 {
|
||||
CREATE VIRTUAL TABLE xyz USING fts5 (
|
||||
name,
|
||||
content=''
|
||||
);
|
||||
|
||||
INSERT INTO xyz(xyz, rank) VALUES('secure-delete', 1);
|
||||
INSERT INTO xyz (rowid, name) VALUES(1, 'A');
|
||||
INSERT INTO xyz (rowid, name) VALUES(2, 'A');
|
||||
INSERT INTO xyz(xyz, rowid, name) VALUES('delete', 2, 'A');
|
||||
}
|
||||
|
||||
do_execsql_test 2.1 {
|
||||
pragma quick_check;
|
||||
} {ok}
|
||||
|
||||
|
||||
|
||||
|
||||
|
@@ -16,7 +16,7 @@ source [file join [file dirname [info script]] fts5_common.tcl]
|
||||
source $testdir/malloc_common.tcl
|
||||
set testprefix fts5securefault
|
||||
|
||||
# If SQLITE_ENABLE_FTS5 is defined, omit this file.
|
||||
# If SQLITE_ENABLE_FTS5 is not defined, omit this file.
|
||||
return_if_no_fts5
|
||||
|
||||
do_execsql_test 1.0 {
|
||||
|
@@ -13,7 +13,7 @@
|
||||
source [file join [file dirname [info script]] fts5_common.tcl]
|
||||
set testprefix fts5simple
|
||||
|
||||
# If SQLITE_ENABLE_FTS5 is defined, omit this file.
|
||||
# If SQLITE_ENABLE_FTS5 is not defined, omit this file.
|
||||
ifcapable !fts5 {
|
||||
finish_test
|
||||
return
|
||||
|
@@ -13,7 +13,7 @@
|
||||
source [file join [file dirname [info script]] fts5_common.tcl]
|
||||
set testprefix fts5simple2
|
||||
|
||||
# If SQLITE_ENABLE_FTS5 is defined, omit this file.
|
||||
# If SQLITE_ENABLE_FTS5 is not defined, omit this file.
|
||||
ifcapable !fts5 {
|
||||
finish_test
|
||||
return
|
||||
|
@@ -13,7 +13,7 @@
|
||||
source [file join [file dirname [info script]] fts5_common.tcl]
|
||||
set testprefix fts5simple3
|
||||
|
||||
# If SQLITE_ENABLE_FTS5 is defined, omit this file.
|
||||
# If SQLITE_ENABLE_FTS5 is not defined, omit this file.
|
||||
ifcapable !fts5 {
|
||||
finish_test
|
||||
return
|
||||
|
@@ -15,7 +15,7 @@
|
||||
source [file join [file dirname [info script]] fts5_common.tcl]
|
||||
set testprefix fts5synonym
|
||||
|
||||
# If SQLITE_ENABLE_FTS5 is defined, omit this file.
|
||||
# If SQLITE_ENABLE_FTS5 is not defined, omit this file.
|
||||
ifcapable !fts5 {
|
||||
finish_test
|
||||
return
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user