update to 3.6.21

This commit is contained in:
Stephen Lombardo 2009-12-19 15:56:40 -05:00
parent 7941e188aa
commit 090d3d3b9b
178 changed files with 11938 additions and 10556 deletions

View File

@ -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

View File

@ -1 +1 @@
3.6.20
3.6.21

18
configure vendored
View File

@ -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'`\\"

View File

@ -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]=='/' ){

File diff suppressed because it is too large Load Diff

279
ext/fts3/fts3Int.h Normal file
View File

@ -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 */

View File

@ -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));
}
}

View File

@ -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

View File

@ -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);

View File

@ -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);

View File

@ -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++);

734
ext/fts3/fts3_snippet.c Normal file
View File

@ -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

View File

@ -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
);

View File

@ -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;

2171
ext/fts3/fts3_write.c Normal file

File diff suppressed because it is too large Load Diff

View File

@ -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)

View File

@ -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]

View File

@ -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]

View File

@ -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

View File

@ -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]

View File

@ -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]

View File

@ -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

View File

@ -72,5 +72,3 @@ set rtree_select_time [time {
}
}]
puts "$rtree_select_time"

View File

@ -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
}

View File

@ -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

View File

@ -186,4 +186,3 @@ proc cell_report {db zTab iParent iCell} {
view_node
bind .c <Configure> view_node

20
main.mk
View File

@ -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
View File

@ -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-----

View File

@ -1 +1 @@
eb7a544fe49d1626bacecfe53ddc03fe082e3243
1ed88e9d01e9eda5cbc622e7614277f29bcc551c

View File

@ -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)

View File

@ -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"

View File

@ -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"

View File

@ -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"

View File

@ -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"

View File

@ -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"

View File

@ -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"

View File

@ -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

View File

@ -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;

View File

@ -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(

View File

@ -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
**

View File

@ -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"

View File

@ -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"

View File

@ -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;

View File

@ -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

View File

@ -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;
}

View File

@ -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, &regFree1);
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, &regFree1);
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, &regFree1);
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: {

View File

@ -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

View File

@ -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);

View File

@ -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 ),

View File

@ -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;

View File

@ -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>

View File

@ -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_

View File

@ -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_

View File

@ -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"

View File

@ -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"

View File

@ -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"

View File

@ -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

View File

@ -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>

View File

@ -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"

View File

@ -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"

View File

@ -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"

View File

@ -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"

View File

@ -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"

View File

@ -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"

View File

@ -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 $
*/

View File

@ -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"

View File

@ -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,

View File

@ -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"

View File

@ -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"

View File

@ -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"

View File

@ -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

View File

@ -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_

View File

@ -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_

View File

@ -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"

View File

@ -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;
}
}

View File

@ -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;

View File

@ -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_

View File

@ -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 {

File diff suppressed because it is too large Load Diff

View File

@ -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"

View File

@ -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_

View File

@ -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;
}

View File

@ -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);

View File

@ -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"

View File

@ -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

View File

@ -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"

View File

@ -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;

View File

@ -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"

View File

@ -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

View File

@ -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 ){

View File

@ -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 */

View File

@ -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_

View File

@ -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*);

View File

@ -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

View File

@ -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"

View File

@ -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>

View File

@ -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;

View File

@ -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"

View File

@ -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"

View File

@ -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