#endif
+/*
+** Each time a blob is read from the %_data table, it is padded with this
+** many zero bytes. This makes it easier to decode the various record formats
+** without overreading if the records are corrupt.
+*/
+#define FTS5_DATA_ZERO_PADDING 8
+
typedef struct Fts5BtreeIter Fts5BtreeIter;
typedef struct Fts5BtreeIterLevel Fts5BtreeIterLevel;
typedef struct Fts5ChunkIter Fts5ChunkIter;
aOut = pBuf->p;
pBuf->n = nByte;
}else{
- pRet = (Fts5Data*)sqlite3Fts5MallocZero(&rc, nByte+sizeof(Fts5Data));
+ int nSpace = nByte + FTS5_DATA_ZERO_PADDING;
+ pRet = (Fts5Data*)sqlite3Fts5MallocZero(&rc, nSpace+sizeof(Fts5Data));
if( pRet ){
pRet->n = nByte;
aOut = pRet->p = (u8*)&pRet[1];
){
i64 iRowid; /* Rowid for record being decoded */
int iIdx,iSegid,iHeight,iPgno; /* Rowid components */
- const u8 *a; int n; /* Record to decode */
+ const u8 *aBlob; int n; /* Record to decode */
+ u8 *a = 0;
Fts5Buffer s; /* Build up text to return here */
int rc = SQLITE_OK; /* Return code */
+ int nSpace = 0;
assert( nArg==2 );
memset(&s, 0, sizeof(Fts5Buffer));
iRowid = sqlite3_value_int64(apVal[0]);
n = sqlite3_value_bytes(apVal[1]);
- a = sqlite3_value_blob(apVal[1]);
+ aBlob = sqlite3_value_blob(apVal[1]);
+
+ nSpace = n + FTS5_DATA_ZERO_PADDING;
+ a = (u8*)sqlite3Fts5MallocZero(&rc, nSpace);
+ if( a==0 ) goto decode_out;
+ memcpy(a, aBlob, n);
fts5DecodeRowid(iRowid, &iIdx, &iSegid, &iHeight, &iPgno);
fts5DebugRowid(&rc, &s, iRowid);
int iOff;
int nKeep = 0;
- iRowidOff = fts5GetU16(&a[0]);
- iTermOff = fts5GetU16(&a[2]);
+ if( n>=4 ){
+ iRowidOff = fts5GetU16(&a[0]);
+ iTermOff = fts5GetU16(&a[2]);
+ }else{
+ sqlite3Fts5BufferSet(&rc, &s, 8, (const u8*)"corrupt");
+ goto decode_out;
+ }
if( iRowidOff ){
iOff = iRowidOff;
}
}
+ decode_out:
+ sqlite3_free(a);
if( rc==SQLITE_OK ){
sqlite3_result_text(pCtx, (const char*)s.p, s.n, SQLITE_TRANSIENT);
}else{
}else {
sqlite3_result_error(pCtx,
"first arg to fts5_rowid() must be 'segment' "
- "or 'start-of-index' ..."
+ "or 'start-of-index'"
, -1
);
}
#
#
-if 1 {
+if 0 {
faultsim_save_and_close
do_faultsim_test 1 -prep {
"
}
+
+}
+
#-------------------------------------------------------------------------
# The following tests use a larger database populated with random data.
#
faultsim_test_result [list 0 {}]
}
+do_faultsim_test 5.5.1 -faults oom* -body {
+ execsql {
+ SELECT count(fts5_decode(rowid, block)) FROM x1_data WHERE rowid=1
+ }
+} -test {
+ faultsim_test_result [list 0 1]
+}
+do_faultsim_test 5.5.2 -faults oom* -body {
+ execsql {
+ SELECT count(fts5_decode(rowid, block)) FROM x1_data WHERE rowid=10
+ }
+} -test {
+ faultsim_test_result [list 0 1]
+}
+do_faultsim_test 5.5.3 -faults oom* -body {
+ execsql {
+ SELECT count(fts5_decode(rowid, block)) FROM x1_data WHERE rowid = (
+ SELECT min(rowid) FROM x1_data WHERE rowid>20
+ )
+ }
+} -test {
+ faultsim_test_result [list 0 1]
+}
+do_faultsim_test 5.5.4 -faults oom* -body {
+ execsql {
+ SELECT count(fts5_decode(rowid, block)) FROM x1_data WHERE rowid = (
+ SELECT max(rowid) FROM x1_data
+ )
+ }
+} -test {
+ faultsim_test_result [list 0 1]
}
+finish_test
+
#-------------------------------------------------------------------------
#
reset_db
faultsim_save_and_close
-do_faultsim_test 6.1 -faults oom-tr* -prep {
+do_faultsim_test 6.1 -faults oom* -prep {
faultsim_restore_and_reopen
} -body {
execsql { INSERT INTO x1 VALUES('d e f') }
}
}
+#-------------------------------------------------------------------------
+do_faultsim_test 7.0 -faults oom* -prep {
+ catch { db close }
+} -body {
+ sqlite3 db test.db
+} -test {
+ faultsim_test_result [list 0 {}] [list 1 {}]
+}
+
+
finish_test
--- /dev/null
+# 2014 Dec 20
+#
+# The author disclaims copyright to this source code. In place of
+# a legal notice, here is a blessing:
+#
+# May you do good and not evil.
+# May you find forgiveness for yourself and forgive others.
+# May you share freely, never taking more than you give.
+#
+#***********************************************************************
+#
+# Tests of the scalar fts5_rowid() and fts5_decode() functions.
+#
+
+source [file join [file dirname [info script]] fts5_common.tcl]
+set testprefix fts5rowid
+
+do_catchsql_test 1.1 {
+ SELECT fts5_rowid()
+} {1 {should be: fts5_rowid(subject, ....)}}
+
+do_catchsql_test 1.2 {
+ SELECT fts5_rowid('segment')
+} {1 {should be: fts5_rowid('segment', idx, segid, height, pgno))}}
+
+do_execsql_test 1.3 {
+ SELECT fts5_rowid('segment', 1, 1, 1, 1)
+} {4503670494330881}
+
+do_catchsql_test 1.4 {
+ SELECT fts5_rowid('start-of-index');
+} {1 {should be: fts5_rowid('start-of-index', idx)}}
+
+do_execsql_test 1.5 {
+ SELECT fts5_rowid('start-of-index', 1);
+} {4503668346847232}
+
+do_catchsql_test 1.4 {
+ SELECT fts5_rowid('nosucharg');
+} {1 {first arg to fts5_rowid() must be 'segment' or 'start-of-index'}}
+
+
+#-------------------------------------------------------------------------
+# Tests of the fts5_decode() function.
+#
+reset_db
+do_execsql_test 2.1 {
+ CREATE VIRTUAL TABLE x1 USING fts5(a, b);
+ INSERT INTO x1(x1, rank) VALUES('pgsz', 32);
+} {}
+
+proc rnddoc {n} {
+ set map [list 0 a 1 b 2 c 3 d 4 e 5 f 6 g 7 h 8 i 9 j]
+ set doc [list]
+ for {set i 0} {$i < $n} {incr i} {
+ lappend doc [string map $map [format %.3d [expr int(rand()*100)]]]
+ }
+ set doc
+}
+db func rnddoc rnddoc
+
+do_execsql_test 2.2 {
+ WITH r(a, b) AS (
+ SELECT rnddoc(6), rnddoc(6) UNION ALL
+ SELECT rnddoc(6), rnddoc(6) FROM r
+ )
+ INSERT INTO x1 SELECT * FROM r LIMIT 10000;
+}
+
+set res [db one {SELECT count(*) FROM x1_data}]
+do_execsql_test 2.3 {
+ SELECT count(fts5_decode(rowid, block)) FROM x1_data;
+} $res
+do_execsql_test 2.4 {
+ UPDATE x1_data SET block = X'';
+ SELECT count(fts5_decode(rowid, block)) FROM x1_data;
+} $res
+
+do_execsql_test 2.5 {
+ INSERT INTO x1(x1, rank) VALUES('pgsz', 1024);
+ INSERT INTO x1(x1) VALUES('rebuild');
+}
+
+set res [db one {SELECT count(*) FROM x1_data}]
+do_execsql_test 2.6 {
+ SELECT count(fts5_decode(rowid, block)) FROM x1_data;
+} $res
+do_execsql_test 2.7 {
+ UPDATE x1_data SET block = X'';
+ SELECT count(fts5_decode(rowid, block)) FROM x1_data;
+} $res
+
+#-------------------------------------------------------------------------
+# Tests with very large tokens.
+#
+set strlist [list \
+ "[string repeat x 400]" \
+ "[string repeat x 300][string repeat w 100]" \
+ "[string repeat x 300][string repeat y 100]" \
+ "[string repeat x 300][string repeat z 600]" \
+]
+do_test 3.0 {
+ execsql {
+ BEGIN;
+ CREATE VIRTUAL TABLE x2 USING fts5(a);
+ }
+ foreach str $strlist { execsql { INSERT INTO x2 VALUES($str) } }
+ execsql COMMIT
+} {}
+
+for {set tn 0} {$tn<[llength $strlist]} {incr tn} {
+ set str [lindex $strlist $tn]
+ do_execsql_test 3.1.$tn {
+ SELECT rowid FROM x2 WHERE x2 MATCH $str
+ } [expr $tn+1]
+}
+
+set res [db one {SELECT count(*) FROM x2_data}]
+do_execsql_test 3.2 {
+ SELECT count(fts5_decode(rowid, block)) FROM x2_data;
+} $res
+
+finish_test
+
-C Merge\slatest\strunk\schanges\swith\sthis\sbranch.
-D 2015-01-21T06:36:07.043
+C Add\sfurther\stests\sfor\sfts5\sbackend.
+D 2015-01-21T16:10:59.815
F Makefile.arm-wince-mingw32ce-gcc d6df77f1f48d690bd73162294bbba7f59507c72f
F Makefile.in 5407a688f4d77a05c18a8142be8ae5a2829dd610
F Makefile.linux-gcc 91d710bdc4998cb015f39edf3cb314ec4f4d7e23
F autoconf/tea/Makefile.in d55bcc63832caf0309c2ff80358756116618cfca
F autoconf/tea/README 3e9a3c060f29a44344ab50aec506f4db903fb873
F autoconf/tea/aclocal.m4 52c47aac44ce0ddb1f918b6993e8beb8eee88f43
-F autoconf/tea/configure.ac 93d43c79e936fb16556e22498177d7e8571efa04 w autoconf/tea/configure.in
+F autoconf/tea/configure.ac 93d43c79e936fb16556e22498177d7e8571efa04
F autoconf/tea/doc/sqlite3.n e1fe45d4f5286ee3d0ccc877aca2a0def488e9bb
F autoconf/tea/license.terms 13bd403c9610fd2b76ece0ab50c4c5eda933d523
F autoconf/tea/pkgIndex.tcl.in 3ef61715cf1c7bdcff56947ffadb26bc991ca39d
F ext/fts5/fts5_config.c 33534ca25198cc62c54ff7d285d455c57ad19399
F ext/fts5/fts5_expr.c 8a0e643768666dc2bffe74104141274809699808
F ext/fts5/fts5_hash.c 63fa8379c5f2ac107d47c2b7d9ac04c95ef8a279
-F ext/fts5/fts5_index.c 8c34dd95f780ff4010af75643a1960bbde70045d
+F ext/fts5/fts5_index.c 49e470a6380e572d2e7dcce48399f6dc294d7247
F ext/fts5/fts5_storage.c 8bc9e5b6654e1545e9513def277ef3f025921664
F ext/fts5/fts5_tcl.c 1293fac2bb26903fd3d5cdee59c5885ba7e620d5
F ext/fts5/fts5_tokenize.c 7c61d5c35c3449597bdeaa54dd48afe26852c7b0
F ext/fts5/test/fts5content.test 4234e0b11e003fe1e80472aa637f70464396fdd0
F ext/fts5/test/fts5ea.test 04695560a444fcc00c3c4f27783bdcfbf71f030c
F ext/fts5/test/fts5eb.test 728a1f23f263548f5c29b29dfb851b5f2dbe723e
-F ext/fts5/test/fts5fault1.test 2c077402045f0b4e69ae1de6cfa51b0c4c5044c2
+F ext/fts5/test/fts5fault1.test 73b55c5b777f6dfb18022abd5cec2e569464e21c
F ext/fts5/test/fts5near.test 3f9f64e16cac82725d03d4e04c661090f0b3b947
F ext/fts5/test/fts5optimize.test 0028c90a7817d3e576d1148fc8dff17d89054e54
F ext/fts5/test/fts5porter.test 50322599823cb8080a99f0ec0c39f7d0c12bcb5e
F ext/fts5/test/fts5prefix.test 4610dfba4460d92f23a8014874a46493f1be77b5
F ext/fts5/test/fts5rebuild.test 2a5e98205393487b4a732c8290999af7c0b907b4
+F ext/fts5/test/fts5rowid.test 44f90d91538f037470f6a438f21bfe65916129f4
F ext/fts5/test/fts5tokenizer.test b34ae592db66f6e89546d791ce1f905ba0b3395c
F ext/fts5/test/fts5unicode.test 79b3e34eb29ce4929628aa514a40cb467fdabe4d
F ext/fts5/test/fts5unicode2.test 64a5267fd6082fcb46439892ebd0cbaa5c38acee
F tool/warnings-clang.sh f6aa929dc20ef1f856af04a730772f59283631d4
F tool/warnings.sh 0abfd78ceb09b7f7c27c688c8e3fe93268a13b32
F tool/win/sqlite.vsix deb315d026cc8400325c5863eef847784a219a2f
-P f45a0dc0a8911c8aac5a1028ac4f543a709656e7 0077f64510f9b9ce90032df2696cb242d097ab84
-R e06147bbdf5a4901c5e35690744486d9
+P b3348b1e07e168b156636a29fc8c6d6afb3129c2
+R 7d4ce350ba9859353b62d149a7c21faf
U dan
-Z a4fb835870b87f88f9fea880f3a15d66
+Z 7c0fe174f4df11b7c7390d0e1d1bdddb
-b3348b1e07e168b156636a29fc8c6d6afb3129c2
\ No newline at end of file
+09dabb3b9e140eec6cfda83bcb86b6b9f5cf54b6
\ No newline at end of file