update to 3.6.21
This commit is contained in:
parent
7941e188aa
commit
090d3d3b9b
23
Makefile.in
23
Makefile.in
|
@ -175,7 +175,7 @@ OBJS0 = alter.lo analyze.lo attach.lo auth.lo backup.lo bitvec.lo btmutex.lo \
|
|||
random.lo resolve.lo rowset.lo select.lo status.lo \
|
||||
table.lo tokenize.lo trigger.lo update.lo \
|
||||
util.lo vacuum.lo \
|
||||
vdbe.lo vdbeapi.lo vdbeaux.lo vdbeblob.lo vdbemem.lo \
|
||||
vdbe.lo vdbeapi.lo vdbeaux.lo vdbeblob.lo vdbemem.lo vdbetrace.lo \
|
||||
walker.lo where.lo utf.lo vtab.lo
|
||||
|
||||
# Object files for the amalgamation.
|
||||
|
@ -272,6 +272,7 @@ SRC = \
|
|||
$(TOP)/src/vdbeaux.c \
|
||||
$(TOP)/src/vdbeblob.c \
|
||||
$(TOP)/src/vdbemem.c \
|
||||
$(TOP)/src/vdbetrace.c \
|
||||
$(TOP)/src/vdbeInt.h \
|
||||
$(TOP)/src/vtab.c \
|
||||
$(TOP)/src/walker.c \
|
||||
|
@ -311,15 +312,17 @@ SRC += \
|
|||
SRC += \
|
||||
$(TOP)/ext/fts3/fts3.c \
|
||||
$(TOP)/ext/fts3/fts3.h \
|
||||
$(TOP)/ext/fts3/fts3Int.h \
|
||||
$(TOP)/ext/fts3/fts3_expr.c \
|
||||
$(TOP)/ext/fts3/fts3_expr.h \
|
||||
$(TOP)/ext/fts3/fts3_hash.c \
|
||||
$(TOP)/ext/fts3/fts3_hash.h \
|
||||
$(TOP)/ext/fts3/fts3_icu.c \
|
||||
$(TOP)/ext/fts3/fts3_porter.c \
|
||||
$(TOP)/ext/fts3/fts3_snippet.c \
|
||||
$(TOP)/ext/fts3/fts3_tokenizer.h \
|
||||
$(TOP)/ext/fts3/fts3_tokenizer.c \
|
||||
$(TOP)/ext/fts3/fts3_tokenizer1.c
|
||||
$(TOP)/ext/fts3/fts3_tokenizer1.c \
|
||||
$(TOP)/ext/fts3/fts3_write.c
|
||||
SRC += \
|
||||
$(TOP)/ext/icu/sqliteicu.h \
|
||||
$(TOP)/ext/icu/icu.c
|
||||
|
@ -359,6 +362,7 @@ TESTSRC2 = \
|
|||
$(TOP)/src/vdbeapi.c \
|
||||
$(TOP)/src/vdbeaux.c \
|
||||
$(TOP)/src/vdbemem.c \
|
||||
$(TOP)/src/vdbetrace.c \
|
||||
$(TOP)/src/where.c \
|
||||
parse.c
|
||||
|
||||
|
@ -383,6 +387,7 @@ TESTSRC = \
|
|||
$(TOP)/src/test_func.c \
|
||||
$(TOP)/src/test_hexio.c \
|
||||
$(TOP)/src/test_init.c \
|
||||
$(TOP)/src/test_intarray.c \
|
||||
$(TOP)/src/test_journal.c \
|
||||
$(TOP)/src/test_malloc.c \
|
||||
$(TOP)/src/test_mutex.c \
|
||||
|
@ -427,7 +432,7 @@ HDR += \
|
|||
$(TOP)/ext/fts2/fts2_tokenizer.h
|
||||
HDR += \
|
||||
$(TOP)/ext/fts3/fts3.h \
|
||||
$(TOP)/ext/fts3/fts3_expr.h \
|
||||
$(TOP)/ext/fts3/fts3Int.h \
|
||||
$(TOP)/ext/fts3/fts3_hash.h \
|
||||
$(TOP)/ext/fts3/fts3_tokenizer.h
|
||||
HDR += \
|
||||
|
@ -456,13 +461,6 @@ Makefile: $(TOP)/Makefile.in
|
|||
sqlite3.pc: $(TOP)/sqlite3.pc.in
|
||||
./config.status
|
||||
|
||||
# Generate the file "last_change" which contains the date of change
|
||||
# of the most recently modified source code file
|
||||
#
|
||||
last_change: $(SRC)
|
||||
cat $(SRC) | grep '$$Id: ' | sort -k 5 | tail -1 \
|
||||
| $(NAWK) '{print $$5,$$6}' >last_change
|
||||
|
||||
libsqlite3.la: $(LIBOBJ)
|
||||
$(LTLINK) -o $@ $(LIBOBJ) $(TLIBS) \
|
||||
${ALLOWRELEASE} -rpath "$(libdir)" -version-info "8:6:8"
|
||||
|
@ -733,6 +731,9 @@ vdbeblob.lo: $(TOP)/src/vdbeblob.c $(HDR)
|
|||
vdbemem.lo: $(TOP)/src/vdbemem.c $(HDR)
|
||||
$(LTCOMPILE) $(TEMP_STORE) -c $(TOP)/src/vdbemem.c
|
||||
|
||||
vdbetrace.lo: $(TOP)/src/vdbetrace.c $(HDR)
|
||||
$(LTCOMPILE) $(TEMP_STORE) -c $(TOP)/src/vdbetrace.c
|
||||
|
||||
vtab.lo: $(TOP)/src/vtab.c $(HDR)
|
||||
$(LTCOMPILE) $(TEMP_STORE) -c $(TOP)/src/vtab.c
|
||||
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
#! /bin/sh
|
||||
# Guess values for system-dependent variables and create Makefiles.
|
||||
# Generated by GNU Autoconf 2.62 for sqlite 3.6.20.
|
||||
# Generated by GNU Autoconf 2.62 for sqlite 3.6.21.
|
||||
#
|
||||
# Copyright (C) 1992, 1993, 1994, 1995, 1996, 1998, 1999, 2000, 2001,
|
||||
# 2002, 2003, 2004, 2005, 2006, 2007, 2008 Free Software Foundation, Inc.
|
||||
|
@ -743,8 +743,8 @@ SHELL=${CONFIG_SHELL-/bin/sh}
|
|||
# Identity of this package.
|
||||
PACKAGE_NAME='sqlite'
|
||||
PACKAGE_TARNAME='sqlite'
|
||||
PACKAGE_VERSION='3.6.20'
|
||||
PACKAGE_STRING='sqlite 3.6.20'
|
||||
PACKAGE_VERSION='3.6.21'
|
||||
PACKAGE_STRING='sqlite 3.6.21'
|
||||
PACKAGE_BUGREPORT=''
|
||||
|
||||
# Factoring default headers for most tests.
|
||||
|
@ -1487,7 +1487,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.6.20 to adapt to many kinds of systems.
|
||||
\`configure' configures sqlite 3.6.21 to adapt to many kinds of systems.
|
||||
|
||||
Usage: $0 [OPTION]... [VAR=VALUE]...
|
||||
|
||||
|
@ -1552,7 +1552,7 @@ fi
|
|||
|
||||
if test -n "$ac_init_help"; then
|
||||
case $ac_init_help in
|
||||
short | recursive ) echo "Configuration of sqlite 3.6.20:";;
|
||||
short | recursive ) echo "Configuration of sqlite 3.6.21:";;
|
||||
esac
|
||||
cat <<\_ACEOF
|
||||
|
||||
|
@ -1670,7 +1670,7 @@ fi
|
|||
test -n "$ac_init_help" && exit $ac_status
|
||||
if $ac_init_version; then
|
||||
cat <<\_ACEOF
|
||||
sqlite configure 3.6.20
|
||||
sqlite configure 3.6.21
|
||||
generated by GNU Autoconf 2.62
|
||||
|
||||
Copyright (C) 1992, 1993, 1994, 1995, 1996, 1998, 1999, 2000, 2001,
|
||||
|
@ -1684,7 +1684,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.6.20, which was
|
||||
It was created by sqlite $as_me 3.6.21, which was
|
||||
generated by GNU Autoconf 2.62. Invocation command line was
|
||||
|
||||
$ $0 $@
|
||||
|
@ -13972,7 +13972,7 @@ exec 6>&1
|
|||
# report actual input values of CONFIG_FILES etc. instead of their
|
||||
# values after options handling.
|
||||
ac_log="
|
||||
This file was extended by sqlite $as_me 3.6.20, which was
|
||||
This file was extended by sqlite $as_me 3.6.21, which was
|
||||
generated by GNU Autoconf 2.62. Invocation command line was
|
||||
|
||||
CONFIG_FILES = $CONFIG_FILES
|
||||
|
@ -14025,7 +14025,7 @@ Report bugs to <bug-autoconf@gnu.org>."
|
|||
_ACEOF
|
||||
cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
|
||||
ac_cs_version="\\
|
||||
sqlite config.status 3.6.20
|
||||
sqlite config.status 3.6.21
|
||||
configured by $0, generated by GNU Autoconf 2.62,
|
||||
with options \\"`$as_echo "$ac_configure_args" | sed 's/^ //; s/[\\""\`\$]/\\\\&/g'`\\"
|
||||
|
||||
|
|
|
@ -1231,8 +1231,8 @@ static int asyncFullPathname(
|
|||
*/
|
||||
if( rc==SQLITE_OK ){
|
||||
int i, j;
|
||||
int n = nPathOut;
|
||||
char *z = zPathOut;
|
||||
int n = strlen(z);
|
||||
while( n>1 && z[n-1]=='/' ){ n--; }
|
||||
for(i=j=0; i<n; i++){
|
||||
if( z[i]=='/' ){
|
||||
|
|
7909
ext/fts3/fts3.c
7909
ext/fts3/fts3.c
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,279 @@
|
|||
/*
|
||||
** 2009 Nov 12
|
||||
**
|
||||
** 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.
|
||||
**
|
||||
******************************************************************************
|
||||
**
|
||||
*/
|
||||
|
||||
#ifndef _FTSINT_H
|
||||
#define _FTSINT_H
|
||||
|
||||
#if !defined(NDEBUG) && !defined(SQLITE_DEBUG)
|
||||
# define NDEBUG 1
|
||||
#endif
|
||||
|
||||
#include "sqlite3.h"
|
||||
#include "fts3_tokenizer.h"
|
||||
#include "fts3_hash.h"
|
||||
|
||||
/*
|
||||
** This constant controls how often segments are merged. Once there are
|
||||
** FTS3_MERGE_COUNT segments of level N, they are merged into a single
|
||||
** segment of level N+1.
|
||||
*/
|
||||
#define FTS3_MERGE_COUNT 16
|
||||
|
||||
/*
|
||||
** This is the maximum amount of data (in bytes) to store in the
|
||||
** Fts3Table.pendingTerms hash table. Normally, the hash table is
|
||||
** populated as documents are inserted/updated/deleted in a transaction
|
||||
** and used to create a new segment when the transaction is committed.
|
||||
** However if this limit is reached midway through a transaction, a new
|
||||
** segment is created and the hash table cleared immediately.
|
||||
*/
|
||||
#define FTS3_MAX_PENDING_DATA (1*1024*1024)
|
||||
|
||||
/*
|
||||
** Macro to return the number of elements in an array. SQLite has a
|
||||
** similar macro called ArraySize(). Use a different name to avoid
|
||||
** a collision when building an amalgamation with built-in FTS3.
|
||||
*/
|
||||
#define SizeofArray(X) ((int)(sizeof(X)/sizeof(X[0])))
|
||||
|
||||
/*
|
||||
** Maximum length of a varint encoded integer. The varint format is different
|
||||
** from that used by SQLite, so the maximum length is 10, not 9.
|
||||
*/
|
||||
#define FTS3_VARINT_MAX 10
|
||||
|
||||
/*
|
||||
** This section provides definitions to allow the
|
||||
** FTS3 extension to be compiled outside of the
|
||||
** amalgamation.
|
||||
*/
|
||||
#ifndef SQLITE_AMALGAMATION
|
||||
/*
|
||||
** Macros indicating that conditional expressions are always true or
|
||||
** false.
|
||||
*/
|
||||
# define ALWAYS(x) (x)
|
||||
# define NEVER(X) (x)
|
||||
/*
|
||||
** Internal types used by SQLite.
|
||||
*/
|
||||
typedef unsigned char u8; /* 1-byte (or larger) unsigned integer */
|
||||
typedef short int i16; /* 2-byte (or larger) signed integer */
|
||||
/*
|
||||
** Macro used to suppress compiler warnings for unused parameters.
|
||||
*/
|
||||
#define UNUSED_PARAMETER(x) (void)(x)
|
||||
#endif
|
||||
|
||||
typedef struct Fts3Table Fts3Table;
|
||||
typedef struct Fts3Cursor Fts3Cursor;
|
||||
typedef struct Fts3Expr Fts3Expr;
|
||||
typedef struct Fts3Phrase Fts3Phrase;
|
||||
typedef struct Fts3SegReader Fts3SegReader;
|
||||
typedef struct Fts3SegFilter Fts3SegFilter;
|
||||
|
||||
/*
|
||||
** A connection to a fulltext index is an instance of the following
|
||||
** structure. The xCreate and xConnect methods create an instance
|
||||
** of this structure and xDestroy and xDisconnect free that instance.
|
||||
** All other methods receive a pointer to the structure as one of their
|
||||
** arguments.
|
||||
*/
|
||||
struct Fts3Table {
|
||||
sqlite3_vtab base; /* Base class used by SQLite core */
|
||||
sqlite3 *db; /* The database connection */
|
||||
const char *zDb; /* logical database name */
|
||||
const char *zName; /* virtual table name */
|
||||
int nColumn; /* number of named columns in virtual table */
|
||||
char **azColumn; /* column names. malloced */
|
||||
sqlite3_tokenizer *pTokenizer; /* tokenizer for inserts and queries */
|
||||
|
||||
/* Precompiled statements used by the implementation. Each of these
|
||||
** statements is run and reset within a single virtual table API call.
|
||||
*/
|
||||
sqlite3_stmt *aStmt[18];
|
||||
|
||||
/* Pointer to string containing the SQL:
|
||||
**
|
||||
** "SELECT block FROM %_segments WHERE blockid BETWEEN ? AND ?
|
||||
** ORDER BY blockid"
|
||||
*/
|
||||
char *zSelectLeaves;
|
||||
int nLeavesStmt; /* Valid statements in aLeavesStmt */
|
||||
int nLeavesTotal; /* Total number of prepared leaves stmts */
|
||||
int nLeavesAlloc; /* Allocated size of aLeavesStmt */
|
||||
sqlite3_stmt **aLeavesStmt; /* Array of prepared zSelectLeaves stmts */
|
||||
|
||||
int nNodeSize; /* Soft limit for node size */
|
||||
|
||||
/* The following hash table is used to buffer pending index updates during
|
||||
** transactions. Variable nPendingData estimates the memory size of the
|
||||
** pending data, including hash table overhead, but not malloc overhead.
|
||||
** When nPendingData exceeds FTS3_MAX_PENDING_DATA, the buffer is flushed
|
||||
** automatically. Variable iPrevDocid is the docid of the most recently
|
||||
** inserted record.
|
||||
*/
|
||||
int nPendingData;
|
||||
sqlite_int64 iPrevDocid;
|
||||
Fts3Hash pendingTerms;
|
||||
};
|
||||
|
||||
/*
|
||||
** When the core wants to read from the virtual table, it creates a
|
||||
** virtual table cursor (an instance of the following structure) using
|
||||
** the xOpen method. Cursors are destroyed using the xClose method.
|
||||
*/
|
||||
struct Fts3Cursor {
|
||||
sqlite3_vtab_cursor base; /* Base class used by SQLite core */
|
||||
i16 eSearch; /* Search strategy (see below) */
|
||||
u8 isEof; /* True if at End Of Results */
|
||||
u8 isRequireSeek; /* True if must seek pStmt to %_content row */
|
||||
sqlite3_stmt *pStmt; /* Prepared statement in use by the cursor */
|
||||
Fts3Expr *pExpr; /* Parsed MATCH query string */
|
||||
sqlite3_int64 iPrevId; /* Previous id read from aDoclist */
|
||||
char *pNextId; /* Pointer into the body of aDoclist */
|
||||
char *aDoclist; /* List of docids for full-text queries */
|
||||
int nDoclist; /* Size of buffer at aDoclist */
|
||||
};
|
||||
|
||||
/*
|
||||
** The Fts3Cursor.eSearch member is always set to one of the following.
|
||||
** Actualy, Fts3Cursor.eSearch can be greater than or equal to
|
||||
** FTS3_FULLTEXT_SEARCH. If so, then Fts3Cursor.eSearch - 2 is the index
|
||||
** of the column to be searched. For example, in
|
||||
**
|
||||
** CREATE VIRTUAL TABLE ex1 USING fts3(a,b,c,d);
|
||||
** SELECT docid FROM ex1 WHERE b MATCH 'one two three';
|
||||
**
|
||||
** Because the LHS of the MATCH operator is 2nd column "b",
|
||||
** Fts3Cursor.eSearch will be set to FTS3_FULLTEXT_SEARCH+1. (+0 for a,
|
||||
** +1 for b, +2 for c, +3 for d.) If the LHS of MATCH were "ex1"
|
||||
** indicating that all columns should be searched,
|
||||
** then eSearch would be set to FTS3_FULLTEXT_SEARCH+4.
|
||||
*/
|
||||
#define FTS3_FULLSCAN_SEARCH 0 /* Linear scan of %_content table */
|
||||
#define FTS3_DOCID_SEARCH 1 /* Lookup by rowid on %_content table */
|
||||
#define FTS3_FULLTEXT_SEARCH 2 /* Full-text index search */
|
||||
|
||||
/*
|
||||
** A "phrase" is a sequence of one or more tokens that must match in
|
||||
** sequence. A single token is the base case and the most common case.
|
||||
** For a sequence of tokens contained in "...", nToken will be the number
|
||||
** of tokens in the string.
|
||||
*/
|
||||
struct Fts3Phrase {
|
||||
int nToken; /* Number of tokens in the phrase */
|
||||
int iColumn; /* Index of column this phrase must match */
|
||||
int isNot; /* Phrase prefixed by unary not (-) operator */
|
||||
struct PhraseToken {
|
||||
char *z; /* Text of the token */
|
||||
int n; /* Number of bytes in buffer pointed to by z */
|
||||
int isPrefix; /* True if token ends in with a "*" character */
|
||||
} aToken[1]; /* One entry for each token in the phrase */
|
||||
};
|
||||
|
||||
/*
|
||||
** A tree of these objects forms the RHS of a MATCH operator.
|
||||
*/
|
||||
struct Fts3Expr {
|
||||
int eType; /* One of the FTSQUERY_XXX values defined below */
|
||||
int nNear; /* Valid if eType==FTSQUERY_NEAR */
|
||||
Fts3Expr *pParent; /* pParent->pLeft==this or pParent->pRight==this */
|
||||
Fts3Expr *pLeft; /* Left operand */
|
||||
Fts3Expr *pRight; /* Right operand */
|
||||
Fts3Phrase *pPhrase; /* Valid if eType==FTSQUERY_PHRASE */
|
||||
};
|
||||
|
||||
/*
|
||||
** Candidate values for Fts3Query.eType. Note that the order of the first
|
||||
** four values is in order of precedence when parsing expressions. For
|
||||
** example, the following:
|
||||
**
|
||||
** "a OR b AND c NOT d NEAR e"
|
||||
**
|
||||
** is equivalent to:
|
||||
**
|
||||
** "a OR (b AND (c NOT (d NEAR e)))"
|
||||
*/
|
||||
#define FTSQUERY_NEAR 1
|
||||
#define FTSQUERY_NOT 2
|
||||
#define FTSQUERY_AND 3
|
||||
#define FTSQUERY_OR 4
|
||||
#define FTSQUERY_PHRASE 5
|
||||
|
||||
|
||||
/* fts3_init.c */
|
||||
int sqlite3Fts3DeleteVtab(int, sqlite3_vtab *);
|
||||
int sqlite3Fts3InitVtab(int, sqlite3*, void*, int, const char*const*,
|
||||
sqlite3_vtab **, char **);
|
||||
|
||||
/* fts3_write.c */
|
||||
int sqlite3Fts3UpdateMethod(sqlite3_vtab*,int,sqlite3_value**,sqlite3_int64*);
|
||||
int sqlite3Fts3PendingTermsFlush(Fts3Table *);
|
||||
void sqlite3Fts3PendingTermsClear(Fts3Table *);
|
||||
int sqlite3Fts3Optimize(Fts3Table *);
|
||||
int sqlite3Fts3SegReaderNew(Fts3Table *,int, sqlite3_int64,
|
||||
sqlite3_int64, sqlite3_int64, const char *, int, Fts3SegReader**);
|
||||
void sqlite3Fts3SegReaderFree(Fts3Table *, Fts3SegReader *);
|
||||
int sqlite3Fts3SegReaderIterate(
|
||||
Fts3Table *, Fts3SegReader **, int, Fts3SegFilter *,
|
||||
int (*)(Fts3Table *, void *, char *, int, char *, int), void *
|
||||
);
|
||||
int sqlite3Fts3ReadBlock(Fts3Table*, sqlite3_int64, char const**, int*);
|
||||
int sqlite3Fts3AllSegdirs(Fts3Table*, sqlite3_stmt **);
|
||||
|
||||
/* Flags allowed as part of the 4th argument to SegmentReaderIterate() */
|
||||
#define FTS3_SEGMENT_REQUIRE_POS 0x00000001
|
||||
#define FTS3_SEGMENT_IGNORE_EMPTY 0x00000002
|
||||
#define FTS3_SEGMENT_COLUMN_FILTER 0x00000004
|
||||
#define FTS3_SEGMENT_PREFIX 0x00000008
|
||||
|
||||
/* Type passed as 4th argument to SegmentReaderIterate() */
|
||||
struct Fts3SegFilter {
|
||||
const char *zTerm;
|
||||
int nTerm;
|
||||
int iCol;
|
||||
int flags;
|
||||
};
|
||||
|
||||
/* fts3.c */
|
||||
int sqlite3Fts3PutVarint(char *, sqlite3_int64);
|
||||
int sqlite3Fts3GetVarint(const char *, sqlite_int64 *);
|
||||
int sqlite3Fts3GetVarint32(const char *, int *);
|
||||
int sqlite3Fts3VarintLen(sqlite3_uint64);
|
||||
void sqlite3Fts3Dequote(char *);
|
||||
|
||||
/* fts3_tokenizer.c */
|
||||
const char *sqlite3Fts3NextToken(const char *, int *);
|
||||
int sqlite3Fts3InitHashTable(sqlite3 *, Fts3Hash *, const char *);
|
||||
int sqlite3Fts3InitTokenizer(Fts3Hash *pHash,
|
||||
const char *, sqlite3_tokenizer **, const char **, char **
|
||||
);
|
||||
|
||||
/* fts3_snippet.c */
|
||||
void sqlite3Fts3Offsets(sqlite3_context*, Fts3Cursor*);
|
||||
void sqlite3Fts3Snippet(sqlite3_context*, Fts3Cursor*,
|
||||
const char *, const char *, const char *
|
||||
);
|
||||
|
||||
/* fts3_expr.c */
|
||||
int sqlite3Fts3ExprParse(sqlite3_tokenizer *,
|
||||
char **, int, int, const char *, int, Fts3Expr **
|
||||
);
|
||||
void sqlite3Fts3ExprFree(Fts3Expr *);
|
||||
#ifdef SQLITE_TEST
|
||||
void sqlite3Fts3ExprInitTestInterface(sqlite3 *db);
|
||||
#endif
|
||||
|
||||
#endif /* _FTSINT_H */
|
|
@ -13,8 +13,7 @@
|
|||
** This module contains code that implements a parser for fts3 query strings
|
||||
** (the right-hand argument to the MATCH operator). Because the supported
|
||||
** syntax is relatively simple, the whole tokenizer/parser system is
|
||||
** hand-coded. The public interface to this module is declared in source
|
||||
** code file "fts3_expr.h".
|
||||
** hand-coded.
|
||||
*/
|
||||
#if !defined(SQLITE_CORE) || defined(SQLITE_ENABLE_FTS3)
|
||||
|
||||
|
@ -40,7 +39,29 @@
|
|||
** to zero causes the module to use the old syntax. If it is set to
|
||||
** non-zero the new syntax is activated. This is so both syntaxes can
|
||||
** be tested using a single build of testfixture.
|
||||
**
|
||||
** The following describes the syntax supported by the fts3 MATCH
|
||||
** operator in a similar format to that used by the lemon parser
|
||||
** generator. This module does not use actually lemon, it uses a
|
||||
** custom parser.
|
||||
**
|
||||
** query ::= andexpr (OR andexpr)*.
|
||||
**
|
||||
** andexpr ::= notexpr (AND? notexpr)*.
|
||||
**
|
||||
** notexpr ::= nearexpr (NOT nearexpr|-TOKEN)*.
|
||||
** notexpr ::= LP query RP.
|
||||
**
|
||||
** nearexpr ::= phrase (NEAR distance_opt nearexpr)*.
|
||||
**
|
||||
** distance_opt ::= .
|
||||
** distance_opt ::= / INTEGER.
|
||||
**
|
||||
** phrase ::= TOKEN.
|
||||
** phrase ::= COLUMN:TOKEN.
|
||||
** phrase ::= "TOKEN TOKEN TOKEN...".
|
||||
*/
|
||||
|
||||
#ifdef SQLITE_TEST
|
||||
int sqlite3_fts3_enable_parentheses = 0;
|
||||
#else
|
||||
|
@ -56,8 +77,7 @@ int sqlite3_fts3_enable_parentheses = 0;
|
|||
*/
|
||||
#define SQLITE_FTS3_DEFAULT_NEAR_PARAM 10
|
||||
|
||||
#include "fts3_expr.h"
|
||||
#include "sqlite3.h"
|
||||
#include "fts3Int.h"
|
||||
#include <ctype.h>
|
||||
#include <string.h>
|
||||
#include <assert.h>
|
||||
|
@ -232,7 +252,7 @@ static int getNextString(
|
|||
|
||||
if( rc==SQLITE_DONE ){
|
||||
int jj;
|
||||
char *zNew;
|
||||
char *zNew = NULL;
|
||||
int nNew = 0;
|
||||
int nByte = sizeof(Fts3Expr) + sizeof(Fts3Phrase);
|
||||
nByte += (p?(p->pPhrase->nToken-1):0) * sizeof(struct PhraseToken);
|
||||
|
@ -291,7 +311,7 @@ static int getNextNode(
|
|||
int *pnConsumed /* OUT: Number of bytes consumed */
|
||||
){
|
||||
static const struct Fts3Keyword {
|
||||
char z[4]; /* Keyword text */
|
||||
char *z; /* Keyword text */
|
||||
unsigned char n; /* Length of the keyword */
|
||||
unsigned char parenOnly; /* Only valid in paren mode */
|
||||
unsigned char eType; /* Keyword code */
|
||||
|
@ -354,11 +374,14 @@ static int getNextNode(
|
|||
|| cNext=='"' || cNext=='(' || cNext==')' || cNext==0
|
||||
){
|
||||
pRet = (Fts3Expr *)sqlite3_malloc(sizeof(Fts3Expr));
|
||||
if( !pRet ){
|
||||
return SQLITE_NOMEM;
|
||||
}
|
||||
memset(pRet, 0, sizeof(Fts3Expr));
|
||||
pRet->eType = pKey->eType;
|
||||
pRet->nNear = nNear;
|
||||
*ppExpr = pRet;
|
||||
*pnConsumed = (zInput - z) + nKey;
|
||||
*pnConsumed = (int)((zInput - z) + nKey);
|
||||
return SQLITE_OK;
|
||||
}
|
||||
|
||||
|
@ -378,14 +401,14 @@ static int getNextNode(
|
|||
if( rc==SQLITE_OK && !*ppExpr ){
|
||||
rc = SQLITE_DONE;
|
||||
}
|
||||
*pnConsumed = (zInput - z) + 1 + nConsumed;
|
||||
*pnConsumed = (int)((zInput - z) + 1 + nConsumed);
|
||||
return rc;
|
||||
}
|
||||
|
||||
/* Check for a close bracket. */
|
||||
if( *zInput==')' ){
|
||||
pParse->nNest--;
|
||||
*pnConsumed = (zInput - z) + 1;
|
||||
*pnConsumed = (int)((zInput - z) + 1);
|
||||
return SQLITE_DONE;
|
||||
}
|
||||
}
|
||||
|
@ -397,7 +420,7 @@ static int getNextNode(
|
|||
*/
|
||||
if( *zInput=='"' ){
|
||||
for(ii=1; ii<nInput && zInput[ii]!='"'; ii++);
|
||||
*pnConsumed = (zInput - z) + ii + 1;
|
||||
*pnConsumed = (int)((zInput - z) + ii + 1);
|
||||
if( ii==nInput ){
|
||||
return SQLITE_ERROR;
|
||||
}
|
||||
|
@ -420,12 +443,12 @@ static int getNextNode(
|
|||
iColLen = 0;
|
||||
for(ii=0; ii<pParse->nCol; ii++){
|
||||
const char *zStr = pParse->azCol[ii];
|
||||
int nStr = strlen(zStr);
|
||||
int nStr = (int)strlen(zStr);
|
||||
if( nInput>nStr && zInput[nStr]==':'
|
||||
&& sqlite3_strnicmp(zStr, zInput, nStr)==0
|
||||
){
|
||||
iCol = ii;
|
||||
iColLen = ((zInput - z) + nStr + 1);
|
||||
iColLen = (int)((zInput - z) + nStr + 1);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
@ -691,7 +714,7 @@ int sqlite3Fts3ExprParse(
|
|||
return SQLITE_OK;
|
||||
}
|
||||
if( n<0 ){
|
||||
n = strlen(z);
|
||||
n = (int)strlen(z);
|
||||
}
|
||||
rc = fts3ExprParse(&sParse, z, n, ppExpr, &nParsed);
|
||||
|
||||
|
@ -746,7 +769,7 @@ static int queryTestTokenizer(
|
|||
sqlite3_bind_text(pStmt, 1, zName, -1, SQLITE_STATIC);
|
||||
if( SQLITE_ROW==sqlite3_step(pStmt) ){
|
||||
if( sqlite3_column_type(pStmt, 0)==SQLITE_BLOB ){
|
||||
memcpy(pp, sqlite3_column_blob(pStmt, 0), sizeof(*pp));
|
||||
memcpy((void *)pp, sqlite3_column_blob(pStmt, 0), sizeof(*pp));
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -1,96 +0,0 @@
|
|||
/*
|
||||
** 2008 Nov 28
|
||||
**
|
||||
** 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.
|
||||
**
|
||||
******************************************************************************
|
||||
**
|
||||
*/
|
||||
|
||||
#include "fts3_tokenizer.h"
|
||||
#include "sqlite3.h"
|
||||
|
||||
/*
|
||||
** The following describes the syntax supported by the fts3 MATCH
|
||||
** operator in a similar format to that used by the lemon parser
|
||||
** generator. This module does not use actually lemon, it uses a
|
||||
** custom parser.
|
||||
**
|
||||
** query ::= andexpr (OR andexpr)*.
|
||||
**
|
||||
** andexpr ::= notexpr (AND? notexpr)*.
|
||||
**
|
||||
** notexpr ::= nearexpr (NOT nearexpr|-TOKEN)*.
|
||||
** notexpr ::= LP query RP.
|
||||
**
|
||||
** nearexpr ::= phrase (NEAR distance_opt nearexpr)*.
|
||||
**
|
||||
** distance_opt ::= .
|
||||
** distance_opt ::= / INTEGER.
|
||||
**
|
||||
** phrase ::= TOKEN.
|
||||
** phrase ::= COLUMN:TOKEN.
|
||||
** phrase ::= "TOKEN TOKEN TOKEN...".
|
||||
*/
|
||||
|
||||
typedef struct Fts3Expr Fts3Expr;
|
||||
typedef struct Fts3Phrase Fts3Phrase;
|
||||
|
||||
/*
|
||||
** A "phrase" is a sequence of one or more tokens that must match in
|
||||
** sequence. A single token is the base case and the most common case.
|
||||
** For a sequence of tokens contained in "...", nToken will be the number
|
||||
** of tokens in the string.
|
||||
*/
|
||||
struct Fts3Phrase {
|
||||
int nToken; /* Number of tokens in the phrase */
|
||||
int iColumn; /* Index of column this phrase must match */
|
||||
int isNot; /* Phrase prefixed by unary not (-) operator */
|
||||
struct PhraseToken {
|
||||
char *z; /* Text of the token */
|
||||
int n; /* Number of bytes in buffer pointed to by z */
|
||||
int isPrefix; /* True if token ends in with a "*" character */
|
||||
} aToken[1]; /* One entry for each token in the phrase */
|
||||
};
|
||||
|
||||
/*
|
||||
** A tree of these objects forms the RHS of a MATCH operator.
|
||||
*/
|
||||
struct Fts3Expr {
|
||||
int eType; /* One of the FTSQUERY_XXX values defined below */
|
||||
int nNear; /* Valid if eType==FTSQUERY_NEAR */
|
||||
Fts3Expr *pParent; /* pParent->pLeft==this or pParent->pRight==this */
|
||||
Fts3Expr *pLeft; /* Left operand */
|
||||
Fts3Expr *pRight; /* Right operand */
|
||||
Fts3Phrase *pPhrase; /* Valid if eType==FTSQUERY_PHRASE */
|
||||
};
|
||||
|
||||
int sqlite3Fts3ExprParse(sqlite3_tokenizer *, char **, int, int,
|
||||
const char *, int, Fts3Expr **);
|
||||
void sqlite3Fts3ExprFree(Fts3Expr *);
|
||||
|
||||
/*
|
||||
** Candidate values for Fts3Query.eType. Note that the order of the first
|
||||
** four values is in order of precedence when parsing expressions. For
|
||||
** example, the following:
|
||||
**
|
||||
** "a OR b AND c NOT d NEAR e"
|
||||
**
|
||||
** is equivalent to:
|
||||
**
|
||||
** "a OR (b AND (c NOT (d NEAR e)))"
|
||||
*/
|
||||
#define FTSQUERY_NEAR 1
|
||||
#define FTSQUERY_NOT 2
|
||||
#define FTSQUERY_AND 3
|
||||
#define FTSQUERY_OR 4
|
||||
#define FTSQUERY_PHRASE 5
|
||||
|
||||
#ifdef SQLITE_TEST
|
||||
void sqlite3Fts3ExprInitTestInterface(sqlite3 *db);
|
||||
#endif
|
|
@ -56,7 +56,7 @@ static void fts3HashFree(void *p){
|
|||
** true if the hash table should make its own private copy of keys and
|
||||
** false if it should just use the supplied pointer.
|
||||
*/
|
||||
void sqlite3Fts3HashInit(fts3Hash *pNew, int keyClass, int copyKey){
|
||||
void sqlite3Fts3HashInit(Fts3Hash *pNew, char keyClass, char copyKey){
|
||||
assert( pNew!=0 );
|
||||
assert( keyClass>=FTS3_HASH_STRING && keyClass<=FTS3_HASH_BINARY );
|
||||
pNew->keyClass = keyClass;
|
||||
|
@ -71,8 +71,8 @@ void sqlite3Fts3HashInit(fts3Hash *pNew, int keyClass, int copyKey){
|
|||
** Call this routine to delete a hash table or to reset a hash table
|
||||
** to the empty state.
|
||||
*/
|
||||
void sqlite3Fts3HashClear(fts3Hash *pH){
|
||||
fts3HashElem *elem; /* For looping over all elements of the table */
|
||||
void sqlite3Fts3HashClear(Fts3Hash *pH){
|
||||
Fts3HashElem *elem; /* For looping over all elements of the table */
|
||||
|
||||
assert( pH!=0 );
|
||||
elem = pH->first;
|
||||
|
@ -81,7 +81,7 @@ void sqlite3Fts3HashClear(fts3Hash *pH){
|
|||
pH->ht = 0;
|
||||
pH->htsize = 0;
|
||||
while( elem ){
|
||||
fts3HashElem *next_elem = elem->next;
|
||||
Fts3HashElem *next_elem = elem->next;
|
||||
if( pH->copyKey && elem->pKey ){
|
||||
fts3HashFree(elem->pKey);
|
||||
}
|
||||
|
@ -164,11 +164,11 @@ static int (*ftsCompareFunction(int keyClass))(const void*,int,const void*,int){
|
|||
/* Link an element into the hash table
|
||||
*/
|
||||
static void fts3HashInsertElement(
|
||||
fts3Hash *pH, /* The complete hash table */
|
||||
Fts3Hash *pH, /* The complete hash table */
|
||||
struct _fts3ht *pEntry, /* The entry into which pNew is inserted */
|
||||
fts3HashElem *pNew /* The element to be inserted */
|
||||
Fts3HashElem *pNew /* The element to be inserted */
|
||||
){
|
||||
fts3HashElem *pHead; /* First element already in pEntry */
|
||||
Fts3HashElem *pHead; /* First element already in pEntry */
|
||||
pHead = pEntry->chain;
|
||||
if( pHead ){
|
||||
pNew->next = pHead;
|
||||
|
@ -190,15 +190,17 @@ static void fts3HashInsertElement(
|
|||
/* Resize the hash table so that it cantains "new_size" buckets.
|
||||
** "new_size" must be a power of 2. The hash table might fail
|
||||
** to resize if sqliteMalloc() fails.
|
||||
**
|
||||
** Return non-zero if a memory allocation error occurs.
|
||||
*/
|
||||
static void fts3Rehash(fts3Hash *pH, int new_size){
|
||||
static int fts3Rehash(Fts3Hash *pH, int new_size){
|
||||
struct _fts3ht *new_ht; /* The new hash table */
|
||||
fts3HashElem *elem, *next_elem; /* For looping over existing elements */
|
||||
Fts3HashElem *elem, *next_elem; /* For looping over existing elements */
|
||||
int (*xHash)(const void*,int); /* The hash function */
|
||||
|
||||
assert( (new_size & (new_size-1))==0 );
|
||||
new_ht = (struct _fts3ht *)fts3HashMalloc( new_size*sizeof(struct _fts3ht) );
|
||||
if( new_ht==0 ) return;
|
||||
if( new_ht==0 ) return 1;
|
||||
fts3HashFree(pH->ht);
|
||||
pH->ht = new_ht;
|
||||
pH->htsize = new_size;
|
||||
|
@ -208,19 +210,20 @@ static void fts3Rehash(fts3Hash *pH, int new_size){
|
|||
next_elem = elem->next;
|
||||
fts3HashInsertElement(pH, &new_ht[h], elem);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* This function (for internal use only) locates an element in an
|
||||
** hash table that matches the given key. The hash for this key has
|
||||
** already been computed and is passed as the 4th parameter.
|
||||
*/
|
||||
static fts3HashElem *fts3FindElementByHash(
|
||||
const fts3Hash *pH, /* The pH to be searched */
|
||||
static Fts3HashElem *fts3FindElementByHash(
|
||||
const Fts3Hash *pH, /* The pH to be searched */
|
||||
const void *pKey, /* The key we are searching for */
|
||||
int nKey,
|
||||
int h /* The hash for this key. */
|
||||
){
|
||||
fts3HashElem *elem; /* Used to loop thru the element list */
|
||||
Fts3HashElem *elem; /* Used to loop thru the element list */
|
||||
int count; /* Number of elements left to test */
|
||||
int (*xCompare)(const void*,int,const void*,int); /* comparison function */
|
||||
|
||||
|
@ -243,8 +246,8 @@ static fts3HashElem *fts3FindElementByHash(
|
|||
** element and a hash on the element's key.
|
||||
*/
|
||||
static void fts3RemoveElementByHash(
|
||||
fts3Hash *pH, /* The pH containing "elem" */
|
||||
fts3HashElem* elem, /* The element to be removed from the pH */
|
||||
Fts3Hash *pH, /* The pH containing "elem" */
|
||||
Fts3HashElem* elem, /* The element to be removed from the pH */
|
||||
int h /* Hash value for the element */
|
||||
){
|
||||
struct _fts3ht *pEntry;
|
||||
|
@ -280,9 +283,9 @@ static void fts3RemoveElementByHash(
|
|||
** that matches pKey,nKey. Return the data for this element if it is
|
||||
** found, or NULL if there is no match.
|
||||
*/
|
||||
void *sqlite3Fts3HashFind(const fts3Hash *pH, const void *pKey, int nKey){
|
||||
void *sqlite3Fts3HashFind(const Fts3Hash *pH, const void *pKey, int nKey){
|
||||
int h; /* A hash on key */
|
||||
fts3HashElem *elem; /* The element that matches key */
|
||||
Fts3HashElem *elem; /* The element that matches key */
|
||||
int (*xHash)(const void*,int); /* The hash function */
|
||||
|
||||
if( pH==0 || pH->ht==0 ) return 0;
|
||||
|
@ -310,15 +313,15 @@ void *sqlite3Fts3HashFind(const fts3Hash *pH, const void *pKey, int nKey){
|
|||
** element corresponding to "key" is removed from the hash table.
|
||||
*/
|
||||
void *sqlite3Fts3HashInsert(
|
||||
fts3Hash *pH, /* The hash table to insert into */
|
||||
Fts3Hash *pH, /* The hash table to insert into */
|
||||
const void *pKey, /* The key */
|
||||
int nKey, /* Number of bytes in the key */
|
||||
void *data /* The data */
|
||||
){
|
||||
int hraw; /* Raw hash value of the key */
|
||||
int h; /* the hash of the key modulo hash table size */
|
||||
fts3HashElem *elem; /* Used to loop thru the element list */
|
||||
fts3HashElem *new_elem; /* New element added to the pH */
|
||||
Fts3HashElem *elem; /* Used to loop thru the element list */
|
||||
Fts3HashElem *new_elem; /* New element added to the pH */
|
||||
int (*xHash)(const void*,int); /* The hash function */
|
||||
|
||||
assert( pH!=0 );
|
||||
|
@ -338,14 +341,14 @@ void *sqlite3Fts3HashInsert(
|
|||
return old_data;
|
||||
}
|
||||
if( data==0 ) return 0;
|
||||
if( pH->htsize==0 ){
|
||||
fts3Rehash(pH,8);
|
||||
if( pH->htsize==0 ){
|
||||
pH->count = 0;
|
||||
return data;
|
||||
}
|
||||
if( (pH->htsize==0 && fts3Rehash(pH,8))
|
||||
|| (pH->count>=pH->htsize && fts3Rehash(pH, pH->htsize*2))
|
||||
){
|
||||
pH->count = 0;
|
||||
return data;
|
||||
}
|
||||
new_elem = (fts3HashElem*)fts3HashMalloc( sizeof(fts3HashElem) );
|
||||
assert( pH->htsize>0 );
|
||||
new_elem = (Fts3HashElem*)fts3HashMalloc( sizeof(Fts3HashElem) );
|
||||
if( new_elem==0 ) return data;
|
||||
if( pH->copyKey && pKey!=0 ){
|
||||
new_elem->pKey = fts3HashMalloc( nKey );
|
||||
|
@ -359,9 +362,6 @@ void *sqlite3Fts3HashInsert(
|
|||
}
|
||||
new_elem->nKey = nKey;
|
||||
pH->count++;
|
||||
if( pH->count > pH->htsize ){
|
||||
fts3Rehash(pH,pH->htsize*2);
|
||||
}
|
||||
assert( pH->htsize>0 );
|
||||
assert( (pH->htsize & (pH->htsize-1))==0 );
|
||||
h = hraw & (pH->htsize-1);
|
||||
|
|
|
@ -18,8 +18,8 @@
|
|||
#define _FTS3_HASH_H_
|
||||
|
||||
/* Forward declarations of structures. */
|
||||
typedef struct fts3Hash fts3Hash;
|
||||
typedef struct fts3HashElem fts3HashElem;
|
||||
typedef struct Fts3Hash Fts3Hash;
|
||||
typedef struct Fts3HashElem Fts3HashElem;
|
||||
|
||||
/* A complete hash table is an instance of the following structure.
|
||||
** The internals of this structure are intended to be opaque -- client
|
||||
|
@ -29,15 +29,15 @@ typedef struct fts3HashElem fts3HashElem;
|
|||
** accessing this structure are really macros, so we can't really make
|
||||
** this structure opaque.
|
||||
*/
|
||||
struct fts3Hash {
|
||||
struct Fts3Hash {
|
||||
char keyClass; /* HASH_INT, _POINTER, _STRING, _BINARY */
|
||||
char copyKey; /* True if copy of key made on insert */
|
||||
int count; /* Number of entries in this table */
|
||||
fts3HashElem *first; /* The first element of the array */
|
||||
Fts3HashElem *first; /* The first element of the array */
|
||||
int htsize; /* Number of buckets in the hash table */
|
||||
struct _fts3ht { /* the hash table */
|
||||
int count; /* Number of entries with this hash */
|
||||
fts3HashElem *chain; /* Pointer to first entry with this hash */
|
||||
Fts3HashElem *chain; /* Pointer to first entry with this hash */
|
||||
} *ht;
|
||||
};
|
||||
|
||||
|
@ -47,8 +47,8 @@ struct fts3Hash {
|
|||
** Again, this structure is intended to be opaque, but it can't really
|
||||
** be opaque because it is used by macros.
|
||||
*/
|
||||
struct fts3HashElem {
|
||||
fts3HashElem *next, *prev; /* Next and previous elements in the table */
|
||||
struct Fts3HashElem {
|
||||
Fts3HashElem *next, *prev; /* Next and previous elements in the table */
|
||||
void *data; /* Data associated with this element */
|
||||
void *pKey; int nKey; /* Key associated with this element */
|
||||
};
|
||||
|
@ -71,10 +71,10 @@ struct fts3HashElem {
|
|||
/*
|
||||
** Access routines. To delete, insert a NULL pointer.
|
||||
*/
|
||||
void sqlite3Fts3HashInit(fts3Hash*, int keytype, int copyKey);
|
||||
void *sqlite3Fts3HashInsert(fts3Hash*, const void *pKey, int nKey, void *pData);
|
||||
void *sqlite3Fts3HashFind(const fts3Hash*, const void *pKey, int nKey);
|
||||
void sqlite3Fts3HashClear(fts3Hash*);
|
||||
void sqlite3Fts3HashInit(Fts3Hash *pNew, char keyClass, char copyKey);
|
||||
void *sqlite3Fts3HashInsert(Fts3Hash*, const void *pKey, int nKey, void *pData);
|
||||
void *sqlite3Fts3HashFind(const Fts3Hash*, const void *pKey, int nKey);
|
||||
void sqlite3Fts3HashClear(Fts3Hash*);
|
||||
|
||||
/*
|
||||
** Shorthand for the functions above
|
||||
|
@ -88,8 +88,8 @@ void sqlite3Fts3HashClear(fts3Hash*);
|
|||
** Macros for looping over all elements of a hash table. The idiom is
|
||||
** like this:
|
||||
**
|
||||
** fts3Hash h;
|
||||
** fts3HashElem *p;
|
||||
** Fts3Hash h;
|
||||
** Fts3HashElem *p;
|
||||
** ...
|
||||
** for(p=fts3HashFirst(&h); p; p=fts3HashNext(p)){
|
||||
** SomeStructure *pData = fts3HashData(p);
|
||||
|
|
|
@ -24,6 +24,7 @@
|
|||
*/
|
||||
#if !defined(SQLITE_CORE) || defined(SQLITE_ENABLE_FTS3)
|
||||
|
||||
#include "fts3Int.h"
|
||||
|
||||
#include <assert.h>
|
||||
#include <stdlib.h>
|
||||
|
@ -54,10 +55,6 @@ typedef struct porter_tokenizer_cursor {
|
|||
} porter_tokenizer_cursor;
|
||||
|
||||
|
||||
/* Forward declaration */
|
||||
static const sqlite3_tokenizer_module porterTokenizerModule;
|
||||
|
||||
|
||||
/*
|
||||
** Create a new tokenizer instance.
|
||||
*/
|
||||
|
@ -66,6 +63,10 @@ static int porterCreate(
|
|||
sqlite3_tokenizer **ppTokenizer
|
||||
){
|
||||
porter_tokenizer *t;
|
||||
|
||||
UNUSED_PARAMETER(argc);
|
||||
UNUSED_PARAMETER(argv);
|
||||
|
||||
t = (porter_tokenizer *) sqlite3_malloc(sizeof(*t));
|
||||
if( t==NULL ) return SQLITE_NOMEM;
|
||||
memset(t, 0, sizeof(*t));
|
||||
|
@ -94,6 +95,8 @@ static int porterOpen(
|
|||
){
|
||||
porter_tokenizer_cursor *c;
|
||||
|
||||
UNUSED_PARAMETER(pTokenizer);
|
||||
|
||||
c = (porter_tokenizer_cursor *) sqlite3_malloc(sizeof(*c));
|
||||
if( c==NULL ) return SQLITE_NOMEM;
|
||||
|
||||
|
@ -234,7 +237,7 @@ static int hasVowel(const char *z){
|
|||
** the first two characters of z[].
|
||||
*/
|
||||
static int doubleConsonant(const char *z){
|
||||
return isConsonant(z) && z[0]==z[1] && isConsonant(z+1);
|
||||
return isConsonant(z) && z[0]==z[1];
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -247,10 +250,10 @@ static int doubleConsonant(const char *z){
|
|||
*/
|
||||
static int star_oh(const char *z){
|
||||
return
|
||||
z[0]!=0 && isConsonant(z) &&
|
||||
isConsonant(z) &&
|
||||
z[0]!='w' && z[0]!='x' && z[0]!='y' &&
|
||||
z[1]!=0 && isVowel(z+1) &&
|
||||
z[2]!=0 && isConsonant(z+2);
|
||||
isVowel(z+1) &&
|
||||
isConsonant(z+2);
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -294,7 +297,7 @@ static void copy_stemmer(const char *zIn, int nIn, char *zOut, int *pnOut){
|
|||
int i, mx, j;
|
||||
int hasDigit = 0;
|
||||
for(i=0; i<nIn; i++){
|
||||
int c = zIn[i];
|
||||
char c = zIn[i];
|
||||
if( c>='A' && c<='Z' ){
|
||||
zOut[i] = c - 'A' + 'a';
|
||||
}else{
|
||||
|
@ -338,7 +341,7 @@ static void copy_stemmer(const char *zIn, int nIn, char *zOut, int *pnOut){
|
|||
** no chance of overflowing the zOut buffer.
|
||||
*/
|
||||
static void porter_stemmer(const char *zIn, int nIn, char *zOut, int *pnOut){
|
||||
int i, j, c;
|
||||
int i, j;
|
||||
char zReverse[28];
|
||||
char *z, *z2;
|
||||
if( nIn<3 || nIn>=sizeof(zReverse)-7 ){
|
||||
|
@ -348,7 +351,7 @@ static void porter_stemmer(const char *zIn, int nIn, char *zOut, int *pnOut){
|
|||
return;
|
||||
}
|
||||
for(i=0, j=sizeof(zReverse)-6; i<nIn; i++, j--){
|
||||
c = zIn[i];
|
||||
char c = zIn[i];
|
||||
if( c>='A' && c<='Z' ){
|
||||
zReverse[j] = c + 'a' - 'A';
|
||||
}else if( c>='a' && c<='z' ){
|
||||
|
@ -547,7 +550,7 @@ static void porter_stemmer(const char *zIn, int nIn, char *zOut, int *pnOut){
|
|||
/* z[] is now the stemmed word in reverse order. Flip it back
|
||||
** around into forward order and return.
|
||||
*/
|
||||
*pnOut = i = strlen(z);
|
||||
*pnOut = i = (int)strlen(z);
|
||||
zOut[i] = 0;
|
||||
while( *z ){
|
||||
zOut[--i] = *(z++);
|
||||
|
|
|
@ -0,0 +1,734 @@
|
|||
/*
|
||||
** 2009 Oct 23
|
||||
**
|
||||
** 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.
|
||||
**
|
||||
******************************************************************************
|
||||
*/
|
||||
|
||||
#if !defined(SQLITE_CORE) || defined(SQLITE_ENABLE_FTS3)
|
||||
|
||||
#include "fts3Int.h"
|
||||
#include <string.h>
|
||||
#include <assert.h>
|
||||
#include <ctype.h>
|
||||
|
||||
typedef struct Snippet Snippet;
|
||||
|
||||
/*
|
||||
** An instance of the following structure keeps track of generated
|
||||
** matching-word offset information and snippets.
|
||||
*/
|
||||
struct Snippet {
|
||||
int nMatch; /* Total number of matches */
|
||||
int nAlloc; /* Space allocated for aMatch[] */
|
||||
struct snippetMatch { /* One entry for each matching term */
|
||||
char snStatus; /* Status flag for use while constructing snippets */
|
||||
short int nByte; /* Number of bytes in the term */
|
||||
short int iCol; /* The column that contains the match */
|
||||
short int iTerm; /* The index in Query.pTerms[] of the matching term */
|
||||
int iToken; /* The index of the matching document token */
|
||||
int iStart; /* The offset to the first character of the term */
|
||||
} *aMatch; /* Points to space obtained from malloc */
|
||||
char *zOffset; /* Text rendering of aMatch[] */
|
||||
int nOffset; /* strlen(zOffset) */
|
||||
char *zSnippet; /* Snippet text */
|
||||
int nSnippet; /* strlen(zSnippet) */
|
||||
};
|
||||
|
||||
|
||||
/* It is not safe to call isspace(), tolower(), or isalnum() on
|
||||
** hi-bit-set characters. This is the same solution used in the
|
||||
** tokenizer.
|
||||
*/
|
||||
static int fts3snippetIsspace(char c){
|
||||
return (c&0x80)==0 ? isspace(c) : 0;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
** A StringBuffer object holds a zero-terminated string that grows
|
||||
** arbitrarily by appending. Space to hold the string is obtained
|
||||
** from sqlite3_malloc(). After any memory allocation failure,
|
||||
** StringBuffer.z is set to NULL and no further allocation is attempted.
|
||||
*/
|
||||
typedef struct StringBuffer {
|
||||
char *z; /* Text of the string. Space from malloc. */
|
||||
int nUsed; /* Number bytes of z[] used, not counting \000 terminator */
|
||||
int nAlloc; /* Bytes allocated for z[] */
|
||||
} StringBuffer;
|
||||
|
||||
|
||||
/*
|
||||
** Initialize a new StringBuffer.
|
||||
*/
|
||||
static void fts3SnippetSbInit(StringBuffer *p){
|
||||
p->nAlloc = 100;
|
||||
p->nUsed = 0;
|
||||
p->z = sqlite3_malloc( p->nAlloc );
|
||||
}
|
||||
|
||||
/*
|
||||
** Append text to the string buffer.
|
||||
*/
|
||||
static void fts3SnippetAppend(StringBuffer *p, const char *zNew, int nNew){
|
||||
if( p->z==0 ) return;
|
||||
if( nNew<0 ) nNew = (int)strlen(zNew);
|
||||
if( p->nUsed + nNew >= p->nAlloc ){
|
||||
int nAlloc;
|
||||
char *zNew;
|
||||
|
||||
nAlloc = p->nUsed + nNew + p->nAlloc;
|
||||
zNew = sqlite3_realloc(p->z, nAlloc);
|
||||
if( zNew==0 ){
|
||||
sqlite3_free(p->z);
|
||||
p->z = 0;
|
||||
return;
|
||||
}
|
||||
p->z = zNew;
|
||||
p->nAlloc = nAlloc;
|
||||
}
|
||||
memcpy(&p->z[p->nUsed], zNew, nNew);
|
||||
p->nUsed += nNew;
|
||||
p->z[p->nUsed] = 0;
|
||||
}
|
||||
|
||||
/* If the StringBuffer ends in something other than white space, add a
|
||||
** single space character to the end.
|
||||
*/
|
||||
static void fts3SnippetAppendWhiteSpace(StringBuffer *p){
|
||||
if( p->z && p->nUsed && !fts3snippetIsspace(p->z[p->nUsed-1]) ){
|
||||
fts3SnippetAppend(p, " ", 1);
|
||||
}
|
||||
}
|
||||
|
||||
/* Remove white space from the end of the StringBuffer */
|
||||
static void fts3SnippetTrimWhiteSpace(StringBuffer *p){
|
||||
if( p->z ){
|
||||
while( p->nUsed && fts3snippetIsspace(p->z[p->nUsed-1]) ){
|
||||
p->nUsed--;
|
||||
}
|
||||
p->z[p->nUsed] = 0;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
** Release all memory associated with the Snippet structure passed as
|
||||
** an argument.
|
||||
*/
|
||||
static void fts3SnippetFree(Snippet *p){
|
||||
if( p ){
|
||||
sqlite3_free(p->aMatch);
|
||||
sqlite3_free(p->zOffset);
|
||||
sqlite3_free(p->zSnippet);
|
||||
sqlite3_free(p);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
** Append a single entry to the p->aMatch[] log.
|
||||
*/
|
||||
static int snippetAppendMatch(
|
||||
Snippet *p, /* Append the entry to this snippet */
|
||||
int iCol, int iTerm, /* The column and query term */
|
||||
int iToken, /* Matching token in document */
|
||||
int iStart, int nByte /* Offset and size of the match */
|
||||
){
|
||||
int i;
|
||||
struct snippetMatch *pMatch;
|
||||
if( p->nMatch+1>=p->nAlloc ){
|
||||
struct snippetMatch *pNew;
|
||||
p->nAlloc = p->nAlloc*2 + 10;
|
||||
pNew = sqlite3_realloc(p->aMatch, p->nAlloc*sizeof(p->aMatch[0]) );
|
||||
if( pNew==0 ){
|
||||
p->aMatch = 0;
|
||||
p->nMatch = 0;
|
||||
p->nAlloc = 0;
|
||||
return SQLITE_NOMEM;
|
||||
}
|
||||
p->aMatch = pNew;
|
||||
}
|
||||
i = p->nMatch++;
|
||||
pMatch = &p->aMatch[i];
|
||||
pMatch->iCol = (short)iCol;
|
||||
pMatch->iTerm = (short)iTerm;
|
||||
pMatch->iToken = iToken;
|
||||
pMatch->iStart = iStart;
|
||||
pMatch->nByte = (short)nByte;
|
||||
return SQLITE_OK;
|
||||
}
|
||||
|
||||
/*
|
||||
** Sizing information for the circular buffer used in snippetOffsetsOfColumn()
|
||||
*/
|
||||
#define FTS3_ROTOR_SZ (32)
|
||||
#define FTS3_ROTOR_MASK (FTS3_ROTOR_SZ-1)
|
||||
|
||||
/*
|
||||
** Function to iterate through the tokens of a compiled expression.
|
||||
**
|
||||
** Except, skip all tokens on the right-hand side of a NOT operator.
|
||||
** This function is used to find tokens as part of snippet and offset
|
||||
** generation and we do nt want snippets and offsets to report matches
|
||||
** for tokens on the RHS of a NOT.
|
||||
*/
|
||||
static int fts3NextExprToken(Fts3Expr **ppExpr, int *piToken){
|
||||
Fts3Expr *p = *ppExpr;
|
||||
int iToken = *piToken;
|
||||
if( iToken<0 ){
|
||||
/* In this case the expression p is the root of an expression tree.
|
||||
** Move to the first token in the expression tree.
|
||||
*/
|
||||
while( p->pLeft ){
|
||||
p = p->pLeft;
|
||||
}
|
||||
iToken = 0;
|
||||
}else{
|
||||
assert(p && p->eType==FTSQUERY_PHRASE );
|
||||
if( iToken<(p->pPhrase->nToken-1) ){
|
||||
iToken++;
|
||||
}else{
|
||||
iToken = 0;
|
||||
while( p->pParent && p->pParent->pLeft!=p ){
|
||||
assert( p->pParent->pRight==p );
|
||||
p = p->pParent;
|
||||
}
|
||||
p = p->pParent;
|
||||
if( p ){
|
||||
assert( p->pRight!=0 );
|
||||
p = p->pRight;
|
||||
while( p->pLeft ){
|
||||
p = p->pLeft;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
*ppExpr = p;
|
||||
*piToken = iToken;
|
||||
return p?1:0;
|
||||
}
|
||||
|
||||
/*
|
||||
** Return TRUE if the expression node pExpr is located beneath the
|
||||
** RHS of a NOT operator.
|
||||
*/
|
||||
static int fts3ExprBeneathNot(Fts3Expr *p){
|
||||
Fts3Expr *pParent;
|
||||
while( p ){
|
||||
pParent = p->pParent;
|
||||
if( pParent && pParent->eType==FTSQUERY_NOT && pParent->pRight==p ){
|
||||
return 1;
|
||||
}
|
||||
p = pParent;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
** Add entries to pSnippet->aMatch[] for every match that occurs against
|
||||
** document zDoc[0..nDoc-1] which is stored in column iColumn.
|
||||
*/
|
||||
static int snippetOffsetsOfColumn(
|
||||
Fts3Cursor *pCur, /* The fulltest search cursor */
|
||||
Snippet *pSnippet, /* The Snippet object to be filled in */
|
||||
int iColumn, /* Index of fulltext table column */
|
||||
const char *zDoc, /* Text of the fulltext table column */
|
||||
int nDoc /* Length of zDoc in bytes */
|
||||
){
|
||||
const sqlite3_tokenizer_module *pTModule; /* The tokenizer module */
|
||||
sqlite3_tokenizer *pTokenizer; /* The specific tokenizer */
|
||||
sqlite3_tokenizer_cursor *pTCursor; /* Tokenizer cursor */
|
||||
Fts3Table *pVtab; /* The full text index */
|
||||
int nColumn; /* Number of columns in the index */
|
||||
int i, j; /* Loop counters */
|
||||
int rc; /* Return code */
|
||||
unsigned int match, prevMatch; /* Phrase search bitmasks */
|
||||
const char *zToken; /* Next token from the tokenizer */
|
||||
int nToken; /* Size of zToken */
|
||||
int iBegin, iEnd, iPos; /* Offsets of beginning and end */
|
||||
|
||||
/* The following variables keep a circular buffer of the last
|
||||
** few tokens */
|
||||
unsigned int iRotor = 0; /* Index of current token */
|
||||
int iRotorBegin[FTS3_ROTOR_SZ]; /* Beginning offset of token */
|
||||
int iRotorLen[FTS3_ROTOR_SZ]; /* Length of token */
|
||||
|
||||
pVtab = (Fts3Table *)pCur->base.pVtab;
|
||||
nColumn = pVtab->nColumn;
|
||||
pTokenizer = pVtab->pTokenizer;
|
||||
pTModule = pTokenizer->pModule;
|
||||
rc = pTModule->xOpen(pTokenizer, zDoc, nDoc, &pTCursor);
|
||||
if( rc ) return rc;
|
||||
pTCursor->pTokenizer = pTokenizer;
|
||||
|
||||
prevMatch = 0;
|
||||
while( (rc = pTModule->xNext(pTCursor, &zToken, &nToken,
|
||||
&iBegin, &iEnd, &iPos))==SQLITE_OK ){
|
||||
Fts3Expr *pIter = pCur->pExpr;
|
||||
int iIter = -1;
|
||||
iRotorBegin[iRotor&FTS3_ROTOR_MASK] = iBegin;
|
||||
iRotorLen[iRotor&FTS3_ROTOR_MASK] = iEnd-iBegin;
|
||||
match = 0;
|
||||
for(i=0; i<(FTS3_ROTOR_SZ-1) && fts3NextExprToken(&pIter, &iIter); i++){
|
||||
int nPhrase; /* Number of tokens in current phrase */
|
||||
struct PhraseToken *pToken; /* Current token */
|
||||
int iCol; /* Column index */
|
||||
|
||||
if( fts3ExprBeneathNot(pIter) ) continue;
|
||||
nPhrase = pIter->pPhrase->nToken;
|
||||
pToken = &pIter->pPhrase->aToken[iIter];
|
||||
iCol = pIter->pPhrase->iColumn;
|
||||
if( iCol>=0 && iCol<nColumn && iCol!=iColumn ) continue;
|
||||
if( pToken->n>nToken ) continue;
|
||||
if( !pToken->isPrefix && pToken->n<nToken ) continue;
|
||||
assert( pToken->n<=nToken );
|
||||
if( memcmp(pToken->z, zToken, pToken->n) ) continue;
|
||||
if( iIter>0 && (prevMatch & (1<<i))==0 ) continue;
|
||||
match |= 1<<i;
|
||||
if( i==(FTS3_ROTOR_SZ-2) || nPhrase==iIter+1 ){
|
||||
for(j=nPhrase-1; j>=0; j--){
|
||||
int k = (iRotor-j) & FTS3_ROTOR_MASK;
|
||||
rc = snippetAppendMatch(pSnippet, iColumn, i-j, iPos-j,
|
||||
iRotorBegin[k], iRotorLen[k]);
|
||||
if( rc ) goto end_offsets_of_column;
|
||||
}
|
||||
}
|
||||
}
|
||||
prevMatch = match<<1;
|
||||
iRotor++;
|
||||
}
|
||||
end_offsets_of_column:
|
||||
pTModule->xClose(pTCursor);
|
||||
return rc==SQLITE_DONE ? SQLITE_OK : rc;
|
||||
}
|
||||
|
||||
/*
|
||||
** Remove entries from the pSnippet structure to account for the NEAR
|
||||
** operator. When this is called, pSnippet contains the list of token
|
||||
** offsets produced by treating all NEAR operators as AND operators.
|
||||
** This function removes any entries that should not be present after
|
||||
** accounting for the NEAR restriction. For example, if the queried
|
||||
** document is:
|
||||
**
|
||||
** "A B C D E A"
|
||||
**
|
||||
** and the query is:
|
||||
**
|
||||
** A NEAR/0 E
|
||||
**
|
||||
** then when this function is called the Snippet contains token offsets
|
||||
** 0, 4 and 5. This function removes the "0" entry (because the first A
|
||||
** is not near enough to an E).
|
||||
**
|
||||
** When this function is called, the value pointed to by parameter piLeft is
|
||||
** the integer id of the left-most token in the expression tree headed by
|
||||
** pExpr. This function increments *piLeft by the total number of tokens
|
||||
** in the expression tree headed by pExpr.
|
||||
**
|
||||
** Return 1 if any trimming occurs. Return 0 if no trimming is required.
|
||||
*/
|
||||
static int trimSnippetOffsets(
|
||||
Fts3Expr *pExpr, /* The search expression */
|
||||
Snippet *pSnippet, /* The set of snippet offsets to be trimmed */
|
||||
int *piLeft /* Index of left-most token in pExpr */
|
||||
){
|
||||
if( pExpr ){
|
||||
if( trimSnippetOffsets(pExpr->pLeft, pSnippet, piLeft) ){
|
||||
return 1;
|
||||
}
|
||||
|
||||
switch( pExpr->eType ){
|
||||
case FTSQUERY_PHRASE:
|
||||
*piLeft += pExpr->pPhrase->nToken;
|
||||
break;
|
||||
case FTSQUERY_NEAR: {
|
||||
/* The right-hand-side of a NEAR operator is always a phrase. The
|
||||
** left-hand-side is either a phrase or an expression tree that is
|
||||
** itself headed by a NEAR operator. The following initializations
|
||||
** set local variable iLeft to the token number of the left-most
|
||||
** token in the right-hand phrase, and iRight to the right most
|
||||
** token in the same phrase. For example, if we had:
|
||||
**
|
||||
** <col> MATCH '"abc def" NEAR/2 "ghi jkl"'
|
||||
**
|
||||
** then iLeft will be set to 2 (token number of ghi) and nToken will
|
||||
** be set to 4.
|
||||
*/
|
||||
Fts3Expr *pLeft = pExpr->pLeft;
|
||||
Fts3Expr *pRight = pExpr->pRight;
|
||||
int iLeft = *piLeft;
|
||||
int nNear = pExpr->nNear;
|
||||
int nToken = pRight->pPhrase->nToken;
|
||||
int jj, ii;
|
||||
if( pLeft->eType==FTSQUERY_NEAR ){
|
||||
pLeft = pLeft->pRight;
|
||||
}
|
||||
assert( pRight->eType==FTSQUERY_PHRASE );
|
||||
assert( pLeft->eType==FTSQUERY_PHRASE );
|
||||
nToken += pLeft->pPhrase->nToken;
|
||||
|
||||
for(ii=0; ii<pSnippet->nMatch; ii++){
|
||||
struct snippetMatch *p = &pSnippet->aMatch[ii];
|
||||
if( p->iTerm==iLeft ){
|
||||
int isOk = 0;
|
||||
/* Snippet ii is an occurence of query term iLeft in the document.
|
||||
** It occurs at position (p->iToken) of the document. We now
|
||||
** search for an instance of token (iLeft-1) somewhere in the
|
||||
** range (p->iToken - nNear)...(p->iToken + nNear + nToken) within
|
||||
** the set of snippetMatch structures. If one is found, proceed.
|
||||
** If one cannot be found, then remove snippets ii..(ii+N-1)
|
||||
** from the matching snippets, where N is the number of tokens
|
||||
** in phrase pRight->pPhrase.
|
||||
*/
|
||||
for(jj=0; isOk==0 && jj<pSnippet->nMatch; jj++){
|
||||
struct snippetMatch *p2 = &pSnippet->aMatch[jj];
|
||||
if( p2->iTerm==(iLeft-1) ){
|
||||
if( p2->iToken>=(p->iToken-nNear-1)
|
||||
&& p2->iToken<(p->iToken+nNear+nToken)
|
||||
){
|
||||
isOk = 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
if( !isOk ){
|
||||
int kk;
|
||||
for(kk=0; kk<pRight->pPhrase->nToken; kk++){
|
||||
pSnippet->aMatch[kk+ii].iTerm = -2;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
if( p->iTerm==(iLeft-1) ){
|
||||
int isOk = 0;
|
||||
for(jj=0; isOk==0 && jj<pSnippet->nMatch; jj++){
|
||||
struct snippetMatch *p2 = &pSnippet->aMatch[jj];
|
||||
if( p2->iTerm==iLeft ){
|
||||
if( p2->iToken<=(p->iToken+nNear+1)
|
||||
&& p2->iToken>(p->iToken-nNear-nToken)
|
||||
){
|
||||
isOk = 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
if( !isOk ){
|
||||
int kk;
|
||||
for(kk=0; kk<pLeft->pPhrase->nToken; kk++){
|
||||
pSnippet->aMatch[ii-kk].iTerm = -2;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if( trimSnippetOffsets(pExpr->pRight, pSnippet, piLeft) ){
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
** Compute all offsets for the current row of the query.
|
||||
** If the offsets have already been computed, this routine is a no-op.
|
||||
*/
|
||||
static int snippetAllOffsets(Fts3Cursor *pCsr, Snippet **ppSnippet){
|
||||
Fts3Table *p = (Fts3Table *)pCsr->base.pVtab; /* The FTS3 virtual table */
|
||||
int nColumn; /* Number of columns. Docid does count */
|
||||
int iColumn; /* Index of of a column */
|
||||
int i; /* Loop index */
|
||||
int iFirst; /* First column to search */
|
||||
int iLast; /* Last coumn to search */
|
||||
int iTerm = 0;
|
||||
Snippet *pSnippet;
|
||||
int rc = SQLITE_OK;
|
||||
|
||||
if( pCsr->pExpr==0 ){
|
||||
return SQLITE_OK;
|
||||
}
|
||||
|
||||
pSnippet = (Snippet *)sqlite3_malloc(sizeof(Snippet));
|
||||
*ppSnippet = pSnippet;
|
||||
if( !pSnippet ){
|
||||
return SQLITE_NOMEM;
|
||||
}
|
||||
memset(pSnippet, 0, sizeof(Snippet));
|
||||
|
||||
nColumn = p->nColumn;
|
||||
iColumn = (pCsr->eSearch - 2);
|
||||
if( iColumn<0 || iColumn>=nColumn ){
|
||||
/* Look for matches over all columns of the full-text index */
|
||||
iFirst = 0;
|
||||
iLast = nColumn-1;
|
||||
}else{
|
||||
/* Look for matches in the iColumn-th column of the index only */
|
||||
iFirst = iColumn;
|
||||
iLast = iColumn;
|
||||
}
|
||||
for(i=iFirst; rc==SQLITE_OK && i<=iLast; i++){
|
||||
const char *zDoc;
|
||||
int nDoc;
|
||||
zDoc = (const char*)sqlite3_column_text(pCsr->pStmt, i+1);
|
||||
nDoc = sqlite3_column_bytes(pCsr->pStmt, i+1);
|
||||
if( zDoc==0 && sqlite3_column_type(pCsr->pStmt, i+1)!=SQLITE_NULL ){
|
||||
rc = SQLITE_NOMEM;
|
||||
}else{
|
||||
rc = snippetOffsetsOfColumn(pCsr, pSnippet, i, zDoc, nDoc);
|
||||
}
|
||||
}
|
||||
|
||||
while( trimSnippetOffsets(pCsr->pExpr, pSnippet, &iTerm) ){
|
||||
iTerm = 0;
|
||||
}
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
/*
|
||||
** Convert the information in the aMatch[] array of the snippet
|
||||
** into the string zOffset[0..nOffset-1]. This string is used as
|
||||
** the return of the SQL offsets() function.
|
||||
*/
|
||||
static void snippetOffsetText(Snippet *p){
|
||||
int i;
|
||||
int cnt = 0;
|
||||
StringBuffer sb;
|
||||
char zBuf[200];
|
||||
if( p->zOffset ) return;
|
||||
fts3SnippetSbInit(&sb);
|
||||
for(i=0; i<p->nMatch; i++){
|
||||
struct snippetMatch *pMatch = &p->aMatch[i];
|
||||
if( pMatch->iTerm>=0 ){
|
||||
/* If snippetMatch.iTerm is less than 0, then the match was
|
||||
** discarded as part of processing the NEAR operator (see the
|
||||
** trimSnippetOffsetsForNear() function for details). Ignore
|
||||
** it in this case
|
||||
*/
|
||||
zBuf[0] = ' ';
|
||||
sqlite3_snprintf(sizeof(zBuf)-1, &zBuf[cnt>0], "%d %d %d %d",
|
||||
pMatch->iCol, pMatch->iTerm, pMatch->iStart, pMatch->nByte);
|
||||
fts3SnippetAppend(&sb, zBuf, -1);
|
||||
cnt++;
|
||||
}
|
||||
}
|
||||
p->zOffset = sb.z;
|
||||
p->nOffset = sb.z ? sb.nUsed : 0;
|
||||
}
|
||||
|
||||
/*
|
||||
** zDoc[0..nDoc-1] is phrase of text. aMatch[0..nMatch-1] are a set
|
||||
** of matching words some of which might be in zDoc. zDoc is column
|
||||
** number iCol.
|
||||
**
|
||||
** iBreak is suggested spot in zDoc where we could begin or end an
|
||||
** excerpt. Return a value similar to iBreak but possibly adjusted
|
||||
** to be a little left or right so that the break point is better.
|
||||
*/
|
||||
static int wordBoundary(
|
||||
int iBreak, /* The suggested break point */
|
||||
const char *zDoc, /* Document text */
|
||||
int nDoc, /* Number of bytes in zDoc[] */
|
||||
struct snippetMatch *aMatch, /* Matching words */
|
||||
int nMatch, /* Number of entries in aMatch[] */
|
||||
int iCol /* The column number for zDoc[] */
|
||||
){
|
||||
int i;
|
||||
if( iBreak<=10 ){
|
||||
return 0;
|
||||
}
|
||||
if( iBreak>=nDoc-10 ){
|
||||
return nDoc;
|
||||
}
|
||||
for(i=0; ALWAYS(i<nMatch) && aMatch[i].iCol<iCol; i++){}
|
||||
while( i<nMatch && aMatch[i].iStart+aMatch[i].nByte<iBreak ){ i++; }
|
||||
if( i<nMatch ){
|
||||
if( aMatch[i].iStart<iBreak+10 ){
|
||||
return aMatch[i].iStart;
|
||||
}
|
||||
if( i>0 && aMatch[i-1].iStart+aMatch[i-1].nByte>=iBreak ){
|
||||
return aMatch[i-1].iStart;
|
||||
}
|
||||
}
|
||||
for(i=1; i<=10; i++){
|
||||
if( fts3snippetIsspace(zDoc[iBreak-i]) ){
|
||||
return iBreak - i + 1;
|
||||
}
|
||||
if( fts3snippetIsspace(zDoc[iBreak+i]) ){
|
||||
return iBreak + i + 1;
|
||||
}
|
||||
}
|
||||
return iBreak;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*
|
||||
** Allowed values for Snippet.aMatch[].snStatus
|
||||
*/
|
||||
#define SNIPPET_IGNORE 0 /* It is ok to omit this match from the snippet */
|
||||
#define SNIPPET_DESIRED 1 /* We want to include this match in the snippet */
|
||||
|
||||
/*
|
||||
** Generate the text of a snippet.
|
||||
*/
|
||||
static void snippetText(
|
||||
Fts3Cursor *pCursor, /* The cursor we need the snippet for */
|
||||
Snippet *pSnippet,
|
||||
const char *zStartMark, /* Markup to appear before each match */
|
||||
const char *zEndMark, /* Markup to appear after each match */
|
||||
const char *zEllipsis /* Ellipsis mark */
|
||||
){
|
||||
int i, j;
|
||||
struct snippetMatch *aMatch;
|
||||
int nMatch;
|
||||
int nDesired;
|
||||
StringBuffer sb;
|
||||
int tailCol;
|
||||
int tailOffset;
|
||||
int iCol;
|
||||
int nDoc;
|
||||
const char *zDoc;
|
||||
int iStart, iEnd;
|
||||
int tailEllipsis = 0;
|
||||
int iMatch;
|
||||
|
||||
|
||||
sqlite3_free(pSnippet->zSnippet);
|
||||
pSnippet->zSnippet = 0;
|
||||
aMatch = pSnippet->aMatch;
|
||||
nMatch = pSnippet->nMatch;
|
||||
fts3SnippetSbInit(&sb);
|
||||
|
||||
for(i=0; i<nMatch; i++){
|
||||
aMatch[i].snStatus = SNIPPET_IGNORE;
|
||||
}
|
||||
nDesired = 0;
|
||||
for(i=0; i<FTS3_ROTOR_SZ; i++){
|
||||
for(j=0; j<nMatch; j++){
|
||||
if( aMatch[j].iTerm==i ){
|
||||
aMatch[j].snStatus = SNIPPET_DESIRED;
|
||||
nDesired++;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
iMatch = 0;
|
||||
tailCol = -1;
|
||||
tailOffset = 0;
|
||||
for(i=0; i<nMatch && nDesired>0; i++){
|
||||
if( aMatch[i].snStatus!=SNIPPET_DESIRED ) continue;
|
||||
nDesired--;
|
||||
iCol = aMatch[i].iCol;
|
||||
zDoc = (const char*)sqlite3_column_text(pCursor->pStmt, iCol+1);
|
||||
nDoc = sqlite3_column_bytes(pCursor->pStmt, iCol+1);
|
||||
iStart = aMatch[i].iStart - 40;
|
||||
iStart = wordBoundary(iStart, zDoc, nDoc, aMatch, nMatch, iCol);
|
||||
if( iStart<=10 ){
|
||||
iStart = 0;
|
||||
}
|
||||
if( iCol==tailCol && iStart<=tailOffset+20 ){
|
||||
iStart = tailOffset;
|
||||
}
|
||||
if( (iCol!=tailCol && tailCol>=0) || iStart!=tailOffset ){
|
||||
fts3SnippetTrimWhiteSpace(&sb);
|
||||
fts3SnippetAppendWhiteSpace(&sb);
|
||||
fts3SnippetAppend(&sb, zEllipsis, -1);
|
||||
fts3SnippetAppendWhiteSpace(&sb);
|
||||
}
|
||||
iEnd = aMatch[i].iStart + aMatch[i].nByte + 40;
|
||||
iEnd = wordBoundary(iEnd, zDoc, nDoc, aMatch, nMatch, iCol);
|
||||
if( iEnd>=nDoc-10 ){
|
||||
iEnd = nDoc;
|
||||
tailEllipsis = 0;
|
||||
}else{
|
||||
tailEllipsis = 1;
|
||||
}
|
||||
while( iMatch<nMatch && aMatch[iMatch].iCol<iCol ){ iMatch++; }
|
||||
while( iStart<iEnd ){
|
||||
while( iMatch<nMatch && aMatch[iMatch].iStart<iStart
|
||||
&& aMatch[iMatch].iCol<=iCol ){
|
||||
iMatch++;
|
||||
}
|
||||
if( iMatch<nMatch && aMatch[iMatch].iStart<iEnd
|
||||
&& aMatch[iMatch].iCol==iCol ){
|
||||
fts3SnippetAppend(&sb, &zDoc[iStart], aMatch[iMatch].iStart - iStart);
|
||||
iStart = aMatch[iMatch].iStart;
|
||||
fts3SnippetAppend(&sb, zStartMark, -1);
|
||||
fts3SnippetAppend(&sb, &zDoc[iStart], aMatch[iMatch].nByte);
|
||||
fts3SnippetAppend(&sb, zEndMark, -1);
|
||||
iStart += aMatch[iMatch].nByte;
|
||||
for(j=iMatch+1; j<nMatch; j++){
|
||||
if( aMatch[j].iTerm==aMatch[iMatch].iTerm
|
||||
&& aMatch[j].snStatus==SNIPPET_DESIRED ){
|
||||
nDesired--;
|
||||
aMatch[j].snStatus = SNIPPET_IGNORE;
|
||||
}
|
||||
}
|
||||
}else{
|
||||
fts3SnippetAppend(&sb, &zDoc[iStart], iEnd - iStart);
|
||||
iStart = iEnd;
|
||||
}
|
||||
}
|
||||
tailCol = iCol;
|
||||
tailOffset = iEnd;
|
||||
}
|
||||
fts3SnippetTrimWhiteSpace(&sb);
|
||||
if( tailEllipsis ){
|
||||
fts3SnippetAppendWhiteSpace(&sb);
|
||||
fts3SnippetAppend(&sb, zEllipsis, -1);
|
||||
}
|
||||
pSnippet->zSnippet = sb.z;
|
||||
pSnippet->nSnippet = sb.z ? sb.nUsed : 0;
|
||||
}
|
||||
|
||||
void sqlite3Fts3Offsets(
|
||||
sqlite3_context *pCtx, /* SQLite function call context */
|
||||
Fts3Cursor *pCsr /* Cursor object */
|
||||
){
|
||||
Snippet *p; /* Snippet structure */
|
||||
int rc = snippetAllOffsets(pCsr, &p);
|
||||
if( rc==SQLITE_OK ){
|
||||
snippetOffsetText(p);
|
||||
if( p->zOffset ){
|
||||
sqlite3_result_text(pCtx, p->zOffset, p->nOffset, SQLITE_TRANSIENT);
|
||||
}else{
|
||||
sqlite3_result_error_nomem(pCtx);
|
||||
}
|
||||
}else{
|
||||
sqlite3_result_error_nomem(pCtx);
|
||||
}
|
||||
fts3SnippetFree(p);
|
||||
}
|
||||
|
||||
void sqlite3Fts3Snippet(
|
||||
sqlite3_context *pCtx, /* SQLite function call context */
|
||||
Fts3Cursor *pCsr, /* Cursor object */
|
||||
const char *zStart, /* Snippet start text - "<b>" */
|
||||
const char *zEnd, /* Snippet end text - "</b>" */
|
||||
const char *zEllipsis /* Snippet ellipsis text - "<b>...</b>" */
|
||||
){
|
||||
Snippet *p; /* Snippet structure */
|
||||
int rc = snippetAllOffsets(pCsr, &p);
|
||||
if( rc==SQLITE_OK ){
|
||||
snippetText(pCsr, p, zStart, zEnd, zEllipsis);
|
||||
if( p->zSnippet ){
|
||||
sqlite3_result_text(pCtx, p->zSnippet, p->nSnippet, SQLITE_TRANSIENT);
|
||||
}else{
|
||||
sqlite3_result_error_nomem(pCtx);
|
||||
}
|
||||
}else{
|
||||
sqlite3_result_error_nomem(pCtx);
|
||||
}
|
||||
fts3SnippetFree(p);
|
||||
}
|
||||
|
||||
#endif
|
|
@ -30,9 +30,10 @@
|
|||
SQLITE_EXTENSION_INIT1
|
||||
#endif
|
||||
|
||||
#include "fts3_hash.h"
|
||||
#include "fts3_tokenizer.h"
|
||||
#include "fts3Int.h"
|
||||
#include <assert.h>
|
||||
#include <ctype.h>
|
||||
#include <string.h>
|
||||
|
||||
/*
|
||||
** Implementation of the SQL scalar function for accessing the underlying
|
||||
|
@ -59,14 +60,14 @@ static void scalarFunc(
|
|||
int argc,
|
||||
sqlite3_value **argv
|
||||
){
|
||||
fts3Hash *pHash;
|
||||
Fts3Hash *pHash;
|
||||
void *pPtr = 0;
|
||||
const unsigned char *zName;
|
||||
int nName;
|
||||
|
||||
assert( argc==1 || argc==2 );
|
||||
|
||||
pHash = (fts3Hash *)sqlite3_user_data(context);
|
||||
pHash = (Fts3Hash *)sqlite3_user_data(context);
|
||||
|
||||
zName = sqlite3_value_text(argv[0]);
|
||||
nName = sqlite3_value_bytes(argv[0])+1;
|
||||
|
@ -97,6 +98,127 @@ static void scalarFunc(
|
|||
sqlite3_result_blob(context, (void *)&pPtr, sizeof(pPtr), SQLITE_TRANSIENT);
|
||||
}
|
||||
|
||||
static int fts3IsIdChar(char c){
|
||||
static const char isFtsIdChar[] = {
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0x */
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 1x */
|
||||
0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 2x */
|
||||
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, /* 3x */
|
||||
0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* 4x */
|
||||
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 1, /* 5x */
|
||||
0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* 6x */
|
||||
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, /* 7x */
|
||||
};
|
||||
return (c&0x80 || isFtsIdChar[(int)(c)]);
|
||||
}
|
||||
|
||||
const char *sqlite3Fts3NextToken(const char *zStr, int *pn){
|
||||
const char *z1;
|
||||
const char *z2 = 0;
|
||||
|
||||
/* Find the start of the next token. */
|
||||
z1 = zStr;
|
||||
while( z2==0 ){
|
||||
switch( *z1 ){
|
||||
case '\0': return 0; /* No more tokens here */
|
||||
case '\'':
|
||||
case '"':
|
||||
case '`': {
|
||||
z2 = &z1[1];
|
||||
while( *z2 && (z2[0]!=*z1 || z2[1]==*z1) ) z2++;
|
||||
if( *z2 ) z2++;
|
||||
break;
|
||||
}
|
||||
case '[':
|
||||
z2 = &z1[1];
|
||||
while( *z2 && z2[0]!=']' ) z2++;
|
||||
if( *z2 ) z2++;
|
||||
break;
|
||||
|
||||
default:
|
||||
if( fts3IsIdChar(*z1) ){
|
||||
z2 = &z1[1];
|
||||
while( fts3IsIdChar(*z2) ) z2++;
|
||||
}else{
|
||||
z1++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
*pn = (int)(z2-z1);
|
||||
return z1;
|
||||
}
|
||||
|
||||
int sqlite3Fts3InitTokenizer(
|
||||
Fts3Hash *pHash, /* Tokenizer hash table */
|
||||
const char *zArg, /* Possible tokenizer specification */
|
||||
sqlite3_tokenizer **ppTok, /* OUT: Tokenizer (if applicable) */
|
||||
const char **pzTokenizer, /* OUT: Set to zArg if is tokenizer */
|
||||
char **pzErr /* OUT: Set to malloced error message */
|
||||
){
|
||||
int rc;
|
||||
char *z = (char *)zArg;
|
||||
int n;
|
||||
char *zCopy;
|
||||
char *zEnd; /* Pointer to nul-term of zCopy */
|
||||
sqlite3_tokenizer_module *m;
|
||||
|
||||
if( !z ){
|
||||
zCopy = sqlite3_mprintf("simple");
|
||||
}else{
|
||||
if( sqlite3_strnicmp(z, "tokenize", 8) || fts3IsIdChar(z[8])){
|
||||
return SQLITE_OK;
|
||||
}
|
||||
zCopy = sqlite3_mprintf("%s", &z[8]);
|
||||
*pzTokenizer = zArg;
|
||||
}
|
||||
if( !zCopy ){
|
||||
return SQLITE_NOMEM;
|
||||
}
|
||||
|
||||
zEnd = &zCopy[strlen(zCopy)];
|
||||
|
||||
z = (char *)sqlite3Fts3NextToken(zCopy, &n);
|
||||
z[n] = '\0';
|
||||
sqlite3Fts3Dequote(z);
|
||||
|
||||
m = (sqlite3_tokenizer_module *)sqlite3Fts3HashFind(pHash, z, (int)strlen(z)+1);
|
||||
if( !m ){
|
||||
*pzErr = sqlite3_mprintf("unknown tokenizer: %s", z);
|
||||
rc = SQLITE_ERROR;
|
||||
}else{
|
||||
char const **aArg = 0;
|
||||
int iArg = 0;
|
||||
z = &z[n+1];
|
||||
while( z<zEnd && (NULL!=(z = (char *)sqlite3Fts3NextToken(z, &n))) ){
|
||||
int nNew = sizeof(char *)*(iArg+1);
|
||||
char const **aNew = (const char **)sqlite3_realloc((void *)aArg, nNew);
|
||||
if( !aNew ){
|
||||
sqlite3_free(zCopy);
|
||||
sqlite3_free((void *)aArg);
|
||||
return SQLITE_NOMEM;
|
||||
}
|
||||
aArg = aNew;
|
||||
aArg[iArg++] = z;
|
||||
z[n] = '\0';
|
||||
sqlite3Fts3Dequote(z);
|
||||
z = &z[n+1];
|
||||
}
|
||||
rc = m->xCreate(iArg, aArg, ppTok);
|
||||
assert( rc!=SQLITE_OK || *ppTok );
|
||||
if( rc!=SQLITE_OK ){
|
||||
*pzErr = sqlite3_mprintf("unknown tokenizer");
|
||||
}else{
|
||||
(*ppTok)->pModule = m;
|
||||
}
|
||||
sqlite3_free((void *)aArg);
|
||||
}
|
||||
|
||||
sqlite3_free(zCopy);
|
||||
return rc;
|
||||
}
|
||||
|
||||
|
||||
#ifdef SQLITE_TEST
|
||||
|
||||
#include <tcl.h>
|
||||
|
@ -133,7 +255,7 @@ static void testFunc(
|
|||
int argc,
|
||||
sqlite3_value **argv
|
||||
){
|
||||
fts3Hash *pHash;
|
||||
Fts3Hash *pHash;
|
||||
sqlite3_tokenizer_module *p;
|
||||
sqlite3_tokenizer *pTokenizer = 0;
|
||||
sqlite3_tokenizer_cursor *pCsr = 0;
|
||||
|
@ -166,7 +288,7 @@ static void testFunc(
|
|||
zArg = (const char *)sqlite3_value_text(argv[1]);
|
||||
}
|
||||
|
||||
pHash = (fts3Hash *)sqlite3_user_data(context);
|
||||
pHash = (Fts3Hash *)sqlite3_user_data(context);
|
||||
p = (sqlite3_tokenizer_module *)sqlite3Fts3HashFind(pHash, zName, nName+1);
|
||||
|
||||
if( !p ){
|
||||
|
@ -257,7 +379,7 @@ int queryTokenizer(
|
|||
sqlite3_bind_text(pStmt, 1, zName, -1, SQLITE_STATIC);
|
||||
if( SQLITE_ROW==sqlite3_step(pStmt) ){
|
||||
if( sqlite3_column_type(pStmt, 0)==SQLITE_BLOB ){
|
||||
memcpy(pp, sqlite3_column_blob(pStmt, 0), sizeof(*pp));
|
||||
memcpy((void *)pp, sqlite3_column_blob(pStmt, 0), sizeof(*pp));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -294,6 +416,9 @@ static void intTestFunc(
|
|||
const sqlite3_tokenizer_module *p2;
|
||||
sqlite3 *db = (sqlite3 *)sqlite3_user_data(context);
|
||||
|
||||
UNUSED_PARAMETER(argc);
|
||||
UNUSED_PARAMETER(argv);
|
||||
|
||||
/* Test the query function */
|
||||
sqlite3Fts3SimpleTokenizerModule(&p1);
|
||||
rc = queryTokenizer(db, "simple", &p2);
|
||||
|
@ -335,7 +460,7 @@ static void intTestFunc(
|
|||
*/
|
||||
int sqlite3Fts3InitHashTable(
|
||||
sqlite3 *db,
|
||||
fts3Hash *pHash,
|
||||
Fts3Hash *pHash,
|
||||
const char *zName
|
||||
){
|
||||
int rc = SQLITE_OK;
|
||||
|
@ -353,13 +478,13 @@ int sqlite3Fts3InitHashTable(
|
|||
}
|
||||
#endif
|
||||
|
||||
if( rc!=SQLITE_OK
|
||||
|| (rc = sqlite3_create_function(db, zName, 1, any, p, scalarFunc, 0, 0))
|
||||
|| (rc = sqlite3_create_function(db, zName, 2, any, p, scalarFunc, 0, 0))
|
||||
if( SQLITE_OK!=rc
|
||||
|| SQLITE_OK!=(rc = sqlite3_create_function(db, zName, 1, any, p, scalarFunc, 0, 0))
|
||||
|| SQLITE_OK!=(rc = sqlite3_create_function(db, zName, 2, any, p, scalarFunc, 0, 0))
|
||||
#ifdef SQLITE_TEST
|
||||
|| (rc = sqlite3_create_function(db, zTest, 2, any, p, testFunc, 0, 0))
|
||||
|| (rc = sqlite3_create_function(db, zTest, 3, any, p, testFunc, 0, 0))
|
||||
|| (rc = sqlite3_create_function(db, zTest2, 0, any, pdb, intTestFunc, 0, 0))
|
||||
|| SQLITE_OK!=(rc = sqlite3_create_function(db, zTest, 2, any, p, testFunc, 0, 0))
|
||||
|| SQLITE_OK!=(rc = sqlite3_create_function(db, zTest, 3, any, p, testFunc, 0, 0))
|
||||
|| SQLITE_OK!=(rc = sqlite3_create_function(db, zTest2, 0, any, pdb, intTestFunc, 0, 0))
|
||||
#endif
|
||||
);
|
||||
|
||||
|
|
|
@ -24,6 +24,7 @@
|
|||
*/
|
||||
#if !defined(SQLITE_CORE) || defined(SQLITE_ENABLE_FTS3)
|
||||
|
||||
#include "fts3Int.h"
|
||||
|
||||
#include <assert.h>
|
||||
#include <stdlib.h>
|
||||
|
@ -49,9 +50,6 @@ typedef struct simple_tokenizer_cursor {
|
|||
} simple_tokenizer_cursor;
|
||||
|
||||
|
||||
/* Forward declaration */
|
||||
static const sqlite3_tokenizer_module simpleTokenizerModule;
|
||||
|
||||
static int simpleDelim(simple_tokenizer *t, unsigned char c){
|
||||
return c<0x80 && t->delim[c];
|
||||
}
|
||||
|
@ -75,7 +73,7 @@ static int simpleCreate(
|
|||
** information on the initial create.
|
||||
*/
|
||||
if( argc>1 ){
|
||||
int i, n = strlen(argv[1]);
|
||||
int i, n = (int)strlen(argv[1]);
|
||||
for(i=0; i<n; i++){
|
||||
unsigned char ch = argv[1][i];
|
||||
/* We explicitly don't support UTF-8 delimiters for now. */
|
||||
|
@ -89,7 +87,7 @@ static int simpleCreate(
|
|||
/* Mark non-alphanumeric ASCII characters as delimiters */
|
||||
int i;
|
||||
for(i=1; i<0x80; i++){
|
||||
t->delim[i] = !isalnum(i);
|
||||
t->delim[i] = !isalnum(i) ? -1 : 0;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -118,6 +116,8 @@ static int simpleOpen(
|
|||
){
|
||||
simple_tokenizer_cursor *c;
|
||||
|
||||
UNUSED_PARAMETER(pTokenizer);
|
||||
|
||||
c = (simple_tokenizer_cursor *) sqlite3_malloc(sizeof(*c));
|
||||
if( c==NULL ) return SQLITE_NOMEM;
|
||||
|
||||
|
@ -191,7 +191,7 @@ static int simpleNext(
|
|||
** case-insensitivity.
|
||||
*/
|
||||
unsigned char ch = p[iStartOffset+i];
|
||||
c->pToken[i] = ch<0x80 ? tolower(ch) : ch;
|
||||
c->pToken[i] = (char)(ch<0x80 ? tolower(ch) : ch);
|
||||
}
|
||||
*ppToken = c->pToken;
|
||||
*pnBytes = n;
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -11,8 +11,6 @@
|
|||
*************************************************************************
|
||||
** This file contains code for implementations of the r-tree and r*-tree
|
||||
** algorithms packaged as an SQLite virtual table module.
|
||||
**
|
||||
** $Id: rtree.c,v 1.14 2009/08/06 18:36:47 danielk1977 Exp $
|
||||
*/
|
||||
|
||||
#if !defined(SQLITE_CORE) || defined(SQLITE_ENABLE_RTREE)
|
||||
|
|
|
@ -11,8 +11,6 @@
|
|||
#
|
||||
# The focus of this file is testing the r-tree extension.
|
||||
#
|
||||
# $Id: rtree1.test,v 1.7 2009/07/17 16:54:48 danielk1977 Exp $
|
||||
#
|
||||
|
||||
if {![info exists testdir]} {
|
||||
set testdir [file join [file dirname $argv0] .. .. test]
|
||||
|
|
|
@ -11,8 +11,6 @@
|
|||
#
|
||||
# The focus of this file is testing the r-tree extension.
|
||||
#
|
||||
# $Id: rtree2.test,v 1.4 2008/07/14 15:37:01 danielk1977 Exp $
|
||||
#
|
||||
|
||||
if {![info exists testdir]} {
|
||||
set testdir [file join [file dirname $argv0] .. .. test]
|
||||
|
|
|
@ -12,8 +12,6 @@
|
|||
# The focus of this file is testing that the r-tree correctly handles
|
||||
# out-of-memory conditions.
|
||||
#
|
||||
# $Id: rtree3.test,v 1.2 2008/06/23 15:55:52 danielk1977 Exp $
|
||||
#
|
||||
|
||||
if {![info exists testdir]} {
|
||||
set testdir [file join [file dirname $argv0] .. .. test]
|
||||
|
@ -71,4 +69,3 @@ do_malloc_test rtree3-3 -sqlprep {
|
|||
}
|
||||
|
||||
finish_test
|
||||
|
||||
|
|
|
@ -11,8 +11,6 @@
|
|||
#
|
||||
# Randomized test cases for the rtree extension.
|
||||
#
|
||||
# $Id: rtree4.test,v 1.3 2008/06/23 15:55:52 danielk1977 Exp $
|
||||
#
|
||||
|
||||
if {![info exists testdir]} {
|
||||
set testdir [file join [file dirname $argv0] .. .. test]
|
||||
|
|
|
@ -12,8 +12,6 @@
|
|||
# The focus of this file is testing the r-tree extension when it is
|
||||
# configured to store values as 32 bit integers.
|
||||
#
|
||||
# $Id: rtree5.test,v 1.1 2008/07/14 15:37:01 danielk1977 Exp $
|
||||
#
|
||||
|
||||
if {![info exists testdir]} {
|
||||
set testdir [file join [file dirname $argv0] .. .. test]
|
||||
|
|
|
@ -8,8 +8,7 @@
|
|||
# May you share freely, never taking more than you give.
|
||||
#
|
||||
#***********************************************************************
|
||||
#
|
||||
# $Id: rtree6.test,v 1.1 2008/09/01 12:47:00 danielk1977 Exp $
|
||||
#
|
||||
#
|
||||
|
||||
if {![info exists testdir]} {
|
||||
|
@ -108,4 +107,3 @@ do_test rtree6.2.5 {
|
|||
]
|
||||
|
||||
finish_test
|
||||
|
||||
|
|
|
@ -72,5 +72,3 @@ set rtree_select_time [time {
|
|||
}
|
||||
}]
|
||||
puts "$rtree_select_time"
|
||||
|
||||
|
||||
|
|
|
@ -13,8 +13,6 @@
|
|||
# analyzing r-tree structures created with this module. It is
|
||||
# used by both test procedures and the r-tree viewer application.
|
||||
#
|
||||
# $Id: rtree_util.tcl,v 1.1 2008/05/26 18:41:54 danielk1977 Exp $
|
||||
#
|
||||
|
||||
|
||||
#--------------------------------------------------------------------------
|
||||
|
@ -192,4 +190,3 @@ proc rtree_treedump {db zTab} {
|
|||
set d [rtree_depth $db $zTab]
|
||||
rtree_nodetreedump $db $zTab "" $d 1
|
||||
}
|
||||
|
||||
|
|
|
@ -11,8 +11,6 @@
|
|||
#
|
||||
# The focus of this file is testing that ticket #3363 is fixed.
|
||||
#
|
||||
# $Id: tkt3363.test,v 1.1 2008/09/08 11:07:03 danielk1977 Exp $
|
||||
#
|
||||
|
||||
if {![info exists testdir]} {
|
||||
set testdir [file join [file dirname $argv0] .. .. test]
|
||||
|
@ -50,5 +48,3 @@ do_test tkt3363.1.4 {
|
|||
} {7}
|
||||
|
||||
finish_test
|
||||
|
||||
|
||||
|
|
|
@ -186,4 +186,3 @@ proc cell_report {db zTab iParent iCell} {
|
|||
|
||||
view_node
|
||||
bind .c <Configure> view_node
|
||||
|
||||
|
|
20
main.mk
20
main.mk
|
@ -54,7 +54,7 @@ LIBOBJ+= alter.o analyze.o attach.o auth.o \
|
|||
backup.o bitvec.o btmutex.o btree.o build.o \
|
||||
callback.o complete.o date.o delete.o expr.o fault.o fkey.o \
|
||||
fts3.o fts3_expr.o fts3_hash.o fts3_icu.o fts3_porter.o \
|
||||
fts3_tokenizer.o fts3_tokenizer1.o \
|
||||
fts3_snippet.o fts3_tokenizer.o fts3_tokenizer1.o fts3_write.o \
|
||||
func.o global.o hash.o \
|
||||
icu.o insert.o journal.o legacy.o loadext.o \
|
||||
main.o malloc.o mem0.o mem1.o mem2.o mem3.o mem5.o \
|
||||
|
@ -65,7 +65,7 @@ LIBOBJ+= alter.o analyze.o attach.o auth.o \
|
|||
random.o resolve.o rowset.o rtree.o select.o status.o \
|
||||
table.o tokenize.o trigger.o \
|
||||
update.o util.o vacuum.o \
|
||||
vdbe.o vdbeapi.o vdbeaux.o vdbeblob.o vdbemem.o \
|
||||
vdbe.o vdbeapi.o vdbeaux.o vdbeblob.o vdbemem.o vdbetrace.o \
|
||||
walker.o where.o utf.o vtab.o
|
||||
|
||||
|
||||
|
@ -154,6 +154,7 @@ SRC = \
|
|||
$(TOP)/src/vdbeaux.c \
|
||||
$(TOP)/src/vdbeblob.c \
|
||||
$(TOP)/src/vdbemem.c \
|
||||
$(TOP)/src/vdbetrace.c \
|
||||
$(TOP)/src/vdbeInt.h \
|
||||
$(TOP)/src/vtab.c \
|
||||
$(TOP)/src/walker.c \
|
||||
|
@ -182,15 +183,17 @@ SRC += \
|
|||
SRC += \
|
||||
$(TOP)/ext/fts3/fts3.c \
|
||||
$(TOP)/ext/fts3/fts3.h \
|
||||
$(TOP)/ext/fts3/fts3Int.h \
|
||||
$(TOP)/ext/fts3/fts3_expr.c \
|
||||
$(TOP)/ext/fts3/fts3_expr.h \
|
||||
$(TOP)/ext/fts3/fts3_hash.c \
|
||||
$(TOP)/ext/fts3/fts3_hash.h \
|
||||
$(TOP)/ext/fts3/fts3_icu.c \
|
||||
$(TOP)/ext/fts3/fts3_porter.c \
|
||||
$(TOP)/ext/fts3/fts3_snippet.c \
|
||||
$(TOP)/ext/fts3/fts3_tokenizer.h \
|
||||
$(TOP)/ext/fts3/fts3_tokenizer.c \
|
||||
$(TOP)/ext/fts3/fts3_tokenizer1.c
|
||||
$(TOP)/ext/fts3/fts3_tokenizer1.c \
|
||||
$(TOP)/ext/fts3/fts3_write.c
|
||||
SRC += \
|
||||
$(TOP)/ext/icu/sqliteicu.h \
|
||||
$(TOP)/ext/icu/icu.c
|
||||
|
@ -231,6 +234,7 @@ TESTSRC = \
|
|||
$(TOP)/src/test_func.c \
|
||||
$(TOP)/src/test_hexio.c \
|
||||
$(TOP)/src/test_init.c \
|
||||
$(TOP)/src/test_intarray.c \
|
||||
$(TOP)/src/test_journal.c \
|
||||
$(TOP)/src/test_malloc.c \
|
||||
$(TOP)/src/test_mutex.c \
|
||||
|
@ -295,7 +299,7 @@ EXTHDR += \
|
|||
$(TOP)/ext/fts2/fts2_tokenizer.h
|
||||
EXTHDR += \
|
||||
$(TOP)/ext/fts3/fts3.h \
|
||||
$(TOP)/ext/fts3/fts3_expr.h \
|
||||
$(TOP)/ext/fts3/fts3Int.h \
|
||||
$(TOP)/ext/fts3/fts3_hash.h \
|
||||
$(TOP)/ext/fts3/fts3_tokenizer.h
|
||||
EXTHDR += \
|
||||
|
@ -434,6 +438,9 @@ fts3_hash.o: $(TOP)/ext/fts3/fts3_hash.c $(HDR) $(EXTHDR)
|
|||
fts3_icu.o: $(TOP)/ext/fts3/fts3_icu.c $(HDR) $(EXTHDR)
|
||||
$(TCCX) -DSQLITE_CORE -c $(TOP)/ext/fts3/fts3_icu.c
|
||||
|
||||
fts3_snippet.o: $(TOP)/ext/fts3/fts3_snippet.c $(HDR) $(EXTHDR)
|
||||
$(TCCX) -DSQLITE_CORE -c $(TOP)/ext/fts3/fts3_snippet.c
|
||||
|
||||
fts3_porter.o: $(TOP)/ext/fts3/fts3_porter.c $(HDR) $(EXTHDR)
|
||||
$(TCCX) -DSQLITE_CORE -c $(TOP)/ext/fts3/fts3_porter.c
|
||||
|
||||
|
@ -443,6 +450,9 @@ fts3_tokenizer.o: $(TOP)/ext/fts3/fts3_tokenizer.c $(HDR) $(EXTHDR)
|
|||
fts3_tokenizer1.o: $(TOP)/ext/fts3/fts3_tokenizer1.c $(HDR) $(EXTHDR)
|
||||
$(TCCX) -DSQLITE_CORE -c $(TOP)/ext/fts3/fts3_tokenizer1.c
|
||||
|
||||
fts3_write.o: $(TOP)/ext/fts3/fts3_write.c $(HDR) $(EXTHDR)
|
||||
$(TCCX) -DSQLITE_CORE -c $(TOP)/ext/fts3/fts3_write.c
|
||||
|
||||
rtree.o: $(TOP)/ext/rtree/rtree.c $(HDR) $(EXTHDR)
|
||||
$(TCCX) -DSQLITE_CORE -c $(TOP)/ext/rtree/rtree.c
|
||||
|
||||
|
|
349
manifest
349
manifest
|
@ -1,14 +1,14 @@
|
|||
-----BEGIN PGP SIGNED MESSAGE-----
|
||||
Hash: SHA1
|
||||
|
||||
C Remove\s"const"\sfrom\sparameter\sof\ssqlite3BtreeFactory()\sto\savoid\sa\scompiler\nwarning.
|
||||
D 2009-11-04T13:30:02
|
||||
C Version\s3.6.21\srelease\scandidate\s3.
|
||||
D 2009-12-07T16:39:13
|
||||
F Makefile.arm-wince-mingw32ce-gcc fcd5e9cd67fe88836360bb4f9ef4cb7f8e2fb5a0
|
||||
F Makefile.in a77dfde96ad86aafd3f71651a4333a104debe86a
|
||||
F Makefile.in c5827ead754ab32b9585487177c93bb00b9497b3
|
||||
F Makefile.linux-gcc d53183f4aa6a9192d249731c90dbdffbd2c68654
|
||||
F Makefile.vxworks 10010ddbf52e2503c7c49c7c0b7c7a096f8638a6
|
||||
F README cd04a36fbc7ea56932a4052d7d0b7f09f27c33d6
|
||||
F VERSION 1dc0be471f26258df462bc85387f8255daad5f26
|
||||
F VERSION aa30c4b131a981624ab576df19eb4c5c9cd582ac
|
||||
F aclocal.m4 a5c22d164aff7ed549d53a90fa56d56955281f50
|
||||
F addopcodes.awk 17dc593f791f874d2c23a0f9360850ded0286531
|
||||
F art/2005osaward.gif 0d1851b2a7c1c9d0ccce545f3e14bca42d7fd248
|
||||
|
@ -22,13 +22,13 @@ F art/src_logo.gif 9341ef09f0e53cd44c0c9b6fc3c16f7f3d6c2ad9
|
|||
F config.guess 226d9a188c6196f3033ffc651cbc9dcee1a42977
|
||||
F config.h.in 868fdb48c028421a203470e15c69ada15b9ba673
|
||||
F config.sub 9ebe4c3b3dab6431ece34f16828b594fb420da55
|
||||
F configure 71cfacd7732f55af4aecaa8e7bea518e11cecc5e
|
||||
F configure beb6a7b293d15978ac274e6b43b37b356d3070b2
|
||||
F configure.ac 14740970ddb674d92a9f5da89083dff1179014ff
|
||||
F contrib/sqlitecon.tcl 210a913ad63f9f991070821e599d600bd913e0ad
|
||||
F doc/lemon.html f0f682f50210928c07e562621c3b7e8ab912a538
|
||||
F ext/README.txt 913a7bd3f4837ab14d7e063304181787658b14e1
|
||||
F ext/async/README.txt 0c541f418b14b415212264cbaaf51c924ec62e5b
|
||||
F ext/async/sqlite3async.c 3d5396cd69851f5633ef29c7491ca9249eac903a
|
||||
F ext/async/sqlite3async.c 676066c2a111a8b3107aeb59bdbbbf335c348f4a
|
||||
F ext/async/sqlite3async.h a21e1252deb14a2c211f0e165c4b9122a8f1f344
|
||||
F ext/fts1/README.txt 20ac73b006a70bcfd80069bdaf59214b6cf1db5e
|
||||
F ext/fts1/ft_hash.c 3927bd880e65329bdc6f506555b228b28924921b
|
||||
|
@ -59,42 +59,44 @@ F ext/fts2/mkfts2amal.tcl 974d5d438cb3f7c4a652639262f82418c1e4cff0
|
|||
F ext/fts3/README.syntax a19711dc5458c20734b8e485e75fb1981ec2427a
|
||||
F ext/fts3/README.tokenizers 998756696647400de63d5ba60e9655036cb966e9
|
||||
F ext/fts3/README.txt 8c18f41574404623b76917b9da66fcb0ab38328d
|
||||
F ext/fts3/fts3.c 35bfa67d9cd659b799b8498895fe60b1e8bd3500
|
||||
F ext/fts3/fts3.c 684a55d603f11c8432323171082ff8a9437b4681
|
||||
F ext/fts3/fts3.h 3a10a0af180d502cecc50df77b1b22df142817fe
|
||||
F ext/fts3/fts3_expr.c 0bfdae44d0d8ea2cb3ccad32bb6d6843d78d1a2d
|
||||
F ext/fts3/fts3_expr.h b5412dcf565c6d90d6a8c22090ceb9ed8c745634
|
||||
F ext/fts3/fts3_hash.c e15e84d18f8df149ab290029872d4559c4c7c15a
|
||||
F ext/fts3/fts3_hash.h 004b759e1602ff16dfa02fea3ca1c77336ad6798
|
||||
F ext/fts3/fts3Int.h cc716c74afa7da8e0f8ef39404f33ea62a823eb3
|
||||
F ext/fts3/fts3_expr.c c18794a62c257d3456d3314c5a18e348ae0d84bd
|
||||
F ext/fts3/fts3_hash.c 18feef38fca216992725e9eae775a0c7735e6724
|
||||
F ext/fts3/fts3_hash.h d410ff2c93c81a56b927fcf07b2099ccbfa7a479
|
||||
F ext/fts3/fts3_icu.c ac494aed69835008185299315403044664bda295
|
||||
F ext/fts3/fts3_porter.c 3063da945fb0a935781c135f7575f39166173eca
|
||||
F ext/fts3/fts3_tokenizer.c fcc8fdb5c161df7d61c77285ec2991da131f0181
|
||||
F ext/fts3/fts3_porter.c a651e287e02b49b565a6ccf9441959d434489156
|
||||
F ext/fts3/fts3_snippet.c 6c2eb6d872d66b2a9aa5663f2662e993f18a6496
|
||||
F ext/fts3/fts3_tokenizer.c 52112e7b50fbf24eb68e356081c5969917406cc6
|
||||
F ext/fts3/fts3_tokenizer.h 7ff73caa3327589bf6550f60d93ebdd1f6a0fb5c
|
||||
F ext/fts3/fts3_tokenizer1.c 0a5bcc579f35de5d24a9345d7908dc25ae403ee7
|
||||
F ext/fts3/fts3_tokenizer1.c 11a604a53cff5e8c28882727bf794e5252e5227b
|
||||
F ext/fts3/fts3_write.c ec51fb6886f910e78ae32158ec0301aa675f52d8
|
||||
F ext/fts3/mkfts3amal.tcl 252ecb7fe6467854f2aa237bf2c390b74e71f100
|
||||
F ext/icu/README.txt 3b130aa66e7a681136f6add198b076a2f90d1e33
|
||||
F ext/icu/icu.c 12e763d288d23b5a49de37caa30737b971a2f1e2
|
||||
F ext/icu/sqliteicu.h 728867a802baa5a96de7495e9689a8e01715ef37
|
||||
F ext/rtree/README 6315c0d73ebf0ec40dedb5aa0e942bc8b54e3761
|
||||
F ext/rtree/rtree.c 5275d8f851c366f4a01e8a0c63aa0af492567f28
|
||||
F ext/rtree/rtree.c 038d59b05783c2e6c927a7352bb118a76c31065a
|
||||
F ext/rtree/rtree.h 834dbcb82dc85b2481cde6a07cdadfddc99e9b9e
|
||||
F ext/rtree/rtree1.test 207041aba07fdcdd93aa797a745839d305181857
|
||||
F ext/rtree/rtree2.test 9ac9d28fa948779df66916c67a5dcf9704c3cb74
|
||||
F ext/rtree/rtree3.test 877a09c1a0c2b87af0f94f3a286e7dd3b65adf22
|
||||
F ext/rtree/rtree4.test 11724f766a74f48710998cdd7552cec140c55bf9
|
||||
F ext/rtree/rtree5.test 7d0643482829038f0263881ddf7e2d51bff1d60f
|
||||
F ext/rtree/rtree6.test 119d991e8651fb1dbb1fa31af67ad280fbe4adf7
|
||||
F ext/rtree/rtree_perf.tcl 0fabb6d5c48cb8024e042ce5d4bb88998b6ec1cb
|
||||
F ext/rtree/rtree_util.tcl ee0a0311eb12175319d78bfb37302320496cee6e
|
||||
F ext/rtree/tkt3363.test 6662237ea75bb431cd5d262dfc9535e1023315fc
|
||||
F ext/rtree/viewrtree.tcl 09526398dae87a5a87c5aac2b3854dbaf8376869
|
||||
F ext/rtree/rtree1.test f72885ed80a329d6bd7991043016d74b51edf2c5
|
||||
F ext/rtree/rtree2.test 7b665c44d25e51b3098068d983a39902b2e2d7a1
|
||||
F ext/rtree/rtree3.test dece988c363368af8c11862995c762071894918f
|
||||
F ext/rtree/rtree4.test 94fdd570ab5bc47244d87d4590023be43ac786bd
|
||||
F ext/rtree/rtree5.test 92508f5152a50110af6551fa5b769d1bbd7c4ef3
|
||||
F ext/rtree/rtree6.test 11aade5311789068ca659be24a47cc0d852b1971
|
||||
F ext/rtree/rtree_perf.tcl 6c18c1f23cd48e0f948930c98dfdd37dfccb5195
|
||||
F ext/rtree/rtree_util.tcl 06aab2ed5b826545bf215fff90ecb9255a8647ea
|
||||
F ext/rtree/tkt3363.test 2bf324f7908084a5f463de3109db9c6e607feb1b
|
||||
F ext/rtree/viewrtree.tcl eea6224b3553599ae665b239bd827e182b466024
|
||||
F install-sh 9d4de14ab9fb0facae2f48780b874848cbf2f895
|
||||
F ltmain.sh 3ff0879076df340d2e23ae905484d8c15d5fdea8
|
||||
F main.mk d588eab5d51b0bfe924a1cccdfdd2cbb4cbe40b4
|
||||
F main.mk a92b99b264c3b277f8cf74d50aadc22c55967ef0
|
||||
F mkdll.sh 7d09b23c05d56532e9d44a50868eb4b12ff4f74a
|
||||
F mkextu.sh 416f9b7089d80e5590a29692c9d9280a10dbad9f
|
||||
F mkextw.sh 4123480947681d9b434a5e7b1ee08135abe409ac
|
||||
F mkopcodec.awk 3fb9bf077053c968451f4dd03d11661ac373f9d1
|
||||
F mkopcodeh.awk 104fa333e4a7a689fac074437cbd51a31a803bd4
|
||||
F mkopcodeh.awk 29b84656502eee5f444c3147f331ee686956ab0e
|
||||
F mkso.sh fd21c06b063bb16a5d25deea1752c2da6ac3ed83
|
||||
F publish.sh c74b6c2b6b63435aa1b4b43b1396dfebfae84095
|
||||
F publish_osx.sh 2ad2ee7d50632dff99949edc9c162dbb052f7534
|
||||
|
@ -102,122 +104,125 @@ F spec.template 86a4a43b99ebb3e75e6b9a735d5fd293a24e90ca
|
|||
F sqlite.pc.in 42b7bf0d02e08b9e77734a47798d1a55a9e0716b
|
||||
F sqlite3.1 6be1ad09113570e1fc8dcaff84c9b0b337db5ffc
|
||||
F sqlite3.pc.in ae6f59a76e862f5c561eb32a380228a02afc3cad
|
||||
F src/alter.c 9e4b52e6b1d3a26242cf2ce680c9fce801f00aa1
|
||||
F src/analyze.c 5a8b8aa3d170eac5e71af45458cec61f83c623ee
|
||||
F src/attach.c 1f2ae6ca3de365c8e959f1d56beb6af589fef75b
|
||||
F src/auth.c a5471a6951a18f79d783da34be22cd94dfbe603a
|
||||
F src/backup.c 6f1c2d9862c8a3feb7739dfcca02c1f5352e37f3
|
||||
F src/bitvec.c ed215b95734045e58358c3b3e16448f8fe6a235a
|
||||
F src/btmutex.c 0f43a75bb5b8147b386e8e1c3e71ba734e3863b7
|
||||
F src/btree.c 3b29423f08987bddeb115562d6a699b002f653ae
|
||||
F src/btree.h 577448a890c2ab9b21e6ab74f073526184bceebe
|
||||
F src/btreeInt.h 1c863e543bb55772fa8db95535c370bb386c578c
|
||||
F src/build.c 3c5762687d0554ebe8844dfaddb828fcc15fe16d
|
||||
F src/callback.c 10d237171472865f58fb07d515737238c9e06688
|
||||
F src/complete.c 5ad5c6cd4548211867c204c41a126d73a9fbcea0
|
||||
F src/date.c 657ff12ca0f1195b531561afacbb38b772d16638
|
||||
F src/delete.c 308e300d599d2d11b838687e2cf7309d42f29a1a
|
||||
F src/expr.c 11c163003b79f38a5b5100228052aca57b454807
|
||||
F src/fault.c dc88c821842157460750d2d61a8a8b4197d047ff
|
||||
F src/fkey.c 41219cba186bcf0a053e42327dfa23aaba4f834a
|
||||
F src/func.c e536218d193b8d326aab91120bc4c6f28aa2b606
|
||||
F src/global.c 271952d199a8cc59d4ce840b3bbbfd2f30c8ba32
|
||||
F src/hash.c ebcaa921ffd9d86f7ea5ae16a0a29d1c871130a7
|
||||
F src/hash.h 35b216c13343d0b4f87d9f21969ac55ad72174e1
|
||||
F src/hwtime.h 4a1d45f4cae1f402ea19686acf24acf4f0cb53cb
|
||||
F src/insert.c 2fe2ef7bd03d6e0120e4525727c4ae7de5a2d571
|
||||
F src/journal.c e00df0c0da8413ab6e1bb7d7cab5665d4a9000d0
|
||||
F src/legacy.c 303b4ffcf1ae652fcf5ef635846c563c254564f6
|
||||
F src/alter.c 92ba938565d7cc6bfe92aad6cc90c00800ff21d3
|
||||
F src/analyze.c 55155f05ee9ab4ce33b7a4d19c449053f8935200
|
||||
F src/attach.c 0ba38b38252a34bb9721de35514a1d14058a8e49
|
||||
F src/auth.c 523da7fb4979469955d822ff9298352d6b31de34
|
||||
F src/backup.c 744e98359dfc79fed43e8dec911e33e108b06aae
|
||||
F src/bitvec.c 06ad2c36a9c3819c0b9cbffec7b15f58d5d834e0
|
||||
F src/btmutex.c 96a12f50f7a17475155971a241d85ec5171573ff
|
||||
F src/btree.c efdef3953c49e28f8b8fa9cc0ac5754cc1a7489a
|
||||
F src/btree.h 7944a9dac59eb3e541aad45fd2747f1051e7c63d
|
||||
F src/btreeInt.h 54f4245decd0409ea52cf9aee422d3d761d7ac10
|
||||
F src/build.c a48e74d24897100017d39ceba5de255e53ec9488
|
||||
F src/callback.c 908f3e0172c3d4058f4ca0acd42c637c52e9669f
|
||||
F src/complete.c 417df1ef5ea798532bb6290b0cc4265fef82980a
|
||||
F src/date.c a79c0a8f219370b972e320741f995a3bef9df33f
|
||||
F src/delete.c 8b8afb9cd7783d573eae55a3f4208bc0637a2bb8
|
||||
F src/expr.c 50385ed51f1cd7f1ab289629cd0f87d5b2fcca52
|
||||
F src/fault.c 160a0c015b6c2629d3899ed2daf63d75754a32bb
|
||||
F src/fkey.c e2116672a6bd610dc888e27df292ebc7999c9bb0
|
||||
F src/func.c bf54e1202cbfb28bf4b1fd9b58899009ae76716f
|
||||
F src/global.c 75946a4a2ab41c6ae58f10ca0ed31b3449694b26
|
||||
F src/hash.c 458488dcc159c301b8e7686280ab209f1fb915af
|
||||
F src/hash.h 2894c932d84d9f892d4b4023a75e501f83050970
|
||||
F src/hwtime.h d32741c8f4df852c7d959236615444e2b1063b08
|
||||
F src/insert.c f9c6098988675ac258b2f98ea5f7e370fc9990fa
|
||||
F src/journal.c b0ea6b70b532961118ab70301c00a33089f9315c
|
||||
F src/legacy.c 9304428e71b1d622b764913e1432e69156814755
|
||||
F src/lempar.c 7f026423f4d71d989e719a743f98a1cbd4e6d99e
|
||||
F src/loadext.c 0e88a335665db0b2fb4cece3e49dcb65d832635a
|
||||
F src/loadext.c 1c7a61ce1281041f437333f366a96aa0d29bb581
|
||||
F src/main.c aae32d5af35b88faff0664e0f937ee7133d77c8d
|
||||
F src/malloc.c 685561d2f1602042e349aea5d7a88c3f10a63454
|
||||
F src/mem0.c f2f84062d1f35814d6535c9f9e33de3bfb3b132c
|
||||
F src/mem1.c e6d5c23941288df8191b8a98c28e3f57771e2270
|
||||
F src/mem2.c d02bd6a5b34f2d59012a852615621939d9c09548
|
||||
F src/mem3.c 805ab642adfafa171781a5d8ab112119dfaef118
|
||||
F src/malloc.c 5fa175797f982b178eaf38afba9c588a866be729
|
||||
F src/mem0.c 6a55ebe57c46ca1a7d98da93aaa07f99f1059645
|
||||
F src/mem1.c 552f7e11486272f27948d2de9c012884d1f52908
|
||||
F src/mem2.c 3f196f6fd3f4320035eb4acbe4530686da2f14b1
|
||||
F src/mem3.c 9b237d911ba9904142a804be727cc6664873f8a3
|
||||
F src/mem5.c 4837b795ebdecc0cfe1522cd0c8b2c5d84ea490d
|
||||
F src/memjournal.c e68cb5f7e828b84d5bf2ea16c5d87f1ed7e9fe7f
|
||||
F src/mutex.c 828a40bc7bf79f01ef95ccbf8db8b02857739449
|
||||
F src/mutex.h 32ddef38560ce0128d7e7b3eb063f5c6eff889a3
|
||||
F src/mutex_noop.c f5a07671f25a1a9bd7c10ad7107bc2585446200f
|
||||
F src/mutex_os2.c 6b5a74f812082a8483c3df05b47bbaac2424b9a0
|
||||
F src/mutex_unix.c aff26c77f698b552becfedfa677ad1036c42d790
|
||||
F src/mutex_w32.c b2c1481ee93b0ac7a8fa5346570fd173b6763fdb
|
||||
F src/notify.c 0127121816d8a861deb0dfd111b495346bf233db
|
||||
F src/os.c 8d62d8d98ad7909cb0dd294c1e5f3835c887ccb6
|
||||
F src/os.h 00a1334a4eecee7f7bef79ac606b88d325119f21
|
||||
F src/os_common.h 8c61457df58f1a4bd5f5adc3e90e01b37bf7afbc
|
||||
F src/os_os2.c bed77dc26e3a95ce4a204936b9a1ca6fe612fcc5
|
||||
F src/os_unix.c a4b4ea928ce31ed34cb8f90ed36a35df19312fad
|
||||
F src/memjournal.c 5bfc2f33c914946e2f77ed3f882aff14dfc9355d
|
||||
F src/mutex.c 581a272e09098040ca3ef543cb5f3d643eff7d50
|
||||
F src/mutex.h 6fde601e55fa6c3fae768783c439797ab84c87c6
|
||||
F src/mutex_noop.c 5f58eaa31f2d742cb8957a747f7887ae98f16053
|
||||
F src/mutex_os2.c 20477db50cf3817c2f1cd3eb61e5c177e50231db
|
||||
F src/mutex_unix.c 04a25238abce7e3d06b358dcf706e26624270809
|
||||
F src/mutex_w32.c 9ec75bcef0ca722821be7968c320fd725abfb984
|
||||
F src/notify.c f799bbda67ab6619b36b0a24153b49518874a203
|
||||
F src/os.c 4500ff276e277730776fe9b6c6c5930383ec4000
|
||||
F src/os.h 534b082c3cb349ad05fa6fa0b06087e022af282c
|
||||
F src/os_common.h 240c88b163b02c21a9f21f87d49678a0aa21ff30
|
||||
F src/os_os2.c 75a8c7b9a00a2cf1a65f9fa4afbc27d46634bb2f
|
||||
F src/os_unix.c fe85acfeded5cc13c2340ab73c9baf841de4e6d9
|
||||
F src/os_win.c 5ffab20249a61e0625f869efe157fa009747039b
|
||||
F src/pager.c 729f73feeb33355ae1f0982a74f112ce190c74aa
|
||||
F src/pager.h 11852d044c86cf5a9d6e34171fb0c4fcf1f6265f
|
||||
F src/parse.y 0204f0dfe8974dc2a0d46eb9ab98a433a1f963d6
|
||||
F src/pcache.c c92ffd4f3e1279b3766854c6d18b5bf4aac0d1fa
|
||||
F src/pcache.h 435ef324197f79391f9c92b71d7f92b548ad7a36
|
||||
F src/pcache1.c 211295a9ff6a5b30f1ca50516731a5cf3e9bf82c
|
||||
F src/pragma.c c25d0d15dd0bbc5ec34e9760629353358705a447
|
||||
F src/prepare.c 665d52303135833c53b9be03e68533e249e1de54
|
||||
F src/printf.c 508a1c59433353552b6553cba175eaa7331f8fc1
|
||||
F src/random.c 676b9d7ac820fe81e6fb2394ac8c10cff7f38628
|
||||
F src/resolve.c f263d685bf21d0707b595455e0a0c95a3f5398f6
|
||||
F src/rowset.c c64dafba1f9fd876836c8db8682966b9d197eb1f
|
||||
F src/select.c cbe366a0ce114856e66f5daf0f848d7c48a88298
|
||||
F src/shell.c f66531a57fff927f95c98d99c28237d88e400c86
|
||||
F src/sqlite.h.in 9106176cf206c36f01f8b761ba62671818bbe6ff
|
||||
F src/sqlite3ext.h 1db7d63ab5de4b3e6b83dd03d1a4e64fef6d2a17
|
||||
F src/sqliteInt.h 67a9ae42527204726d8eb7a58cdb238d659a82fa
|
||||
F src/sqliteLimit.h 38b2fffcd01faeaeaadea71b2b47695a81580c8b
|
||||
F src/status.c 237b193efae0cf6ac3f0817a208de6c6c6ef6d76
|
||||
F src/table.c cc86ad3d6ad54df7c63a3e807b5783c90411a08d
|
||||
F src/tclsqlite.c c2c4047177213baf485d4401c7dbb30a3c2ba322
|
||||
F src/test1.c 2232a39540a6b72f3be8f84b34d1ca0714f92aee
|
||||
F src/test2.c 0de743ec8890ca4f09e0bce5d6d5a681f5957fec
|
||||
F src/test3.c 2445c2beb5e7a0c91fd8136dc1339ec369a24898
|
||||
F src/test4.c b5fd530f02a6a0dbffb23be202168a690985dedd
|
||||
F src/test5.c 162a1cea2105a2c460a3f39fa6919617b562a288
|
||||
F src/test6.c 1a0a7a1f179469044b065b4a88aab9faee114101
|
||||
F src/test7.c b94e68c2236de76889d82b8d7d8e00ad6a4d80b1
|
||||
F src/test8.c 34719910286a0a6ca233f10ba66558be938494dd
|
||||
F src/test9.c 963d380922f25c1c323712d05db01b19197ee6f7
|
||||
F src/test_async.c 731d23f953ece5bf40ce87810cfb7607218953c5
|
||||
F src/test_autoext.c f53b0cdf7bf5f08100009572a5d65cdb540bd0ad
|
||||
F src/test_backup.c 1384a18985a5a2d275c2662e48473bf1542ebd08
|
||||
F src/test_btree.c 5adbba9b138988a3cf4d3b5424dbc7c85651da02
|
||||
F src/test_config.c 4ac1e6257dcf926a71b7934410b71c5c326e68f2
|
||||
F src/test_devsym.c 9f4bc2551e267ce7aeda195f3897d0f30c5228f4
|
||||
F src/test_func.c c6e9d7cfbd7bb0bd7c392a10d76adab4b48e813b
|
||||
F src/test_hexio.c 2f1122aa3f012fa0142ee3c36ce5c902a70cd12f
|
||||
F src/test_init.c f6a5dfaf2fb52d697eec1c825a641e5893c339d2
|
||||
F src/test_journal.c dab49b7c47b53242f039c9563b18cafb67ebfe03
|
||||
F src/test_loadext.c 97dc8800e46a46ed002c2968572656f37e9c0dd9
|
||||
F src/test_malloc.c d054506b095d711e4e5575558dd576a2cbf035a2
|
||||
F src/test_mutex.c 482d9d987c1c678199691efc23c8cd3464e01ff5
|
||||
F src/test_onefile.c d2c3126633592aeef14e8d268fc40c74449b69d8
|
||||
F src/test_osinst.c 9a70a61e127f9e72bcfca000b20368b1c5367873
|
||||
F src/test_pcache.c d770f933888b2afe856c1abcefc64eda5941ffef
|
||||
F src/test_schema.c 4b4bf7bb329326458c491b0e6facd4c8c4c5b479
|
||||
F src/test_server.c f0a403b5f699c09bd2b1236b6f69830fd6221f6b
|
||||
F src/test_tclvar.c 9e42fa59d3d2f064b7ab8628e7ab2dc8a9fe93d4
|
||||
F src/test_thread.c b8a1ab7ca1a632f18e8a361880d5d65eeea08eac
|
||||
F src/test_wsd.c 3ae5101de6cbfda2720152ab659ea84079719241
|
||||
F src/tokenize.c af8a56e6a50c5042fc305bfa796275e9bf26ff2b
|
||||
F src/trigger.c 2053afa9952f69cf451bc0e6ea88072701f2925e
|
||||
F src/update.c 8e8535f66c32d946199cb1caad19646a97ead3a7
|
||||
F src/utf.c 3586a6a2457c5c88b6816f6cda58a54e291883f8
|
||||
F src/util.c 59d4e9456bf1fe581f415a783fa0cee6115c8f35
|
||||
F src/vacuum.c 48e1282bbd5eac4b461587c51658378658c00770
|
||||
F src/vdbe.c a435ffcf6bfc7f14eb40998062ccbd7dfa482319
|
||||
F src/vdbe.h 449323a21c02226790acb6189dae78af17b92b78
|
||||
F src/vdbeInt.h 53b430ad3ff91bc5c963d5573299801c54cb7cba
|
||||
F src/vdbeapi.c 44b5f387459d5faa158aa8d3a26967f0c8596efd
|
||||
F src/vdbeaux.c 0fac44db16b5dc116eb1cacbe619033cb09569c3
|
||||
F src/vdbeblob.c 9bfaeab22e261a6a7b6df04e7faaf7d6dfdbef5a
|
||||
F src/vdbemem.c 7055a2941a7802094f4704cedc7a28cc88a23749
|
||||
F src/vtab.c 3e54fe39374e5feb8b174de32a90e7a21966025d
|
||||
F src/walker.c 1edca756275f158b80f20eb6f104c8d3fcc96a04
|
||||
F src/where.c fac37876e09e005e52cdfcf896090b6f5ebbf25b
|
||||
F src/pager.c a0ed14b86de9d012a962b83389ca01003b6acccb
|
||||
F src/pager.h 1b32faf2e578ac3e7bcf9c9d11217128261c5c54
|
||||
F src/parse.y b172fba9a954855502271556497c440506b6daf4
|
||||
F src/pcache.c 3b079306376e0e04c0d3df40c0a4b750a1839310
|
||||
F src/pcache.h c683390d50f856d4cd8e24342ae62027d1bb6050
|
||||
F src/pcache1.c 2bb2261190b42a348038f5b1c285c8cef415fcc8
|
||||
F src/pragma.c 6936d7df5e04b9f996f8f320d15e65b6944b2caa
|
||||
F src/prepare.c ad90970bba3aead154266d8bb6faf9fbb5233b94
|
||||
F src/printf.c 644bc7d59df3dc56d6d8b9a510914bfc6b51bc69
|
||||
F src/random.c cd4a67b3953b88019f8cd4ccd81394a8ddfaba50
|
||||
F src/resolve.c d052e5c44bab34f83b3c1741aaa07478d18b5dd5
|
||||
F src/rowset.c 69afa95a97c524ba6faf3805e717b5b7ae85a697
|
||||
F src/select.c 2f9ed7482e7a25b0b127fc41693bbdbe1caf5647
|
||||
F src/shell.c f4948cb6d30665d755a6b5e0ec313d1094aab828
|
||||
F src/sqlite.h.in 2d34605565e021851255e0bbcb15f8c1930d1f6f
|
||||
F src/sqlite3ext.h 69dfb8116af51b84a029cddb3b35062354270c89
|
||||
F src/sqliteInt.h e946a6a3f2df015cdbc7668e9626987e8badbb5f
|
||||
F src/sqliteLimit.h 3afab2291762b5d09ae20c18feb8e9fa935a60a6
|
||||
F src/status.c e651be6b30d397d86384c6867bc016e4913bcac7
|
||||
F src/table.c 2cd62736f845d82200acfa1287e33feb3c15d62e
|
||||
F src/tclsqlite.c bad6570a005b234ea670b9f7b48256da19a032d3
|
||||
F src/test1.c db4d8fd2849ab9aca0f27fd3773b8d68d078cf86
|
||||
F src/test2.c b6b43413d495addd039a88b87d65c839f86b18cb
|
||||
F src/test3.c f17eeaf8114205844d76f4e69bab27ea341087af
|
||||
F src/test4.c ad03bb987ddedce928f4258c1e7fa4109a73497d
|
||||
F src/test5.c cc55900118fa4add8ec9cf69fc4225a4662f76b1
|
||||
F src/test6.c a8ece4284d0e34477f349ac05655db73c48e0926
|
||||
F src/test7.c 3f2d63e4ccf97f8c2cf1a7fa0a3c8e2e2a354e6e
|
||||
F src/test8.c f959db9a22d882013b64c92753fa793b2ce3bdea
|
||||
F src/test9.c bea1e8cf52aa93695487badedd6e1886c321ea60
|
||||
F src/test_async.c c1656facbaf43cb2e71b62621e5b9eb080e2621c
|
||||
F src/test_autoext.c 30e7bd98ab6d70a62bb9ba572e4c7df347fe645e
|
||||
F src/test_backup.c c129c91127e9b46e335715ae2e75756e25ba27de
|
||||
F src/test_btree.c 47cd771250f09cdc6e12dda5bc71bc0b3abc96e2
|
||||
F src/test_config.c 220a67047af393756f55760fdf442d935d0d88f3
|
||||
F src/test_devsym.c de3c9af2bb9a8b1e44525c449e4ec3f88e3d4110
|
||||
F src/test_func.c 1c94388a23d4a9e7cd62ec79d612d1bae2451fa2
|
||||
F src/test_hexio.c 415adbdb88cd9388831ce10edff76cb9e73d8a0b
|
||||
F src/test_init.c 5d624ffd0409d424cf9adbfe1f056b200270077c
|
||||
F src/test_intarray.c d879bbf8e4ce085ab966d1f3c896a7c8b4f5fc99
|
||||
F src/test_intarray.h 489edb9068bb926583445cb02589344961054207
|
||||
F src/test_journal.c adc0ce3840ed19b49feb1d583b2212f560ef7866
|
||||
F src/test_loadext.c df586c27176e3c2cb2e099c78da67bf14379a56e
|
||||
F src/test_malloc.c f777d15df756bea0e98271932464ac5d882e66fe
|
||||
F src/test_mutex.c ce06b59aca168cd8c520b77159a24352a7469bd3
|
||||
F src/test_onefile.c 06da7e085dce42924cf062b91763dd4bb84c6101
|
||||
F src/test_osinst.c 90fb03d396f39956897dfb4bd0e62c6711db1cca
|
||||
F src/test_pcache.c 7bf828972ac0d2403f5cfa4cd14da41f8ebe73d8
|
||||
F src/test_schema.c 8c06ef9ddb240c7a0fcd31bc221a6a2aade58bf0
|
||||
F src/test_server.c bbba05c144b5fc4b52ff650a4328027b3fa5fcc6
|
||||
F src/test_tclvar.c f4dc67d5f780707210d6bb0eb6016a431c04c7fa
|
||||
F src/test_thread.c 00fed80690ae7f1525483a35861511c48bc579f2
|
||||
F src/test_wsd.c 41cadfd9d97fe8e3e4e44f61a4a8ccd6f7ca8fe9
|
||||
F src/tokenize.c 9f7d39da1a1346fa0cf106ea0bf10bb6b8b61ddf
|
||||
F src/trigger.c d46f9389e3bf3dd1cc1d288aba2f289c96b34200
|
||||
F src/update.c c0dc6b75ad28b76b619042d934f337b02acee208
|
||||
F src/utf.c dad16adcc0c35ef2437dca125a4b07419d361052
|
||||
F src/util.c ad4f03079ba0fe83590d1cc9197e8e4844e38592
|
||||
F src/vacuum.c 03309a08d549f9389cc3a3589afd4fadbdaf0679
|
||||
F src/vdbe.c 5ed06318aac5d57849170a8bf39e807c22c5fedd
|
||||
F src/vdbe.h bea1f0cd530775bdb58a340265f3cf3ee920e9b2
|
||||
F src/vdbeInt.h d7ea821ac7813c9bea0fe87558c35e07b2c7c44d
|
||||
F src/vdbeapi.c bb128b819b9ef1a2ce211a36a6cb70a1643fa239
|
||||
F src/vdbeaux.c 0981dcb5b933b74ae7bc9bfa7770df5e4da849b3
|
||||
F src/vdbeblob.c 84f924700a7a889152aeebef77ca5f4e3875ffb4
|
||||
F src/vdbemem.c 1e16e3a16e55f4c3452834f0e041726021aa66e0
|
||||
F src/vdbetrace.c 864cef96919323482ebd9986f2132435115e9cc2
|
||||
F src/vtab.c 456fc226614569f0e46f216e33265bea268bd917
|
||||
F src/walker.c 3112bb3afe1d85dc52317cb1d752055e9a781f8f
|
||||
F src/where.c 11b5b00c49d53e767a7eb855bc60790edeca6185
|
||||
F test/aggerror.test a867e273ef9e3d7919f03ef4f0e8c0d2767944f2
|
||||
F test/alias.test 4529fbc152f190268a15f9384a5651bbbabc9d87
|
||||
F test/all.test 14165b3e32715b700b5f0cbf8f6e3833dda0be45
|
||||
|
@ -228,13 +233,13 @@ F test/alter4.test 9386ffd1e9c7245f43eca412b2058d747509cc1f
|
|||
F test/altermalloc.test e81ac9657ed25c6c5bb09bebfa5a047cd8e4acfc
|
||||
F test/analyze.test ad5329098fe4de4a96852231d53e3e9e6283ad4b
|
||||
F test/analyze2.test a2ad7b0a4e13801ee3968fe70f22aff52326569c
|
||||
F test/analyze3.test 851bcc0738b87e1c1990d8dbad6ab53cdfcc19d6
|
||||
F test/analyze3.test ae06e0f8b3eaae0dd644ac9ac9d617058b5ac131
|
||||
F test/async.test 8c75d31b8330f8b70cf2571b014d4476a063efdb
|
||||
F test/async2.test bf5e2ca2c96763b4cba3d016249ad7259a5603b6
|
||||
F test/async3.test 93edaa9122f498e56ea98c36c72abc407f4fb11e
|
||||
F test/async4.test aafa6328c559d3e4bb587de770cbdecfca06f0da
|
||||
F test/async5.test f3592d79c84d6e83a5f50d3fd500445f7d97dfdf
|
||||
F test/attach.test 1d1be27b9e4c654f9bb14d011a4a87753c0b197a
|
||||
F test/attach.test 826f7676c41c12b035181d257299b8c8a17d64f3
|
||||
F test/attach2.test a295d2d7061adcee5884ef4a93c7c96a82765437
|
||||
F test/attach3.test bd9830bc3a0d22ed1310c9bff6896927937017dc
|
||||
F test/attachmalloc.test cf8cf17d183de357b1147a9baacbdfc85b940b61
|
||||
|
@ -274,6 +279,7 @@ F test/capi3c.test d9d293ce8fd4dc2944ce2dae5718fc7a6184a567
|
|||
F test/capi3d.test 57d83b690d7364bde02cddbf8339a4b50d80ce23
|
||||
F test/cast.test 166951664a0b0a2e0f8fb5997a152490c6363932
|
||||
F test/check.test b897cd3cc839b34b31cdd073e9882ccd03da977b
|
||||
F test/coalesce.test cee0dccb9fbd2d494b77234bccf9dc6c6786eb91
|
||||
F test/collate1.test e3eaa48c21e150814be1a7b852d2a8af24458d04
|
||||
F test/collate2.test 04cebe4a033be319d6ddbb3bbc69464e01700b49
|
||||
F test/collate3.test d28d2cfab2c3a3d4628ae4b2b7afc9965daa3b4c
|
||||
|
@ -287,7 +293,7 @@ F test/collateA.test b8218ab90d1fa5c59dcf156efabb1b2599c580d6
|
|||
F test/colmeta.test 087c42997754b8c648819832241daf724f813322
|
||||
F test/colname.test 08948a4809d22817e0e5de89c7c0a8bd90cb551b
|
||||
F test/conflict.test 0ed68b11f22721052d880ee80bd528a0e0828236
|
||||
F test/corrupt.test f47f220959b40f79f30c4271eefcec0587e984e3
|
||||
F test/corrupt.test 85c3fececa01bc6d24ff5d7bf1373844840c0b98
|
||||
F test/corrupt2.test a571e30ea4e82318f319a24b6cc55935ce862079
|
||||
F test/corrupt3.test 263e8bb04e2728df832fddf6973cf54c91db0c32
|
||||
F test/corrupt4.test acdb01afaedf529004b70e55de1a6f5a05ae7fff
|
||||
|
@ -322,7 +328,8 @@ F test/descidx2.test 1310ed1326cdfed4ea2c55169631579f082d174f
|
|||
F test/descidx3.test 3394ad4d089335cac743c36a14129d6d931c316f
|
||||
F test/diskfull.test 0cede7ef9d8f415d9d3944005c76be7589bb5ebb
|
||||
F test/distinctagg.test 1a6ef9c87a58669438fc771450d7a72577417376
|
||||
F test/e_fkey.test af2750eddb48280cfd5ce1d8b2f7948bbd8779ad
|
||||
F test/e_fkey.test fd1fcf89badd5f2773d7ac04775b5ff3488eda17
|
||||
F test/e_fts3.test 8907e25b2c7d6bda9f7077356f64bc5e26c251a7
|
||||
F test/enc.test e54531cd6bf941ee6760be041dff19a104c7acea
|
||||
F test/enc2.test 6d91a5286f59add0cfcbb2d0da913b76f2242398
|
||||
F test/enc3.test 5c550d59ff31dccdba5d1a02ae11c7047d77c041
|
||||
|
@ -372,31 +379,35 @@ F test/fts2p.test 4b48c35c91e6a7dbf5ac8d1e5691823cc999aafb
|
|||
F test/fts2q.test b2fbbe038b7a31a52a6079b215e71226d8c6a682
|
||||
F test/fts2r.test b154c30b63061d8725e320fba1a39e2201cadd5e
|
||||
F test/fts2token.test d8070b241a15ff13592a9ae4a8b7c171af6f445a
|
||||
F test/fts3.test efb41507c90f47e8af2a9101d7460cddeb84656b
|
||||
F test/fts3aa.test 432d1d5c41939bb5405d4d6c80a9ec759b363393
|
||||
F test/fts3ab.test 7f6cf260ae80dda064023df8e8e503e9a412b91f
|
||||
F test/fts3.test ae0433b09b12def08105640e57693726c4949338
|
||||
F test/fts3_common.tcl 31935839b1b601a5955572cb4e8060513c96bde0
|
||||
F test/fts3aa.test 5327d4c1d9b6c61021696746cc9a6cdc5bf159c0
|
||||
F test/fts3ab.test 09aeaa162aee6513d9ff336b6932211008b9d1f9
|
||||
F test/fts3ac.test 356280144a2c92aa7b11474afadfe62a437fcd69
|
||||
F test/fts3ad.test 32a114c6f214081f244f642bde9fd5517938788e
|
||||
F test/fts3ae.test 31d8137fc7c14b5b991e3c4fa041ad2ac1255c7b
|
||||
F test/fts3ad.test e40570cb6f74f059129ad48bcef3d7cbc20dda49
|
||||
F test/fts3ae.test ce32a13b34b0260928e4213b4481acf801533bda
|
||||
F test/fts3af.test d394978c534eabf22dd0837e718b913fd66b499c
|
||||
F test/fts3ag.test 1c316bedb40a7c962e38998df854ea3ae26a3daa
|
||||
F test/fts3ag.test 38d9c7dd4b607929498e8e0b32299af5665da1ab
|
||||
F test/fts3ah.test ba181d6a3dee0c929f0d69df67cac9c47cda6bff
|
||||
F test/fts3ai.test d29cee6ed653e30de478066881cec8aa766531b2
|
||||
F test/fts3aj.test 584facbc9ac4381a7ec624bfde677340ffc2a5a4
|
||||
F test/fts3ak.test bd14deafe9d1586e8e9bf032411026ac4f8c925d
|
||||
F test/fts3al.test 6d19619402d2133773262652fc3f185cdf6be667
|
||||
F test/fts3am.test 218aa6ba0dfc50c7c16b2022aac5c6be593d08d8
|
||||
F test/fts3an.test 4b4fdab5abe2f308bdc47f6e822df2bcae30361c
|
||||
F test/fts3an.test 931fa21bd80641ca594bfa32e105250a8a07918b
|
||||
F test/fts3ao.test 0aa29dd4fc1c8d46b1f7cfe5926f7ac97551bea9
|
||||
F test/fts3atoken.test 25c2070e1e8755d414bf9c8200427b277a9f99fa
|
||||
F test/fts3b.test b3a25180a633873d37d86e1ccd00ed690d37237a
|
||||
F test/fts3c.test 4c7ef29b37aca3e8ebb6a39b57910caa6506034e
|
||||
F test/fts3d.test d92a47fe8ed59c9e53d2d8e6d2685bb380aadadc
|
||||
F test/fts3b.test e93bbb653e52afde110ad53bbd793f14fe7a8984
|
||||
F test/fts3c.test fc723a9cf10b397fdfc2b32e73c53c8b1ec02958
|
||||
F test/fts3d.test 95fb3c862cbc4297c93fceb9a635543744e9ef52
|
||||
F test/fts3e.test 1f6c6ac9cc8b772ca256e6b22aaeed50c9350851
|
||||
F test/fts3expr.test 05dab77387801e4900009917bb18f556037d82da
|
||||
F test/fts3expr2.test 18da930352e5693eaa163a3eacf96233b7290d1a
|
||||
F test/fts3malloc.test d02ee86b21edd2b43044e0d6dfdcd26cb6efddcb
|
||||
F test/fts3near.test dc196dd17b4606f440c580d45b3d23aa975fd077
|
||||
F test/fts3rnd.test ec82795eb358b7a4d6ce79e764d8d55556197584
|
||||
F test/func.test af106ed834001738246d276659406823e35cde7b
|
||||
F test/func2.test 772d66227e4e6684b86053302e2d74a2500e1e0f
|
||||
F test/fuzz.test a4174c3009a3e2c2e14b31b364ebf7ddb49de2c9
|
||||
F test/fuzz2.test ea38692ce2da99ad79fe0be5eb1a452c1c4d37bb
|
||||
F test/fuzz3.test aec64345184d1662bd30e6a17851ff659d596dc5
|
||||
|
@ -424,6 +435,7 @@ F test/insert2.test 4f3a04d168c728ed5ec2c88842e772606c7ce435
|
|||
F test/insert3.test 1b7db95a03ad9c5013fdf7d6722b6cd66ee55e30
|
||||
F test/insert4.test 6e382eaf7295a4463e6f29ea20fcd8e63d097eeb
|
||||
F test/insert5.test 1f93cbe9742110119133d7e8e3ccfe6d7c249766
|
||||
F test/intarray.test 066b7d7ac38d25bf96f87f1b017bfc687551cdd4
|
||||
F test/interrupt.test 42e7cf98646fd9cb4a3b131a93ed3c50b9e149f1
|
||||
F test/intpkey.test 537669fd535f62632ca64828e435b9e54e8d677f
|
||||
F test/io.test e7bd58edb4e2131a8ecd81b4b00af3ee5c79d464
|
||||
|
@ -511,10 +523,10 @@ F test/pcache2.test 0d85f2ab6963aee28c671d4c71bec038c00a1d16
|
|||
F test/permutations.test 1ce2874df8fec876d0b963c7a3ef61c4e9df8827
|
||||
F test/pragma.test 5aeb48a442dba3c3e8e38773b121371814ab3b17
|
||||
F test/pragma2.test 5364893491b9231dd170e3459bfc2e2342658b47
|
||||
F test/printf.test 47e9e5bbec8509023479d54ceb71c9d05a95308a
|
||||
F test/printf.test 05970cde31b1a9f54bd75af60597be75a5c54fea
|
||||
F test/progress.test 5b075c3c790c7b2a61419bc199db87aaf48b8301
|
||||
F test/ptrchng.test ef1aa72d6cf35a2bbd0869a649b744e9d84977fc
|
||||
F test/quick.test 12fdc7656b4d20a537a686fb223eb99b5fe54483
|
||||
F test/quick.test d6591e74f3ac19da7fd076845f06dca48fd43cff
|
||||
F test/quote.test 215897dbe8de1a6f701265836d6601cc6ed103e6
|
||||
F test/randexpr1.tcl 40dec52119ed3a2b8b2a773bce24b63a3a746459
|
||||
F test/randexpr1.test 1084050991e9ba22c1c10edd8d84673b501cc25a
|
||||
|
@ -578,7 +590,7 @@ F test/tclsqlite.test bf4227eb236a4c097aa7974a2bf7d3225acf34be
|
|||
F test/tempdb.test 1bf52da28a9c24e29717362a87722dff08feb72b
|
||||
F test/temptable.test f42121a0d29a62f00f93274464164177ab1cc24a
|
||||
F test/temptrigger.test b0273db072ce5f37cf19140ceb1f0d524bbe9f05
|
||||
F test/tester.tcl 2caf7980d7dbb99dab9507ae0646802bc4d12c79
|
||||
F test/tester.tcl 02f671e71d1646440d226bed2dde8433f0a7bfa9
|
||||
F test/thread001.test a3e6a7254d1cb057836cb3145b60c10bf5b7e60f
|
||||
F test/thread002.test afd20095e6e845b405df4f2c920cb93301ca69db
|
||||
F test/thread003.test b824d4f52b870ae39fc5bae4d8070eca73085dca
|
||||
|
@ -593,7 +605,7 @@ F test/tkt-2ea2425d34.test 1cf13e6f75d149b3209a0cb32927a82d3d79fb28
|
|||
F test/tkt-3fe897352e.test 8084dad39807eac10b10720c84193bd1a5980973
|
||||
F test/tkt-4a03edc4c8.test 2865e4edbc075b954daa82f8da7cc973033ec76e
|
||||
F test/tkt-5ee23731f.test 3581260f2a71e51db94e1506ba6b0f7311d002a9
|
||||
F test/tkt-94c04eaadb.test 40e6b1fce420fbecf8c2379d3ec3cb6889e49091
|
||||
F test/tkt-94c04eaadb.test be5ea61cb04dfdc047d19b5c5a9e75fa3da67a7f
|
||||
F test/tkt-d82e3f3721.txt cbed12b1a1e4740382de43ef1bb45c6bc0f8f473
|
||||
F test/tkt-f777251dc7a.test 6f24c053bc5cdb7e1e19be9a72c8887cf41d5e87
|
||||
F test/tkt1435.test f8c52c41de6e5ca02f1845f3a46e18e25cadac00
|
||||
|
@ -681,7 +693,7 @@ F test/tkt3992.test f3e7d548ac26f763b47bc0f750da3d03c81071da
|
|||
F test/tkt3997.test a335fa41ca3985660a139df7b734a26ef53284bd
|
||||
F test/tkt4018.test 7c2c9ba4df489c676a0a7a0e809a1fb9b2185bd1
|
||||
F test/tokenize.test ce430a7aed48fc98301611429595883fdfcab5d7
|
||||
F test/trace.test 19ffbc09885c3321d56358a5738feae8587fb377
|
||||
F test/trace.test 2739f8dcc6739a9235523819c4cd30e78c44985c
|
||||
F test/trans.test d887cb07630dc39879a322d958ad8b006137485c
|
||||
F test/trans2.test d5337e61de45e66b1fcbf9db833fa8c82e624b22
|
||||
F test/trans3.test d728abaa318ca364dc370e06576aa7e5fbed7e97
|
||||
|
@ -696,7 +708,7 @@ F test/trigger8.test 30cb0530bd7c4728055420e3f739aa00412eafa4
|
|||
F test/trigger9.test 5b0789f1c5c4600961f8e68511b825b87be53e31
|
||||
F test/triggerA.test 0718ad2d9bfef27c7af00e636df79bee6b988da7
|
||||
F test/triggerB.test 56780c031b454abac2340dbb3b71ac5c56c3d7fe
|
||||
F test/triggerC.test 0acc1d22d9c3d6cf0018bf795d544732a25657dc
|
||||
F test/triggerC.test 4083c64d80854d271bad211268a08985f3d61cbd
|
||||
F test/types.test 9a825ec8eea4e965d7113b74c76a78bb5240f2ac
|
||||
F test/types2.test 3555aacf8ed8dc883356e59efc314707e6247a84
|
||||
F test/types3.test a0f66bf12f80fad89493535474f7a6d16fa58150
|
||||
|
@ -722,6 +734,7 @@ F test/vtabA.test 0dcd4c81ffb56649f47d1b5fb9c5ae807ccf41f7
|
|||
F test/vtabB.test 04df5dc531b9f44d9ca65b9c1b79f12b5922a796
|
||||
F test/vtabC.test 1cf7896ab6859bfe3074244b2b0e12de5cbdd766
|
||||
F test/vtabD.test 74167b1578e5886fe4c886d6bef2fd1406444c42
|
||||
F test/vtabE.test 7c4693638d7797ce2eda17af74292b97e705cc61
|
||||
F test/vtab_alter.test 9e374885248f69e251bdaacf480b04a197f125e5
|
||||
F test/vtab_err.test 0d4d8eb4def1d053ac7c5050df3024fd47a3fbd8
|
||||
F test/vtab_shared.test 0eff9ce4f19facbe0a3e693f6c14b80711a4222d
|
||||
|
@ -732,7 +745,7 @@ F test/where4.test e9b9e2f2f98f00379e6031db6a6fca29bae782a2
|
|||
F test/where5.test fdf66f96d29a064b63eb543e28da4dfdccd81ad2
|
||||
F test/where6.test 42c4373595f4409d9c6a9987b4a60000ad664faf
|
||||
F test/where7.test fdd58ab9dec9f97679e65d4414bf5e07d725d79f
|
||||
F test/where8.test 8d3704d04a683e792d373005f2e4e13bfd7e2dd5
|
||||
F test/where8.test 434f08974964b10378d67867773a2c3aedaf1d4b
|
||||
F test/where8m.test da346596e19d54f0aba35ebade032a7c47d79739
|
||||
F test/where9.test be19e1a92f80985c1a121b4678bf7d2123eaa623
|
||||
F test/whereA.test 1d1674254614147c866ab9b59af6582f454a858c
|
||||
|
@ -748,11 +761,13 @@ F tool/lempar.c 01ca97f87610d1dac6d8cd96ab109ab1130e76dc
|
|||
F tool/mkkeywordhash.c 9216336085e7a7c226a35c0bd780239968f8304f
|
||||
F tool/mkopts.tcl 66ac10d240cc6e86abd37dc908d50382f84ff46e
|
||||
F tool/mkspeedsql.tcl a1a334d288f7adfe6e996f2e712becf076745c97
|
||||
F tool/mksqlite3c.tcl a7e87ce780cbf30782bca3fd1197e86f92ae6f24
|
||||
F tool/mksqlite3c.tcl 1da28229695fdebdfe8a7d19902ef6c76d6c1c2d
|
||||
F tool/mksqlite3h.tcl eb100dce83f24b501b325b340f8b5eb8e5106b3b
|
||||
F tool/mksqlite3internalh.tcl 7b43894e21bcb1bb39e11547ce7e38a063357e87
|
||||
F tool/omittest.tcl 27d6f6e3b1e95aeb26a1c140e6eb57771c6d794a
|
||||
F tool/opcodeDoc.awk b3a2a3d5d3075b8bd90b7afe24283efdd586659c
|
||||
F tool/shell1.test f85b976bef45f435fa39bf3690501cd5c0bdbb86
|
||||
F tool/shell2.test c985140ca75d96dad5bef8a5f49ed51b9c002dfb
|
||||
F tool/showdb.c 8ab8b3b53884312aafb7ef60982e255a6c31d238
|
||||
F tool/showjournal.c ec3b171be148656827c4949fbfb8ab4370822f87
|
||||
F tool/soak1.tcl 8d407956e1a45b485a8e072470a3e629a27037fe
|
||||
|
@ -764,14 +779,14 @@ F tool/speedtest2.tcl ee2149167303ba8e95af97873c575c3e0fab58ff
|
|||
F tool/speedtest8.c 2902c46588c40b55661e471d7a86e4dd71a18224
|
||||
F tool/speedtest8inst1.c 293327bc76823f473684d589a8160bde1f52c14e
|
||||
F tool/vdbe-compress.tcl d70ea6d8a19e3571d7ab8c9b75cba86d1173ff0f
|
||||
P 24a4d520d540d92b611abc4eb57dc6da9be4eac6
|
||||
R a2178242a921307d19fbc8b7d2eec4f0
|
||||
P cd50acf37fd1e3b388f98fb2df7ed03cff454b24
|
||||
R 5d0b6a47a50c8a9cdc60d3d4d61a8cf2
|
||||
U drh
|
||||
Z a8d4aa9309aed4b69860cd88128a4708
|
||||
Z 8b76b0c0726e570aef93558fa0c3fdc7
|
||||
-----BEGIN PGP SIGNATURE-----
|
||||
Version: GnuPG v1.4.6 (GNU/Linux)
|
||||
|
||||
iD8DBQFK8YHdoxKgR168RlERAs0DAJ447A8mNmnCD0zy/gACLgqIHsmF8QCfYMHu
|
||||
do95dSeuDXCMLnSZQtGGeQE=
|
||||
=FnZg
|
||||
iD8DBQFLHS+0oxKgR168RlERArAKAJ97NTyJvzQHmWC2GXt2Xt7D52m04QCeLeQt
|
||||
HYPTNDWgvT/KRZ19RtHNjDQ=
|
||||
=tE2+
|
||||
-----END PGP SIGNATURE-----
|
||||
|
|
|
@ -1 +1 @@
|
|||
eb7a544fe49d1626bacecfe53ddc03fe082e3243
|
||||
1ed88e9d01e9eda5cbc622e7614277f29bcc551c
|
||||
|
|
|
@ -49,6 +49,7 @@
|
|||
in1[name] = 0
|
||||
in2[name] = 0
|
||||
in3[name] = 0
|
||||
out2[name] = 0
|
||||
out3[name] = 0
|
||||
for(i=3; i<NF; i++){
|
||||
if($i=="same" && $(i+1)=="as"){
|
||||
|
@ -70,6 +71,8 @@
|
|||
in2[name] = 1
|
||||
}else if(x=="in3"){
|
||||
in3[name] = 1
|
||||
}else if(x=="out2"){
|
||||
out2[name] = 1
|
||||
}else if(x=="out3"){
|
||||
out3[name] = 1
|
||||
}
|
||||
|
@ -125,13 +128,14 @@ END {
|
|||
name = order[i];
|
||||
x = op[name]
|
||||
a0 = a1 = a2 = a3 = a4 = a5 = a6 = a7 = 0
|
||||
# a8 = a9 = a10 = a11 = a12 = a13 = a14 = a15 = 0
|
||||
# a7 = a9 = a10 = a11 = a12 = a13 = a14 = a15 = 0
|
||||
if( jump[name] ) a0 = 1;
|
||||
if( out2_prerelease[name] ) a1 = 2;
|
||||
if( in1[name] ) a2 = 4;
|
||||
if( in2[name] ) a3 = 8;
|
||||
if( in3[name] ) a4 = 16;
|
||||
if( out3[name] ) a5 = 32;
|
||||
if( out2[name] ) a5 = 32;
|
||||
if( out3[name] ) a6 = 64;
|
||||
# bv[x] = a0+a1+a2+a3+a4+a5+a6+a7+a8+a9+a10+a11+a12+a13+a14+a15;
|
||||
bv[x] = a0+a1+a2+a3+a4+a5+a6+a7;
|
||||
}
|
||||
|
@ -145,7 +149,8 @@ END {
|
|||
print "#define OPFLG_IN1 0x0004 /* in1: P1 is an input */"
|
||||
print "#define OPFLG_IN2 0x0008 /* in2: P2 is an input */"
|
||||
print "#define OPFLG_IN3 0x0010 /* in3: P3 is an input */"
|
||||
print "#define OPFLG_OUT3 0x0020 /* out3: P3 is an output */"
|
||||
print "#define OPFLG_OUT2 0x0020 /* out2: P2 is an output */"
|
||||
print "#define OPFLG_OUT3 0x0040 /* out3: P3 is an output */"
|
||||
print "#define OPFLG_INITIALIZER {\\"
|
||||
for(i=0; i<=max; i++){
|
||||
if( i%8==0 ) printf("/* %3d */",i)
|
||||
|
|
|
@ -11,8 +11,6 @@
|
|||
*************************************************************************
|
||||
** This file contains C code routines that used to generate VDBE code
|
||||
** that implements the ALTER TABLE command.
|
||||
**
|
||||
** $Id: alter.c,v 1.62 2009/07/24 17:58:53 danielk1977 Exp $
|
||||
*/
|
||||
#include "sqliteInt.h"
|
||||
|
||||
|
|
|
@ -10,8 +10,6 @@
|
|||
**
|
||||
*************************************************************************
|
||||
** This file contains code associated with the ANALYZE command.
|
||||
**
|
||||
** @(#) $Id: analyze.c,v 1.52 2009/04/16 17:45:48 drh Exp $
|
||||
*/
|
||||
#ifndef SQLITE_OMIT_ANALYZE
|
||||
#include "sqliteInt.h"
|
||||
|
|
|
@ -10,8 +10,6 @@
|
|||
**
|
||||
*************************************************************************
|
||||
** This file contains code used to implement the ATTACH and DETACH commands.
|
||||
**
|
||||
** $Id: attach.c,v 1.93 2009/05/31 21:21:41 drh Exp $
|
||||
*/
|
||||
#include "sqliteInt.h"
|
||||
|
||||
|
|
|
@ -13,8 +13,6 @@
|
|||
** API. This facility is an optional feature of the library. Embedded
|
||||
** systems that do not need this facility may omit it by recompiling
|
||||
** the library with -DSQLITE_OMIT_AUTHORIZATION=1
|
||||
**
|
||||
** $Id: auth.c,v 1.32 2009/07/02 18:40:35 danielk1977 Exp $
|
||||
*/
|
||||
#include "sqliteInt.h"
|
||||
|
||||
|
|
|
@ -11,8 +11,6 @@
|
|||
*************************************************************************
|
||||
** This file contains the implementation of the sqlite3_backup_XXX()
|
||||
** API functions and the related features.
|
||||
**
|
||||
** $Id: backup.c,v 1.19 2009/07/06 19:03:13 drh Exp $
|
||||
*/
|
||||
#include "sqliteInt.h"
|
||||
#include "btreeInt.h"
|
||||
|
|
|
@ -33,8 +33,6 @@
|
|||
** Bitvec object is the number of pages in the database file at the
|
||||
** start of a transaction, and is thus usually less than a few thousand,
|
||||
** but can be as large as 2 billion for a really big database.
|
||||
**
|
||||
** @(#) $Id: bitvec.c,v 1.17 2009/07/25 17:33:26 drh Exp $
|
||||
*/
|
||||
#include "sqliteInt.h"
|
||||
|
||||
|
|
|
@ -10,8 +10,6 @@
|
|||
**
|
||||
*************************************************************************
|
||||
**
|
||||
** $Id: btmutex.c,v 1.17 2009/07/20 12:33:33 drh Exp $
|
||||
**
|
||||
** This file contains code used to implement mutexes on Btree objects.
|
||||
** This code really belongs in btree.c. But btree.c is getting too
|
||||
** big and we want to break it down some. This packaged seemed like
|
||||
|
|
70
src/btree.c
70
src/btree.c
|
@ -9,8 +9,6 @@
|
|||
** May you share freely, never taking more than you give.
|
||||
**
|
||||
*************************************************************************
|
||||
** $Id: btree.c,v 1.705 2009/08/10 03:57:58 shane Exp $
|
||||
**
|
||||
** This file implements a external (disk-based) database using BTrees.
|
||||
** See the header comment on "btreeInt.h" for additional information.
|
||||
** Including a description of file format and an overview of operation.
|
||||
|
@ -1145,6 +1143,7 @@ static int allocateSpace(MemPage *pPage, int nByte, int *pIdx){
|
|||
int top; /* First byte of cell content area */
|
||||
int gap; /* First byte of gap between cell pointers and cell content */
|
||||
int rc; /* Integer return code */
|
||||
int usableSize; /* Usable size of the page */
|
||||
|
||||
assert( sqlite3PagerIswriteable(pPage->pDbPage) );
|
||||
assert( pPage->pBt );
|
||||
|
@ -1152,7 +1151,8 @@ static int allocateSpace(MemPage *pPage, int nByte, int *pIdx){
|
|||
assert( nByte>=0 ); /* Minimum cell size is 4 */
|
||||
assert( pPage->nFree>=nByte );
|
||||
assert( pPage->nOverflow==0 );
|
||||
assert( nByte<pPage->pBt->usableSize-8 );
|
||||
usableSize = pPage->pBt->usableSize;
|
||||
assert( nByte < usableSize-8 );
|
||||
|
||||
nFrag = data[hdr+7];
|
||||
assert( pPage->cellOffset == hdr + 12 - 4*pPage->leaf );
|
||||
|
@ -1175,7 +1175,11 @@ static int allocateSpace(MemPage *pPage, int nByte, int *pIdx){
|
|||
*/
|
||||
int pc, addr;
|
||||
for(addr=hdr+1; (pc = get2byte(&data[addr]))>0; addr=pc){
|
||||
int size = get2byte(&data[pc+2]); /* Size of free slot */
|
||||
int size; /* Size of the free slot */
|
||||
if( pc>usableSize-4 || pc<addr+4 ){
|
||||
return SQLITE_CORRUPT_BKPT;
|
||||
}
|
||||
size = get2byte(&data[pc+2]);
|
||||
if( size>=nByte ){
|
||||
int x = size - nByte;
|
||||
testcase( x==4 );
|
||||
|
@ -1185,6 +1189,8 @@ static int allocateSpace(MemPage *pPage, int nByte, int *pIdx){
|
|||
** fragmented bytes within the page. */
|
||||
memcpy(&data[addr], &data[pc], 2);
|
||||
data[hdr+7] = (u8)(nFrag + x);
|
||||
}else if( size+pc > usableSize ){
|
||||
return SQLITE_CORRUPT_BKPT;
|
||||
}else{
|
||||
/* The slot remains on the free-list. Reduce its size to account
|
||||
** for the portion used by the new allocation. */
|
||||
|
@ -1477,7 +1483,9 @@ static void zeroPage(MemPage *pPage, int flags){
|
|||
assert( sqlite3PagerGetData(pPage->pDbPage) == data );
|
||||
assert( sqlite3PagerIswriteable(pPage->pDbPage) );
|
||||
assert( sqlite3_mutex_held(pBt->mutex) );
|
||||
/*memset(&data[hdr], 0, pBt->usableSize - hdr);*/
|
||||
#ifdef SQLITE_SECURE_DELETE
|
||||
memset(&data[hdr], 0, pBt->usableSize - hdr);
|
||||
#endif
|
||||
data[hdr] = (char)flags;
|
||||
first = hdr + 8 + 4*((flags&PTF_LEAF)==0 ?1:0);
|
||||
memset(&data[hdr+1], 0, 4);
|
||||
|
@ -1606,7 +1614,6 @@ static int getAndInitPage(
|
|||
*/
|
||||
static void releasePage(MemPage *pPage){
|
||||
if( pPage ){
|
||||
assert( pPage->nOverflow==0 || sqlite3PagerPageRefcount(pPage->pDbPage)>1 );
|
||||
assert( pPage->aData );
|
||||
assert( pPage->pBt );
|
||||
assert( sqlite3PagerGetExtra(pPage->pDbPage) == (void*)pPage );
|
||||
|
@ -2346,11 +2353,8 @@ static int newDatabase(BtShared *pBt){
|
|||
int nPage;
|
||||
|
||||
assert( sqlite3_mutex_held(pBt->mutex) );
|
||||
/* The database size has already been measured and cached, so failure
|
||||
** is impossible here. If the original size measurement failed, then
|
||||
** processing aborts before entering this routine. */
|
||||
rc = sqlite3PagerPagecount(pBt->pPager, &nPage);
|
||||
if( NEVER(rc!=SQLITE_OK) || nPage>0 ){
|
||||
if( rc!=SQLITE_OK || nPage>0 ){
|
||||
return rc;
|
||||
}
|
||||
pP1 = pBt->pPage1;
|
||||
|
@ -3280,8 +3284,8 @@ int sqlite3BtreeSavepoint(Btree *p, int op, int iSavepoint){
|
|||
** root page of a b-tree. If it is not, then the cursor acquired
|
||||
** will not work correctly.
|
||||
**
|
||||
** It is assumed that the sqlite3BtreeCursorSize() bytes of memory
|
||||
** pointed to by pCur have been zeroed by the caller.
|
||||
** It is assumed that the sqlite3BtreeCursorZero() has been called
|
||||
** on pCur to initialize the memory space prior to invoking this routine.
|
||||
*/
|
||||
static int btreeCursor(
|
||||
Btree *p, /* The btree */
|
||||
|
@ -3354,7 +3358,19 @@ int sqlite3BtreeCursor(
|
|||
** this routine.
|
||||
*/
|
||||
int sqlite3BtreeCursorSize(void){
|
||||
return sizeof(BtCursor);
|
||||
return ROUND8(sizeof(BtCursor));
|
||||
}
|
||||
|
||||
/*
|
||||
** Initialize memory that will be converted into a BtCursor object.
|
||||
**
|
||||
** The simple approach here would be to memset() the entire object
|
||||
** to zero. But it turns out that the apPage[] and aiIdx[] arrays
|
||||
** do not need to be zeroed and they are large, so we can save a lot
|
||||
** of run-time by skipping the initialization of those elements.
|
||||
*/
|
||||
void sqlite3BtreeCursorZero(BtCursor *p){
|
||||
memset(p, 0, offsetof(BtCursor, iPage));
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -5286,8 +5302,13 @@ static void insertCell(
|
|||
assert( i>=0 && i<=pPage->nCell+pPage->nOverflow );
|
||||
assert( pPage->nCell<=MX_CELL(pPage->pBt) && MX_CELL(pPage->pBt)<=5460 );
|
||||
assert( pPage->nOverflow<=ArraySize(pPage->aOvfl) );
|
||||
assert( sz==cellSizePtr(pPage, pCell) );
|
||||
assert( sqlite3_mutex_held(pPage->pBt->mutex) );
|
||||
/* The cell should normally be sized correctly. However, when moving a
|
||||
** malformed cell from a leaf page to an interior page, if the cell size
|
||||
** wanted to be less than 4 but got rounded up to 4 on the leaf, then size
|
||||
** might be less than 8 (leaf-size + pointer) on the interior node. Hence
|
||||
** the term after the || in the following assert(). */
|
||||
assert( sz==cellSizePtr(pPage, pCell) || (sz==8 && iChild>0) );
|
||||
if( pPage->nOverflow || sz+2>pPage->nFree ){
|
||||
if( pTemp ){
|
||||
memcpy(pTemp+nSkip, pCell+nSkip, sz-nSkip);
|
||||
|
@ -5566,7 +5587,7 @@ static void copyNodeContent(MemPage *pFrom, MemPage *pTo, int *pRC){
|
|||
u8 * const aTo = pTo->aData;
|
||||
int const iFromHdr = pFrom->hdrOffset;
|
||||
int const iToHdr = ((pTo->pgno==1) ? 100 : 0);
|
||||
TESTONLY(int rc;)
|
||||
int rc;
|
||||
int iData;
|
||||
|
||||
|
||||
|
@ -5580,11 +5601,16 @@ static void copyNodeContent(MemPage *pFrom, MemPage *pTo, int *pRC){
|
|||
memcpy(&aTo[iToHdr], &aFrom[iFromHdr], pFrom->cellOffset + 2*pFrom->nCell);
|
||||
|
||||
/* Reinitialize page pTo so that the contents of the MemPage structure
|
||||
** match the new data. The initialization of pTo "cannot" fail, as the
|
||||
** data copied from pFrom is known to be valid. */
|
||||
** match the new data. The initialization of pTo can actually fail under
|
||||
** fairly obscure circumstances, even though it is a copy of initialized
|
||||
** page pFrom.
|
||||
*/
|
||||
pTo->isInit = 0;
|
||||
TESTONLY(rc = ) btreeInitPage(pTo);
|
||||
assert( rc==SQLITE_OK );
|
||||
rc = btreeInitPage(pTo);
|
||||
if( rc!=SQLITE_OK ){
|
||||
*pRC = rc;
|
||||
return;
|
||||
}
|
||||
|
||||
/* If this is an auto-vacuum database, update the pointer-map entries
|
||||
** for any b-tree or overflow pages that pTo now contains the pointers to.
|
||||
|
@ -6845,9 +6871,9 @@ int sqlite3BtreeCreateTable(Btree *p, int *piTable, int flags){
|
|||
*/
|
||||
static int clearDatabasePage(
|
||||
BtShared *pBt, /* The BTree that contains the table */
|
||||
Pgno pgno, /* Page number to clear */
|
||||
int freePageFlag, /* Deallocate page if true */
|
||||
int *pnChange
|
||||
Pgno pgno, /* Page number to clear */
|
||||
int freePageFlag, /* Deallocate page if true */
|
||||
int *pnChange /* Add number of Cells freed to this counter */
|
||||
){
|
||||
MemPage *pPage;
|
||||
int rc;
|
||||
|
|
|
@ -12,8 +12,6 @@
|
|||
** This header file defines the interface that the sqlite B-Tree file
|
||||
** subsystem. See comments in the source code for a detailed description
|
||||
** of what each interface routine does.
|
||||
**
|
||||
** @(#) $Id: btree.h,v 1.120 2009/07/22 00:35:24 drh Exp $
|
||||
*/
|
||||
#ifndef _BTREE_H_
|
||||
#define _BTREE_H_
|
||||
|
@ -150,6 +148,7 @@ int sqlite3BtreeCursor(
|
|||
BtCursor *pCursor /* Space to write cursor structure */
|
||||
);
|
||||
int sqlite3BtreeCursorSize(void);
|
||||
void sqlite3BtreeCursorZero(BtCursor*);
|
||||
|
||||
int sqlite3BtreeCloseCursor(BtCursor*);
|
||||
int sqlite3BtreeMovetoUnpacked(
|
||||
|
|
|
@ -9,8 +9,6 @@
|
|||
** May you share freely, never taking more than you give.
|
||||
**
|
||||
*************************************************************************
|
||||
** $Id: btreeInt.h,v 1.52 2009/07/15 17:25:46 drh Exp $
|
||||
**
|
||||
** This file implements a external (disk-based) database using BTrees.
|
||||
** For a detailed discussion of BTrees, refer to
|
||||
**
|
||||
|
|
|
@ -21,8 +21,6 @@
|
|||
** BEGIN TRANSACTION
|
||||
** COMMIT
|
||||
** ROLLBACK
|
||||
**
|
||||
** $Id: build.c,v 1.557 2009/07/24 17:58:53 danielk1977 Exp $
|
||||
*/
|
||||
#include "sqliteInt.h"
|
||||
|
||||
|
|
|
@ -12,8 +12,6 @@
|
|||
**
|
||||
** This file contains functions used to access the internal hash tables
|
||||
** of user defined functions and collation sequences.
|
||||
**
|
||||
** $Id: callback.c,v 1.42 2009/06/17 00:35:31 drh Exp $
|
||||
*/
|
||||
|
||||
#include "sqliteInt.h"
|
||||
|
|
|
@ -15,8 +15,6 @@
|
|||
** This code used to be part of the tokenizer.c source file. But by
|
||||
** separating it out, the code will be automatically omitted from
|
||||
** static links that do not use it.
|
||||
**
|
||||
** $Id: complete.c,v 1.8 2009/04/28 04:46:42 drh Exp $
|
||||
*/
|
||||
#include "sqliteInt.h"
|
||||
#ifndef SQLITE_OMIT_COMPLETE
|
||||
|
@ -26,8 +24,7 @@
|
|||
*/
|
||||
#ifndef SQLITE_AMALGAMATION
|
||||
#ifdef SQLITE_ASCII
|
||||
extern const char sqlite3IsAsciiIdChar[];
|
||||
#define IdChar(C) (((c=C)&0x80)!=0 || (c>0x1f && sqlite3IsAsciiIdChar[c-0x20]))
|
||||
#define IdChar(C) ((sqlite3CtypeMap[(unsigned char)C]&0x46)!=0)
|
||||
#endif
|
||||
#ifdef SQLITE_EBCDIC
|
||||
extern const char sqlite3IsEbcdicIdChar[];
|
||||
|
@ -184,7 +181,9 @@ int sqlite3_complete(const char *zSql){
|
|||
break;
|
||||
}
|
||||
default: {
|
||||
int c;
|
||||
#ifdef SQLITE_EBCDIC
|
||||
unsigned char c;
|
||||
#endif
|
||||
if( IdChar((u8)*zSql) ){
|
||||
/* Keywords and unquoted identifiers */
|
||||
int nId;
|
||||
|
|
|
@ -16,8 +16,6 @@
|
|||
** sqlite3RegisterDateTimeFunctions() found at the bottom of the file.
|
||||
** All other code has file scope.
|
||||
**
|
||||
** $Id: date.c,v 1.107 2009/05/03 20:23:53 drh Exp $
|
||||
**
|
||||
** SQLite processes all times and dates as Julian Day numbers. The
|
||||
** dates and times are stored as the number of days since noon
|
||||
** in Greenwich on November 24, 4714 B.C. according to the Gregorian
|
||||
|
|
|
@ -11,8 +11,6 @@
|
|||
*************************************************************************
|
||||
** This file contains C code routines that are called by the parser
|
||||
** in order to generate code for DELETE FROM statements.
|
||||
**
|
||||
** $Id: delete.c,v 1.207 2009/08/08 18:01:08 drh Exp $
|
||||
*/
|
||||
#include "sqliteInt.h"
|
||||
|
||||
|
@ -498,7 +496,9 @@ void sqlite3GenerateRowDelete(
|
|||
|
||||
/* TODO: Could use temporary registers here. Also could attempt to
|
||||
** avoid copying the contents of the rowid register. */
|
||||
mask = sqlite3TriggerOldmask(pParse, pTrigger, 0, pTab, onconf);
|
||||
mask = sqlite3TriggerColmask(
|
||||
pParse, pTrigger, 0, 0, TRIGGER_BEFORE|TRIGGER_AFTER, pTab, onconf
|
||||
);
|
||||
mask |= sqlite3FkOldmask(pParse, pTab);
|
||||
iOld = pParse->nMem+1;
|
||||
pParse->nMem += (1 + pTab->nCol);
|
||||
|
@ -635,4 +635,3 @@ int sqlite3GenerateIndexKey(
|
|||
sqlite3ReleaseTempRange(pParse, regBase, nCol+1);
|
||||
return regBase;
|
||||
}
|
||||
|
||||
|
|
491
src/expr.c
491
src/expr.c
|
@ -627,11 +627,10 @@ void sqlite3ExprAssignVarNumber(Parse *pParse, Expr *pExpr){
|
|||
}
|
||||
|
||||
/*
|
||||
** Clear an expression structure without deleting the structure itself.
|
||||
** Substructure is deleted.
|
||||
** Recursively delete an expression tree.
|
||||
*/
|
||||
void sqlite3ExprClear(sqlite3 *db, Expr *p){
|
||||
assert( p!=0 );
|
||||
void sqlite3ExprDelete(sqlite3 *db, Expr *p){
|
||||
if( p==0 ) return;
|
||||
if( !ExprHasAnyProperty(p, EP_TokenOnly) ){
|
||||
sqlite3ExprDelete(db, p->pLeft);
|
||||
sqlite3ExprDelete(db, p->pRight);
|
||||
|
@ -644,14 +643,6 @@ void sqlite3ExprClear(sqlite3 *db, Expr *p){
|
|||
sqlite3ExprListDelete(db, p->x.pList);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
** Recursively delete an expression tree.
|
||||
*/
|
||||
void sqlite3ExprDelete(sqlite3 *db, Expr *p){
|
||||
if( p==0 ) return;
|
||||
sqlite3ExprClear(db, p);
|
||||
if( !ExprHasProperty(p, EP_Static) ){
|
||||
sqlite3DbFree(db, p);
|
||||
}
|
||||
|
@ -1258,6 +1249,94 @@ int sqlite3ExprIsInteger(Expr *p, int *pValue){
|
|||
return rc;
|
||||
}
|
||||
|
||||
/*
|
||||
** Return FALSE if there is no chance that the expression can be NULL.
|
||||
**
|
||||
** If the expression might be NULL or if the expression is too complex
|
||||
** to tell return TRUE.
|
||||
**
|
||||
** This routine is used as an optimization, to skip OP_IsNull opcodes
|
||||
** when we know that a value cannot be NULL. Hence, a false positive
|
||||
** (returning TRUE when in fact the expression can never be NULL) might
|
||||
** be a small performance hit but is otherwise harmless. On the other
|
||||
** hand, a false negative (returning FALSE when the result could be NULL)
|
||||
** will likely result in an incorrect answer. So when in doubt, return
|
||||
** TRUE.
|
||||
*/
|
||||
int sqlite3ExprCanBeNull(const Expr *p){
|
||||
u8 op;
|
||||
while( p->op==TK_UPLUS || p->op==TK_UMINUS ){ p = p->pLeft; }
|
||||
op = p->op;
|
||||
if( op==TK_REGISTER ) op = p->op2;
|
||||
switch( op ){
|
||||
case TK_INTEGER:
|
||||
case TK_STRING:
|
||||
case TK_FLOAT:
|
||||
case TK_BLOB:
|
||||
return 0;
|
||||
default:
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
** Generate an OP_IsNull instruction that tests register iReg and jumps
|
||||
** to location iDest if the value in iReg is NULL. The value in iReg
|
||||
** was computed by pExpr. If we can look at pExpr at compile-time and
|
||||
** determine that it can never generate a NULL, then the OP_IsNull operation
|
||||
** can be omitted.
|
||||
*/
|
||||
void sqlite3ExprCodeIsNullJump(
|
||||
Vdbe *v, /* The VDBE under construction */
|
||||
const Expr *pExpr, /* Only generate OP_IsNull if this expr can be NULL */
|
||||
int iReg, /* Test the value in this register for NULL */
|
||||
int iDest /* Jump here if the value is null */
|
||||
){
|
||||
if( sqlite3ExprCanBeNull(pExpr) ){
|
||||
sqlite3VdbeAddOp2(v, OP_IsNull, iReg, iDest);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
** Return TRUE if the given expression is a constant which would be
|
||||
** unchanged by OP_Affinity with the affinity given in the second
|
||||
** argument.
|
||||
**
|
||||
** This routine is used to determine if the OP_Affinity operation
|
||||
** can be omitted. When in doubt return FALSE. A false negative
|
||||
** is harmless. A false positive, however, can result in the wrong
|
||||
** answer.
|
||||
*/
|
||||
int sqlite3ExprNeedsNoAffinityChange(const Expr *p, char aff){
|
||||
u8 op;
|
||||
if( aff==SQLITE_AFF_NONE ) return 1;
|
||||
while( p->op==TK_UPLUS || p->op==TK_UMINUS ){ p = p->pLeft; }
|
||||
op = p->op;
|
||||
if( op==TK_REGISTER ) op = p->op2;
|
||||
switch( op ){
|
||||
case TK_INTEGER: {
|
||||
return aff==SQLITE_AFF_INTEGER || aff==SQLITE_AFF_NUMERIC;
|
||||
}
|
||||
case TK_FLOAT: {
|
||||
return aff==SQLITE_AFF_REAL || aff==SQLITE_AFF_NUMERIC;
|
||||
}
|
||||
case TK_STRING: {
|
||||
return aff==SQLITE_AFF_TEXT;
|
||||
}
|
||||
case TK_BLOB: {
|
||||
return 1;
|
||||
}
|
||||
case TK_COLUMN: {
|
||||
assert( p->iTable>=0 ); /* p cannot be part of a CHECK constraint */
|
||||
return p->iColumn<0
|
||||
&& (aff==SQLITE_AFF_INTEGER || aff==SQLITE_AFF_NUMERIC);
|
||||
}
|
||||
default: {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
** Return TRUE if the given string is a row-id column name.
|
||||
*/
|
||||
|
@ -1345,16 +1424,16 @@ static int isCandidateForInOpt(Select *p){
|
|||
** When the b-tree is being used for membership tests, the calling function
|
||||
** needs to know whether or not the structure contains an SQL NULL
|
||||
** value in order to correctly evaluate expressions like "X IN (Y, Z)".
|
||||
** If there is a chance that the b-tree might contain a NULL value at
|
||||
** If there is any chance that the (...) might contain a NULL value at
|
||||
** runtime, then a register is allocated and the register number written
|
||||
** to *prNotFound. If there is no chance that the b-tree contains a
|
||||
** to *prNotFound. If there is no chance that the (...) contains a
|
||||
** NULL value, then *prNotFound is left unchanged.
|
||||
**
|
||||
** If a register is allocated and its location stored in *prNotFound, then
|
||||
** its initial value is NULL. If the b-tree does not remain constant
|
||||
** for the duration of the query (i.e. the SELECT that generates the b-tree
|
||||
** its initial value is NULL. If the (...) does not remain constant
|
||||
** for the duration of the query (i.e. the SELECT within the (...)
|
||||
** is a correlated subquery) then the value of the allocated register is
|
||||
** reset to NULL each time the b-tree is repopulated. This allows the
|
||||
** reset to NULL each time the subquery is rerun. This allows the
|
||||
** caller to use vdbe code equivalent to the following:
|
||||
**
|
||||
** if( register==NULL ){
|
||||
|
@ -1546,7 +1625,7 @@ int sqlite3CodeSubselect(
|
|||
affinity = sqlite3ExprAffinity(pLeft);
|
||||
|
||||
/* Whether this is an 'x IN(SELECT...)' or an 'x IN(<exprlist>)'
|
||||
** expression it is handled the same way. A virtual table is
|
||||
** expression it is handled the same way. An ephemeral table is
|
||||
** filled with single-field index keys representing the results
|
||||
** from the SELECT or the <exprlist>.
|
||||
**
|
||||
|
@ -1694,6 +1773,128 @@ int sqlite3CodeSubselect(
|
|||
}
|
||||
#endif /* SQLITE_OMIT_SUBQUERY */
|
||||
|
||||
#ifndef SQLITE_OMIT_SUBQUERY
|
||||
/*
|
||||
** Generate code for an IN expression.
|
||||
**
|
||||
** x IN (SELECT ...)
|
||||
** x IN (value, value, ...)
|
||||
**
|
||||
** The left-hand side (LHS) is a scalar expression. The right-hand side (RHS)
|
||||
** is an array of zero or more values. The expression is true if the LHS is
|
||||
** contained within the RHS. The value of the expression is unknown (NULL)
|
||||
** if the LHS is NULL or if the LHS is not contained within the RHS and the
|
||||
** RHS contains one or more NULL values.
|
||||
**
|
||||
** This routine generates code will jump to destIfFalse if the LHS is not
|
||||
** contained within the RHS. If due to NULLs we cannot determine if the LHS
|
||||
** is contained in the RHS then jump to destIfNull. If the LHS is contained
|
||||
** within the RHS then fall through.
|
||||
*/
|
||||
static void sqlite3ExprCodeIN(
|
||||
Parse *pParse, /* Parsing and code generating context */
|
||||
Expr *pExpr, /* The IN expression */
|
||||
int destIfFalse, /* Jump here if LHS is not contained in the RHS */
|
||||
int destIfNull /* Jump here if the results are unknown due to NULLs */
|
||||
){
|
||||
int rRhsHasNull = 0; /* Register that is true if RHS contains NULL values */
|
||||
char affinity; /* Comparison affinity to use */
|
||||
int eType; /* Type of the RHS */
|
||||
int r1; /* Temporary use register */
|
||||
Vdbe *v; /* Statement under construction */
|
||||
|
||||
/* Compute the RHS. After this step, the table with cursor
|
||||
** pExpr->iTable will contains the values that make up the RHS.
|
||||
*/
|
||||
v = pParse->pVdbe;
|
||||
assert( v!=0 ); /* OOM detected prior to this routine */
|
||||
VdbeNoopComment((v, "begin IN expr"));
|
||||
eType = sqlite3FindInIndex(pParse, pExpr, &rRhsHasNull);
|
||||
|
||||
/* Figure out the affinity to use to create a key from the results
|
||||
** of the expression. affinityStr stores a static string suitable for
|
||||
** P4 of OP_MakeRecord.
|
||||
*/
|
||||
affinity = comparisonAffinity(pExpr);
|
||||
|
||||
/* Code the LHS, the <expr> from "<expr> IN (...)".
|
||||
*/
|
||||
sqlite3ExprCachePush(pParse);
|
||||
r1 = sqlite3GetTempReg(pParse);
|
||||
sqlite3ExprCode(pParse, pExpr->pLeft, r1);
|
||||
sqlite3VdbeAddOp2(v, OP_IsNull, r1, destIfNull);
|
||||
|
||||
|
||||
if( eType==IN_INDEX_ROWID ){
|
||||
/* In this case, the RHS is the ROWID of table b-tree
|
||||
*/
|
||||
sqlite3VdbeAddOp2(v, OP_MustBeInt, r1, destIfFalse);
|
||||
sqlite3VdbeAddOp3(v, OP_NotExists, pExpr->iTable, destIfFalse, r1);
|
||||
}else{
|
||||
/* In this case, the RHS is an index b-tree.
|
||||
*/
|
||||
sqlite3VdbeAddOp4(v, OP_Affinity, r1, 1, 0, &affinity, 1);
|
||||
|
||||
/* If the set membership test fails, then the result of the
|
||||
** "x IN (...)" expression must be either 0 or NULL. If the set
|
||||
** contains no NULL values, then the result is 0. If the set
|
||||
** contains one or more NULL values, then the result of the
|
||||
** expression is also NULL.
|
||||
*/
|
||||
if( rRhsHasNull==0 || destIfFalse==destIfNull ){
|
||||
/* This branch runs if it is known at compile time that the RHS
|
||||
** cannot contain NULL values. This happens as the result
|
||||
** of a "NOT NULL" constraint in the database schema.
|
||||
**
|
||||
** Also run this branch if NULL is equivalent to FALSE
|
||||
** for this particular IN operator.
|
||||
*/
|
||||
sqlite3VdbeAddOp4Int(v, OP_NotFound, pExpr->iTable, destIfFalse, r1, 1);
|
||||
|
||||
}else{
|
||||
/* In this branch, the RHS of the IN might contain a NULL and
|
||||
** the presence of a NULL on the RHS makes a difference in the
|
||||
** outcome.
|
||||
*/
|
||||
int j1, j2, j3;
|
||||
|
||||
/* First check to see if the LHS is contained in the RHS. If so,
|
||||
** then the presence of NULLs in the RHS does not matter, so jump
|
||||
** over all of the code that follows.
|
||||
*/
|
||||
j1 = sqlite3VdbeAddOp4Int(v, OP_Found, pExpr->iTable, 0, r1, 1);
|
||||
|
||||
/* Here we begin generating code that runs if the LHS is not
|
||||
** contained within the RHS. Generate additional code that
|
||||
** tests the RHS for NULLs. If the RHS contains a NULL then
|
||||
** jump to destIfNull. If there are no NULLs in the RHS then
|
||||
** jump to destIfFalse.
|
||||
*/
|
||||
j2 = sqlite3VdbeAddOp1(v, OP_NotNull, rRhsHasNull);
|
||||
j3 = sqlite3VdbeAddOp4Int(v, OP_Found, pExpr->iTable, 0, rRhsHasNull, 1);
|
||||
sqlite3VdbeAddOp2(v, OP_Integer, -1, rRhsHasNull);
|
||||
sqlite3VdbeJumpHere(v, j3);
|
||||
sqlite3VdbeAddOp2(v, OP_AddImm, rRhsHasNull, 1);
|
||||
sqlite3VdbeJumpHere(v, j2);
|
||||
|
||||
/* Jump to the appropriate target depending on whether or not
|
||||
** the RHS contains a NULL
|
||||
*/
|
||||
sqlite3VdbeAddOp2(v, OP_If, rRhsHasNull, destIfNull);
|
||||
sqlite3VdbeAddOp2(v, OP_Goto, 0, destIfFalse);
|
||||
|
||||
/* The OP_Found at the top of this branch jumps here when true,
|
||||
** causing the overall IN expression evaluation to fall through.
|
||||
*/
|
||||
sqlite3VdbeJumpHere(v, j1);
|
||||
}
|
||||
}
|
||||
sqlite3ReleaseTempReg(pParse, r1);
|
||||
sqlite3ExprCachePop(pParse, 1);
|
||||
VdbeComment((v, "end IN expr"));
|
||||
}
|
||||
#endif /* SQLITE_OMIT_SUBQUERY */
|
||||
|
||||
/*
|
||||
** Duplicate an 8-byte value
|
||||
*/
|
||||
|
@ -2394,6 +2595,27 @@ int sqlite3ExprCodeTarget(Parse *pParse, Expr *pExpr, int target){
|
|||
sqlite3ErrorMsg(pParse, "unknown function: %.*s()", nId, zId);
|
||||
break;
|
||||
}
|
||||
|
||||
/* Attempt a direct implementation of the built-in COALESCE() and
|
||||
** IFNULL() functions. This avoids unnecessary evalation of
|
||||
** arguments past the first non-NULL argument.
|
||||
*/
|
||||
if( pDef->flags & SQLITE_FUNC_COALESCE ){
|
||||
int endCoalesce = sqlite3VdbeMakeLabel(v);
|
||||
assert( nFarg>=2 );
|
||||
sqlite3ExprCode(pParse, pFarg->a[0].pExpr, target);
|
||||
for(i=1; i<nFarg; i++){
|
||||
sqlite3VdbeAddOp2(v, OP_NotNull, target, endCoalesce);
|
||||
sqlite3ExprCacheRemove(pParse, target);
|
||||
sqlite3ExprCachePush(pParse);
|
||||
sqlite3ExprCode(pParse, pFarg->a[i].pExpr, target);
|
||||
sqlite3ExprCachePop(pParse, 1);
|
||||
}
|
||||
sqlite3VdbeResolveLabel(v, endCoalesce);
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
if( pFarg ){
|
||||
r1 = sqlite3GetTempRange(pParse, nFarg);
|
||||
sqlite3ExprCachePush(pParse); /* Ticket 2ea2425d34be */
|
||||
|
@ -2451,95 +2673,19 @@ int sqlite3ExprCodeTarget(Parse *pParse, Expr *pExpr, int target){
|
|||
break;
|
||||
}
|
||||
case TK_IN: {
|
||||
int rNotFound = 0;
|
||||
int rMayHaveNull = 0;
|
||||
int j2, j3, j4, j5;
|
||||
char affinity;
|
||||
int eType;
|
||||
|
||||
VdbeNoopComment((v, "begin IN expr r%d", target));
|
||||
eType = sqlite3FindInIndex(pParse, pExpr, &rMayHaveNull);
|
||||
if( rMayHaveNull ){
|
||||
rNotFound = ++pParse->nMem;
|
||||
}
|
||||
|
||||
/* Figure out the affinity to use to create a key from the results
|
||||
** of the expression. affinityStr stores a static string suitable for
|
||||
** P4 of OP_MakeRecord.
|
||||
*/
|
||||
affinity = comparisonAffinity(pExpr);
|
||||
|
||||
|
||||
/* Code the <expr> from "<expr> IN (...)". The temporary table
|
||||
** pExpr->iTable contains the values that make up the (...) set.
|
||||
*/
|
||||
sqlite3ExprCachePush(pParse);
|
||||
sqlite3ExprCode(pParse, pExpr->pLeft, target);
|
||||
j2 = sqlite3VdbeAddOp1(v, OP_IsNull, target);
|
||||
if( eType==IN_INDEX_ROWID ){
|
||||
j3 = sqlite3VdbeAddOp1(v, OP_MustBeInt, target);
|
||||
j4 = sqlite3VdbeAddOp3(v, OP_NotExists, pExpr->iTable, 0, target);
|
||||
sqlite3VdbeAddOp2(v, OP_Integer, 1, target);
|
||||
j5 = sqlite3VdbeAddOp0(v, OP_Goto);
|
||||
sqlite3VdbeJumpHere(v, j3);
|
||||
sqlite3VdbeJumpHere(v, j4);
|
||||
sqlite3VdbeAddOp2(v, OP_Integer, 0, target);
|
||||
}else{
|
||||
r2 = regFree2 = sqlite3GetTempReg(pParse);
|
||||
|
||||
/* Create a record and test for set membership. If the set contains
|
||||
** the value, then jump to the end of the test code. The target
|
||||
** register still contains the true (1) value written to it earlier.
|
||||
*/
|
||||
sqlite3VdbeAddOp4(v, OP_MakeRecord, target, 1, r2, &affinity, 1);
|
||||
sqlite3VdbeAddOp2(v, OP_Integer, 1, target);
|
||||
j5 = sqlite3VdbeAddOp3(v, OP_Found, pExpr->iTable, 0, r2);
|
||||
|
||||
/* If the set membership test fails, then the result of the
|
||||
** "x IN (...)" expression must be either 0 or NULL. If the set
|
||||
** contains no NULL values, then the result is 0. If the set
|
||||
** contains one or more NULL values, then the result of the
|
||||
** expression is also NULL.
|
||||
*/
|
||||
if( rNotFound==0 ){
|
||||
/* This branch runs if it is known at compile time (now) that
|
||||
** the set contains no NULL values. This happens as the result
|
||||
** of a "NOT NULL" constraint in the database schema. No need
|
||||
** to test the data structure at runtime in this case.
|
||||
*/
|
||||
sqlite3VdbeAddOp2(v, OP_Integer, 0, target);
|
||||
}else{
|
||||
/* This block populates the rNotFound register with either NULL
|
||||
** or 0 (an integer value). If the data structure contains one
|
||||
** or more NULLs, then set rNotFound to NULL. Otherwise, set it
|
||||
** to 0. If register rMayHaveNull is already set to some value
|
||||
** other than NULL, then the test has already been run and
|
||||
** rNotFound is already populated.
|
||||
*/
|
||||
static const char nullRecord[] = { 0x02, 0x00 };
|
||||
j3 = sqlite3VdbeAddOp1(v, OP_NotNull, rMayHaveNull);
|
||||
sqlite3VdbeAddOp2(v, OP_Null, 0, rNotFound);
|
||||
sqlite3VdbeAddOp4(v, OP_Blob, 2, rMayHaveNull, 0,
|
||||
nullRecord, P4_STATIC);
|
||||
j4 = sqlite3VdbeAddOp3(v, OP_Found, pExpr->iTable, 0, rMayHaveNull);
|
||||
sqlite3VdbeAddOp2(v, OP_Integer, 0, rNotFound);
|
||||
sqlite3VdbeJumpHere(v, j4);
|
||||
sqlite3VdbeJumpHere(v, j3);
|
||||
|
||||
/* Copy the value of register rNotFound (which is either NULL or 0)
|
||||
** into the target register. This will be the result of the
|
||||
** expression.
|
||||
*/
|
||||
sqlite3VdbeAddOp2(v, OP_Copy, rNotFound, target);
|
||||
}
|
||||
}
|
||||
sqlite3VdbeJumpHere(v, j2);
|
||||
sqlite3VdbeJumpHere(v, j5);
|
||||
sqlite3ExprCachePop(pParse, 1);
|
||||
VdbeComment((v, "end IN expr r%d", target));
|
||||
int destIfFalse = sqlite3VdbeMakeLabel(v);
|
||||
int destIfNull = sqlite3VdbeMakeLabel(v);
|
||||
sqlite3VdbeAddOp2(v, OP_Null, 0, target);
|
||||
sqlite3ExprCodeIN(pParse, pExpr, destIfFalse, destIfNull);
|
||||
sqlite3VdbeAddOp2(v, OP_Integer, 1, target);
|
||||
sqlite3VdbeResolveLabel(v, destIfFalse);
|
||||
sqlite3VdbeAddOp2(v, OP_AddImm, target, 0);
|
||||
sqlite3VdbeResolveLabel(v, destIfNull);
|
||||
break;
|
||||
}
|
||||
#endif
|
||||
#endif /* SQLITE_OMIT_SUBQUERY */
|
||||
|
||||
|
||||
/*
|
||||
** x BETWEEN y AND z
|
||||
**
|
||||
|
@ -2970,6 +3116,62 @@ int sqlite3ExprCodeExprList(
|
|||
return n;
|
||||
}
|
||||
|
||||
/*
|
||||
** Generate code for a BETWEEN operator.
|
||||
**
|
||||
** x BETWEEN y AND z
|
||||
**
|
||||
** The above is equivalent to
|
||||
**
|
||||
** x>=y AND x<=z
|
||||
**
|
||||
** Code it as such, taking care to do the common subexpression
|
||||
** elementation of x.
|
||||
*/
|
||||
static void exprCodeBetween(
|
||||
Parse *pParse, /* Parsing and code generating context */
|
||||
Expr *pExpr, /* The BETWEEN expression */
|
||||
int dest, /* Jump here if the jump is taken */
|
||||
int jumpIfTrue, /* Take the jump if the BETWEEN is true */
|
||||
int jumpIfNull /* Take the jump if the BETWEEN is NULL */
|
||||
){
|
||||
Expr exprAnd; /* The AND operator in x>=y AND x<=z */
|
||||
Expr compLeft; /* The x>=y term */
|
||||
Expr compRight; /* The x<=z term */
|
||||
Expr exprX; /* The x subexpression */
|
||||
int regFree1 = 0; /* Temporary use register */
|
||||
|
||||
assert( !ExprHasProperty(pExpr, EP_xIsSelect) );
|
||||
exprX = *pExpr->pLeft;
|
||||
exprAnd.op = TK_AND;
|
||||
exprAnd.pLeft = &compLeft;
|
||||
exprAnd.pRight = &compRight;
|
||||
compLeft.op = TK_GE;
|
||||
compLeft.pLeft = &exprX;
|
||||
compLeft.pRight = pExpr->x.pList->a[0].pExpr;
|
||||
compRight.op = TK_LE;
|
||||
compRight.pLeft = &exprX;
|
||||
compRight.pRight = pExpr->x.pList->a[1].pExpr;
|
||||
exprX.iTable = sqlite3ExprCodeTemp(pParse, &exprX, ®Free1);
|
||||
exprX.op = TK_REGISTER;
|
||||
if( jumpIfTrue ){
|
||||
sqlite3ExprIfTrue(pParse, &exprAnd, dest, jumpIfNull);
|
||||
}else{
|
||||
sqlite3ExprIfFalse(pParse, &exprAnd, dest, jumpIfNull);
|
||||
}
|
||||
sqlite3ReleaseTempReg(pParse, regFree1);
|
||||
|
||||
/* Ensure adequate test coverage */
|
||||
testcase( jumpIfTrue==0 && jumpIfNull==0 && regFree1==0 );
|
||||
testcase( jumpIfTrue==0 && jumpIfNull==0 && regFree1!=0 );
|
||||
testcase( jumpIfTrue==0 && jumpIfNull!=0 && regFree1==0 );
|
||||
testcase( jumpIfTrue==0 && jumpIfNull!=0 && regFree1!=0 );
|
||||
testcase( jumpIfTrue!=0 && jumpIfNull==0 && regFree1==0 );
|
||||
testcase( jumpIfTrue!=0 && jumpIfNull==0 && regFree1!=0 );
|
||||
testcase( jumpIfTrue!=0 && jumpIfNull!=0 && regFree1==0 );
|
||||
testcase( jumpIfTrue!=0 && jumpIfNull!=0 && regFree1!=0 );
|
||||
}
|
||||
|
||||
/*
|
||||
** Generate code for a boolean expression such that a jump is made
|
||||
** to the label "dest" if the expression is true but execution
|
||||
|
@ -3069,36 +3271,16 @@ void sqlite3ExprIfTrue(Parse *pParse, Expr *pExpr, int dest, int jumpIfNull){
|
|||
break;
|
||||
}
|
||||
case TK_BETWEEN: {
|
||||
/* x BETWEEN y AND z
|
||||
**
|
||||
** Is equivalent to
|
||||
**
|
||||
** x>=y AND x<=z
|
||||
**
|
||||
** Code it as such, taking care to do the common subexpression
|
||||
** elementation of x.
|
||||
*/
|
||||
Expr exprAnd;
|
||||
Expr compLeft;
|
||||
Expr compRight;
|
||||
Expr exprX;
|
||||
|
||||
assert( !ExprHasProperty(pExpr, EP_xIsSelect) );
|
||||
exprX = *pExpr->pLeft;
|
||||
exprAnd.op = TK_AND;
|
||||
exprAnd.pLeft = &compLeft;
|
||||
exprAnd.pRight = &compRight;
|
||||
compLeft.op = TK_GE;
|
||||
compLeft.pLeft = &exprX;
|
||||
compLeft.pRight = pExpr->x.pList->a[0].pExpr;
|
||||
compRight.op = TK_LE;
|
||||
compRight.pLeft = &exprX;
|
||||
compRight.pRight = pExpr->x.pList->a[1].pExpr;
|
||||
exprX.iTable = sqlite3ExprCodeTemp(pParse, &exprX, ®Free1);
|
||||
testcase( regFree1==0 );
|
||||
exprX.op = TK_REGISTER;
|
||||
testcase( jumpIfNull==0 );
|
||||
sqlite3ExprIfTrue(pParse, &exprAnd, dest, jumpIfNull);
|
||||
exprCodeBetween(pParse, pExpr, dest, 1, jumpIfNull);
|
||||
break;
|
||||
}
|
||||
case TK_IN: {
|
||||
int destIfFalse = sqlite3VdbeMakeLabel(v);
|
||||
int destIfNull = jumpIfNull ? dest : destIfFalse;
|
||||
sqlite3ExprCodeIN(pParse, pExpr, destIfFalse, destIfNull);
|
||||
sqlite3VdbeAddOp2(v, OP_Goto, 0, dest);
|
||||
sqlite3VdbeResolveLabel(v, destIfFalse);
|
||||
break;
|
||||
}
|
||||
default: {
|
||||
|
@ -3182,6 +3364,7 @@ void sqlite3ExprIfFalse(Parse *pParse, Expr *pExpr, int dest, int jumpIfNull){
|
|||
break;
|
||||
}
|
||||
case TK_NOT: {
|
||||
testcase( jumpIfNull==0 );
|
||||
sqlite3ExprIfTrue(pParse, pExpr->pLeft, dest, jumpIfNull);
|
||||
break;
|
||||
}
|
||||
|
@ -3229,36 +3412,18 @@ void sqlite3ExprIfFalse(Parse *pParse, Expr *pExpr, int dest, int jumpIfNull){
|
|||
break;
|
||||
}
|
||||
case TK_BETWEEN: {
|
||||
/* x BETWEEN y AND z
|
||||
**
|
||||
** Is equivalent to
|
||||
**
|
||||
** x>=y AND x<=z
|
||||
**
|
||||
** Code it as such, taking care to do the common subexpression
|
||||
** elementation of x.
|
||||
*/
|
||||
Expr exprAnd;
|
||||
Expr compLeft;
|
||||
Expr compRight;
|
||||
Expr exprX;
|
||||
|
||||
assert( !ExprHasProperty(pExpr, EP_xIsSelect) );
|
||||
exprX = *pExpr->pLeft;
|
||||
exprAnd.op = TK_AND;
|
||||
exprAnd.pLeft = &compLeft;
|
||||
exprAnd.pRight = &compRight;
|
||||
compLeft.op = TK_GE;
|
||||
compLeft.pLeft = &exprX;
|
||||
compLeft.pRight = pExpr->x.pList->a[0].pExpr;
|
||||
compRight.op = TK_LE;
|
||||
compRight.pLeft = &exprX;
|
||||
compRight.pRight = pExpr->x.pList->a[1].pExpr;
|
||||
exprX.iTable = sqlite3ExprCodeTemp(pParse, &exprX, ®Free1);
|
||||
testcase( regFree1==0 );
|
||||
exprX.op = TK_REGISTER;
|
||||
testcase( jumpIfNull==0 );
|
||||
sqlite3ExprIfFalse(pParse, &exprAnd, dest, jumpIfNull);
|
||||
exprCodeBetween(pParse, pExpr, dest, 0, jumpIfNull);
|
||||
break;
|
||||
}
|
||||
case TK_IN: {
|
||||
if( jumpIfNull ){
|
||||
sqlite3ExprCodeIN(pParse, pExpr, dest, dest);
|
||||
}else{
|
||||
int destIfNull = sqlite3VdbeMakeLabel(v);
|
||||
sqlite3ExprCodeIN(pParse, pExpr, dest, destIfNull);
|
||||
sqlite3VdbeResolveLabel(v, destIfNull);
|
||||
}
|
||||
break;
|
||||
}
|
||||
default: {
|
||||
|
|
|
@ -10,10 +10,6 @@
|
|||
**
|
||||
*************************************************************************
|
||||
**
|
||||
** $Id: fault.c,v 1.11 2008/09/02 00:52:52 drh Exp $
|
||||
*/
|
||||
|
||||
/*
|
||||
** This file contains code to support the concept of "benign"
|
||||
** malloc failures (when the xMalloc() or xRealloc() method of the
|
||||
** sqlite3_mem_methods structure fails to allocate a block of memory
|
||||
|
|
|
@ -399,7 +399,7 @@ static void fkLookupParent(
|
|||
|
||||
sqlite3VdbeAddOp3(v, OP_MakeRecord, regTemp, nCol, regRec);
|
||||
sqlite3VdbeChangeP4(v, -1, sqlite3IndexAffinityStr(v, pIdx), 0);
|
||||
sqlite3VdbeAddOp3(v, OP_Found, iCur, iOk, regRec);
|
||||
sqlite3VdbeAddOp4Int(v, OP_Found, iCur, iOk, regRec, 0);
|
||||
|
||||
sqlite3ReleaseTempReg(pParse, regRec);
|
||||
sqlite3ReleaseTempRange(pParse, regTemp, nCol);
|
||||
|
|
34
src/func.c
34
src/func.c
|
@ -157,6 +157,8 @@ static void absFunc(sqlite3_context *context, int argc, sqlite3_value **argv){
|
|||
** If x is a blob, then we count bytes.
|
||||
**
|
||||
** If p1 is negative, then we begin abs(p1) from the end of x[].
|
||||
**
|
||||
** If p2 is negative, return the p2 characters preceeding p1.
|
||||
*/
|
||||
static void substrFunc(
|
||||
sqlite3_context *context,
|
||||
|
@ -177,6 +179,7 @@ static void substrFunc(
|
|||
return;
|
||||
}
|
||||
p0type = sqlite3_value_type(argv[0]);
|
||||
p1 = sqlite3_value_int(argv[1]);
|
||||
if( p0type==SQLITE_BLOB ){
|
||||
len = sqlite3_value_bytes(argv[0]);
|
||||
z = sqlite3_value_blob(argv[0]);
|
||||
|
@ -186,11 +189,12 @@ static void substrFunc(
|
|||
z = sqlite3_value_text(argv[0]);
|
||||
if( z==0 ) return;
|
||||
len = 0;
|
||||
for(z2=z; *z2; len++){
|
||||
SQLITE_SKIP_UTF8(z2);
|
||||
if( p1<0 ){
|
||||
for(z2=z; *z2; len++){
|
||||
SQLITE_SKIP_UTF8(z2);
|
||||
}
|
||||
}
|
||||
}
|
||||
p1 = sqlite3_value_int(argv[1]);
|
||||
if( argc==3 ){
|
||||
p2 = sqlite3_value_int(argv[2]);
|
||||
if( p2<0 ){
|
||||
|
@ -220,10 +224,6 @@ static void substrFunc(
|
|||
}
|
||||
}
|
||||
assert( p1>=0 && p2>=0 );
|
||||
if( p1+p2>len ){
|
||||
p2 = len-p1;
|
||||
if( p2<0 ) p2 = 0;
|
||||
}
|
||||
if( p0type!=SQLITE_BLOB ){
|
||||
while( *z && p1 ){
|
||||
SQLITE_SKIP_UTF8(z);
|
||||
|
@ -234,6 +234,10 @@ static void substrFunc(
|
|||
}
|
||||
sqlite3_result_text(context, (char*)z, (int)(z2-z), SQLITE_TRANSIENT);
|
||||
}else{
|
||||
if( p1+p2>len ){
|
||||
p2 = len-p1;
|
||||
if( p2<0 ) p2 = 0;
|
||||
}
|
||||
sqlite3_result_blob(context, (char*)&z[p1], (int)p2, SQLITE_TRANSIENT);
|
||||
}
|
||||
}
|
||||
|
@ -335,6 +339,14 @@ static void lowerFunc(sqlite3_context *context, int argc, sqlite3_value **argv){
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
#if 0 /* This function is never used. */
|
||||
/*
|
||||
** The COALESCE() and IFNULL() functions used to be implemented as shown
|
||||
** here. But now they are implemented as VDBE code so that unused arguments
|
||||
** do not have to be computed. This legacy implementation is retained as
|
||||
** comment.
|
||||
*/
|
||||
/*
|
||||
** Implementation of the IFNULL(), NVL(), and COALESCE() functions.
|
||||
** All three do the same thing. They return the first non-NULL
|
||||
|
@ -353,6 +365,8 @@ static void ifnullFunc(
|
|||
}
|
||||
}
|
||||
}
|
||||
#endif /* NOT USED */
|
||||
#define ifnullFunc versionFunc /* Substitute function - never called */
|
||||
|
||||
/*
|
||||
** Implementation of random(). Return a random integer.
|
||||
|
@ -1437,10 +1451,12 @@ void sqlite3RegisterGlobalFunctions(void){
|
|||
FUNCTION(upper, 1, 0, 0, upperFunc ),
|
||||
FUNCTION(lower, 1, 0, 0, lowerFunc ),
|
||||
FUNCTION(coalesce, 1, 0, 0, 0 ),
|
||||
FUNCTION(coalesce, -1, 0, 0, ifnullFunc ),
|
||||
FUNCTION(coalesce, 0, 0, 0, 0 ),
|
||||
/* FUNCTION(coalesce, -1, 0, 0, ifnullFunc ), */
|
||||
{-1,SQLITE_UTF8,SQLITE_FUNC_COALESCE,0,0,ifnullFunc,0,0,"coalesce",0},
|
||||
FUNCTION(hex, 1, 0, 0, hexFunc ),
|
||||
FUNCTION(ifnull, 2, 0, 1, ifnullFunc ),
|
||||
/* FUNCTION(ifnull, 2, 0, 0, ifnullFunc ), */
|
||||
{2,SQLITE_UTF8,SQLITE_FUNC_COALESCE,0,0,ifnullFunc,0,0,"ifnull",0},
|
||||
FUNCTION(random, 0, 0, 0, randomFunc ),
|
||||
FUNCTION(randomblob, 1, 0, 0, randomBlob ),
|
||||
FUNCTION(nullif, 2, 0, 1, nullifFunc ),
|
||||
|
|
52
src/global.c
52
src/global.c
|
@ -14,7 +14,6 @@
|
|||
*/
|
||||
#include "sqliteInt.h"
|
||||
|
||||
|
||||
/* An array to map all upper-case characters into their corresponding
|
||||
** lower-case character.
|
||||
**
|
||||
|
@ -70,6 +69,7 @@ const unsigned char sqlite3UpperToLower[] = {
|
|||
** isalnum() 0x06
|
||||
** isxdigit() 0x08
|
||||
** toupper() 0x20
|
||||
** SQLite identifier character 0x40
|
||||
**
|
||||
** Bit 0x20 is set if the mapped character requires translation to upper
|
||||
** case. i.e. if the character is a lower-case ASCII character.
|
||||
|
@ -81,6 +81,11 @@ const unsigned char sqlite3UpperToLower[] = {
|
|||
** Standard function tolower() is implemented using the sqlite3UpperToLower[]
|
||||
** array. tolower() is used more often than toupper() by SQLite.
|
||||
**
|
||||
** Bit 0x40 is set if the character non-alphanumeric and can be used in an
|
||||
** SQLite identifier. Identifiers are alphanumerics, "_", "$", and any
|
||||
** non-ASCII UTF character. Hence the test for whether or not a character is
|
||||
** part of an identifier is 0x46.
|
||||
**
|
||||
** SQLite's versions are identical to the standard versions assuming a
|
||||
** locale of "C". They are implemented as macros in sqliteInt.h.
|
||||
*/
|
||||
|
@ -90,7 +95,7 @@ const unsigned char sqlite3CtypeMap[256] = {
|
|||
0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x00, 0x00, /* 08..0f ........ */
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 10..17 ........ */
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 18..1f ........ */
|
||||
0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 20..27 !"#$%&' */
|
||||
0x01, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, /* 20..27 !"#$%&' */
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 28..2f ()*+,-./ */
|
||||
0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, /* 30..37 01234567 */
|
||||
0x0c, 0x0c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 38..3f 89:;<=>? */
|
||||
|
@ -98,29 +103,29 @@ const unsigned char sqlite3CtypeMap[256] = {
|
|||
0x00, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x02, /* 40..47 @ABCDEFG */
|
||||
0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, /* 48..4f HIJKLMNO */
|
||||
0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, /* 50..57 PQRSTUVW */
|
||||
0x02, 0x02, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, /* 58..5f XYZ[\]^_ */
|
||||
0x02, 0x02, 0x02, 0x00, 0x00, 0x00, 0x00, 0x40, /* 58..5f XYZ[\]^_ */
|
||||
0x00, 0x2a, 0x2a, 0x2a, 0x2a, 0x2a, 0x2a, 0x22, /* 60..67 `abcdefg */
|
||||
0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, /* 68..6f hijklmno */
|
||||
0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, /* 70..77 pqrstuvw */
|
||||
0x22, 0x22, 0x22, 0x00, 0x00, 0x00, 0x00, 0x00, /* 78..7f xyz{|}~. */
|
||||
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 80..87 ........ */
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 88..8f ........ */
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 90..97 ........ */
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 98..9f ........ */
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* a0..a7 ........ */
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* a8..af ........ */
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* b0..b7 ........ */
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* b8..bf ........ */
|
||||
0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, /* 80..87 ........ */
|
||||
0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, /* 88..8f ........ */
|
||||
0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, /* 90..97 ........ */
|
||||
0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, /* 98..9f ........ */
|
||||
0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, /* a0..a7 ........ */
|
||||
0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, /* a8..af ........ */
|
||||
0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, /* b0..b7 ........ */
|
||||
0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, /* b8..bf ........ */
|
||||
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* c0..c7 ........ */
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* c8..cf ........ */
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* d0..d7 ........ */
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* d8..df ........ */
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* e0..e7 ........ */
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* e8..ef ........ */
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* f0..f7 ........ */
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 /* f8..ff ........ */
|
||||
0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, /* c0..c7 ........ */
|
||||
0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, /* c8..cf ........ */
|
||||
0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, /* d0..d7 ........ */
|
||||
0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, /* d8..df ........ */
|
||||
0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, /* e0..e7 ........ */
|
||||
0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, /* e8..ef ........ */
|
||||
0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, /* f0..f7 ........ */
|
||||
0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40 /* f8..ff ........ */
|
||||
};
|
||||
#endif
|
||||
|
||||
|
@ -188,3 +193,12 @@ SQLITE_WSD FuncDefHash sqlite3GlobalFunctions;
|
|||
** and dileterious behavior.
|
||||
*/
|
||||
int sqlite3PendingByte = 0x40000000;
|
||||
|
||||
#include "opcodes.h"
|
||||
/*
|
||||
** Properties of opcodes. The OPFLG_INITIALIZER macro is
|
||||
** created by mkopcodeh.awk during compilation. Data is obtained
|
||||
** from the comments following the "case OP_xxxx:" statements in
|
||||
** the vdbe.c file.
|
||||
*/
|
||||
const unsigned char sqlite3OpcodeProperty[] = OPFLG_INITIALIZER;
|
||||
|
|
|
@ -11,8 +11,6 @@
|
|||
*************************************************************************
|
||||
** This is the implementation of generic hash-tables
|
||||
** used in SQLite.
|
||||
**
|
||||
** $Id: hash.c,v 1.38 2009/05/09 23:29:12 drh Exp $
|
||||
*/
|
||||
#include "sqliteInt.h"
|
||||
#include <assert.h>
|
||||
|
|
|
@ -11,8 +11,6 @@
|
|||
*************************************************************************
|
||||
** This is the header file for the generic hash-table implemenation
|
||||
** used in SQLite.
|
||||
**
|
||||
** $Id: hash.h,v 1.15 2009/05/02 13:29:38 drh Exp $
|
||||
*/
|
||||
#ifndef _SQLITE_HASH_H_
|
||||
#define _SQLITE_HASH_H_
|
||||
|
|
|
@ -12,8 +12,6 @@
|
|||
**
|
||||
** This file contains inline asm code for retrieving "high-performance"
|
||||
** counters for x86 class CPUs.
|
||||
**
|
||||
** $Id: hwtime.h,v 1.3 2008/08/01 14:33:15 shane Exp $
|
||||
*/
|
||||
#ifndef _HWTIME_H_
|
||||
#define _HWTIME_H_
|
||||
|
|
|
@ -11,8 +11,6 @@
|
|||
*************************************************************************
|
||||
** This file contains C code routines that are called by the parser
|
||||
** to handle INSERT statements in SQLite.
|
||||
**
|
||||
** $Id: insert.c,v 1.270 2009/07/24 17:58:53 danielk1977 Exp $
|
||||
*/
|
||||
#include "sqliteInt.h"
|
||||
|
||||
|
|
|
@ -10,12 +10,6 @@
|
|||
**
|
||||
*************************************************************************
|
||||
**
|
||||
** @(#) $Id: journal.c,v 1.9 2009/01/20 17:06:27 danielk1977 Exp $
|
||||
*/
|
||||
|
||||
#ifdef SQLITE_ENABLE_ATOMIC_WRITE
|
||||
|
||||
/*
|
||||
** This file implements a special kind of sqlite3_file object used
|
||||
** by SQLite to create journal files if the atomic-write optimization
|
||||
** is enabled.
|
||||
|
@ -30,7 +24,7 @@
|
|||
** buffer, or
|
||||
** 2) The sqlite3JournalCreate() function is called.
|
||||
*/
|
||||
|
||||
#ifdef SQLITE_ENABLE_ATOMIC_WRITE
|
||||
#include "sqliteInt.h"
|
||||
|
||||
|
||||
|
|
|
@ -13,8 +13,6 @@
|
|||
** implement the programmer interface to the library. Routines in
|
||||
** other files are for internal use by SQLite and should not be
|
||||
** accessed by users of the library.
|
||||
**
|
||||
** $Id: legacy.c,v 1.35 2009/08/07 16:56:00 danielk1977 Exp $
|
||||
*/
|
||||
|
||||
#include "sqliteInt.h"
|
||||
|
|
|
@ -11,8 +11,6 @@
|
|||
*************************************************************************
|
||||
** This file contains code used to dynamically load extensions into
|
||||
** the SQLite library.
|
||||
**
|
||||
** $Id: loadext.c,v 1.60 2009/06/03 01:24:54 drh Exp $
|
||||
*/
|
||||
|
||||
#ifndef SQLITE_CORE
|
||||
|
|
|
@ -11,8 +11,6 @@
|
|||
*************************************************************************
|
||||
**
|
||||
** Memory allocation functions used throughout sqlite.
|
||||
**
|
||||
** $Id: malloc.c,v 1.66 2009/07/17 11:44:07 drh Exp $
|
||||
*/
|
||||
#include "sqliteInt.h"
|
||||
#include <stdarg.h>
|
||||
|
|
|
@ -15,8 +15,6 @@
|
|||
** here always fail. SQLite will not operate with these drivers. These
|
||||
** are merely placeholders. Real drivers must be substituted using
|
||||
** sqlite3_config() before SQLite will operate.
|
||||
**
|
||||
** $Id: mem0.c,v 1.1 2008/10/28 18:58:20 drh Exp $
|
||||
*/
|
||||
#include "sqliteInt.h"
|
||||
|
||||
|
|
|
@ -16,8 +16,6 @@
|
|||
**
|
||||
** This file contains implementations of the low-level memory allocation
|
||||
** routines specified in the sqlite3_mem_methods object.
|
||||
**
|
||||
** $Id: mem1.c,v 1.30 2009/03/23 04:33:33 danielk1977 Exp $
|
||||
*/
|
||||
#include "sqliteInt.h"
|
||||
|
||||
|
|
|
@ -18,8 +18,6 @@
|
|||
**
|
||||
** This file contains implementations of the low-level memory allocation
|
||||
** routines specified in the sqlite3_mem_methods object.
|
||||
**
|
||||
** $Id: mem2.c,v 1.45 2009/03/23 04:33:33 danielk1977 Exp $
|
||||
*/
|
||||
#include "sqliteInt.h"
|
||||
|
||||
|
|
|
@ -22,8 +22,6 @@
|
|||
**
|
||||
** This version of the memory allocation subsystem is included
|
||||
** in the build only if SQLITE_ENABLE_MEMSYS3 is defined.
|
||||
**
|
||||
** $Id: mem3.c,v 1.25 2008/11/19 16:52:44 danielk1977 Exp $
|
||||
*/
|
||||
#include "sqliteInt.h"
|
||||
|
||||
|
|
|
@ -13,8 +13,6 @@
|
|||
** This file contains code use to implement an in-memory rollback journal.
|
||||
** The in-memory rollback journal is used to journal transactions for
|
||||
** ":memory:" databases and when the journal_mode=MEMORY pragma is used.
|
||||
**
|
||||
** @(#) $Id: memjournal.c,v 1.12 2009/05/04 11:42:30 danielk1977 Exp $
|
||||
*/
|
||||
#include "sqliteInt.h"
|
||||
|
||||
|
|
|
@ -12,9 +12,6 @@
|
|||
** This file contains the C functions that implement mutexes.
|
||||
**
|
||||
** This file contains code that is common across all mutex implementations.
|
||||
|
||||
**
|
||||
** $Id: mutex.c,v 1.31 2009/07/16 18:21:18 drh Exp $
|
||||
*/
|
||||
#include "sqliteInt.h"
|
||||
|
||||
|
|
|
@ -18,8 +18,6 @@
|
|||
** NOTE: source files should *not* #include this header file directly.
|
||||
** Source files should #include the sqliteInt.h file and let that file
|
||||
** include this one indirectly.
|
||||
**
|
||||
** $Id: mutex.h,v 1.9 2008/10/07 15:25:48 drh Exp $
|
||||
*/
|
||||
|
||||
|
||||
|
|
|
@ -24,8 +24,6 @@
|
|||
** If compiled with SQLITE_DEBUG, then additional logic is inserted
|
||||
** that does error checking on mutexes to make sure they are being
|
||||
** called correctly.
|
||||
**
|
||||
** $Id: mutex_noop.c,v 1.3 2008/12/05 17:17:08 drh Exp $
|
||||
*/
|
||||
#include "sqliteInt.h"
|
||||
|
||||
|
|
|
@ -10,8 +10,6 @@
|
|||
**
|
||||
*************************************************************************
|
||||
** This file contains the C functions that implement mutexes for OS/2
|
||||
**
|
||||
** $Id: mutex_os2.c,v 1.11 2008/11/22 19:50:54 pweilbacher Exp $
|
||||
*/
|
||||
#include "sqliteInt.h"
|
||||
|
||||
|
@ -160,6 +158,39 @@ static void os2MutexFree(sqlite3_mutex *p){
|
|||
sqlite3_free( p );
|
||||
}
|
||||
|
||||
#ifdef SQLITE_DEBUG
|
||||
/*
|
||||
** The sqlite3_mutex_held() and sqlite3_mutex_notheld() routine are
|
||||
** intended for use inside assert() statements.
|
||||
*/
|
||||
static int os2MutexHeld(sqlite3_mutex *p){
|
||||
TID tid;
|
||||
PID pid;
|
||||
ULONG ulCount;
|
||||
PTIB ptib;
|
||||
if( p!=0 ) {
|
||||
DosQueryMutexSem(p->mutex, &pid, &tid, &ulCount);
|
||||
} else {
|
||||
DosGetInfoBlocks(&ptib, NULL);
|
||||
tid = ptib->tib_ptib2->tib2_ultid;
|
||||
}
|
||||
return p==0 || (p->nRef!=0 && p->owner==tid);
|
||||
}
|
||||
static int os2MutexNotheld(sqlite3_mutex *p){
|
||||
TID tid;
|
||||
PID pid;
|
||||
ULONG ulCount;
|
||||
PTIB ptib;
|
||||
if( p!= 0 ) {
|
||||
DosQueryMutexSem(p->mutex, &pid, &tid, &ulCount);
|
||||
} else {
|
||||
DosGetInfoBlocks(&ptib, NULL);
|
||||
tid = ptib->tib_ptib2->tib2_ultid;
|
||||
}
|
||||
return p==0 || p->nRef==0 || p->owner!=tid;
|
||||
}
|
||||
#endif
|
||||
|
||||
/*
|
||||
** The sqlite3_mutex_enter() and sqlite3_mutex_try() routines attempt
|
||||
** to enter a mutex. If another thread is already within the mutex,
|
||||
|
@ -220,39 +251,6 @@ static void os2MutexLeave(sqlite3_mutex *p){
|
|||
DosReleaseMutexSem(p->mutex);
|
||||
}
|
||||
|
||||
#ifdef SQLITE_DEBUG
|
||||
/*
|
||||
** The sqlite3_mutex_held() and sqlite3_mutex_notheld() routine are
|
||||
** intended for use inside assert() statements.
|
||||
*/
|
||||
static int os2MutexHeld(sqlite3_mutex *p){
|
||||
TID tid;
|
||||
PID pid;
|
||||
ULONG ulCount;
|
||||
PTIB ptib;
|
||||
if( p!=0 ) {
|
||||
DosQueryMutexSem(p->mutex, &pid, &tid, &ulCount);
|
||||
} else {
|
||||
DosGetInfoBlocks(&ptib, NULL);
|
||||
tid = ptib->tib_ptib2->tib2_ultid;
|
||||
}
|
||||
return p==0 || (p->nRef!=0 && p->owner==tid);
|
||||
}
|
||||
static int os2MutexNotheld(sqlite3_mutex *p){
|
||||
TID tid;
|
||||
PID pid;
|
||||
ULONG ulCount;
|
||||
PTIB ptib;
|
||||
if( p!= 0 ) {
|
||||
DosQueryMutexSem(p->mutex, &pid, &tid, &ulCount);
|
||||
} else {
|
||||
DosGetInfoBlocks(&ptib, NULL);
|
||||
tid = ptib->tib_ptib2->tib2_ultid;
|
||||
}
|
||||
return p==0 || p->nRef==0 || p->owner!=tid;
|
||||
}
|
||||
#endif
|
||||
|
||||
sqlite3_mutex_methods *sqlite3DefaultMutex(void){
|
||||
static sqlite3_mutex_methods sMutex = {
|
||||
os2MutexInit,
|
||||
|
|
|
@ -10,8 +10,6 @@
|
|||
**
|
||||
*************************************************************************
|
||||
** This file contains the C functions that implement mutexes for pthreads
|
||||
**
|
||||
** $Id: mutex_unix.c,v 1.16 2008/12/08 18:19:18 drh Exp $
|
||||
*/
|
||||
#include "sqliteInt.h"
|
||||
|
||||
|
|
|
@ -10,8 +10,6 @@
|
|||
**
|
||||
*************************************************************************
|
||||
** This file contains the C functions that implement mutexes for win32
|
||||
**
|
||||
** $Id: mutex_w32.c,v 1.18 2009/08/10 03:23:21 shane Exp $
|
||||
*/
|
||||
#include "sqliteInt.h"
|
||||
|
||||
|
|
|
@ -12,8 +12,6 @@
|
|||
**
|
||||
** This file contains the implementation of the sqlite3_unlock_notify()
|
||||
** API method and its associated functionality.
|
||||
**
|
||||
** $Id: notify.c,v 1.4 2009/04/07 22:06:57 drh Exp $
|
||||
*/
|
||||
#include "sqliteInt.h"
|
||||
#include "btreeInt.h"
|
||||
|
|
3
src/os.c
3
src/os.c
|
@ -12,8 +12,6 @@
|
|||
**
|
||||
** This file contains OS interface code that is common to all
|
||||
** architectures.
|
||||
**
|
||||
** $Id: os.c,v 1.127 2009/07/27 11:41:21 danielk1977 Exp $
|
||||
*/
|
||||
#define _SQLITE_OS_C_ 1
|
||||
#include "sqliteInt.h"
|
||||
|
@ -140,6 +138,7 @@ int sqlite3OsFullPathname(
|
|||
int nPathOut,
|
||||
char *zPathOut
|
||||
){
|
||||
zPathOut[0] = 0;
|
||||
return pVfs->xFullPathname(pVfs, zPath, nPathOut, zPathOut);
|
||||
}
|
||||
#ifndef SQLITE_OMIT_LOAD_EXTENSION
|
||||
|
|
2
src/os.h
2
src/os.h
|
@ -16,8 +16,6 @@
|
|||
**
|
||||
** This header file is #include-ed by sqliteInt.h and thus ends up
|
||||
** being included by every source file.
|
||||
**
|
||||
** $Id: os.h,v 1.108 2009/02/05 16:31:46 drh Exp $
|
||||
*/
|
||||
#ifndef _SQLITE_OS_H_
|
||||
#define _SQLITE_OS_H_
|
||||
|
|
|
@ -16,8 +16,6 @@
|
|||
**
|
||||
** This file should be #included by the os_*.c files only. It is not a
|
||||
** general purpose header file.
|
||||
**
|
||||
** $Id: os_common.h,v 1.38 2009/02/24 18:40:50 danielk1977 Exp $
|
||||
*/
|
||||
#ifndef _OS_COMMON_H_
|
||||
#define _OS_COMMON_H_
|
||||
|
|
|
@ -11,8 +11,6 @@
|
|||
******************************************************************************
|
||||
**
|
||||
** This file contains code that is specific to OS/2.
|
||||
**
|
||||
** $Id: os_os2.c,v 1.63 2008/12/10 19:26:24 drh Exp $
|
||||
*/
|
||||
|
||||
#include "sqliteInt.h"
|
||||
|
|
|
@ -1159,7 +1159,7 @@ static int unixCheckReservedLock(sqlite3_file *id, int *pResOut){
|
|||
#endif
|
||||
|
||||
unixLeaveMutex();
|
||||
OSTRACE4("TEST WR-LOCK %d %d %d\n", pFile->h, rc, reserved);
|
||||
OSTRACE4("TEST WR-LOCK %d %d %d (unix)\n", pFile->h, rc, reserved);
|
||||
|
||||
*pResOut = reserved;
|
||||
return rc;
|
||||
|
@ -1292,7 +1292,7 @@ static int unixLock(sqlite3_file *id, int locktype){
|
|||
int tErrno;
|
||||
|
||||
assert( pFile );
|
||||
OSTRACE7("LOCK %d %s was %s(%s,%d) pid=%d\n", pFile->h,
|
||||
OSTRACE7("LOCK %d %s was %s(%s,%d) pid=%d (unix)\n", pFile->h,
|
||||
locktypeName(locktype), locktypeName(pFile->locktype),
|
||||
locktypeName(pLock->locktype), pLock->cnt , getpid());
|
||||
|
||||
|
@ -1301,7 +1301,7 @@ static int unixLock(sqlite3_file *id, int locktype){
|
|||
** unixEnterMutex() hasn't been called yet.
|
||||
*/
|
||||
if( pFile->locktype>=locktype ){
|
||||
OSTRACE3("LOCK %d %s ok (already held)\n", pFile->h,
|
||||
OSTRACE3("LOCK %d %s ok (already held) (unix)\n", pFile->h,
|
||||
locktypeName(locktype));
|
||||
return SQLITE_OK;
|
||||
}
|
||||
|
@ -1471,7 +1471,7 @@ static int unixLock(sqlite3_file *id, int locktype){
|
|||
|
||||
end_lock:
|
||||
unixLeaveMutex();
|
||||
OSTRACE4("LOCK %d %s %s\n", pFile->h, locktypeName(locktype),
|
||||
OSTRACE4("LOCK %d %s %s (unix)\n", pFile->h, locktypeName(locktype),
|
||||
rc==SQLITE_OK ? "ok" : "failed");
|
||||
return rc;
|
||||
}
|
||||
|
@ -1535,7 +1535,7 @@ static int unixUnlock(sqlite3_file *id, int locktype){
|
|||
int tErrno; /* Error code from system call errors */
|
||||
|
||||
assert( pFile );
|
||||
OSTRACE7("UNLOCK %d %d was %d(%d,%d) pid=%d\n", pFile->h, locktype,
|
||||
OSTRACE7("UNLOCK %d %d was %d(%d,%d) pid=%d (unix)\n", pFile->h, locktype,
|
||||
pFile->locktype, pFile->pLock->locktype, pFile->pLock->cnt, getpid());
|
||||
|
||||
assert( locktype<=SHARED_LOCK );
|
||||
|
@ -1816,7 +1816,7 @@ static int dotlockCheckReservedLock(sqlite3_file *id, int *pResOut) {
|
|||
const char *zLockFile = (const char*)pFile->lockingContext;
|
||||
reserved = access(zLockFile, 0)==0;
|
||||
}
|
||||
OSTRACE4("TEST WR-LOCK %d %d %d\n", pFile->h, rc, reserved);
|
||||
OSTRACE4("TEST WR-LOCK %d %d %d (dotlock)\n", pFile->h, rc, reserved);
|
||||
*pResOut = reserved;
|
||||
return rc;
|
||||
}
|
||||
|
@ -1906,7 +1906,7 @@ static int dotlockUnlock(sqlite3_file *id, int locktype) {
|
|||
char *zLockFile = (char *)pFile->lockingContext;
|
||||
|
||||
assert( pFile );
|
||||
OSTRACE5("UNLOCK %d %d was %d pid=%d\n", pFile->h, locktype,
|
||||
OSTRACE5("UNLOCK %d %d was %d pid=%d (dotlock)\n", pFile->h, locktype,
|
||||
pFile->locktype, getpid());
|
||||
assert( locktype<=SHARED_LOCK );
|
||||
|
||||
|
@ -2020,7 +2020,7 @@ static int flockCheckReservedLock(sqlite3_file *id, int *pResOut){
|
|||
}
|
||||
}
|
||||
}
|
||||
OSTRACE4("TEST WR-LOCK %d %d %d\n", pFile->h, rc, reserved);
|
||||
OSTRACE4("TEST WR-LOCK %d %d %d (flock)\n", pFile->h, rc, reserved);
|
||||
|
||||
#ifdef SQLITE_IGNORE_FLOCK_LOCK_ERRORS
|
||||
if( (rc & SQLITE_IOERR) == SQLITE_IOERR ){
|
||||
|
@ -2087,7 +2087,7 @@ static int flockLock(sqlite3_file *id, int locktype) {
|
|||
/* got it, set the type and return ok */
|
||||
pFile->locktype = locktype;
|
||||
}
|
||||
OSTRACE4("LOCK %d %s %s\n", pFile->h, locktypeName(locktype),
|
||||
OSTRACE4("LOCK %d %s %s (flock)\n", pFile->h, locktypeName(locktype),
|
||||
rc==SQLITE_OK ? "ok" : "failed");
|
||||
#ifdef SQLITE_IGNORE_FLOCK_LOCK_ERRORS
|
||||
if( (rc & SQLITE_IOERR) == SQLITE_IOERR ){
|
||||
|
@ -2109,7 +2109,7 @@ static int flockUnlock(sqlite3_file *id, int locktype) {
|
|||
unixFile *pFile = (unixFile*)id;
|
||||
|
||||
assert( pFile );
|
||||
OSTRACE5("UNLOCK %d %d was %d pid=%d\n", pFile->h, locktype,
|
||||
OSTRACE5("UNLOCK %d %d was %d pid=%d (flock)\n", pFile->h, locktype,
|
||||
pFile->locktype, getpid());
|
||||
assert( locktype<=SHARED_LOCK );
|
||||
|
||||
|
@ -2211,7 +2211,7 @@ static int semCheckReservedLock(sqlite3_file *id, int *pResOut) {
|
|||
sem_post(pSem);
|
||||
}
|
||||
}
|
||||
OSTRACE4("TEST WR-LOCK %d %d %d\n", pFile->h, rc, reserved);
|
||||
OSTRACE4("TEST WR-LOCK %d %d %d (sem)\n", pFile->h, rc, reserved);
|
||||
|
||||
*pResOut = reserved;
|
||||
return rc;
|
||||
|
@ -2286,7 +2286,7 @@ static int semUnlock(sqlite3_file *id, int locktype) {
|
|||
|
||||
assert( pFile );
|
||||
assert( pSem );
|
||||
OSTRACE5("UNLOCK %d %d was %d pid=%d\n", pFile->h, locktype,
|
||||
OSTRACE5("UNLOCK %d %d was %d pid=%d (sem)\n", pFile->h, locktype,
|
||||
pFile->locktype, getpid());
|
||||
assert( locktype<=SHARED_LOCK );
|
||||
|
||||
|
@ -2456,7 +2456,7 @@ static int afpCheckReservedLock(sqlite3_file *id, int *pResOut){
|
|||
}
|
||||
}
|
||||
|
||||
OSTRACE4("TEST WR-LOCK %d %d %d\n", pFile->h, rc, reserved);
|
||||
OSTRACE4("TEST WR-LOCK %d %d %d (afp)\n", pFile->h, rc, reserved);
|
||||
|
||||
*pResOut = reserved;
|
||||
return rc;
|
||||
|
@ -2492,7 +2492,7 @@ static int afpLock(sqlite3_file *id, int locktype){
|
|||
afpLockingContext *context = (afpLockingContext *) pFile->lockingContext;
|
||||
|
||||
assert( pFile );
|
||||
OSTRACE5("LOCK %d %s was %s pid=%d\n", pFile->h,
|
||||
OSTRACE5("LOCK %d %s was %s pid=%d (afp)\n", pFile->h,
|
||||
locktypeName(locktype), locktypeName(pFile->locktype), getpid());
|
||||
|
||||
/* If there is already a lock of this type or more restrictive on the
|
||||
|
@ -2500,7 +2500,7 @@ static int afpLock(sqlite3_file *id, int locktype){
|
|||
** unixEnterMutex() hasn't been called yet.
|
||||
*/
|
||||
if( pFile->locktype>=locktype ){
|
||||
OSTRACE3("LOCK %d %s ok (already held)\n", pFile->h,
|
||||
OSTRACE3("LOCK %d %s ok (already held) (afp)\n", pFile->h,
|
||||
locktypeName(locktype));
|
||||
return SQLITE_OK;
|
||||
}
|
||||
|
@ -2619,7 +2619,7 @@ static int afpLock(sqlite3_file *id, int locktype){
|
|||
|
||||
afp_end_lock:
|
||||
unixLeaveMutex();
|
||||
OSTRACE4("LOCK %d %s %s\n", pFile->h, locktypeName(locktype),
|
||||
OSTRACE4("LOCK %d %s %s (afp)\n", pFile->h, locktypeName(locktype),
|
||||
rc==SQLITE_OK ? "ok" : "failed");
|
||||
return rc;
|
||||
}
|
||||
|
@ -2637,7 +2637,7 @@ static int afpUnlock(sqlite3_file *id, int locktype) {
|
|||
afpLockingContext *pCtx = (afpLockingContext *) pFile->lockingContext;
|
||||
|
||||
assert( pFile );
|
||||
OSTRACE5("UNLOCK %d %d was %d pid=%d\n", pFile->h, locktype,
|
||||
OSTRACE5("UNLOCK %d %d was %d pid=%d (afp)\n", pFile->h, locktype,
|
||||
pFile->locktype, getpid());
|
||||
|
||||
assert( locktype<=SHARED_LOCK );
|
||||
|
@ -3113,6 +3113,19 @@ static int unixTruncate(sqlite3_file *id, i64 nByte){
|
|||
((unixFile*)id)->lastErrno = errno;
|
||||
return SQLITE_IOERR_TRUNCATE;
|
||||
}else{
|
||||
#ifndef NDEBUG
|
||||
/* If we are doing a normal write to a database file (as opposed to
|
||||
** doing a hot-journal rollback or a write to some file other than a
|
||||
** normal database file) and we truncate the file to zero length,
|
||||
** that effectively updates the change counter. This might happen
|
||||
** when restoring a database using the backup API from a zero-length
|
||||
** source.
|
||||
*/
|
||||
if( ((unixFile*)id)->inNormalWrite && nByte==0 ){
|
||||
((unixFile*)id)->transCntrChng = 1;
|
||||
}
|
||||
#endif
|
||||
|
||||
return SQLITE_OK;
|
||||
}
|
||||
}
|
||||
|
|
83
src/pager.c
83
src/pager.c
|
@ -17,8 +17,6 @@
|
|||
** locking to prevent two processes from writing the same database
|
||||
** file simultaneously, or one process from reading the database while
|
||||
** another is writing.
|
||||
**
|
||||
** @(#) $Id: pager.c,v 1.629 2009/08/10 17:48:57 drh Exp $
|
||||
*/
|
||||
#ifndef SQLITE_OMIT_DISKIO
|
||||
#include "sqliteInt.h"
|
||||
|
@ -913,10 +911,10 @@ static int readJournalHdr(
|
|||
|
||||
/* Check that the values read from the page-size and sector-size fields
|
||||
** are within range. To be 'in range', both values need to be a power
|
||||
** of two greater than or equal to 512, and not greater than their
|
||||
** of two greater than or equal to 512 or 32, and not greater than their
|
||||
** respective compile time maximum limits.
|
||||
*/
|
||||
if( iPageSize<512 || iSectorSize<512
|
||||
if( iPageSize<512 || iSectorSize<32
|
||||
|| iPageSize>SQLITE_MAX_PAGE_SIZE || iSectorSize>MAX_SECTOR_SIZE
|
||||
|| ((iPageSize-1)&iPageSize)!=0 || ((iSectorSize-1)&iSectorSize)!=0
|
||||
){
|
||||
|
@ -1149,6 +1147,7 @@ static void pager_unlock(Pager *pPager){
|
|||
|
||||
pPager->changeCountDone = 0;
|
||||
pPager->state = PAGER_UNLOCK;
|
||||
pPager->dbModified = 0;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1423,7 +1422,7 @@ static int pager_playback_one_page(
|
|||
PgHdr *pPg; /* An existing page in the cache */
|
||||
Pgno pgno; /* The page number of a page in journal */
|
||||
u32 cksum; /* Checksum used for sanity checking */
|
||||
u8 *aData; /* Temporary storage for the page */
|
||||
char *aData; /* Temporary storage for the page */
|
||||
sqlite3_file *jfd; /* The file descriptor for the journal file */
|
||||
|
||||
assert( (isMainJrnl&~1)==0 ); /* isMainJrnl is 0 or 1 */
|
||||
|
@ -1431,7 +1430,7 @@ static int pager_playback_one_page(
|
|||
assert( isMainJrnl || pDone ); /* pDone always used on sub-journals */
|
||||
assert( isSavepnt || pDone==0 ); /* pDone never used on non-savepoint */
|
||||
|
||||
aData = (u8*)pPager->pTmpSpace;
|
||||
aData = pPager->pTmpSpace;
|
||||
assert( aData ); /* Temp storage must have already been allocated */
|
||||
|
||||
/* Read the page number and page data from the journal or sub-journal
|
||||
|
@ -1440,7 +1439,7 @@ static int pager_playback_one_page(
|
|||
jfd = isMainJrnl ? pPager->jfd : pPager->sjfd;
|
||||
rc = read32bits(jfd, *pOffset, &pgno);
|
||||
if( rc!=SQLITE_OK ) return rc;
|
||||
rc = sqlite3OsRead(jfd, aData, pPager->pageSize, (*pOffset)+4);
|
||||
rc = sqlite3OsRead(jfd, (u8*)aData, pPager->pageSize, (*pOffset)+4);
|
||||
if( rc!=SQLITE_OK ) return rc;
|
||||
*pOffset += pPager->pageSize + 4 + isMainJrnl*4;
|
||||
|
||||
|
@ -1459,7 +1458,7 @@ static int pager_playback_one_page(
|
|||
if( isMainJrnl ){
|
||||
rc = read32bits(jfd, (*pOffset)-4, &cksum);
|
||||
if( rc ) return rc;
|
||||
if( !isSavepnt && pager_cksum(pPager, aData)!=cksum ){
|
||||
if( !isSavepnt && pager_cksum(pPager, (u8*)aData)!=cksum ){
|
||||
return SQLITE_DONE;
|
||||
}
|
||||
}
|
||||
|
@ -1505,8 +1504,8 @@ static int pager_playback_one_page(
|
|||
pPg = pager_lookup(pPager, pgno);
|
||||
assert( pPg || !MEMDB );
|
||||
PAGERTRACE(("PLAYBACK %d page %d hash(%08x) %s\n",
|
||||
PAGERID(pPager), pgno, pager_datahash(pPager->pageSize, aData),
|
||||
(isMainJrnl?"main-journal":"sub-journal")
|
||||
PAGERID(pPager), pgno, pager_datahash(pPager->pageSize, (u8*)aData),
|
||||
(isMainJrnl?"main-journal":"sub-journal")
|
||||
));
|
||||
if( (pPager->state>=PAGER_EXCLUSIVE)
|
||||
&& (pPg==0 || 0==(pPg->flags&PGHDR_NEED_SYNC))
|
||||
|
@ -1514,14 +1513,14 @@ static int pager_playback_one_page(
|
|||
&& !isUnsync
|
||||
){
|
||||
i64 ofst = (pgno-1)*(i64)pPager->pageSize;
|
||||
rc = sqlite3OsWrite(pPager->fd, aData, pPager->pageSize, ofst);
|
||||
rc = sqlite3OsWrite(pPager->fd, (u8*)aData, pPager->pageSize, ofst);
|
||||
if( pgno>pPager->dbFileSize ){
|
||||
pPager->dbFileSize = pgno;
|
||||
}
|
||||
if( pPager->pBackup ){
|
||||
CODEC1(pPager, aData, pgno, 3, rc=SQLITE_NOMEM);
|
||||
sqlite3BackupUpdate(pPager->pBackup, pgno, aData);
|
||||
CODEC1(pPager, aData, pgno, 0, rc=SQLITE_NOMEM);
|
||||
sqlite3BackupUpdate(pPager->pBackup, pgno, (u8*)aData);
|
||||
CODEC2(pPager, aData, pgno, 7, rc=SQLITE_NOMEM, aData);
|
||||
}
|
||||
}else if( !isMainJrnl && pPg==0 ){
|
||||
/* If this is a rollback of a savepoint and data was not written to
|
||||
|
@ -1556,7 +1555,7 @@ static int pager_playback_one_page(
|
|||
*/
|
||||
void *pData;
|
||||
pData = pPg->pData;
|
||||
memcpy(pData, aData, pPager->pageSize);
|
||||
memcpy(pData, (u8*)aData, pPager->pageSize);
|
||||
pPager->xReiniter(pPg);
|
||||
if( isMainJrnl && (!isSavepnt || *pOffset<=pPager->journalHdr) ){
|
||||
/* If the contents of this page were just restored from the main
|
||||
|
@ -1781,8 +1780,8 @@ static int pager_truncate(Pager *pPager, Pgno nPage){
|
|||
** For temporary files the effective sector size is always 512 bytes.
|
||||
**
|
||||
** Otherwise, for non-temporary files, the effective sector size is
|
||||
** the value returned by the xSectorSize() method rounded up to 512 if
|
||||
** it is less than 512, or rounded down to MAX_SECTOR_SIZE if it
|
||||
** the value returned by the xSectorSize() method rounded up to 32 if
|
||||
** it is less than 32, or rounded down to MAX_SECTOR_SIZE if it
|
||||
** is greater than MAX_SECTOR_SIZE.
|
||||
*/
|
||||
static void setSectorSize(Pager *pPager){
|
||||
|
@ -1795,7 +1794,7 @@ static void setSectorSize(Pager *pPager){
|
|||
*/
|
||||
pPager->sectorSize = sqlite3OsSectorSize(pPager->fd);
|
||||
}
|
||||
if( pPager->sectorSize<512 ){
|
||||
if( pPager->sectorSize<32 ){
|
||||
pPager->sectorSize = 512;
|
||||
}
|
||||
if( pPager->sectorSize>MAX_SECTOR_SIZE ){
|
||||
|
@ -2525,8 +2524,11 @@ static int pager_wait_on_lock(Pager *pPager, int locktype){
|
|||
assert( PAGER_RESERVED==RESERVED_LOCK );
|
||||
assert( PAGER_EXCLUSIVE==EXCLUSIVE_LOCK );
|
||||
|
||||
/* If the file is currently unlocked then the size must be unknown */
|
||||
/* If the file is currently unlocked then the size must be unknown. It
|
||||
** must not have been modified at this point.
|
||||
*/
|
||||
assert( pPager->state>=PAGER_SHARED || pPager->dbSizeValid==0 );
|
||||
assert( pPager->state>=PAGER_SHARED || pPager->dbModified==0 );
|
||||
|
||||
/* Check that this is either a no-op (because the requested lock is
|
||||
** already held, or one of the transistions that the busy-handler
|
||||
|
@ -2873,7 +2875,9 @@ static int pager_write_pagelist(PgHdr *pList){
|
|||
** any such pages to the file.
|
||||
**
|
||||
** Also, do not write out any page that has the PGHDR_DONT_WRITE flag
|
||||
** set (set by sqlite3PagerDontWrite()).
|
||||
** set (set by sqlite3PagerDontWrite()). Note that if compiled with
|
||||
** SQLITE_SECURE_DELETE the PGHDR_DONT_WRITE bit is never set and so
|
||||
** the second test is always true.
|
||||
*/
|
||||
if( pgno<=pPager->dbSize && 0==(pList->flags&PGHDR_DONT_WRITE) ){
|
||||
i64 offset = (pgno-1)*(i64)pPager->pageSize; /* Offset to write */
|
||||
|
@ -3838,7 +3842,7 @@ int sqlite3PagerAcquire(
|
|||
goto pager_acquire_err;
|
||||
}
|
||||
|
||||
if( nMax<(int)pgno || MEMDB || noContent ){
|
||||
if( MEMDB || nMax<(int)pgno || noContent ){
|
||||
if( pgno>pPager->mxPgno ){
|
||||
rc = SQLITE_FULL;
|
||||
goto pager_acquire_err;
|
||||
|
@ -4382,6 +4386,7 @@ int sqlite3PagerIswriteable(DbPage *pPg){
|
|||
}
|
||||
#endif
|
||||
|
||||
#ifndef SQLITE_SECURE_DELETE
|
||||
/*
|
||||
** A call to this routine tells the pager that it is not necessary to
|
||||
** write the information on page pPg back to the disk, even though
|
||||
|
@ -4407,6 +4412,7 @@ void sqlite3PagerDontWrite(PgHdr *pPg){
|
|||
#endif
|
||||
}
|
||||
}
|
||||
#endif /* !defined(SQLITE_SECURE_DELETE) */
|
||||
|
||||
/*
|
||||
** This routine is called to increment the value of the database file
|
||||
|
@ -4446,7 +4452,7 @@ static int pager_incr_changecounter(Pager *pPager, int isDirectMode){
|
|||
#endif
|
||||
|
||||
assert( pPager->state>=PAGER_RESERVED );
|
||||
if( !pPager->changeCountDone && ALWAYS(pPager->dbSize>0) ){
|
||||
if( !pPager->changeCountDone && pPager->dbSize>0 ){
|
||||
PgHdr *pPgHdr; /* Reference to page 1 */
|
||||
u32 change_counter; /* Initial value of change-counter field */
|
||||
|
||||
|
@ -5054,7 +5060,7 @@ static void sqlite3PagerSetCodec(
|
|||
void *pCodec
|
||||
){
|
||||
if( pPager->xCodecFree ) pPager->xCodecFree(pPager->pCodec);
|
||||
pPager->xCodec = xCodec;
|
||||
pPager->xCodec = pPager->memDb ? 0 : xCodec;
|
||||
pPager->xCodecSizeChng = xCodecSizeChng;
|
||||
pPager->xCodecFree = xCodecFree;
|
||||
pPager->pCodec = pCodec;
|
||||
|
@ -5099,6 +5105,14 @@ int sqlite3PagerMovepage(Pager *pPager, DbPage *pPg, Pgno pgno, int isCommit){
|
|||
|
||||
assert( pPg->nRef>0 );
|
||||
|
||||
/* In order to be able to rollback, an in-memory database must journal
|
||||
** the page we are moving from.
|
||||
*/
|
||||
if( MEMDB ){
|
||||
rc = sqlite3PagerWrite(pPg);
|
||||
if( rc ) return rc;
|
||||
}
|
||||
|
||||
/* If the page being moved is dirty and has not been saved by the latest
|
||||
** savepoint, then save the current contents of the page into the
|
||||
** sub-journal now. This is required to handle the following scenario:
|
||||
|
@ -5117,7 +5131,7 @@ int sqlite3PagerMovepage(Pager *pPager, DbPage *pPg, Pgno pgno, int isCommit){
|
|||
** one or more savepoint bitvecs. This is the reason this function
|
||||
** may return SQLITE_NOMEM.
|
||||
*/
|
||||
if( pPg->flags&PGHDR_DIRTY
|
||||
if( pPg->flags&PGHDR_DIRTY
|
||||
&& subjRequiresPage(pPg)
|
||||
&& SQLITE_OK!=(rc = subjournalPage(pPg))
|
||||
){
|
||||
|
@ -5152,7 +5166,14 @@ int sqlite3PagerMovepage(Pager *pPager, DbPage *pPg, Pgno pgno, int isCommit){
|
|||
assert( !pPgOld || pPgOld->nRef==1 );
|
||||
if( pPgOld ){
|
||||
pPg->flags |= (pPgOld->flags&PGHDR_NEED_SYNC);
|
||||
sqlite3PcacheDrop(pPgOld);
|
||||
if( MEMDB ){
|
||||
/* Do not discard pages from an in-memory database since we might
|
||||
** need to rollback later. Just move the page out of the way. */
|
||||
assert( pPager->dbSizeValid );
|
||||
sqlite3PcacheMove(pPgOld, pPager->dbSize+1);
|
||||
}else{
|
||||
sqlite3PcacheDrop(pPgOld);
|
||||
}
|
||||
}
|
||||
|
||||
origPgno = pPg->pgno;
|
||||
|
@ -5197,18 +5218,12 @@ int sqlite3PagerMovepage(Pager *pPager, DbPage *pPg, Pgno pgno, int isCommit){
|
|||
|
||||
/*
|
||||
** For an in-memory database, make sure the original page continues
|
||||
** to exist, in case the transaction needs to roll back. We allocate
|
||||
** the page now, instead of at rollback, because we can better deal
|
||||
** with an out-of-memory error now. Ticket #3761.
|
||||
** to exist, in case the transaction needs to roll back. Use pPgOld
|
||||
** as the original page since it has already been allocated.
|
||||
*/
|
||||
if( MEMDB ){
|
||||
DbPage *pNew;
|
||||
rc = sqlite3PagerAcquire(pPager, origPgno, &pNew, 1);
|
||||
if( rc!=SQLITE_OK ){
|
||||
sqlite3PcacheMove(pPg, origPgno);
|
||||
return rc;
|
||||
}
|
||||
sqlite3PagerUnref(pNew);
|
||||
sqlite3PcacheMove(pPgOld, origPgno);
|
||||
sqlite3PagerUnref(pPgOld);
|
||||
}
|
||||
|
||||
return SQLITE_OK;
|
||||
|
|
|
@ -12,8 +12,6 @@
|
|||
** This header file defines the interface that the sqlite page cache
|
||||
** subsystem. The page cache subsystem reads and writes a file a page
|
||||
** at a time and provides a journal for rollback.
|
||||
**
|
||||
** @(#) $Id: pager.h,v 1.104 2009/07/24 19:01:19 drh Exp $
|
||||
*/
|
||||
|
||||
#ifndef _PAGER_H_
|
||||
|
|
23
src/parse.y
23
src/parse.y
|
@ -13,8 +13,6 @@
|
|||
** using the lemon parser generator to generate C code that runs
|
||||
** the parser. Lemon will also generate a header file containing
|
||||
** numeric codes for all of the tokens.
|
||||
**
|
||||
** @(#) $Id: parse.y,v 1.286 2009/08/10 03:57:58 shane Exp $
|
||||
*/
|
||||
|
||||
// All token codes are small integers with #defines that begin with "TK_"
|
||||
|
@ -886,6 +884,19 @@ expr(A) ::= expr(X) likeop(OP) expr(Y) escape(E). [LIKE_KW] {
|
|||
expr(A) ::= expr(X) ISNULL|NOTNULL(E). {spanUnaryPostfix(&A,pParse,@E,&X,&E);}
|
||||
expr(A) ::= expr(X) NOT NULL(E). {spanUnaryPostfix(&A,pParse,TK_NOTNULL,&X,&E);}
|
||||
|
||||
%include {
|
||||
/* A routine to convert a binary TK_IS or TK_ISNOT expression into a
|
||||
** unary TK_ISNULL or TK_NOTNULL expression. */
|
||||
static void binaryToUnaryIfNull(Parse *pParse, Expr *pY, Expr *pA, int op){
|
||||
sqlite3 *db = pParse->db;
|
||||
if( db->mallocFailed==0 && pY->op==TK_NULL ){
|
||||
pA->op = (u8)op;
|
||||
sqlite3ExprDelete(db, pA->pRight);
|
||||
pA->pRight = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// expr1 IS expr2
|
||||
// expr1 IS NOT expr2
|
||||
//
|
||||
|
@ -894,15 +905,11 @@ expr(A) ::= expr(X) NOT NULL(E). {spanUnaryPostfix(&A,pParse,TK_NOTNULL,&X,&E);}
|
|||
//
|
||||
expr(A) ::= expr(X) IS expr(Y). {
|
||||
spanBinaryExpr(&A,pParse,TK_IS,&X,&Y);
|
||||
if( pParse->db->mallocFailed==0 && Y.pExpr->op==TK_NULL ){
|
||||
A.pExpr->op = TK_ISNULL;
|
||||
}
|
||||
binaryToUnaryIfNull(pParse, Y.pExpr, A.pExpr, TK_ISNULL);
|
||||
}
|
||||
expr(A) ::= expr(X) IS NOT expr(Y). {
|
||||
spanBinaryExpr(&A,pParse,TK_ISNOT,&X,&Y);
|
||||
if( pParse->db->mallocFailed==0 && Y.pExpr->op==TK_NULL ){
|
||||
A.pExpr->op = TK_NOTNULL;
|
||||
}
|
||||
binaryToUnaryIfNull(pParse, Y.pExpr, A.pExpr, TK_NOTNULL);
|
||||
}
|
||||
|
||||
%include {
|
||||
|
|
1346
src/parse.y.ex1
1346
src/parse.y.ex1
File diff suppressed because it is too large
Load Diff
|
@ -10,8 +10,6 @@
|
|||
**
|
||||
*************************************************************************
|
||||
** This file implements that page cache.
|
||||
**
|
||||
** @(#) $Id: pcache.c,v 1.47 2009/07/25 11:46:49 danielk1977 Exp $
|
||||
*/
|
||||
#include "sqliteInt.h"
|
||||
|
||||
|
|
|
@ -11,8 +11,6 @@
|
|||
*************************************************************************
|
||||
** This header file defines the interface that the sqlite page cache
|
||||
** subsystem.
|
||||
**
|
||||
** @(#) $Id: pcache.h,v 1.20 2009/07/25 11:46:49 danielk1977 Exp $
|
||||
*/
|
||||
|
||||
#ifndef _PCACHE_H_
|
||||
|
|
|
@ -15,8 +15,6 @@
|
|||
** of the SQLITE_CONFIG_PAGECACHE and sqlite3_release_memory() features.
|
||||
** If the default page cache implementation is overriden, then neither of
|
||||
** these two features are available.
|
||||
**
|
||||
** @(#) $Id: pcache1.c,v 1.19 2009/07/17 11:44:07 drh Exp $
|
||||
*/
|
||||
|
||||
#include "sqliteInt.h"
|
||||
|
@ -667,15 +665,7 @@ static void pcache1Rekey(
|
|||
pPage->iKey = iNew;
|
||||
pPage->pNext = pCache->apHash[h];
|
||||
pCache->apHash[h] = pPage;
|
||||
|
||||
/* The xRekey() interface is only used to move pages earlier in the
|
||||
** database file (in order to move all free pages to the end of the
|
||||
** file where they can be truncated off.) Hence, it is not possible
|
||||
** for the new page number to be greater than the largest previously
|
||||
** fetched page. But we retain the following test in case xRekey()
|
||||
** begins to be used in different ways in the future.
|
||||
*/
|
||||
if( NEVER(iNew>pCache->iMaxKey) ){
|
||||
if( iNew>pCache->iMaxKey ){
|
||||
pCache->iMaxKey = iNew;
|
||||
}
|
||||
|
||||
|
|
|
@ -10,8 +10,6 @@
|
|||
**
|
||||
*************************************************************************
|
||||
** This file contains code used to implement the PRAGMA command.
|
||||
**
|
||||
** $Id: pragma.c,v 1.214 2009/07/02 07:47:33 danielk1977 Exp $
|
||||
*/
|
||||
#include "sqliteInt.h"
|
||||
|
||||
|
@ -1130,6 +1128,7 @@ void sqlite3Pragma(
|
|||
sqlite3VdbeAddOp2(v, OP_AddImm, 2, 1); /* increment entry count */
|
||||
for(j=0, pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext, j++){
|
||||
int jmp2;
|
||||
int r1;
|
||||
static const VdbeOpList idxErr[] = {
|
||||
{ OP_AddImm, 1, -1, 0},
|
||||
{ OP_String8, 0, 3, 0}, /* 1 */
|
||||
|
@ -1143,8 +1142,8 @@ void sqlite3Pragma(
|
|||
{ OP_IfPos, 1, 0, 0}, /* 9 */
|
||||
{ OP_Halt, 0, 0, 0},
|
||||
};
|
||||
sqlite3GenerateIndexKey(pParse, pIdx, 1, 3, 1);
|
||||
jmp2 = sqlite3VdbeAddOp3(v, OP_Found, j+2, 0, 3);
|
||||
r1 = sqlite3GenerateIndexKey(pParse, pIdx, 1, 3, 0);
|
||||
jmp2 = sqlite3VdbeAddOp4Int(v, OP_Found, j+2, 0, r1, pIdx->nColumn+1);
|
||||
addr = sqlite3VdbeAddOpList(v, ArraySize(idxErr), idxErr);
|
||||
sqlite3VdbeChangeP4(v, addr+1, "rowid ", P4_STATIC);
|
||||
sqlite3VdbeChangeP4(v, addr+3, " missing from index ", P4_STATIC);
|
||||
|
|
|
@ -12,8 +12,6 @@
|
|||
** This file contains the implementation of the sqlite3_prepare()
|
||||
** interface, and routines that contribute to loading the database schema
|
||||
** from disk.
|
||||
**
|
||||
** $Id: prepare.c,v 1.131 2009/08/06 17:43:31 drh Exp $
|
||||
*/
|
||||
#include "sqliteInt.h"
|
||||
|
||||
|
|
29
src/printf.c
29
src/printf.c
|
@ -5,8 +5,6 @@
|
|||
** an historical reference. Most of the "enhancements" have been backed
|
||||
** out so that the functionality is now the same as standard printf().
|
||||
**
|
||||
** $Id: printf.c,v 1.104 2009/06/03 01:24:54 drh Exp $
|
||||
**
|
||||
**************************************************************************
|
||||
**
|
||||
** The following modules is an enhanced replacement for the "printf" subroutines
|
||||
|
@ -647,14 +645,15 @@ void sqlite3VXPrintf(
|
|||
case etSQLESCAPE:
|
||||
case etSQLESCAPE2:
|
||||
case etSQLESCAPE3: {
|
||||
int i, j, n, isnull;
|
||||
int i, j, k, n, isnull;
|
||||
int needQuote;
|
||||
char ch;
|
||||
char q = ((xtype==etSQLESCAPE3)?'"':'\''); /* Quote character */
|
||||
char *escarg = va_arg(ap,char*);
|
||||
isnull = escarg==0;
|
||||
if( isnull ) escarg = (xtype==etSQLESCAPE2 ? "NULL" : "(NULL)");
|
||||
for(i=n=0; (ch=escarg[i])!=0; i++){
|
||||
k = precision;
|
||||
for(i=n=0; (ch=escarg[i])!=0 && k!=0; i++, k--){
|
||||
if( ch==q ) n++;
|
||||
}
|
||||
needQuote = !isnull && xtype==etSQLESCAPE2;
|
||||
|
@ -670,15 +669,17 @@ void sqlite3VXPrintf(
|
|||
}
|
||||
j = 0;
|
||||
if( needQuote ) bufpt[j++] = q;
|
||||
for(i=0; (ch=escarg[i])!=0; i++){
|
||||
bufpt[j++] = ch;
|
||||
k = i;
|
||||
for(i=0; i<k; i++){
|
||||
bufpt[j++] = ch = escarg[i];
|
||||
if( ch==q ) bufpt[j++] = ch;
|
||||
}
|
||||
if( needQuote ) bufpt[j++] = q;
|
||||
bufpt[j] = 0;
|
||||
length = j;
|
||||
/* The precision is ignored on %q and %Q */
|
||||
/* if( precision>=0 && precision<length ) length = precision; */
|
||||
/* The precision in %q and %Q means how many input characters to
|
||||
** consume, not the length of the output...
|
||||
** if( precision>=0 && precision<length ) length = precision; */
|
||||
break;
|
||||
}
|
||||
case etTOKEN: {
|
||||
|
@ -956,3 +957,15 @@ void sqlite3DebugPrintf(const char *zFormat, ...){
|
|||
fflush(stdout);
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifndef SQLITE_OMIT_TRACE
|
||||
/*
|
||||
** variable-argument wrapper around sqlite3VXPrintf().
|
||||
*/
|
||||
void sqlite3XPrintf(StrAccum *p, const char *zFormat, ...){
|
||||
va_list ap;
|
||||
va_start(ap,zFormat);
|
||||
sqlite3VXPrintf(p, 1, zFormat, ap);
|
||||
va_end(ap);
|
||||
}
|
||||
#endif
|
||||
|
|
|
@ -14,8 +14,6 @@
|
|||
**
|
||||
** Random numbers are used by some of the database backends in order
|
||||
** to generate random integer keys for tables or random filenames.
|
||||
**
|
||||
** $Id: random.c,v 1.29 2008/12/10 19:26:24 drh Exp $
|
||||
*/
|
||||
#include "sqliteInt.h"
|
||||
|
||||
|
|
|
@ -13,8 +13,6 @@
|
|||
** This file contains routines used for walking the parser tree and
|
||||
** resolve all identifiers by associating them with a particular
|
||||
** table and column.
|
||||
**
|
||||
** $Id: resolve.c,v 1.30 2009/06/15 23:15:59 drh Exp $
|
||||
*/
|
||||
#include "sqliteInt.h"
|
||||
#include <stdlib.h>
|
||||
|
@ -89,7 +87,13 @@ static void resolveAlias(
|
|||
pDup->pColl = pExpr->pColl;
|
||||
pDup->flags |= EP_ExpCollate;
|
||||
}
|
||||
sqlite3ExprClear(db, pExpr);
|
||||
|
||||
/* Before calling sqlite3ExprDelete(), set the EP_Static flag. This
|
||||
** prevents ExprDelete() from deleting the Expr structure itself,
|
||||
** allowing it to be repopulated by the memcpy() on the following line.
|
||||
*/
|
||||
ExprSetProperty(pExpr, EP_Static);
|
||||
sqlite3ExprDelete(db, pExpr);
|
||||
memcpy(pExpr, pDup, sizeof(*pExpr));
|
||||
sqlite3DbFree(db, pDup);
|
||||
}
|
||||
|
@ -260,6 +264,10 @@ static int lookupName(
|
|||
testcase( iCol==31 );
|
||||
testcase( iCol==32 );
|
||||
pParse->oldmask |= (iCol>=32 ? 0xffffffff : (((u32)1)<<iCol));
|
||||
}else{
|
||||
testcase( iCol==31 );
|
||||
testcase( iCol==32 );
|
||||
pParse->newmask |= (iCol>=32 ? 0xffffffff : (((u32)1)<<iCol));
|
||||
}
|
||||
pExpr->iColumn = (i16)iCol;
|
||||
pExpr->pTab = pTab;
|
||||
|
|
|
@ -59,8 +59,6 @@
|
|||
**
|
||||
** There is an added cost of O(N) when switching between TEST and
|
||||
** SMALLEST primitives.
|
||||
**
|
||||
** $Id: rowset.c,v 1.7 2009/05/22 01:00:13 drh Exp $
|
||||
*/
|
||||
#include "sqliteInt.h"
|
||||
|
||||
|
|
30
src/select.c
30
src/select.c
|
@ -11,8 +11,6 @@
|
|||
*************************************************************************
|
||||
** This file contains C code routines that are called by the parser
|
||||
** to handle SELECT statements in SQLite.
|
||||
**
|
||||
** $Id: select.c,v 1.526 2009/08/01 15:09:58 drh Exp $
|
||||
*/
|
||||
#include "sqliteInt.h"
|
||||
|
||||
|
@ -441,8 +439,8 @@ static void codeDistinct(
|
|||
|
||||
v = pParse->pVdbe;
|
||||
r1 = sqlite3GetTempReg(pParse);
|
||||
sqlite3VdbeAddOp4Int(v, OP_Found, iTab, addrRepeat, iMem, N);
|
||||
sqlite3VdbeAddOp3(v, OP_MakeRecord, iMem, N, r1);
|
||||
sqlite3VdbeAddOp3(v, OP_Found, iTab, addrRepeat, r1);
|
||||
sqlite3VdbeAddOp2(v, OP_IdxInsert, iTab, r1);
|
||||
sqlite3ReleaseTempReg(pParse, r1);
|
||||
}
|
||||
|
@ -683,8 +681,7 @@ static void selectInnerLoop(
|
|||
if( p->iLimit ){
|
||||
assert( pOrderBy==0 ); /* If there is an ORDER BY, the call to
|
||||
** pushOntoSorter() would have cleared p->iLimit */
|
||||
sqlite3VdbeAddOp2(v, OP_AddImm, p->iLimit, -1);
|
||||
sqlite3VdbeAddOp2(v, OP_IfZero, p->iLimit, iBreak);
|
||||
sqlite3VdbeAddOp3(v, OP_IfZero, p->iLimit, iBreak, -1);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1310,7 +1307,7 @@ static void computeLimitRegisters(Parse *pParse, Select *p, int iBreak){
|
|||
Vdbe *v = 0;
|
||||
int iLimit = 0;
|
||||
int iOffset;
|
||||
int addr1;
|
||||
int addr1, n;
|
||||
if( p->iLimit ) return;
|
||||
|
||||
/*
|
||||
|
@ -1325,10 +1322,18 @@ static void computeLimitRegisters(Parse *pParse, Select *p, int iBreak){
|
|||
p->iLimit = iLimit = ++pParse->nMem;
|
||||
v = sqlite3GetVdbe(pParse);
|
||||
if( NEVER(v==0) ) return; /* VDBE should have already been allocated */
|
||||
sqlite3ExprCode(pParse, p->pLimit, iLimit);
|
||||
sqlite3VdbeAddOp1(v, OP_MustBeInt, iLimit);
|
||||
VdbeComment((v, "LIMIT counter"));
|
||||
sqlite3VdbeAddOp2(v, OP_IfZero, iLimit, iBreak);
|
||||
if( sqlite3ExprIsInteger(p->pLimit, &n) ){
|
||||
sqlite3VdbeAddOp2(v, OP_Integer, n, iLimit);
|
||||
VdbeComment((v, "LIMIT counter"));
|
||||
if( n==0 ){
|
||||
sqlite3VdbeAddOp2(v, OP_Goto, 0, iBreak);
|
||||
}
|
||||
}else{
|
||||
sqlite3ExprCode(pParse, p->pLimit, iLimit);
|
||||
sqlite3VdbeAddOp1(v, OP_MustBeInt, iLimit);
|
||||
VdbeComment((v, "LIMIT counter"));
|
||||
sqlite3VdbeAddOp2(v, OP_IfZero, iLimit, iBreak);
|
||||
}
|
||||
if( p->pOffset ){
|
||||
p->iOffset = iOffset = ++pParse->nMem;
|
||||
pParse->nMem++; /* Allocate an extra register for limit+offset */
|
||||
|
@ -1664,7 +1669,7 @@ static int multiSelect(
|
|||
sqlite3VdbeAddOp2(v, OP_Rewind, tab1, iBreak);
|
||||
r1 = sqlite3GetTempReg(pParse);
|
||||
iStart = sqlite3VdbeAddOp2(v, OP_RowKey, tab1, r1);
|
||||
sqlite3VdbeAddOp3(v, OP_NotFound, tab2, iCont, r1);
|
||||
sqlite3VdbeAddOp4Int(v, OP_NotFound, tab2, iCont, r1, 0);
|
||||
sqlite3ReleaseTempReg(pParse, r1);
|
||||
selectInnerLoop(pParse, p, p->pEList, tab1, p->pEList->nExpr,
|
||||
0, -1, &dest, iCont, iBreak);
|
||||
|
@ -1883,8 +1888,7 @@ static int generateOutputSubroutine(
|
|||
/* Jump to the end of the loop if the LIMIT is reached.
|
||||
*/
|
||||
if( p->iLimit ){
|
||||
sqlite3VdbeAddOp2(v, OP_AddImm, p->iLimit, -1);
|
||||
sqlite3VdbeAddOp2(v, OP_IfZero, p->iLimit, iBreak);
|
||||
sqlite3VdbeAddOp3(v, OP_IfZero, p->iLimit, iBreak, -1);
|
||||
}
|
||||
|
||||
/* Generate the subroutine return
|
||||
|
|
104
src/shell.c
104
src/shell.c
|
@ -11,8 +11,6 @@
|
|||
*************************************************************************
|
||||
** This file contains code to implement the "sqlite" command line
|
||||
** utility for accessing SQLite databases.
|
||||
**
|
||||
** $Id: shell.c,v 1.210 2009/05/31 17:16:10 drh Exp $
|
||||
*/
|
||||
#if defined(_WIN32) || defined(WIN32)
|
||||
/* This needs to come before any includes for MSVC compiler */
|
||||
|
@ -2140,7 +2138,8 @@ static char zHelp[] =
|
|||
" LIKE pattern TABLE.\n"
|
||||
".echo ON|OFF Turn command echo on or off\n"
|
||||
".exit Exit this program\n"
|
||||
".explain ON|OFF Turn output mode suitable for EXPLAIN on or off.\n"
|
||||
".explain ?ON|OFF? Turn output mode suitable for EXPLAIN on or off.\n"
|
||||
" With no args, it turns EXPLAIN on.\n"
|
||||
#if !defined(SQLITE_OMIT_VIRTUALTABLE) && !defined(SQLITE_OMIT_SUBQUERY)
|
||||
".genfkey ?OPTIONS? Options are:\n"
|
||||
" --no-drop: Do not drop old fkey triggers.\n"
|
||||
|
@ -2186,7 +2185,7 @@ static char zHelp[] =
|
|||
" If TABLE specified, only list tables matching\n"
|
||||
" LIKE pattern TABLE.\n"
|
||||
".timeout MS Try opening locked tables for MS milliseconds\n"
|
||||
".width NUM NUM ... Set column widths for \"column\" mode\n"
|
||||
".width NUM1 NUM2 ... Set column widths for \"column\" mode\n"
|
||||
;
|
||||
|
||||
static char zTimerHelp[] =
|
||||
|
@ -2313,7 +2312,7 @@ static int do_meta_command(char *zLine, struct callback_data *p){
|
|||
if( nArg==0 ) return 0; /* no tokens, no error */
|
||||
n = strlen30(azArg[0]);
|
||||
c = azArg[0][0];
|
||||
if( c=='b' && n>=3 && strncmp(azArg[0], "backup", n)==0 && nArg>1 ){
|
||||
if( c=='b' && n>=3 && strncmp(azArg[0], "backup", n)==0 && nArg>1 && nArg<4){
|
||||
const char *zDestFile;
|
||||
const char *zDb;
|
||||
sqlite3 *pDest;
|
||||
|
@ -2349,11 +2348,11 @@ static int do_meta_command(char *zLine, struct callback_data *p){
|
|||
sqlite3_close(pDest);
|
||||
}else
|
||||
|
||||
if( c=='b' && n>=3 && strncmp(azArg[0], "bail", n)==0 && nArg>1 ){
|
||||
if( c=='b' && n>=3 && strncmp(azArg[0], "bail", n)==0 && nArg>1 && nArg<3 ){
|
||||
bail_on_error = booleanValue(azArg[1]);
|
||||
}else
|
||||
|
||||
if( c=='d' && n>1 && strncmp(azArg[0], "databases", n)==0 ){
|
||||
if( c=='d' && n>1 && strncmp(azArg[0], "databases", n)==0 && nArg==1 ){
|
||||
struct callback_data data;
|
||||
char *zErrMsg = 0;
|
||||
open_db(p);
|
||||
|
@ -2372,7 +2371,7 @@ static int do_meta_command(char *zLine, struct callback_data *p){
|
|||
}
|
||||
}else
|
||||
|
||||
if( c=='d' && strncmp(azArg[0], "dump", n)==0 ){
|
||||
if( c=='d' && strncmp(azArg[0], "dump", n)==0 && nArg<3 ){
|
||||
char *zErrMsg = 0;
|
||||
open_db(p);
|
||||
/* When playing back a "dump", the content might appear in an order
|
||||
|
@ -2425,15 +2424,15 @@ static int do_meta_command(char *zLine, struct callback_data *p){
|
|||
}
|
||||
}else
|
||||
|
||||
if( c=='e' && strncmp(azArg[0], "echo", n)==0 && nArg>1 ){
|
||||
if( c=='e' && strncmp(azArg[0], "echo", n)==0 && nArg>1 && nArg<3 ){
|
||||
p->echoOn = booleanValue(azArg[1]);
|
||||
}else
|
||||
|
||||
if( c=='e' && strncmp(azArg[0], "exit", n)==0 ){
|
||||
if( c=='e' && strncmp(azArg[0], "exit", n)==0 && nArg==1 ){
|
||||
rc = 2;
|
||||
}else
|
||||
|
||||
if( c=='e' && strncmp(azArg[0], "explain", n)==0 ){
|
||||
if( c=='e' && strncmp(azArg[0], "explain", n)==0 && nArg<3 ){
|
||||
int val = nArg>=2 ? booleanValue(azArg[1]) : 1;
|
||||
if(val == 1) {
|
||||
if(!p->explainPrev.valid) {
|
||||
|
@ -2480,7 +2479,7 @@ static int do_meta_command(char *zLine, struct callback_data *p){
|
|||
#endif
|
||||
|
||||
if( c=='h' && (strncmp(azArg[0], "header", n)==0 ||
|
||||
strncmp(azArg[0], "headers", n)==0 )&& nArg>1 ){
|
||||
strncmp(azArg[0], "headers", n)==0) && nArg>1 && nArg<3 ){
|
||||
p->showHeader = booleanValue(azArg[1]);
|
||||
}else
|
||||
|
||||
|
@ -2491,7 +2490,7 @@ static int do_meta_command(char *zLine, struct callback_data *p){
|
|||
}
|
||||
}else
|
||||
|
||||
if( c=='i' && strncmp(azArg[0], "import", n)==0 && nArg>=3 ){
|
||||
if( c=='i' && strncmp(azArg[0], "import", n)==0 && nArg==3 ){
|
||||
char *zTable = azArg[2]; /* Insert data into this table */
|
||||
char *zFile = azArg[1]; /* The file from which to extract data */
|
||||
sqlite3_stmt *pStmt = NULL; /* A statement */
|
||||
|
@ -2608,7 +2607,7 @@ static int do_meta_command(char *zLine, struct callback_data *p){
|
|||
sqlite3_exec(p->db, zCommit, 0, 0, 0);
|
||||
}else
|
||||
|
||||
if( c=='i' && strncmp(azArg[0], "indices", n)==0 ){
|
||||
if( c=='i' && strncmp(azArg[0], "indices", n)==0 && nArg<3 ){
|
||||
struct callback_data data;
|
||||
char *zErrMsg = 0;
|
||||
open_db(p);
|
||||
|
@ -2687,35 +2686,31 @@ static int do_meta_command(char *zLine, struct callback_data *p){
|
|||
}else
|
||||
#endif
|
||||
|
||||
if( c=='m' && strncmp(azArg[0], "mode", n)==0 && nArg>=2 ){
|
||||
if( c=='m' && strncmp(azArg[0], "mode", n)==0 && nArg==2 ){
|
||||
int n2 = strlen30(azArg[1]);
|
||||
if( strncmp(azArg[1],"line",n2)==0
|
||||
if( (n2==4 && strncmp(azArg[1],"line",n2)==0)
|
||||
||
|
||||
strncmp(azArg[1],"lines",n2)==0 ){
|
||||
(n2==5 && strncmp(azArg[1],"lines",n2)==0) ){
|
||||
p->mode = MODE_Line;
|
||||
}else if( strncmp(azArg[1],"column",n2)==0
|
||||
}else if( (n2==6 && strncmp(azArg[1],"column",n2)==0)
|
||||
||
|
||||
strncmp(azArg[1],"columns",n2)==0 ){
|
||||
(n2==7 && strncmp(azArg[1],"columns",n2)==0) ){
|
||||
p->mode = MODE_Column;
|
||||
}else if( strncmp(azArg[1],"list",n2)==0 ){
|
||||
}else if( n2==4 && strncmp(azArg[1],"list",n2)==0 ){
|
||||
p->mode = MODE_List;
|
||||
}else if( strncmp(azArg[1],"html",n2)==0 ){
|
||||
}else if( n2==4 && strncmp(azArg[1],"html",n2)==0 ){
|
||||
p->mode = MODE_Html;
|
||||
}else if( strncmp(azArg[1],"tcl",n2)==0 ){
|
||||
}else if( n2==3 && strncmp(azArg[1],"tcl",n2)==0 ){
|
||||
p->mode = MODE_Tcl;
|
||||
}else if( strncmp(azArg[1],"csv",n2)==0 ){
|
||||
}else if( n2==3 && strncmp(azArg[1],"csv",n2)==0 ){
|
||||
p->mode = MODE_Csv;
|
||||
sqlite3_snprintf(sizeof(p->separator), p->separator, ",");
|
||||
}else if( strncmp(azArg[1],"tabs",n2)==0 ){
|
||||
}else if( n2==4 && strncmp(azArg[1],"tabs",n2)==0 ){
|
||||
p->mode = MODE_List;
|
||||
sqlite3_snprintf(sizeof(p->separator), p->separator, "\t");
|
||||
}else if( strncmp(azArg[1],"insert",n2)==0 ){
|
||||
}else if( n2==6 && strncmp(azArg[1],"insert",n2)==0 ){
|
||||
p->mode = MODE_Insert;
|
||||
if( nArg>=3 ){
|
||||
set_table_name(p, azArg[2]);
|
||||
}else{
|
||||
set_table_name(p, "table");
|
||||
}
|
||||
set_table_name(p, "table");
|
||||
}else {
|
||||
fprintf(stderr,"Error: mode should be one of: "
|
||||
"column csv html insert line list tabs tcl\n");
|
||||
|
@ -2723,6 +2718,18 @@ static int do_meta_command(char *zLine, struct callback_data *p){
|
|||
}
|
||||
}else
|
||||
|
||||
if( c=='m' && strncmp(azArg[0], "mode", n)==0 && nArg==3 ){
|
||||
int n2 = strlen30(azArg[1]);
|
||||
if( n2==6 && strncmp(azArg[1],"insert",n2)==0 ){
|
||||
p->mode = MODE_Insert;
|
||||
set_table_name(p, azArg[2]);
|
||||
}else {
|
||||
fprintf(stderr, "Error: invalid arguments: "
|
||||
" \"%s\". Enter \".help\" for help\n", azArg[2]);
|
||||
rc = 1;
|
||||
}
|
||||
}else
|
||||
|
||||
if( c=='n' && strncmp(azArg[0], "nullvalue", n)==0 && nArg==2 ) {
|
||||
sqlite3_snprintf(sizeof(p->nullvalue), p->nullvalue,
|
||||
"%.*s", (int)ArraySize(p->nullvalue)-1, azArg[1]);
|
||||
|
@ -2756,7 +2763,7 @@ static int do_meta_command(char *zLine, struct callback_data *p){
|
|||
}
|
||||
}else
|
||||
|
||||
if( c=='q' && strncmp(azArg[0], "quit", n)==0 ){
|
||||
if( c=='q' && strncmp(azArg[0], "quit", n)==0 && nArg==1 ){
|
||||
rc = 2;
|
||||
}else
|
||||
|
||||
|
@ -2771,7 +2778,7 @@ static int do_meta_command(char *zLine, struct callback_data *p){
|
|||
}
|
||||
}else
|
||||
|
||||
if( c=='r' && n>=3 && strncmp(azArg[0], "restore", n)==0 && nArg>1 ){
|
||||
if( c=='r' && n>=3 && strncmp(azArg[0], "restore", n)==0 && nArg>1 && nArg<4){
|
||||
const char *zSrcFile;
|
||||
const char *zDb;
|
||||
sqlite3 *pSrc;
|
||||
|
@ -2818,7 +2825,7 @@ static int do_meta_command(char *zLine, struct callback_data *p){
|
|||
sqlite3_close(pSrc);
|
||||
}else
|
||||
|
||||
if( c=='s' && strncmp(azArg[0], "schema", n)==0 ){
|
||||
if( c=='s' && strncmp(azArg[0], "schema", n)==0 && nArg<3 ){
|
||||
struct callback_data data;
|
||||
char *zErrMsg = 0;
|
||||
open_db(p);
|
||||
|
@ -2896,7 +2903,7 @@ static int do_meta_command(char *zLine, struct callback_data *p){
|
|||
"%.*s", (int)sizeof(p->separator)-1, azArg[1]);
|
||||
}else
|
||||
|
||||
if( c=='s' && strncmp(azArg[0], "show", n)==0){
|
||||
if( c=='s' && strncmp(azArg[0], "show", n)==0 && nArg==1 ){
|
||||
int i;
|
||||
fprintf(p->out,"%9.9s: %s\n","echo", p->echoOn ? "on" : "off");
|
||||
fprintf(p->out,"%9.9s: %s\n","explain", p->explainPrev.valid ? "on" :"off");
|
||||
|
@ -2917,7 +2924,7 @@ static int do_meta_command(char *zLine, struct callback_data *p){
|
|||
fprintf(p->out,"\n");
|
||||
}else
|
||||
|
||||
if( c=='t' && n>1 && strncmp(azArg[0], "tables", n)==0 ){
|
||||
if( c=='t' && n>1 && strncmp(azArg[0], "tables", n)==0 && nArg<3 ){
|
||||
char **azResult;
|
||||
int nRow;
|
||||
char *zErrMsg;
|
||||
|
@ -2975,12 +2982,16 @@ static int do_meta_command(char *zLine, struct callback_data *p){
|
|||
sqlite3_free_table(azResult);
|
||||
}else
|
||||
|
||||
if( c=='t' && n>4 && strncmp(azArg[0], "timeout", n)==0 && nArg>=2 ){
|
||||
if( c=='t' && n>4 && strncmp(azArg[0], "timeout", n)==0 && nArg==2 ){
|
||||
open_db(p);
|
||||
sqlite3_busy_timeout(p->db, atoi(azArg[1]));
|
||||
}else if( HAS_TIMER && c=='t' && n>=5 && strncmp(azArg[0], "timer", n)==0 && nArg>1 ){
|
||||
}else
|
||||
|
||||
if( HAS_TIMER && c=='t' && n>=5 && strncmp(azArg[0], "timer", n)==0 && nArg==2 ){
|
||||
enableTimer = booleanValue(azArg[1]);
|
||||
}else if( c=='w' && strncmp(azArg[0], "width", n)==0 ){
|
||||
}else
|
||||
|
||||
if( c=='w' && strncmp(azArg[0], "width", n)==0 && nArg>1 ){
|
||||
int j;
|
||||
assert( nArg<=ArraySize(azArg) );
|
||||
for(j=1; j<nArg && j<ArraySize(p->colWidth); j++){
|
||||
|
@ -3283,6 +3294,7 @@ static int process_sqliterc(
|
|||
** Show available command line options
|
||||
*/
|
||||
static const char zOptions[] =
|
||||
" -help show this message\n"
|
||||
" -init filename read/process named file\n"
|
||||
" -echo print commands before execution\n"
|
||||
" -[no]header turn headers on or off\n"
|
||||
|
@ -3361,7 +3373,6 @@ int main(int argc, char **argv){
|
|||
** we do the actual processing of arguments later in a second pass.
|
||||
*/
|
||||
}else if( strcmp(argv[i],"-batch")==0 ){
|
||||
i++;
|
||||
stdin_is_interactive = 0;
|
||||
}
|
||||
}
|
||||
|
@ -3381,6 +3392,11 @@ int main(int argc, char **argv){
|
|||
if( i<argc ){
|
||||
zFirstCmd = argv[i++];
|
||||
}
|
||||
if( i<argc ){
|
||||
fprintf(stderr,"%s: Error: too many options: \"%s\"\n", Argv0, argv[i]);
|
||||
fprintf(stderr,"Use -help for a list of options.\n");
|
||||
return 1;
|
||||
}
|
||||
data.out = stdout;
|
||||
|
||||
#ifdef SQLITE_OMIT_MEMORYDB
|
||||
|
@ -3431,10 +3447,20 @@ int main(int argc, char **argv){
|
|||
memcpy(data.separator,",",2);
|
||||
}else if( strcmp(z,"-separator")==0 ){
|
||||
i++;
|
||||
if(i>=argc){
|
||||
fprintf(stderr,"%s: Error: missing argument for option: %s\n", Argv0, z);
|
||||
fprintf(stderr,"Use -help for a list of options.\n");
|
||||
return 1;
|
||||
}
|
||||
sqlite3_snprintf(sizeof(data.separator), data.separator,
|
||||
"%.*s",(int)sizeof(data.separator)-1,argv[i]);
|
||||
}else if( strcmp(z,"-nullvalue")==0 ){
|
||||
i++;
|
||||
if(i>=argc){
|
||||
fprintf(stderr,"%s: Error: missing argument for option: %s\n", Argv0, z);
|
||||
fprintf(stderr,"Use -help for a list of options.\n");
|
||||
return 1;
|
||||
}
|
||||
sqlite3_snprintf(sizeof(data.nullvalue), data.nullvalue,
|
||||
"%.*s",(int)sizeof(data.nullvalue)-1,argv[i]);
|
||||
}else if( strcmp(z,"-header")==0 ){
|
||||
|
|
|
@ -820,7 +820,7 @@ struct sqlite3_vfs {
|
|||
** The sqlite3_initialize() routine initializes the
|
||||
** SQLite library. The sqlite3_shutdown() routine
|
||||
** deallocates any resources that were allocated by sqlite3_initialize().
|
||||
** This routines are designed to aid in process initialization and
|
||||
** These routines are designed to aid in process initialization and
|
||||
** shutdown on embedded systems. Workstation applications using
|
||||
** SQLite normally do not need to invoke either of these routines.
|
||||
**
|
||||
|
@ -1290,6 +1290,9 @@ int sqlite3_extended_result_codes(sqlite3*, int onoff);
|
|||
** For the purposes of this routine, an [INSERT] is considered to
|
||||
** be successful even if it is subsequently rolled back.
|
||||
**
|
||||
** This function is accessible to SQL statements via the
|
||||
** [last_insert_rowid() SQL function].
|
||||
**
|
||||
** Requirements:
|
||||
** [H12221] [H12223]
|
||||
**
|
||||
|
@ -1347,8 +1350,8 @@ sqlite3_int64 sqlite3_last_insert_rowid(sqlite3*);
|
|||
** However, the number returned does not include changes
|
||||
** caused by subtriggers since those have their own context.
|
||||
**
|
||||
** See also the [sqlite3_total_changes()] interface and the
|
||||
** [count_changes pragma].
|
||||
** See also the [sqlite3_total_changes()] interface, the
|
||||
** [count_changes pragma], and the [changes() SQL function].
|
||||
**
|
||||
** Requirements:
|
||||
** [H12241] [H12243]
|
||||
|
@ -1375,8 +1378,8 @@ int sqlite3_changes(sqlite3*);
|
|||
** completed (when the statement handle is passed to [sqlite3_reset()] or
|
||||
** [sqlite3_finalize()]).
|
||||
**
|
||||
** See also the [sqlite3_changes()] interface and the
|
||||
** [count_changes pragma].
|
||||
** See also the [sqlite3_changes()] interface, the
|
||||
** [count_changes pragma], and the [total_changes() SQL function].
|
||||
**
|
||||
** Requirements:
|
||||
** [H12261] [H12263]
|
||||
|
@ -2390,7 +2393,7 @@ int sqlite3_limit(sqlite3*, int id, int newVal);
|
|||
** In the "v2" interfaces, the prepared statement
|
||||
** that is returned (the [sqlite3_stmt] object) contains a copy of the
|
||||
** original SQL text. This causes the [sqlite3_step()] interface to
|
||||
** behave a differently in three ways:
|
||||
** behave differently in three ways:
|
||||
**
|
||||
** <ol>
|
||||
** <li>
|
||||
|
@ -4137,6 +4140,8 @@ int sqlite3_table_column_metadata(
|
|||
** {H12606} Extension loading must be enabled using
|
||||
** [sqlite3_enable_load_extension()] prior to calling this API,
|
||||
** otherwise an error will be returned.
|
||||
**
|
||||
** See also the [load_extension() SQL function].
|
||||
*/
|
||||
int sqlite3_load_extension(
|
||||
sqlite3 *db, /* Load the extension into this database connection */
|
||||
|
|
|
@ -14,8 +14,6 @@
|
|||
** an SQLite instance. Shared libraries that intend to be loaded
|
||||
** as extensions by SQLite should #include this file instead of
|
||||
** sqlite3.h.
|
||||
**
|
||||
** @(#) $Id: sqlite3ext.h,v 1.25 2008/10/12 00:27:54 shane Exp $
|
||||
*/
|
||||
#ifndef _SQLITE3EXT_H_
|
||||
#define _SQLITE3EXT_H_
|
||||
|
|
|
@ -484,9 +484,19 @@ extern const int sqlite3one;
|
|||
#define ROUNDDOWN8(x) ((x)&~7)
|
||||
|
||||
/*
|
||||
** Assert that the pointer X is aligned to an 8-byte boundary.
|
||||
** Assert that the pointer X is aligned to an 8-byte boundary. This
|
||||
** macro is used only within assert() to verify that the code gets
|
||||
** all alignment restrictions correct.
|
||||
**
|
||||
** Except, if SQLITE_4_BYTE_ALIGNED_MALLOC is defined, then the
|
||||
** underlying malloc() implemention might return us 4-byte aligned
|
||||
** pointers. In that case, only verify 4-byte alignment.
|
||||
*/
|
||||
#define EIGHT_BYTE_ALIGNMENT(X) ((((char*)(X) - (char*)0)&7)==0)
|
||||
#ifdef SQLITE_4_BYTE_ALIGNED_MALLOC
|
||||
# define EIGHT_BYTE_ALIGNMENT(X) ((((char*)(X) - (char*)0)&3)==0)
|
||||
#else
|
||||
# define EIGHT_BYTE_ALIGNMENT(X) ((((char*)(X) - (char*)0)&7)==0)
|
||||
#endif
|
||||
|
||||
|
||||
/*
|
||||
|
@ -959,6 +969,7 @@ struct FuncDef {
|
|||
#define SQLITE_FUNC_NEEDCOLL 0x08 /* sqlite3GetFuncCollSeq() might be called */
|
||||
#define SQLITE_FUNC_PRIVATE 0x10 /* Allowed for internal use only */
|
||||
#define SQLITE_FUNC_COUNT 0x20 /* Built-in count(*) aggregate */
|
||||
#define SQLITE_FUNC_COALESCE 0x40 /* Built-in coalesce() or ifnull() function */
|
||||
|
||||
/*
|
||||
** The following three macros, FUNCTION(), LIKEFUNC() and AGGREGATE() are
|
||||
|
@ -1508,7 +1519,7 @@ struct AggInfo {
|
|||
** the option is available (at compile-time).
|
||||
*/
|
||||
#if SQLITE_MAX_VARIABLE_NUMBER<=32767
|
||||
typedef i64 ynVar;
|
||||
typedef i16 ynVar;
|
||||
#else
|
||||
typedef int ynVar;
|
||||
#endif
|
||||
|
@ -2058,15 +2069,16 @@ struct AutoincInfo {
|
|||
** The Parse.pTriggerPrg list never contains two entries with the same
|
||||
** values for both pTrigger and orconf.
|
||||
**
|
||||
** The TriggerPrg.oldmask variable is set to a mask of old.* columns
|
||||
** The TriggerPrg.aColmask[0] variable is set to a mask of old.* columns
|
||||
** accessed (or set to 0 for triggers fired as a result of INSERT
|
||||
** statements).
|
||||
** statements). Similarly, the TriggerPrg.aColmask[1] variable is set to
|
||||
** a mask of new.* columns used by the program.
|
||||
*/
|
||||
struct TriggerPrg {
|
||||
Trigger *pTrigger; /* Trigger this program was coded from */
|
||||
int orconf; /* Default ON CONFLICT policy */
|
||||
SubProgram *pProgram; /* Program implementing pTrigger/orconf */
|
||||
u32 oldmask; /* Mask of old.* columns accessed */
|
||||
u32 aColmask[2]; /* Masks of old.*, new.* columns accessed */
|
||||
TriggerPrg *pNext; /* Next entry in Parse.pTriggerPrg list */
|
||||
};
|
||||
|
||||
|
@ -2138,6 +2150,7 @@ struct Parse {
|
|||
Parse *pToplevel; /* Parse structure for main program (or NULL) */
|
||||
Table *pTriggerTab; /* Table triggers are being coded for */
|
||||
u32 oldmask; /* Mask of old.* columns referenced */
|
||||
u32 newmask; /* Mask of new.* columns referenced */
|
||||
u8 eTriggerOp; /* TK_UPDATE, TK_INSERT or TK_DELETE */
|
||||
u8 eOrconf; /* Default ON CONFLICT policy for trigger steps */
|
||||
u8 disableTriggers; /* True to disable triggers */
|
||||
|
@ -2516,6 +2529,9 @@ void sqlite3StatusSet(int, int);
|
|||
int sqlite3IsNaN(double);
|
||||
|
||||
void sqlite3VXPrintf(StrAccum*, int, const char*, va_list);
|
||||
#ifndef SQLITE_OMIT_TRACE
|
||||
void sqlite3XPrintf(StrAccum*, const char*, ...);
|
||||
#endif
|
||||
char *sqlite3MPrintf(sqlite3*,const char*, ...);
|
||||
char *sqlite3VMPrintf(sqlite3*,const char*, va_list);
|
||||
char *sqlite3MAppendf(sqlite3*,char*,const char*,...);
|
||||
|
@ -2543,7 +2559,6 @@ Expr *sqlite3PExpr(Parse*, int, Expr*, Expr*, const Token*);
|
|||
Expr *sqlite3ExprAnd(sqlite3*,Expr*, Expr*);
|
||||
Expr *sqlite3ExprFunction(Parse*,ExprList*, Token*);
|
||||
void sqlite3ExprAssignVarNumber(Parse*, Expr*);
|
||||
void sqlite3ExprClear(sqlite3*, Expr*);
|
||||
void sqlite3ExprDelete(sqlite3*, Expr*);
|
||||
ExprList *sqlite3ExprListAppend(Parse*,ExprList*,Expr*);
|
||||
void sqlite3ExprListSetName(Parse*,ExprList*,Token*,int);
|
||||
|
@ -2673,6 +2688,9 @@ int sqlite3ExprIsConstant(Expr*);
|
|||
int sqlite3ExprIsConstantNotJoin(Expr*);
|
||||
int sqlite3ExprIsConstantOrFunction(Expr*);
|
||||
int sqlite3ExprIsInteger(Expr*, int*);
|
||||
int sqlite3ExprCanBeNull(const Expr*);
|
||||
void sqlite3ExprCodeIsNullJump(Vdbe*, const Expr*, int, int);
|
||||
int sqlite3ExprNeedsNoAffinityChange(const Expr*, char);
|
||||
int sqlite3IsRowid(const char*);
|
||||
void sqlite3GenerateRowDelete(Parse*, Table*, int, int, int, Trigger *, int);
|
||||
void sqlite3GenerateRowIndexDelete(Parse*, Table*, int, int*);
|
||||
|
@ -2730,7 +2748,7 @@ void sqlite3MaterializeView(Parse*, Table*, Expr*, int);
|
|||
TriggerStep *sqlite3TriggerDeleteStep(sqlite3*,Token*, Expr*);
|
||||
void sqlite3DeleteTrigger(sqlite3*, Trigger*);
|
||||
void sqlite3UnlinkAndDeleteTrigger(sqlite3*,int,const char*);
|
||||
u32 sqlite3TriggerOldmask(Parse*,Trigger*,ExprList*,Table*,int);
|
||||
u32 sqlite3TriggerColmask(Parse*,Trigger*,ExprList*,int,int,Table*,int);
|
||||
# define sqlite3ParseToplevel(p) ((p)->pToplevel ? (p)->pToplevel : (p))
|
||||
#else
|
||||
# define sqlite3TriggersExist(B,C,D,E,F) 0
|
||||
|
@ -2741,7 +2759,7 @@ void sqlite3MaterializeView(Parse*, Table*, Expr*, int);
|
|||
# define sqlite3CodeRowTriggerDirect(A,B,C,D,E,F)
|
||||
# define sqlite3TriggerList(X, Y) 0
|
||||
# define sqlite3ParseToplevel(p) p
|
||||
# define sqlite3TriggerOldmask(A,B,C,D,E) 0
|
||||
# define sqlite3TriggerColmask(A,B,C,D,E,F,G) 0
|
||||
#endif
|
||||
|
||||
int sqlite3JoinType(Parse*, Token*, Token*, Token*);
|
||||
|
@ -2844,6 +2862,7 @@ char *sqlite3Utf8to16(sqlite3 *, u8, char *, int, int *);
|
|||
int sqlite3ValueFromExpr(sqlite3 *, Expr *, u8, u8, sqlite3_value **);
|
||||
void sqlite3ValueApplyAffinity(sqlite3_value *, u8, u8);
|
||||
#ifndef SQLITE_AMALGAMATION
|
||||
extern const unsigned char sqlite3OpcodeProperty[];
|
||||
extern const unsigned char sqlite3UpperToLower[];
|
||||
extern const unsigned char sqlite3CtypeMap[];
|
||||
extern SQLITE_WSD struct Sqlite3Config sqlite3Config;
|
||||
|
@ -2954,6 +2973,7 @@ int sqlite3VtabCallDestroy(sqlite3*, int, const char *);
|
|||
int sqlite3VtabBegin(sqlite3 *, VTable *);
|
||||
FuncDef *sqlite3VtabOverloadFunction(sqlite3 *,FuncDef*, int nArg, Expr*);
|
||||
void sqlite3InvalidFunction(sqlite3_context*,int,sqlite3_value**);
|
||||
int sqlite3VdbeParameterIndex(Vdbe*, const char*, int);
|
||||
int sqlite3TransferBindings(sqlite3_stmt *, sqlite3_stmt *);
|
||||
int sqlite3Reprepare(Vdbe*);
|
||||
void sqlite3ExprListCheckLength(Parse*, ExprList*, const char*);
|
||||
|
|
|
@ -11,8 +11,6 @@
|
|||
*************************************************************************
|
||||
**
|
||||
** This file defines various limits of what SQLite can process.
|
||||
**
|
||||
** @(#) $Id: sqliteLimit.h,v 1.10 2009/01/10 16:15:09 danielk1977 Exp $
|
||||
*/
|
||||
|
||||
/*
|
||||
|
@ -197,9 +195,5 @@
|
|||
** may be executed.
|
||||
*/
|
||||
#ifndef SQLITE_MAX_TRIGGER_DEPTH
|
||||
#if defined(SQLITE_SMALL_STACK)
|
||||
# define SQLITE_MAX_TRIGGER_DEPTH 10
|
||||
#else
|
||||
# define SQLITE_MAX_TRIGGER_DEPTH 1000
|
||||
#endif
|
||||
#endif
|
||||
|
|
|
@ -12,8 +12,6 @@
|
|||
**
|
||||
** This module implements the sqlite3_status() interface and related
|
||||
** functionality.
|
||||
**
|
||||
** $Id: status.c,v 1.9 2008/09/02 00:52:52 drh Exp $
|
||||
*/
|
||||
#include "sqliteInt.h"
|
||||
|
||||
|
|
|
@ -15,8 +15,6 @@
|
|||
**
|
||||
** These routines are in a separate files so that they will not be linked
|
||||
** if they are not used.
|
||||
**
|
||||
** $Id: table.c,v 1.40 2009/04/10 14:28:00 drh Exp $
|
||||
*/
|
||||
#include "sqliteInt.h"
|
||||
#include <stdlib.h>
|
||||
|
|
|
@ -33,10 +33,11 @@
|
|||
** appended to the amalgamation.
|
||||
*/
|
||||
#ifndef SQLITE_AMALGAMATION
|
||||
# include "sqliteInt.h"
|
||||
# include "sqlite3.h"
|
||||
# include <stdlib.h>
|
||||
# include <string.h>
|
||||
# include <assert.h>
|
||||
typedef unsigned char u8;
|
||||
#endif
|
||||
#include <ctype.h>
|
||||
|
||||
|
@ -3447,16 +3448,6 @@ static char zMainloop[] =
|
|||
;
|
||||
#endif
|
||||
|
||||
/*
|
||||
** If the macro TCLSH is two, then get the main loop code out of
|
||||
** the separate file "spaceanal_tcl.h".
|
||||
*/
|
||||
#if TCLSH==2
|
||||
static char zMainloop[] =
|
||||
#include "spaceanal_tcl.h"
|
||||
;
|
||||
#endif
|
||||
|
||||
#define TCLSH_MAIN main /* Needed to fake out mktclapp */
|
||||
int TCLSH_MAIN(int argc, char **argv){
|
||||
Tcl_Interp *interp;
|
||||
|
@ -3498,6 +3489,7 @@ int TCLSH_MAIN(int argc, char **argv){
|
|||
extern int SqlitetestOnefile_Init();
|
||||
extern int SqlitetestOsinst_Init(Tcl_Interp*);
|
||||
extern int Sqlitetestbackup_Init(Tcl_Interp*);
|
||||
extern int Sqlitetestintarray_Init(Tcl_Interp*);
|
||||
|
||||
Sqliteconfig_Init(interp);
|
||||
Sqlitetest1_Init(interp);
|
||||
|
@ -3522,13 +3514,14 @@ int TCLSH_MAIN(int argc, char **argv){
|
|||
SqlitetestOnefile_Init(interp);
|
||||
SqlitetestOsinst_Init(interp);
|
||||
Sqlitetestbackup_Init(interp);
|
||||
Sqlitetestintarray_Init(interp);
|
||||
|
||||
#ifdef SQLITE_SSE
|
||||
Sqlitetestsse_Init(interp);
|
||||
#endif
|
||||
}
|
||||
#endif
|
||||
if( argc>=2 || TCLSH==2 ){
|
||||
if( argc>=2 ){
|
||||
int i;
|
||||
char zArgc[32];
|
||||
sqlite3_snprintf(sizeof(zArgc), zArgc, "%d", argc-(3-TCLSH));
|
||||
|
@ -3539,14 +3532,14 @@ int TCLSH_MAIN(int argc, char **argv){
|
|||
Tcl_SetVar(interp, "argv", argv[i],
|
||||
TCL_GLOBAL_ONLY | TCL_LIST_ELEMENT | TCL_APPEND_VALUE);
|
||||
}
|
||||
if( TCLSH==1 && Tcl_EvalFile(interp, argv[1])!=TCL_OK ){
|
||||
if( Tcl_EvalFile(interp, argv[1])!=TCL_OK ){
|
||||
const char *zInfo = Tcl_GetVar(interp, "errorInfo", TCL_GLOBAL_ONLY);
|
||||
if( zInfo==0 ) zInfo = Tcl_GetStringResult(interp);
|
||||
fprintf(stderr,"%s: %s\n", *argv, zInfo);
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
if( argc<=1 || TCLSH==2 ){
|
||||
if( argc<=1 ){
|
||||
Tcl_GlobalEval(interp, zMainloop);
|
||||
}
|
||||
return 0;
|
||||
|
|
|
@ -12,8 +12,6 @@
|
|||
** Code for testing all sorts of SQLite interfaces. This code
|
||||
** is not included in the SQLite library. It is used for automated
|
||||
** testing of the SQLite library.
|
||||
**
|
||||
** $Id: test1.c,v 1.354 2009/08/10 04:37:50 danielk1977 Exp $
|
||||
*/
|
||||
#include "sqliteInt.h"
|
||||
#include "tcl.h"
|
||||
|
|
|
@ -12,8 +12,6 @@
|
|||
** Code for testing the pager.c module in SQLite. This code
|
||||
** is not included in the SQLite library. It is used for automated
|
||||
** testing of the SQLite library.
|
||||
**
|
||||
** $Id: test2.c,v 1.74 2009/07/24 19:01:20 drh Exp $
|
||||
*/
|
||||
#include "sqliteInt.h"
|
||||
#include "tcl.h"
|
||||
|
|
|
@ -12,8 +12,6 @@
|
|||
** Code for testing the btree.c module in SQLite. This code
|
||||
** is not included in the SQLite library. It is used for automated
|
||||
** testing of the SQLite library.
|
||||
**
|
||||
** $Id: test3.c,v 1.111 2009/07/09 05:07:38 danielk1977 Exp $
|
||||
*/
|
||||
#include "sqliteInt.h"
|
||||
#include "btreeInt.h"
|
||||
|
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue