Compare commits
7 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| a90a2d58a4 | |||
| 61f8e86f93 | |||
| 8385becfe1 | |||
| d37ce8396a | |||
| 56c9311c63 | |||
| 53bf7175af | |||
| fa337cc115 |
@@ -89,6 +89,9 @@ TCC += $(OPT_FEATURE_FLAGS)
|
||||
# ie. make "OPTS=-DSQLITE_ENABLE_FOO=1 -DSQLITE_OMIT_FOO=1".
|
||||
TCC += $(OPTS)
|
||||
|
||||
# Add in compile-time options for some libraries used by extensions
|
||||
TCC += @HAVE_ZLIB@
|
||||
|
||||
# Version numbers and release number for the SQLite being compiled.
|
||||
#
|
||||
VERSION = @VERSION@
|
||||
|
||||
@@ -772,6 +772,7 @@ LIBOBJS
|
||||
BUILD_CFLAGS
|
||||
USE_GCOV
|
||||
OPT_FEATURE_FLAGS
|
||||
HAVE_ZLIB
|
||||
USE_AMALGAMATION
|
||||
TARGET_DEBUG
|
||||
TARGET_HAVE_EDITLINE
|
||||
@@ -3931,13 +3932,13 @@ if ${lt_cv_nm_interface+:} false; then :
|
||||
else
|
||||
lt_cv_nm_interface="BSD nm"
|
||||
echo "int some_variable = 0;" > conftest.$ac_ext
|
||||
(eval echo "\"\$as_me:3934: $ac_compile\"" >&5)
|
||||
(eval echo "\"\$as_me:3935: $ac_compile\"" >&5)
|
||||
(eval "$ac_compile" 2>conftest.err)
|
||||
cat conftest.err >&5
|
||||
(eval echo "\"\$as_me:3937: $NM \\\"conftest.$ac_objext\\\"\"" >&5)
|
||||
(eval echo "\"\$as_me:3938: $NM \\\"conftest.$ac_objext\\\"\"" >&5)
|
||||
(eval "$NM \"conftest.$ac_objext\"" 2>conftest.err > conftest.out)
|
||||
cat conftest.err >&5
|
||||
(eval echo "\"\$as_me:3940: output\"" >&5)
|
||||
(eval echo "\"\$as_me:3941: output\"" >&5)
|
||||
cat conftest.out >&5
|
||||
if $GREP 'External.*some_variable' conftest.out > /dev/null; then
|
||||
lt_cv_nm_interface="MS dumpbin"
|
||||
@@ -5143,7 +5144,7 @@ ia64-*-hpux*)
|
||||
;;
|
||||
*-*-irix6*)
|
||||
# Find out which ABI we are using.
|
||||
echo '#line 5146 "configure"' > conftest.$ac_ext
|
||||
echo '#line 5147 "configure"' > conftest.$ac_ext
|
||||
if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_compile\""; } >&5
|
||||
(eval $ac_compile) 2>&5
|
||||
ac_status=$?
|
||||
@@ -6668,11 +6669,11 @@ else
|
||||
-e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \
|
||||
-e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \
|
||||
-e 's:$: $lt_compiler_flag:'`
|
||||
(eval echo "\"\$as_me:6671: $lt_compile\"" >&5)
|
||||
(eval echo "\"\$as_me:6672: $lt_compile\"" >&5)
|
||||
(eval "$lt_compile" 2>conftest.err)
|
||||
ac_status=$?
|
||||
cat conftest.err >&5
|
||||
echo "$as_me:6675: \$? = $ac_status" >&5
|
||||
echo "$as_me:6676: \$? = $ac_status" >&5
|
||||
if (exit $ac_status) && test -s "$ac_outfile"; then
|
||||
# The compiler can only warn and ignore the option if not recognized
|
||||
# So say no if there are warnings other than the usual output.
|
||||
@@ -7007,11 +7008,11 @@ else
|
||||
-e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \
|
||||
-e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \
|
||||
-e 's:$: $lt_compiler_flag:'`
|
||||
(eval echo "\"\$as_me:7010: $lt_compile\"" >&5)
|
||||
(eval echo "\"\$as_me:7011: $lt_compile\"" >&5)
|
||||
(eval "$lt_compile" 2>conftest.err)
|
||||
ac_status=$?
|
||||
cat conftest.err >&5
|
||||
echo "$as_me:7014: \$? = $ac_status" >&5
|
||||
echo "$as_me:7015: \$? = $ac_status" >&5
|
||||
if (exit $ac_status) && test -s "$ac_outfile"; then
|
||||
# The compiler can only warn and ignore the option if not recognized
|
||||
# So say no if there are warnings other than the usual output.
|
||||
@@ -7112,11 +7113,11 @@ else
|
||||
-e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \
|
||||
-e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \
|
||||
-e 's:$: $lt_compiler_flag:'`
|
||||
(eval echo "\"\$as_me:7115: $lt_compile\"" >&5)
|
||||
(eval echo "\"\$as_me:7116: $lt_compile\"" >&5)
|
||||
(eval "$lt_compile" 2>out/conftest.err)
|
||||
ac_status=$?
|
||||
cat out/conftest.err >&5
|
||||
echo "$as_me:7119: \$? = $ac_status" >&5
|
||||
echo "$as_me:7120: \$? = $ac_status" >&5
|
||||
if (exit $ac_status) && test -s out/conftest2.$ac_objext
|
||||
then
|
||||
# The compiler can only warn and ignore the option if not recognized
|
||||
@@ -7167,11 +7168,11 @@ else
|
||||
-e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \
|
||||
-e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \
|
||||
-e 's:$: $lt_compiler_flag:'`
|
||||
(eval echo "\"\$as_me:7170: $lt_compile\"" >&5)
|
||||
(eval echo "\"\$as_me:7171: $lt_compile\"" >&5)
|
||||
(eval "$lt_compile" 2>out/conftest.err)
|
||||
ac_status=$?
|
||||
cat out/conftest.err >&5
|
||||
echo "$as_me:7174: \$? = $ac_status" >&5
|
||||
echo "$as_me:7175: \$? = $ac_status" >&5
|
||||
if (exit $ac_status) && test -s out/conftest2.$ac_objext
|
||||
then
|
||||
# The compiler can only warn and ignore the option if not recognized
|
||||
@@ -9547,7 +9548,7 @@ else
|
||||
lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2
|
||||
lt_status=$lt_dlunknown
|
||||
cat > conftest.$ac_ext <<_LT_EOF
|
||||
#line 9550 "configure"
|
||||
#line 9551 "configure"
|
||||
#include "confdefs.h"
|
||||
|
||||
#if HAVE_DLFCN_H
|
||||
@@ -9643,7 +9644,7 @@ else
|
||||
lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2
|
||||
lt_status=$lt_dlunknown
|
||||
cat > conftest.$ac_ext <<_LT_EOF
|
||||
#line 9646 "configure"
|
||||
#line 9647 "configure"
|
||||
#include "confdefs.h"
|
||||
|
||||
#if HAVE_DLFCN_H
|
||||
@@ -11274,6 +11275,80 @@ if test "${use_amalgamation}" != "yes" ; then
|
||||
fi
|
||||
|
||||
|
||||
#########
|
||||
# Look for zlib. Only needed by extensions and by the sqlite3.exe shell
|
||||
for ac_header in zlib.h
|
||||
do :
|
||||
ac_fn_c_check_header_mongrel "$LINENO" "zlib.h" "ac_cv_header_zlib_h" "$ac_includes_default"
|
||||
if test "x$ac_cv_header_zlib_h" = xyes; then :
|
||||
cat >>confdefs.h <<_ACEOF
|
||||
#define HAVE_ZLIB_H 1
|
||||
_ACEOF
|
||||
|
||||
fi
|
||||
|
||||
done
|
||||
|
||||
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for library containing deflate" >&5
|
||||
$as_echo_n "checking for library containing deflate... " >&6; }
|
||||
if ${ac_cv_search_deflate+:} false; then :
|
||||
$as_echo_n "(cached) " >&6
|
||||
else
|
||||
ac_func_search_save_LIBS=$LIBS
|
||||
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
|
||||
/* end confdefs.h. */
|
||||
|
||||
/* Override any GCC internal prototype to avoid an error.
|
||||
Use char because int might match the return type of a GCC
|
||||
builtin and then its argument prototype would still apply. */
|
||||
#ifdef __cplusplus
|
||||
extern "C"
|
||||
#endif
|
||||
char deflate ();
|
||||
int
|
||||
main ()
|
||||
{
|
||||
return deflate ();
|
||||
;
|
||||
return 0;
|
||||
}
|
||||
_ACEOF
|
||||
for ac_lib in '' z; do
|
||||
if test -z "$ac_lib"; then
|
||||
ac_res="none required"
|
||||
else
|
||||
ac_res=-l$ac_lib
|
||||
LIBS="-l$ac_lib $ac_func_search_save_LIBS"
|
||||
fi
|
||||
if ac_fn_c_try_link "$LINENO"; then :
|
||||
ac_cv_search_deflate=$ac_res
|
||||
fi
|
||||
rm -f core conftest.err conftest.$ac_objext \
|
||||
conftest$ac_exeext
|
||||
if ${ac_cv_search_deflate+:} false; then :
|
||||
break
|
||||
fi
|
||||
done
|
||||
if ${ac_cv_search_deflate+:} false; then :
|
||||
|
||||
else
|
||||
ac_cv_search_deflate=no
|
||||
fi
|
||||
rm conftest.$ac_ext
|
||||
LIBS=$ac_func_search_save_LIBS
|
||||
fi
|
||||
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_search_deflate" >&5
|
||||
$as_echo "$ac_cv_search_deflate" >&6; }
|
||||
ac_res=$ac_cv_search_deflate
|
||||
if test "$ac_res" != no; then :
|
||||
test "$ac_res" = "none required" || LIBS="$ac_res $LIBS"
|
||||
HAVE_ZLIB="-DSQLITE_HAVE_ZLIB=1"
|
||||
else
|
||||
HAVE_ZLIB=""
|
||||
fi
|
||||
|
||||
|
||||
|
||||
#########
|
||||
# See whether we should allow loadable extensions
|
||||
# Check whether --enable-load-extension was given.
|
||||
|
||||
@@ -576,6 +576,12 @@ if test "${use_amalgamation}" != "yes" ; then
|
||||
fi
|
||||
AC_SUBST(USE_AMALGAMATION)
|
||||
|
||||
#########
|
||||
# Look for zlib. Only needed by extensions and by the sqlite3.exe shell
|
||||
AC_CHECK_HEADERS(zlib.h)
|
||||
AC_SEARCH_LIBS(deflate, z, [HAVE_ZLIB="-DSQLITE_HAVE_ZLIB=1"], [HAVE_ZLIB=""])
|
||||
AC_SUBST(HAVE_ZLIB)
|
||||
|
||||
#########
|
||||
# See whether we should allow loadable extensions
|
||||
AC_ARG_ENABLE(load-extension, AC_HELP_STRING([--disable-load-extension],
|
||||
|
||||
@@ -722,6 +722,8 @@ Fts5ExprPhrase *sqlite3Fts5ParseTerm(
|
||||
int bPrefix
|
||||
);
|
||||
|
||||
void sqlite3Fts5ParseSetCaret(Fts5ExprPhrase*);
|
||||
|
||||
Fts5ExprNearset *sqlite3Fts5ParseNearset(
|
||||
Fts5Parse*,
|
||||
Fts5ExprNearset*,
|
||||
|
||||
+44
-18
@@ -87,7 +87,8 @@ struct Fts5ExprNode {
|
||||
** or term prefix.
|
||||
*/
|
||||
struct Fts5ExprTerm {
|
||||
int bPrefix; /* True for a prefix term */
|
||||
u8 bPrefix; /* True for a prefix term */
|
||||
u8 bFirst; /* True if token must be first in column */
|
||||
char *zTerm; /* nul-terminated term */
|
||||
Fts5IndexIter *pIter; /* Iterator for this term */
|
||||
Fts5ExprTerm *pSynonym; /* Pointer to first in list of synonyms */
|
||||
@@ -168,6 +169,7 @@ static int fts5ExprGetToken(
|
||||
case '+': tok = FTS5_PLUS; break;
|
||||
case '*': tok = FTS5_STAR; break;
|
||||
case '-': tok = FTS5_MINUS; break;
|
||||
case '^': tok = FTS5_CARET; break;
|
||||
case '\0': tok = FTS5_EOF; break;
|
||||
|
||||
case '"': {
|
||||
@@ -427,6 +429,7 @@ static int fts5ExprPhraseIsMatch(
|
||||
Fts5PoslistReader *aIter = aStatic;
|
||||
int i;
|
||||
int rc = SQLITE_OK;
|
||||
int bFirst = pPhrase->aTerm[0].bFirst;
|
||||
|
||||
fts5BufferZero(&pPhrase->poslist);
|
||||
|
||||
@@ -481,8 +484,10 @@ static int fts5ExprPhraseIsMatch(
|
||||
}while( bMatch==0 );
|
||||
|
||||
/* Append position iPos to the output */
|
||||
rc = sqlite3Fts5PoslistWriterAppend(&pPhrase->poslist, &writer, iPos);
|
||||
if( rc!=SQLITE_OK ) goto ismatch_out;
|
||||
if( bFirst==0 || FTS5_POS2OFFSET(iPos)==0 ){
|
||||
rc = sqlite3Fts5PoslistWriterAppend(&pPhrase->poslist, &writer, iPos);
|
||||
if( rc!=SQLITE_OK ) goto ismatch_out;
|
||||
}
|
||||
|
||||
for(i=0; i<pPhrase->nTerm; i++){
|
||||
if( sqlite3Fts5PoslistReaderNext(&aIter[i]) ) goto ismatch_out;
|
||||
@@ -736,7 +741,9 @@ static int fts5ExprNearTest(
|
||||
** phrase is not a match, break out of the loop early. */
|
||||
for(i=0; rc==SQLITE_OK && i<pNear->nPhrase; i++){
|
||||
Fts5ExprPhrase *pPhrase = pNear->apPhrase[i];
|
||||
if( pPhrase->nTerm>1 || pPhrase->aTerm[0].pSynonym || pNear->pColset ){
|
||||
if( pPhrase->nTerm>1 || pPhrase->aTerm[0].pSynonym
|
||||
|| pNear->pColset || pPhrase->aTerm[0].bFirst
|
||||
){
|
||||
int bMatch = 0;
|
||||
rc = fts5ExprPhraseIsMatch(pNode, pPhrase, &bMatch);
|
||||
if( bMatch==0 ) break;
|
||||
@@ -917,6 +924,7 @@ static int fts5ExprNodeTest_STRING(
|
||||
assert( pNear->nPhrase>1
|
||||
|| pNear->apPhrase[0]->nTerm>1
|
||||
|| pNear->apPhrase[0]->aTerm[0].pSynonym
|
||||
|| pNear->apPhrase[0]->aTerm[0].bFirst
|
||||
);
|
||||
|
||||
/* Initialize iLast, the "lastest" rowid any iterator points to. If the
|
||||
@@ -1441,6 +1449,16 @@ static void fts5ExprPhraseFree(Fts5ExprPhrase *pPhrase){
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
** Set the "bFirst" flag on the first token of the phrase passed as the
|
||||
** only argument.
|
||||
*/
|
||||
void sqlite3Fts5ParseSetCaret(Fts5ExprPhrase *pPhrase){
|
||||
if( pPhrase && pPhrase->nTerm ){
|
||||
pPhrase->aTerm[0].bFirst = 1;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
** If argument pNear is NULL, then a new Fts5ExprNearset object is allocated
|
||||
** and populated with pPhrase. Or, if pNear is not NULL, phrase pPhrase is
|
||||
@@ -1719,6 +1737,7 @@ int sqlite3Fts5ExprClonePhrase(
|
||||
}
|
||||
if( rc==SQLITE_OK ){
|
||||
sCtx.pPhrase->aTerm[i].bPrefix = pOrig->aTerm[i].bPrefix;
|
||||
sCtx.pPhrase->aTerm[i].bFirst = pOrig->aTerm[i].bFirst;
|
||||
}
|
||||
}
|
||||
}else{
|
||||
@@ -1737,7 +1756,10 @@ int sqlite3Fts5ExprClonePhrase(
|
||||
pNew->pRoot->pNear->nPhrase = 1;
|
||||
sCtx.pPhrase->pNode = pNew->pRoot;
|
||||
|
||||
if( pOrig->nTerm==1 && pOrig->aTerm[0].pSynonym==0 ){
|
||||
if( pOrig->nTerm==1
|
||||
&& pOrig->aTerm[0].pSynonym==0
|
||||
&& pOrig->aTerm[0].bFirst==0
|
||||
){
|
||||
pNew->pRoot->eType = FTS5_TERM;
|
||||
pNew->pRoot->xNext = fts5ExprNodeNext_TERM;
|
||||
}else{
|
||||
@@ -2011,6 +2033,7 @@ static void fts5ExprAssignXNext(Fts5ExprNode *pNode){
|
||||
Fts5ExprNearset *pNear = pNode->pNear;
|
||||
if( pNear->nPhrase==1 && pNear->apPhrase[0]->nTerm==1
|
||||
&& pNear->apPhrase[0]->aTerm[0].pSynonym==0
|
||||
&& pNear->apPhrase[0]->aTerm[0].bFirst==0
|
||||
){
|
||||
pNode->eType = FTS5_TERM;
|
||||
pNode->xNext = fts5ExprNodeNext_TERM;
|
||||
@@ -2097,20 +2120,23 @@ Fts5ExprNode *sqlite3Fts5ParseNode(
|
||||
}
|
||||
}
|
||||
|
||||
if( pParse->pConfig->eDetail!=FTS5_DETAIL_FULL
|
||||
&& (pNear->nPhrase!=1 || pNear->apPhrase[0]->nTerm>1)
|
||||
){
|
||||
assert( pParse->rc==SQLITE_OK );
|
||||
pParse->rc = SQLITE_ERROR;
|
||||
assert( pParse->zErr==0 );
|
||||
pParse->zErr = sqlite3_mprintf(
|
||||
"fts5: %s queries are not supported (detail!=full)",
|
||||
pNear->nPhrase==1 ? "phrase": "NEAR"
|
||||
);
|
||||
sqlite3_free(pRet);
|
||||
pRet = 0;
|
||||
if( pParse->pConfig->eDetail!=FTS5_DETAIL_FULL ){
|
||||
Fts5ExprPhrase *pPhrase = pNear->apPhrase[0];
|
||||
if( pNear->nPhrase!=1
|
||||
|| pPhrase->nTerm>1
|
||||
|| (pPhrase->nTerm>0 && pPhrase->aTerm[0].bFirst)
|
||||
){
|
||||
assert( pParse->rc==SQLITE_OK );
|
||||
pParse->rc = SQLITE_ERROR;
|
||||
assert( pParse->zErr==0 );
|
||||
pParse->zErr = sqlite3_mprintf(
|
||||
"fts5: %s queries are not supported (detail!=full)",
|
||||
pNear->nPhrase==1 ? "phrase": "NEAR"
|
||||
);
|
||||
sqlite3_free(pRet);
|
||||
pRet = 0;
|
||||
}
|
||||
}
|
||||
|
||||
}else{
|
||||
fts5ExprAddChildren(pRet, pLeft);
|
||||
fts5ExprAddChildren(pRet, pRight);
|
||||
|
||||
@@ -148,7 +148,11 @@ cnearset(A) ::= colset(X) COLON nearset(Y). {
|
||||
%destructor nearset { sqlite3Fts5ParseNearsetFree($$); }
|
||||
%destructor nearphrases { sqlite3Fts5ParseNearsetFree($$); }
|
||||
|
||||
nearset(A) ::= phrase(X). { A = sqlite3Fts5ParseNearset(pParse, 0, X); }
|
||||
nearset(A) ::= phrase(Y). { A = sqlite3Fts5ParseNearset(pParse, 0, Y); }
|
||||
nearset(A) ::= CARET phrase(Y). {
|
||||
sqlite3Fts5ParseSetCaret(Y);
|
||||
A = sqlite3Fts5ParseNearset(pParse, 0, Y);
|
||||
}
|
||||
nearset(A) ::= STRING(X) LP nearphrases(Y) neardist_opt(Z) RP. {
|
||||
sqlite3Fts5ParseNear(pParse, &X);
|
||||
sqlite3Fts5ParseSetDistance(pParse, Y, &Z);
|
||||
@@ -189,6 +193,5 @@ phrase(A) ::= STRING(Y) star_opt(Z). {
|
||||
** Optional "*" character.
|
||||
*/
|
||||
%type star_opt {int}
|
||||
|
||||
star_opt(A) ::= STAR. { A = 1; }
|
||||
star_opt(A) ::= . { A = 0; }
|
||||
|
||||
@@ -130,5 +130,22 @@ do_faultsim_test 4.2 -faults oom* -body {
|
||||
faultsim_test_result {0 {2 3}}
|
||||
}
|
||||
|
||||
#-------------------------------------------------------------------------
|
||||
# Test OOM injection while parsing a CARET expression
|
||||
#
|
||||
reset_db
|
||||
do_execsql_test 5.0 {
|
||||
CREATE VIRTUAL TABLE t1 USING fts5(a);
|
||||
INSERT INTO t1 VALUES('a b c d'); -- 1
|
||||
INSERT INTO t1 VALUES('d a b c'); -- 2
|
||||
INSERT INTO t1 VALUES('c d a b'); -- 3
|
||||
INSERT INTO t1 VALUES('b c d a'); -- 4
|
||||
}
|
||||
do_faultsim_test 5.1 -faults oom* -body {
|
||||
execsql { SELECT rowid FROM t1('^a OR ^b') }
|
||||
} -test {
|
||||
faultsim_test_result {0 {1 4}}
|
||||
}
|
||||
|
||||
|
||||
finish_test
|
||||
|
||||
@@ -0,0 +1,96 @@
|
||||
# 2017 November 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.
|
||||
#
|
||||
#***********************************************************************
|
||||
|
||||
source [file join [file dirname [info script]] fts5_common.tcl]
|
||||
set testprefix fts5first
|
||||
|
||||
ifcapable !fts5 {
|
||||
finish_test
|
||||
return
|
||||
}
|
||||
|
||||
|
||||
do_execsql_test 1.0 {
|
||||
CREATE VIRTUAL TABLE x1 USING fts5(a, b);
|
||||
}
|
||||
|
||||
foreach {tn expr ok} {
|
||||
1 {^abc} 1
|
||||
2 {^abc + def} 1
|
||||
3 {^ "abc def"} 1
|
||||
4 {^"abc def"} 1
|
||||
5 {abc ^def} 1
|
||||
6 {abc + ^def} 0
|
||||
7 {abc ^+ def} 0
|
||||
8 {"^abc"} 1
|
||||
9 {NEAR(^abc def)} 0
|
||||
} {
|
||||
set res(0) {/1 {fts5: syntax error near .*}/}
|
||||
set res(1) {0 {}}
|
||||
|
||||
do_catchsql_test 1.$tn { SELECT * FROM x1($expr) } $res($ok)
|
||||
}
|
||||
|
||||
#-------------------------------------------------------------------------
|
||||
#
|
||||
do_execsql_test 2.0 {
|
||||
INSERT INTO x1 VALUES('a b c', 'b c a');
|
||||
}
|
||||
|
||||
foreach {tn expr match} {
|
||||
1 {^a} 1
|
||||
2 {^b} 1
|
||||
3 {^c} 0
|
||||
4 {^a + b} 1
|
||||
5 {^b + c} 1
|
||||
6 {^c + a} 0
|
||||
7 {^"c a"} 0
|
||||
8 {a:^a} 1
|
||||
9 {a:^b} 0
|
||||
10 {a:^"a b"} 1
|
||||
} {
|
||||
do_execsql_test 2.$tn { SELECT EXISTS (SELECT rowid FROM x1($expr)) } $match
|
||||
}
|
||||
|
||||
#-------------------------------------------------------------------------
|
||||
#
|
||||
do_execsql_test 3.0 {
|
||||
DELETE FROM x1;
|
||||
INSERT INTO x1 VALUES('b a', 'c a');
|
||||
INSERT INTO x1 VALUES('a a', 'c c');
|
||||
INSERT INTO x1 VALUES('a b', 'a a');
|
||||
}
|
||||
fts5_aux_test_functions db
|
||||
|
||||
foreach {tn expr expect} {
|
||||
1 {^a} {{2 1}}
|
||||
2 {^c AND ^b} {{0 2} {1 0}}
|
||||
} {
|
||||
do_execsql_test 3.$tn {
|
||||
SELECT fts5_test_queryphrase(x1) FROM x1($expr) LIMIT 1
|
||||
} [list $expect]
|
||||
}
|
||||
|
||||
#-------------------------------------------------------------------------
|
||||
#
|
||||
do_execsql_test 3.1 {
|
||||
CREATE VIRTUAL TABLE x2 USING fts5(a, b, c, detail=column);
|
||||
}
|
||||
|
||||
do_catchsql_test 3.2 {
|
||||
SELECT * FROM x2('a + b');
|
||||
} {1 {fts5: phrase queries are not supported (detail!=full)}}
|
||||
|
||||
do_catchsql_test 3.3 {
|
||||
SELECT * FROM x2('^a');
|
||||
} {1 {fts5: phrase queries are not supported (detail!=full)}}
|
||||
finish_test
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
C Fix\sthe\sskip-ahead-distinct\soptimization\son\sjoins\sfor\scases\sthere\sthe\stable\nin\sthe\sinner\sloop\sof\sthe\sjoin\sdoes\snot\scontribute\sany\scolumns\sto\sthe\nresult\sset.\s\sProposed\sfix\sfor\sticket\s[ef9318757b152e3a2]
|
||||
D 2017-11-21T23:38:48.349
|
||||
F Makefile.in b142eb20482922153ebc77b261cdfd0a560ed05a81e9f6d9a2b0e8192922a1d2
|
||||
C Use\sa\ssymbolic\sconstant\sinstead\sof\sa\sliteral\s(-1)\sto\sidentify\sa\nwarn-on-contention\smutex.
|
||||
D 2017-11-28T07:47:57.520
|
||||
F Makefile.in 6a879cbf01e37f9eac131414955f71774b566502d9a57ded1b8585b507503cb8
|
||||
F Makefile.linux-gcc 7bc79876b875010e8c8f9502eb935ca92aa3c434
|
||||
F Makefile.msc e5d7606238f55816da99f719969598df5b091aa2e9a6935c9412fcae8f53fc44
|
||||
F README.md f5c87359573c4d255425e588a56554b50fdcc2afba4e017a2e02a43701456afd
|
||||
@@ -30,8 +30,8 @@ F autoconf/tea/win/rules.vc c511f222b80064096b705dbeb97060ee1d6b6d63
|
||||
F config.guess 226d9a188c6196f3033ffc651cbc9dcee1a42977
|
||||
F config.h.in 6376abec766e9a0785178b1823b5a587e9f1ccbc
|
||||
F config.sub 9ebe4c3b3dab6431ece34f16828b594fb420da55
|
||||
F configure bdc49e9f0b0ced903ebdb2850362dd3391eeb88585e0429d12b94928d2873b6b x
|
||||
F configure.ac 369ebae6c04d9d2de5064e21d300f2f42f2fbf13235cabff9d1a54f2b2c4d05d
|
||||
F configure 9af547be0e0e1a8fca8553b82599b5a3be1528a3d78deb68cb49d3b611215cb7 x
|
||||
F configure.ac d4529ebb26ae046269334f1dac65f2b1d6927c2efe22b2ec24dce24dfe4f83dd
|
||||
F contrib/sqlitecon.tcl 210a913ad63f9f991070821e599d600bd913e0ad
|
||||
F doc/lemon.html 278113807f49d12d04179a93fab92b5b917a08771152ca7949d34e928efa3941
|
||||
F doc/pager-invariants.txt 27fed9a70ddad2088750c4a2b493b63853da2710
|
||||
@@ -99,11 +99,11 @@ F ext/fts3/unicode/mkunicode.tcl ab0543a3b2399092ea2dd75df1bef333405b0d7f6b8c495
|
||||
F ext/fts3/unicode/parseunicode.tcl da577d1384810fb4e2b209bf3313074353193e95
|
||||
F ext/fts5/extract_api_docs.tcl a36e54ec777172ddd3f9a88daf593b00848368e0
|
||||
F ext/fts5/fts5.h 62f3e33ceeb9a428db139f9c012186b371da1cc7
|
||||
F ext/fts5/fts5Int.h 15e7514b46a845937d7c62e5c69e935091f0dbb72eb61aa4c8bcfbd39fdea158
|
||||
F ext/fts5/fts5Int.h eda28e3a0a5d87c412e8355fe35da875b04cb389908c8eb0d867ad662adbc491
|
||||
F ext/fts5/fts5_aux.c 67acf8d51723cf28ffc3828210ba662df4b8d267
|
||||
F ext/fts5/fts5_buffer.c 1dd1ec0446b3acfc2d7d407eb894762a461613e2695273f48e449bfd13e973ff
|
||||
F ext/fts5/fts5_config.c 5af9c360e99669d29f06492c370892394aba0857
|
||||
F ext/fts5/fts5_expr.c f2825f714d91bbe62ab5820aee9ad12e0c94205b2a01725eaa9072415ae9ff1c
|
||||
F ext/fts5/fts5_expr.c 01048018d21524e2c302b063ff5c3cdcf546e03297215e577205d85b47499deb
|
||||
F ext/fts5/fts5_hash.c 32be400cf761868c9db33efe81a06eb19a17c5402ad477ee9efb51301546dd55
|
||||
F ext/fts5/fts5_index.c 2ce9d50ec5508b8205615aad69e1c9b2c77f017f21d4479e1fb2079c01fdd017
|
||||
F ext/fts5/fts5_main.c 24868f88ab2a865defbba7a92eebeb726cc991eb092b71b5f5508f180c72605b
|
||||
@@ -115,7 +115,7 @@ F ext/fts5/fts5_tokenize.c 2ce7b44183538ec46b7907726262ee43ffdd39a8
|
||||
F ext/fts5/fts5_unicode2.c b450b209b157d598f7b9df9f837afb75a14c24bf
|
||||
F ext/fts5/fts5_varint.c a5aceacda04dafcbae725413d7a16818ecd65738
|
||||
F ext/fts5/fts5_vocab.c 1cd79854cb21543e66507b25b0578bc1b20aa6a1349b7feceb8e8fed0e7a77a6
|
||||
F ext/fts5/fts5parse.y a070b538e08ae9e2177d15c337ed2a3464408f0f886e746307098f746efd94ca
|
||||
F ext/fts5/fts5parse.y eb526940f892ade5693f22ffd6c4f2702543a9059942772526eac1fde256bb05
|
||||
F ext/fts5/mkportersteps.tcl 5acf962d2e0074f701620bb5308155fa1e4a63ba
|
||||
F ext/fts5/test/fts5_common.tcl b01c584144b5064f30e6c648145a2dd6bc440841
|
||||
F ext/fts5/test/fts5aa.test cba3fae6466446980caf1b9f5f26df77f95a999d35db7d932d6e82ae7ba0ede9
|
||||
@@ -162,8 +162,9 @@ F ext/fts5/test/fts5fault7.test 0acbec416edb24b8881f154e99c31e9ccf73f539cfcd1640
|
||||
F ext/fts5/test/fts5fault8.test 318238659d35f82ad215ecb57ca4c87486ea85d45dbeedaee42f148ff5105ee2
|
||||
F ext/fts5/test/fts5fault9.test 0111b229388bdf251b91cfead68580227801dd30960a19aa8fe9021a1e73cb6d
|
||||
F ext/fts5/test/fts5faultA.test be4487576bff8c22cee6597d1893b312f306504a8c6ccd3c53ca85af12290c8c
|
||||
F ext/fts5/test/fts5faultB.test 28810d93d37b59ebd5cf9502897f4dc9e6adb8ea6a5f64e125d3088597199d0d
|
||||
F ext/fts5/test/fts5faultB.test e6d04f9ea7b21be1d89abb8df2cb4baf65b0453b744d5a805fcd3ef45ff86a7e
|
||||
F ext/fts5/test/fts5faultD.test cc5d1225556e356615e719c612e845d41bff7d5a
|
||||
F ext/fts5/test/fts5first.test 707a591b1b7d893fcfcb2366cbfe56aefab5d9c7cfa58bef35eba73a1dbf3b29
|
||||
F ext/fts5/test/fts5full.test 49b565da02918c06e58f51f0b953b0302b96f155aa68baba24782b81570685e2
|
||||
F ext/fts5/test/fts5fuzz1.test 238d8c45f3b81342aa384de3e581ff2fa330bf922a7b69e484bbc06051a1080e
|
||||
F ext/fts5/test/fts5hash.test a4cf51acad99bfc43c16fb74f9d22495dc221ae0701fc5e908ca963a9b26a02b
|
||||
@@ -435,7 +436,7 @@ F src/in-operator.md 10cd8f4bcd225a32518407c2fb2484089112fd71
|
||||
F src/insert.c cb67cc56ef2ddd13e6944b2c0dd08a920bcd9503230adef8b9928d338097c722
|
||||
F src/legacy.c 134ab3e3fae00a0f67a5187981d6935b24b337bcf0f4b3e5c9fa5763da95bf4e
|
||||
F src/loadext.c 20865b183bb8a3723d59cf1efffc3c50217eb452c1021d077b908c94da26b0b2
|
||||
F src/main.c 99ed3d45e315afb2ada049991db7944b1210663bb30bfd0b63103537c1ac25d0
|
||||
F src/main.c 6a0cc1c7b8ab92374effecdd7b92792b3273a255c70575b7d67bd9a4315e6d3a
|
||||
F src/malloc.c a02c9e69bc76bee0f639416b947a946412890b606301454727feadcb313536d6
|
||||
F src/mem0.c 6a55ebe57c46ca1a7d98da93aaa07f99f1059645
|
||||
F src/mem1.c c12a42539b1ba105e3707d0e628ad70e611040d8f5e38cf942cee30c867083de
|
||||
@@ -444,7 +445,7 @@ F src/mem3.c 8768ac94694f31ffaf8b4d0ea5dc08af7010a35a
|
||||
F src/mem5.c 9bf955937b07f8c32541c8a9991f33ce3173d944
|
||||
F src/memjournal.c 6f3d36a0a8f72f48f6c3c722f04301ac64f2515435fa42924293e46fc7994661
|
||||
F src/msvc.h 4942752b6a253116baaa8de75256c51a459a5e81
|
||||
F src/mutex.c 8e45800ee78e0cd1f1f3fe8e398853307f4a085c
|
||||
F src/mutex.c 20172f2cc43c4542f7860ab6bafdd16965822c4e56650d62628059a48c7f43c4
|
||||
F src/mutex.h 779d588e3b7756ec3ecf7d78cde1d84aba414f85
|
||||
F src/mutex_noop.c 9d4309c075ba9cc7249e19412d3d62f7f94839c4
|
||||
F src/mutex_unix.c 27bb6cc49485ee46711a6580ab7b3f1402211d23
|
||||
@@ -475,7 +476,7 @@ F src/shell.c.in cb1b5e41ef9c081b2b8927ae32c9c384a9ec110ada808ebfe083ba7c8a19bbb
|
||||
F src/sqlite.h.in 8fd97993d48b50b9bade38c52f12d175942c9497c960905610c7b03a3e4b5818
|
||||
F src/sqlite3.rc 5121c9e10c3964d5755191c80dd1180c122fc3a8
|
||||
F src/sqlite3ext.h c02d628cca67f3889c689d82d25c3eb45e2c155db08e4c6089b5840d64687d34
|
||||
F src/sqliteInt.h 9b26fbab75ef426efae70d88ab535844d59de8954542b122c1d49af580a76f58
|
||||
F src/sqliteInt.h 4c910d9c0d88a90e8639a4f83ef05f701ccfe731cf593e757444074f01df4964
|
||||
F src/sqliteLimit.h 1513bfb7b20378aa0041e7022d04acb73525de35b80b252f1b83fedb4de6a76b
|
||||
F src/status.c 9737ed017279a9e0c5da748701c3c7bf1e8ae0dae459aad20dd64fcff97a7e35
|
||||
F src/table.c b46ad567748f24a326d9de40e5b9659f96ffff34
|
||||
@@ -553,7 +554,7 @@ F src/vxworks.h d2988f4e5a61a4dfe82c6524dd3d6e4f2ce3cdb9
|
||||
F src/wal.c beeb71e4eab65dbf0d95f2717efc6ca3c0f5b3090ce67f3de63828f39a6ff053
|
||||
F src/wal.h 8de5d2d3de0956d6f6cb48c83a4012d5f227b8fe940f3a349a4b7e85ebcb492a
|
||||
F src/walker.c da987a20d40145c0a03c07d8fefcb2ed363becc7680d0500d9c79915591f5b1f
|
||||
F src/where.c 1c0ab20720f1a5e76fb4f78d2c45b4525b59167a20d44baf4467fa5b106679ad
|
||||
F src/where.c 9752b68e03e2044f0faa4708fabb0189769067b660bffa931e1fd65736269659
|
||||
F src/whereInt.h 82c04c5075308abbac59180c8bad5ecb45b07453981f60a53f3c7dee21e1e971
|
||||
F src/wherecode.c 611fcabd05592ed2febd7d182f9621425b0466c5232d70e0981c842d429356d5
|
||||
F src/whereexpr.c 427ea8e96ec24f2a7814c67b8024ad664a9c7656264c4566c34743cb23186e46
|
||||
@@ -735,7 +736,7 @@ F test/descidx2.test 9f1a0c83fd57f8667c82310ca21b30a350888b5d
|
||||
F test/descidx3.test 09ddbe3f5295f482d2f8b687cf6db8bad7acd9a2
|
||||
F test/diskfull.test 106391384780753ea6896b7b4f005d10e9866b6e
|
||||
F test/distinct.test a1783b960ad8c15a77cd9f207be072898db1026c
|
||||
F test/distinct2.test ba239e9674495eda8e130cb5d498036b781dbd65c5868b58e094e36279859e83
|
||||
F test/distinct2.test df0bb52b754661ea84ec9ff488d48913c97bd31d83ca17ce0bf1334645e660cf
|
||||
F test/distinctagg.test 1a6ef9c87a58669438fc771450d7a72577417376
|
||||
F test/e_blobbytes.test 439a945953b35cb6948a552edaec4dc31fd70a05
|
||||
F test/e_blobclose.test 4b3c8c60c2171164d472059c73e9f3c1844bb66d
|
||||
@@ -983,7 +984,7 @@ F test/ioerr4.test f130fe9e71008577b342b8874d52984bd04ede2c
|
||||
F test/ioerr5.test 2edfa4fb0f896f733071303b42224df8bedd9da4
|
||||
F test/ioerr6.test a395a6ab144b26a9e3e21059a1ab6a7149cca65b
|
||||
F test/join.test 442c462eea85cf065d70a663c626b780a95af6e11585d909bb63b87598afe678
|
||||
F test/join2.test ac70b2b79ac593550d1d6f15e9bb3693dd71826b496e84f15166c5053fa518e6
|
||||
F test/join2.test 1a0c26399910b015d9f8f95b884e9a079fd2cfdccd65f7b1603846508cae0dc6
|
||||
F test/join3.test 6f0c774ff1ba0489e6c88a3e77b9d3528fb4fda0
|
||||
F test/join4.test 1a352e4e267114444c29266ce79e941af5885916
|
||||
F test/join5.test bc98ea4b4e5003f5b1453701ebb8cd7d1c01a550
|
||||
@@ -1677,7 +1678,7 @@ F vsixtest/vsixtest.tcl 6a9a6ab600c25a91a7acc6293828957a386a8a93
|
||||
F vsixtest/vsixtest.vcxproj.data 2ed517e100c66dc455b492e1a33350c1b20fbcdc
|
||||
F vsixtest/vsixtest.vcxproj.filters 37e51ffedcdb064aad6ff33b6148725226cd608e
|
||||
F vsixtest/vsixtest_TemporaryKey.pfx e5b1b036facdb453873e7084e1cae9102ccc67a0
|
||||
P 17dd2f7314e7eb124e0a2a7a6cf475850e87fe3041e6ce1e1fd71b38d54852a8
|
||||
R c2dbc2aeaa2d6cfa4070ebdfc171fa89
|
||||
U drh
|
||||
Z 8287b3f25cb0100d8a846549bf308df5
|
||||
P 7d0b12fcb58353b883ffce77df824a5cc8b1e913a21ec3f22fb73481a398c916
|
||||
R a940a7b7e2663c64f019728def2f503f
|
||||
U dan
|
||||
Z d7c77380d4461a6101913d9af19a0151
|
||||
|
||||
+1
-1
@@ -1 +1 @@
|
||||
2dcef5a9ae7f347da65207bf6bf612fb12e18e1a6704799322f0cf2a86154cfd
|
||||
12a23c0a66fac5c9674120b390f6abaeaba3f7ff04693b281af1eefb93d6f47c
|
||||
+9
-1
@@ -2822,6 +2822,7 @@ static int openDatabase(
|
||||
}else{
|
||||
isThreadsafe = sqlite3GlobalConfig.bFullMutex;
|
||||
}
|
||||
|
||||
if( flags & SQLITE_OPEN_PRIVATECACHE ){
|
||||
flags &= ~SQLITE_OPEN_SHAREDCACHE;
|
||||
}else if( sqlite3GlobalConfig.sharedCacheEnabled ){
|
||||
@@ -2854,13 +2855,20 @@ static int openDatabase(
|
||||
/* Allocate the sqlite data structure */
|
||||
db = sqlite3MallocZero( sizeof(sqlite3) );
|
||||
if( db==0 ) goto opendb_out;
|
||||
if( isThreadsafe ){
|
||||
if( isThreadsafe
|
||||
#ifdef SQLITE_ENABLE_MULTITHREADED_CHECKS
|
||||
|| sqlite3GlobalConfig.bCoreMutex
|
||||
#endif
|
||||
){
|
||||
db->mutex = sqlite3MutexAlloc(SQLITE_MUTEX_RECURSIVE);
|
||||
if( db->mutex==0 ){
|
||||
sqlite3_free(db);
|
||||
db = 0;
|
||||
goto opendb_out;
|
||||
}
|
||||
if( isThreadsafe==0 ){
|
||||
sqlite3MutexWarnOnContention(db->mutex);
|
||||
}
|
||||
}
|
||||
sqlite3_mutex_enter(db->mutex);
|
||||
db->errMask = 0xff;
|
||||
|
||||
+192
@@ -26,6 +26,193 @@ static SQLITE_WSD int mutexIsInit = 0;
|
||||
|
||||
|
||||
#ifndef SQLITE_MUTEX_OMIT
|
||||
|
||||
#ifdef SQLITE_ENABLE_MULTITHREADED_CHECKS
|
||||
/*
|
||||
** This block (enclosed by SQLITE_ENABLE_MULTITHREADED_CHECKS) contains
|
||||
** the implementation of a wrapper around the system default mutex
|
||||
** implementation (sqlite3DefaultMutex()).
|
||||
**
|
||||
** Most calls are passed directly through to the underlying default
|
||||
** mutex implementation. Except, if a mutex is configured by calling
|
||||
** sqlite3MutexWarnOnContention() on it, then if contention is ever
|
||||
** encountered within xMutexEnter() a warning is emitted via sqlite3_log().
|
||||
**
|
||||
** This type of mutex is used as the database handle mutex when testing
|
||||
** apps that usually use SQLITE_CONFIG_MULTITHREAD mode.
|
||||
*/
|
||||
|
||||
/*
|
||||
** Type for all mutexes used when SQLITE_ENABLE_MULTITHREADED_CHECKS
|
||||
** is defined. Variable CheckMutex.mutex is a pointer to the real mutex
|
||||
** allocated by the system mutex implementation. Variable iType is usually set
|
||||
** to the type of mutex requested - SQLITE_MUTEX_RECURSIVE, SQLITE_MUTEX_FAST
|
||||
** or one of the static mutex identifiers. Or, if this is a recursive mutex
|
||||
** that has been configured using sqlite3MutexWarnOnContention(), it is
|
||||
** set to SQLITE_MUTEX_WARNONCONTENTION.
|
||||
*/
|
||||
typedef struct CheckMutex CheckMutex;
|
||||
struct CheckMutex {
|
||||
int iType;
|
||||
sqlite3_mutex *mutex;
|
||||
};
|
||||
|
||||
#define SQLITE_MUTEX_WARNONCONTENTION (-1)
|
||||
|
||||
/*
|
||||
** Pointer to real mutex methods object used by the CheckMutex
|
||||
** implementation. Set by checkMutexInit().
|
||||
*/
|
||||
static SQLITE_WSD const sqlite3_mutex_methods *pGlobalMutexMethods;
|
||||
|
||||
#ifdef SQLITE_DEBUG
|
||||
static int checkMutexHeld(sqlite3_mutex *p){
|
||||
return pGlobalMutexMethods->xMutexHeld(((CheckMutex*)p)->mutex);
|
||||
}
|
||||
static int checkMutexNotheld(sqlite3_mutex *p){
|
||||
return pGlobalMutexMethods->xMutexNotheld(((CheckMutex*)p)->mutex);
|
||||
}
|
||||
#endif
|
||||
|
||||
/*
|
||||
** Initialize and deinitialize the mutex subsystem.
|
||||
*/
|
||||
static int checkMutexInit(void){
|
||||
pGlobalMutexMethods = sqlite3DefaultMutex();
|
||||
return SQLITE_OK;
|
||||
}
|
||||
static int checkMutexEnd(void){
|
||||
pGlobalMutexMethods = 0;
|
||||
return SQLITE_OK;
|
||||
}
|
||||
|
||||
/*
|
||||
** Allocate a mutex.
|
||||
*/
|
||||
static sqlite3_mutex *checkMutexAlloc(int iType){
|
||||
static CheckMutex staticMutexes[] = {
|
||||
{2, 0}, {3, 0}, {4, 0}, {5, 0},
|
||||
{6, 0}, {7, 0}, {8, 0}, {9, 0},
|
||||
{10, 0}, {11, 0}, {12, 0}, {13, 0}
|
||||
};
|
||||
CheckMutex *p = 0;
|
||||
|
||||
assert( SQLITE_MUTEX_RECURSIVE==1 && SQLITE_MUTEX_FAST==0 );
|
||||
if( iType<2 ){
|
||||
p = sqlite3MallocZero(sizeof(CheckMutex));
|
||||
if( p==0 ) return 0;
|
||||
p->iType = iType;
|
||||
}else{
|
||||
#ifdef SQLITE_ENABLE_API_ARMOR
|
||||
if( iType-2>=ArraySize(staticMutexes) ){
|
||||
(void)SQLITE_MISUSE_BKPT;
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
p = &staticMutexes[iType-2];
|
||||
}
|
||||
|
||||
if( p->mutex==0 ){
|
||||
p->mutex = pGlobalMutexMethods->xMutexAlloc(iType);
|
||||
if( p->mutex==0 ){
|
||||
if( iType<2 ){
|
||||
sqlite3_free(p);
|
||||
}
|
||||
p = 0;
|
||||
}
|
||||
}
|
||||
|
||||
return (sqlite3_mutex*)p;
|
||||
}
|
||||
|
||||
/*
|
||||
** Free a mutex.
|
||||
*/
|
||||
static void checkMutexFree(sqlite3_mutex *p){
|
||||
assert( SQLITE_MUTEX_RECURSIVE<2 );
|
||||
assert( SQLITE_MUTEX_FAST<2 );
|
||||
assert( SQLITE_MUTEX_WARNONCONTENTION<2 );
|
||||
|
||||
#if SQLITE_ENABLE_API_ARMOR
|
||||
if( p->iType<2 ){
|
||||
#endif
|
||||
{
|
||||
CheckMutex *pCheck = (CheckMutex*)p;
|
||||
pGlobalMutexMethods->xMutexFree(pCheck->mutex);
|
||||
sqlite3_free(pCheck);
|
||||
}
|
||||
#ifdef SQLITE_ENABLE_API_ARMOR
|
||||
else{
|
||||
(void)SQLITE_MISUSE_BKPT;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
/*
|
||||
** Enter the mutex.
|
||||
*/
|
||||
static void checkMutexEnter(sqlite3_mutex *p){
|
||||
CheckMutex *pCheck = (CheckMutex*)p;
|
||||
if( pCheck->iType==SQLITE_MUTEX_WARNONCONTENTION ){
|
||||
if( SQLITE_OK==pGlobalMutexMethods->xMutexTry(pCheck->mutex) ){
|
||||
return;
|
||||
}
|
||||
sqlite3_log(SQLITE_MISUSE,
|
||||
"illegal multi-threaded access to database connection"
|
||||
);
|
||||
}
|
||||
pGlobalMutexMethods->xMutexEnter(pCheck->mutex);
|
||||
}
|
||||
|
||||
/*
|
||||
** Enter the mutex (do not block).
|
||||
*/
|
||||
static int checkMutexTry(sqlite3_mutex *p){
|
||||
CheckMutex *pCheck = (CheckMutex*)p;
|
||||
return pGlobalMutexMethods->xMutexTry(pCheck->mutex);
|
||||
}
|
||||
|
||||
/*
|
||||
** Leave the mutex.
|
||||
*/
|
||||
static void checkMutexLeave(sqlite3_mutex *p){
|
||||
CheckMutex *pCheck = (CheckMutex*)p;
|
||||
pGlobalMutexMethods->xMutexLeave(pCheck->mutex);
|
||||
}
|
||||
|
||||
sqlite3_mutex_methods const *multiThreadedCheckMutex(void){
|
||||
static const sqlite3_mutex_methods sMutex = {
|
||||
checkMutexInit,
|
||||
checkMutexEnd,
|
||||
checkMutexAlloc,
|
||||
checkMutexFree,
|
||||
checkMutexEnter,
|
||||
checkMutexTry,
|
||||
checkMutexLeave,
|
||||
#ifdef SQLITE_DEBUG
|
||||
checkMutexHeld,
|
||||
checkMutexNotheld
|
||||
#else
|
||||
0,
|
||||
0
|
||||
#endif
|
||||
};
|
||||
return &sMutex;
|
||||
}
|
||||
|
||||
/*
|
||||
** Mark the SQLITE_MUTEX_RECURSIVE mutex passed as the only argument as
|
||||
** one on which there should be no contention.
|
||||
*/
|
||||
void sqlite3MutexWarnOnContention(sqlite3_mutex *p){
|
||||
if( sqlite3GlobalConfig.mutex.xMutexAlloc==checkMutexAlloc ){
|
||||
CheckMutex *pCheck = (CheckMutex*)p;
|
||||
assert( pCheck->iType==SQLITE_MUTEX_RECURSIVE );
|
||||
pCheck->iType = SQLITE_MUTEX_WARNONCONTENTION;
|
||||
}
|
||||
}
|
||||
#endif /* ifdef SQLITE_ENABLE_MULTITHREADED_CHECKS */
|
||||
|
||||
/*
|
||||
** Initialize the mutex system.
|
||||
*/
|
||||
@@ -41,7 +228,11 @@ int sqlite3MutexInit(void){
|
||||
sqlite3_mutex_methods *pTo = &sqlite3GlobalConfig.mutex;
|
||||
|
||||
if( sqlite3GlobalConfig.bCoreMutex ){
|
||||
#ifdef SQLITE_ENABLE_MULTITHREADED_CHECKS
|
||||
pFrom = multiThreadedCheckMutex();
|
||||
#else
|
||||
pFrom = sqlite3DefaultMutex();
|
||||
#endif
|
||||
}else{
|
||||
pFrom = sqlite3NoopMutex();
|
||||
}
|
||||
@@ -167,3 +358,4 @@ int sqlite3_mutex_notheld(sqlite3_mutex *p){
|
||||
#endif
|
||||
|
||||
#endif /* !defined(SQLITE_MUTEX_OMIT) */
|
||||
|
||||
|
||||
@@ -3590,6 +3590,12 @@ int sqlite3LookasideUsed(sqlite3*,int*);
|
||||
sqlite3_mutex *sqlite3Pcache1Mutex(void);
|
||||
sqlite3_mutex *sqlite3MallocMutex(void);
|
||||
|
||||
#if defined(SQLITE_ENABLE_MULTITHREADED_CHECKS) && !defined(SQLITE_MUTEX_OMIT)
|
||||
void sqlite3MutexWarnOnContention(sqlite3_mutex*);
|
||||
#else
|
||||
# define sqlite3MutexWarnOnContention(x)
|
||||
#endif
|
||||
|
||||
#ifndef SQLITE_OMIT_FLOATING_POINT
|
||||
int sqlite3IsNaN(double);
|
||||
#else
|
||||
|
||||
+8
-8
@@ -4707,6 +4707,7 @@ WhereInfo *sqlite3WhereBegin(
|
||||
** LEFT JOIN t2
|
||||
** LEFT JOIN t3 USING (t1.ipk=t3.ipk)
|
||||
*/
|
||||
notReady = ~(Bitmask)0;
|
||||
if( pWInfo->nLevel>=2
|
||||
&& pResultSet!=0 /* guarantees condition (1) above */
|
||||
&& OptimizationEnabled(db, SQLITE_OmitNoopJoin)
|
||||
@@ -4740,6 +4741,12 @@ WhereInfo *sqlite3WhereBegin(
|
||||
}
|
||||
if( pTerm<pEnd ) continue;
|
||||
WHERETRACE(0xffff, ("-> drop loop %c not used\n", pLoop->cId));
|
||||
notReady &= ~pLoop->maskSelf;
|
||||
for(pTerm=sWLB.pWC->a; pTerm<pEnd; pTerm++){
|
||||
if( (pTerm->prereqAll & pLoop->maskSelf)!=0 ){
|
||||
pTerm->wtFlags |= TERM_CODED;
|
||||
}
|
||||
}
|
||||
if( i!=pWInfo->nLevel-1 ){
|
||||
int nByte = (pWInfo->nLevel-1-i) * sizeof(WhereLevel);
|
||||
memmove(&pWInfo->a[i], &pWInfo->a[i+1], nByte);
|
||||
@@ -4898,7 +4905,6 @@ WhereInfo *sqlite3WhereBegin(
|
||||
** loop below generates code for a single nested loop of the VM
|
||||
** program.
|
||||
*/
|
||||
notReady = ~(Bitmask)0;
|
||||
for(ii=0; ii<nTabList; ii++){
|
||||
int addrExplain;
|
||||
int wsFlags;
|
||||
@@ -4962,6 +4968,7 @@ void sqlite3WhereEnd(WhereInfo *pWInfo){
|
||||
Index *pIdx;
|
||||
int n;
|
||||
if( pWInfo->eDistinct==WHERE_DISTINCT_ORDERED
|
||||
&& i==pWInfo->nLevel-1 /* Ticket [ef9318757b152e3] 2017-10-21 */
|
||||
&& (pLoop->wsFlags & WHERE_INDEXED)!=0
|
||||
&& (pIdx = pLoop->u.btree.pIndex)->hasStat1
|
||||
&& (n = pLoop->u.btree.nIdxCol)>0
|
||||
@@ -4978,13 +4985,6 @@ void sqlite3WhereEnd(WhereInfo *pWInfo){
|
||||
VdbeCoverageIf(v, op==OP_SeekLT);
|
||||
VdbeCoverageIf(v, op==OP_SeekGT);
|
||||
sqlite3VdbeAddOp2(v, OP_Goto, 1, pLevel->p2);
|
||||
if( i<pWInfo->nLevel-1 ){
|
||||
/* Ticket https://sqlite.org/src/info/ef9318757b152e3 2017-11-21
|
||||
** The break location for the next inner loop is above the code
|
||||
** generated here, but it should be afterwards. So call re-resolve
|
||||
** the break location to be afterwards. */
|
||||
sqlite3VdbeResolveLabel(v, pWInfo->a[i+1].addrBrk);
|
||||
}
|
||||
}
|
||||
#endif /* SQLITE_DISABLE_SKIPAHEAD_DISTINCT */
|
||||
/* The common case: Advance to the next row */
|
||||
|
||||
@@ -198,5 +198,36 @@ do_execsql_test 1000 {
|
||||
ANALYZE;
|
||||
SELECT DISTINCT y FROM t1, t2 WHERE b=x AND b<>-1;
|
||||
} {1 1}
|
||||
db close
|
||||
sqlite3 db :memory:
|
||||
do_execsql_test 1010 {
|
||||
CREATE TABLE t1(a INTEGER PRIMARY KEY, b INTEGER);
|
||||
CREATE INDEX t1b ON t1(b);
|
||||
CREATE TABLE t2(x INTEGER PRIMARY KEY, y INTEGER);
|
||||
CREATE INDEX t2y ON t2(y);
|
||||
WITH RECURSIVE c(x) AS (VALUES(0) UNION ALL SELECT x+1 FROM c WHERE x<49)
|
||||
INSERT INTO t1(b) SELECT -(x/10 - 1) FROM c;
|
||||
WITH RECURSIVE c(x) AS (VALUES(-1) UNION ALL SELECT x+1 FROM c WHERE x<19)
|
||||
INSERT INTO t2(x,y) SELECT -x, 1 FROM c;
|
||||
SELECT DISTINCT y FROM t1, t2 WHERE b=x AND b<>1 ORDER BY y DESC;
|
||||
ANALYZE;
|
||||
SELECT DISTINCT y FROM t1, t2 WHERE b=x AND b<>1 ORDER BY y DESC;
|
||||
} {1 1}
|
||||
db close
|
||||
sqlite3 db :memory:
|
||||
do_execsql_test 1020 {
|
||||
CREATE TABLE t1(a, b);
|
||||
CREATE INDEX t1a ON t1(a, b);
|
||||
-- Lots of rows of (1, 'no'), followed by a single (1, 'yes').
|
||||
WITH RECURSIVE c(x) AS (VALUES(1) UNION ALL SELECT x+1 FROM c WHERE x<100)
|
||||
INSERT INTO t1(a, b) SELECT 1, 'no' FROM c;
|
||||
INSERT INTO t1(a, b) VALUES(1, 'yes');
|
||||
CREATE TABLE t2(x PRIMARY KEY);
|
||||
INSERT INTO t2 VALUES('yes');
|
||||
SELECT DISTINCT a FROM t1, t2 WHERE x=b;
|
||||
ANALYZE;
|
||||
SELECT DISTINCT a FROM t1, t2 WHERE x=b;
|
||||
} {1 1}
|
||||
|
||||
|
||||
finish_test
|
||||
|
||||
+22
-1
@@ -169,6 +169,27 @@ do_eqp_test 4.2.2 {
|
||||
0 1 2 {SEARCH TABLE c3 USING INTEGER PRIMARY KEY (rowid=?)}
|
||||
}
|
||||
|
||||
|
||||
# 2017-11-23 (Thanksgiving day)
|
||||
# OSSFuzz found an assertion fault in the new LEFT JOIN eliminator code.
|
||||
#
|
||||
do_execsql_test 4.3.0 {
|
||||
DROP TABLE IF EXISTS t1;
|
||||
DROP TABLE IF EXISTS t2;
|
||||
CREATE TABLE t1(x PRIMARY KEY) WITHOUT ROWID;
|
||||
CREATE TABLE t2(x);
|
||||
SELECT a.x
|
||||
FROM t1 AS a
|
||||
LEFT JOIN t1 AS b ON (a.x=b.x)
|
||||
LEFT JOIN t2 AS c ON (a.x=c.x);
|
||||
} {}
|
||||
do_execsql_test 4.3.1 {
|
||||
WITH RECURSIVE c(x) AS (VALUES(1) UNION ALL SELECT x+1 FROM c WHERE x<10)
|
||||
INSERT INTO t1(x) SELECT x FROM c;
|
||||
INSERT INTO t2(x) SELECT x+9 FROM t1;
|
||||
SELECT a.x, c.x
|
||||
FROM t1 AS a
|
||||
LEFT JOIN t1 AS b ON (a.x=b.x)
|
||||
LEFT JOIN t2 AS c ON (a.x=c.x);
|
||||
} {1 {} 2 {} 3 {} 4 {} 5 {} 6 {} 7 {} 8 {} 9 {} 10 10}
|
||||
|
||||
finish_test
|
||||
|
||||
Reference in New Issue
Block a user