Merge latest changes from trunk. Including fts5_expr.c fixes.

FossilOrigin-Name: 716e7e747714d6af502f6a87ca8d789bb7ce162a
This commit is contained in:
dan
2015-09-10 15:52:42 +00:00
30 changed files with 885 additions and 375 deletions
+1 -7
View File
@@ -318,7 +318,6 @@ static int fts5ExprSynonymPoslist(
int *pbDel, /* OUT: Caller should sqlite3_free(*pa) */
u8 **pa, int *pn
){
Fts5PoslistWriter writer = {0};
Fts5PoslistReader aStatic[4];
Fts5PoslistReader *aIter = aStatic;
int nIter = 0;
@@ -653,7 +652,7 @@ static int fts5ExprNearAdvanceFirst(
i64 iFrom
){
Fts5ExprTerm *pTerm = &pNode->pNear->apPhrase[0]->aTerm[0];
int rc;
int rc = SQLITE_OK;
if( pTerm->pSynonym ){
int bEof = 1;
@@ -948,7 +947,6 @@ static int fts5ExprNearNextMatch(
for(j=0; j<pPhrase->nTerm; j++){
Fts5ExprTerm *pTerm = &pPhrase->aTerm[j];
if( pTerm->pSynonym ){
Fts5ExprTerm *p;
int bEof = 1;
i64 iRowid = fts5ExprSynonymRowid(pTerm, bDesc, 0);
if( iRowid==iLast ) continue;
@@ -1657,13 +1655,9 @@ int sqlite3Fts5ExprClonePhrase(
){
int rc = SQLITE_OK; /* Return code */
Fts5ExprPhrase *pOrig; /* The phrase extracted from pExpr */
Fts5ExprPhrase *pCopy; /* Copy of pOrig */
int i; /* Used to iterate through phrase terms */
Fts5Expr *pNew = 0; /* Expression to return via *ppNew */
Fts5ExprPhrase **apPhrase; /* pNew->apPhrase */
Fts5ExprNode *pNode; /* pNew->pRoot */
Fts5ExprNearset *pNear; /* pNew->pRoot->pNear */
TokenCtx sCtx = {0,0}; /* Context object for fts5ParseTokenize */
+38 -25
View File
@@ -83,6 +83,7 @@ static const char * const jsonType[] = {
#define JNODE_REPLACE 0x08 /* Replace with JsonNode.iVal */
#define JNODE_APPEND 0x10 /* More ARRAY/OBJECT entries at u.iAppend */
#define JNODE_JSON 0x20 /* Treat REPLACE as JSON text */
#define JNODE_LABEL 0x40 /* Is a label of an object */
/* A single node of parsed JSON
@@ -583,6 +584,7 @@ static int jsonParseValue(JsonParse *pParse, u32 i){
u32 j;
int iThis;
int x;
JsonNode *pNode;
while( isspace(pParse->zJson[i]) ){ i++; }
if( (c = pParse->zJson[i])==0 ) return 0;
if( c=='{' ){
@@ -597,7 +599,9 @@ static int jsonParseValue(JsonParse *pParse, u32 i){
return -1;
}
if( pParse->oom ) return -1;
if( pParse->aNode[pParse->nNode-1].eType!=JSON_STRING ) return -1;
pNode = &pParse->aNode[pParse->nNode-1];
if( pNode->eType!=JSON_STRING ) return -1;
pNode->jnFlags |= JNODE_LABEL;
j = x;
while( isspace(pParse->zJson[j]) ){ j++; }
if( pParse->zJson[j]!=':' ) return -1;
@@ -1036,13 +1040,20 @@ static void jsonParseFunc(
jsonParseFindParents(&x);
jsonInit(&s, ctx);
for(i=0; i<x.nNode; i++){
jsonPrintf(100, &s,"node %3u: %7s n=%-4d up=%d\n",
i, jsonType[x.aNode[i].eType], x.aNode[i].n, x.aUp[i]);
if( x.aNode[i].u.zJContent!=0 ){
jsonAppendRaw(&s, " text: ", 10);
jsonAppendRaw(&s, x.aNode[i].u.zJContent, x.aNode[i].n);
jsonAppendRaw(&s, "\n", 1);
const char *zType;
if( x.aNode[i].jnFlags & JNODE_LABEL ){
assert( x.aNode[i].eType==JSON_STRING );
zType = "label";
}else{
zType = jsonType[x.aNode[i].eType];
}
jsonPrintf(100, &s,"node %3u: %7s n=%-4d up=%-4d",
i, zType, x.aNode[i].n, x.aUp[i]);
if( x.aNode[i].u.zJContent!=0 ){
jsonAppendRaw(&s, " ", 1);
jsonAppendRaw(&s, x.aNode[i].u.zJContent, x.aNode[i].n);
}
jsonAppendRaw(&s, "\n", 1);
}
jsonParseReset(&x);
jsonResult(&s);
@@ -1427,6 +1438,7 @@ typedef struct JsonEachCursor JsonEachCursor;
struct JsonEachCursor {
sqlite3_vtab_cursor base; /* Base class - must be first */
u32 iRowid; /* The rowid */
u32 iBegin; /* The first node of the scan */
u32 i; /* Index in sParse.aNode[] of current row */
u32 iEnd; /* EOF when i equals or exceeds this value */
u8 eType; /* Type of top-level element */
@@ -1534,16 +1546,10 @@ static int jsonEachEof(sqlite3_vtab_cursor *cur){
static int jsonEachNext(sqlite3_vtab_cursor *cur){
JsonEachCursor *p = (JsonEachCursor*)cur;
if( p->bRecursive ){
if( p->i==0 ){
p->i = 1;
}else{
u32 iUp = p->sParse.aUp[p->i];
JsonNode *pUp = &p->sParse.aNode[iUp];
p->i++;
if( pUp->eType==JSON_OBJECT && (pUp->n + iUp >= p->i) ) p->i++;
}
if( p->sParse.aNode[p->i].jnFlags & JNODE_LABEL ) p->i++;
p->i++;
p->iRowid++;
if( p->i<p->sParse.nNode ){
if( p->i<p->iEnd ){
u32 iUp = p->sParse.aUp[p->i];
JsonNode *pUp = &p->sParse.aNode[iUp];
p->eType = pUp->eType;
@@ -1597,8 +1603,9 @@ static void jsonEachComputePath(
jsonPrintf(30, pStr, "[%d]", pUp->u.iKey);
}else{
assert( pUp->eType==JSON_OBJECT );
if( pNode->eType>=JSON_ARRAY ) pNode--;
if( (pNode->jnFlags & JNODE_LABEL)==0 ) pNode--;
assert( pNode->eType==JSON_STRING );
assert( pNode->jnFlags & JNODE_LABEL );
jsonPrintf(pNode->n+1, pStr, ".%.*s", pNode->n-2, pNode->u.zJContent+1);
}
}
@@ -1629,27 +1636,28 @@ static int jsonEachColumn(
break;
}
case JEACH_VALUE: {
if( p->eType==JSON_OBJECT && p->i>0 ) pThis++;
if( pThis->jnFlags & JNODE_LABEL ) pThis++;
jsonReturn(pThis, ctx, 0);
break;
}
case JEACH_TYPE: {
if( p->eType==JSON_OBJECT && p->i>0 ) pThis++;
if( pThis->jnFlags & JNODE_LABEL ) pThis++;
sqlite3_result_text(ctx, jsonType[pThis->eType], -1, SQLITE_STATIC);
break;
}
case JEACH_ATOM: {
if( p->eType==JSON_OBJECT && p->i>0 ) pThis++;
if( pThis->jnFlags & JNODE_LABEL ) pThis++;
if( pThis->eType>=JSON_ARRAY ) break;
jsonReturn(pThis, ctx, 0);
break;
}
case JEACH_ID: {
sqlite3_result_int64(ctx, (sqlite3_int64)p->i + (p->eType==JSON_OBJECT));
sqlite3_result_int64(ctx,
(sqlite3_int64)p->i + ((pThis->jnFlags & JNODE_LABEL)!=0));
break;
}
case JEACH_PARENT: {
if( p->i>0 && p->bRecursive ){
if( p->i>p->iBegin && p->bRecursive ){
sqlite3_result_int64(ctx, (sqlite3_int64)p->sParse.aUp[p->i]);
}
break;
@@ -1794,7 +1802,6 @@ static int jsonEachFilter(
JsonNode *pNode;
if( idxNum==3 ){
const char *zErr = 0;
p->bRecursive = 0;
n = sqlite3_value_bytes(argv[1]);
p->zPath = sqlite3_malloc64( n+1 );
if( p->zPath==0 ) return SQLITE_NOMEM;
@@ -1811,12 +1818,18 @@ static int jsonEachFilter(
}else{
pNode = p->sParse.aNode;
}
p->i = (int)(pNode - p->sParse.aNode);
p->iBegin = p->i = (int)(pNode - p->sParse.aNode);
p->eType = pNode->eType;
if( p->eType>=JSON_ARRAY ){
pNode->u.iKey = 0;
p->iEnd = p->i + pNode->n + 1;
if( !p->bRecursive ) p->i++;
if( p->bRecursive ){
if( p->i>0 && (p->sParse.aNode[p->i-1].jnFlags & JNODE_LABEL)!=0 ){
p->i--;
}
}else{
p->i++;
}
}else{
p->iEnd = p->i+1;
}
+1 -1
View File
@@ -586,7 +586,7 @@ parse.h: parse.c
parse.c: $(TOP)/src/parse.y lemon $(TOP)/addopcodes.awk
cp $(TOP)/src/parse.y .
rm -f parse.h
./lemon $(OPTS) parse.y
./lemon -s $(OPTS) parse.y
mv parse.h parse.h.temp
$(NAWK) -f $(TOP)/addopcodes.awk parse.h.temp >parse.h
+33 -32
View File
@@ -1,5 +1,5 @@
C Update\sdescription\sof\son-disk\sformat\sin\sfts5_index.c.
D 2015-09-10T15:49:16.123
C Merge\slatest\schanges\sfrom\strunk.\sIncluding\sfts5_expr.c\sfixes.
D 2015-09-10T15:52:42.491
F Makefile.arm-wince-mingw32ce-gcc d6df77f1f48d690bd73162294bbba7f59507c72f
F Makefile.in f85066ce844a28b671aaeeff320921cd0ce36239
F Makefile.linux-gcc 91d710bdc4998cb015f39edf3cb314ec4f4d7e23
@@ -110,7 +110,7 @@ F ext/fts5/fts5Int.h 7e6002582133cb795a21468732cf7c35027a28e4
F ext/fts5/fts5_aux.c 7a307760a9c57c750d043188ec0bad59f5b5ec7e
F ext/fts5/fts5_buffer.c 64dcaf36a3ebda9e84b7c3b8788887ec325e12a4
F ext/fts5/fts5_config.c 57ee5fe71578cb494574fc0e6e51acb9a22a8695
F ext/fts5/fts5_expr.c 1c24e1a2ffb286bfe37e537a43b7fadabfe993d4
F ext/fts5/fts5_expr.c a7726fe7045eec7caca8a074af747c8ea3545b83
F ext/fts5/fts5_hash.c 4bf4b99708848357b8a2b5819e509eb6d3df9246
F ext/fts5/fts5_index.c bd2b6e63c1ed8329176d73a9491023eaf06c572f
F ext/fts5/fts5_main.c 4b04c934084ea24a858438a04b5be8af3a9e0311
@@ -195,7 +195,7 @@ F ext/misc/eval.c f971962e92ebb8b0a4e6b62949463ee454d88fa2
F ext/misc/fileio.c d4171c815d6543a9edef8308aab2951413cd8d0f
F ext/misc/fuzzer.c 4c84635c71c26cfa7c2e5848cf49fe2d2cfcd767
F ext/misc/ieee754.c b0362167289170627659e84173f5d2e8fee8566e
F ext/misc/json1.c bd51e8c1e8ce580e6f21493bd8e94ed5aca3d777
F ext/misc/json1.c 46c2aff110eb8241591cd29267ddb57a8d0ab337
F ext/misc/nextchar.c 35c8b8baacb96d92abbb34a83a997b797075b342
F ext/misc/percentile.c bcbee3c061b884eccb80e21651daaae8e1e43c63
F ext/misc/regexp.c af92cdaa5058fcec1451e49becc7ba44dba023dc
@@ -261,7 +261,7 @@ F ext/userauth/userauth.c 5fa3bdb492f481bbc1709fc83c91ebd13460c69e
F install-sh 9d4de14ab9fb0facae2f48780b874848cbf2f895 x
F ltmain.sh 3ff0879076df340d2e23ae905484d8c15d5fdea8
F magic.txt 8273bf49ba3b0c8559cb2774495390c31fd61c60
F main.mk 2bef49d698dd47369083c148387b4e57fc5bb82b
F main.mk 354f24951fcc2efd62aef684f2ae44e1128bfbeb
F mkopcodec.awk c2ff431854d702cdd2d779c9c0d1f58fa16fa4ea
F mkopcodeh.awk 0e7f04a8eb90f92259e47d80110e4e98d7ce337a
F mkso.sh fd21c06b063bb16a5d25deea1752c2da6ac3ed83
@@ -285,14 +285,14 @@ F src/btmutex.c 45a968cc85afed9b5e6cf55bf1f42f8d18107f79
F src/btree.c 4084d9eed2817331f6e6a82230ba30e448cad497
F src/btree.h 969adc948e89e449220ff0ff724c94bb2a52e9f1
F src/btreeInt.h 8177c9ab90d772d6d2c6c517e05bed774b7c92c0
F src/build.c 5566b3410080a54e5c302c55d3de53fd080cfc7d
F src/build.c f81380bc4d5d239c18b42982a9866a94489fd444
F src/callback.c 7b44ce59674338ad48b0e84e7b72f935ea4f68b0
F src/complete.c addcd8160b081131005d5bc2d34adf20c1c5c92f
F src/ctime.c 5a0b735dc95604766f5dac73973658eef782ee8b
F src/date.c fb1c99172017dcc8e237339132c91a21a0788584
F src/dbstat.c f402e77e25089c6003d0c60b3233b9b3947d599a
F src/dbstat.c e637e7a7ff40ef32132a418c6fdf1cfb63aa27c7
F src/delete.c 6792c80d7fb54c4df9f7680413952600e7439492
F src/expr.c f3c4d165dea72b268a7b922d00035af1d510dd78
F src/expr.c 3a76afcdac925294c39903b7002ddb9e5fd29863
F src/fault.c 160a0c015b6c2629d3899ed2daf63d75754a32bb
F src/fkey.c 83e1baba999bed3144ea5a2143fc922edf51135f
F src/func.c ecdd69ec6a1e406f04cc73324be2ebbf6354197f
@@ -303,10 +303,10 @@ F src/hwtime.h d32741c8f4df852c7d959236615444e2b1063b08
F src/insert.c 076dc5876e261a9908603d54cfc5344cd680166c
F src/journal.c b4124532212b6952f42eb2c12fa3c25701d8ba8d
F src/legacy.c ba1863ea58c4c840335a84ec276fc2b25e22bc4e
F src/lempar.c 92bafa308607dd985ca389a788cd9e0a2b608712
F src/lempar.c d344a95d60c24e2f490ee59db9784b1b17439012
F src/loadext.c dfcee8c7c032cd0fd55af3e0fc1fcfb01e426df2
F src/main.c e17fcffae4306a9b8334faf3bac80d7396850b54
F src/malloc.c 021012e28a81ffdabf4c30ec3df6ce1f6cc93f1d
F src/malloc.c 3a37ce6979a40f499d8cea9e9ab4e8517854d35d
F src/mem0.c 6a55ebe57c46ca1a7d98da93aaa07f99f1059645
F src/mem1.c abe6ee469b6c5a35c7f22bfeb9c9bac664a1c987
F src/mem2.c f1940d9e91948dd6a908fbb9ce3835c36b5d83c3
@@ -314,11 +314,11 @@ F src/mem3.c 61c9d47b792908c532ca3a62b999cf21795c6534
F src/mem5.c 61eeb90134f9a5be6c2e68d8daae7628b25953fb
F src/memjournal.c 3eb2c0b51adbd869cb6a44780323f05fa904dc85
F src/msvc.h d9ba56c6851227ab44b3f228a35f3f5772296495
F src/mutex.c 529e95739f815300a33c73fd8a7d6bdf0c24bd18
F src/mutex.c a39809c6c33f1ebc9cc781186c338ad90433e1e7
F src/mutex.h 779d588e3b7756ec3ecf7d78cde1d84aba414f85
F src/mutex_noop.c 9d4309c075ba9cc7249e19412d3d62f7f94839c4
F src/mutex_unix.c b0d280089df0f49545f1318f45d61d07d2f674a8
F src/mutex_w32.c b601f9e3073f7bd2c1f42a8c0ce59e42d6a08f85
F src/mutex_unix.c 7762c8ec907379204f2ed751a0e33663ab1c14d7
F src/mutex_w32.c 2e025e6642eaf27597403690980f560d1a91f62c
F src/notify.c 9711a7575036f0d3040ba61bc6e217f13a9888e7
F src/os.c 8fd25588eeba74068d41102d26810e216999b6c8
F src/os.h 3e57a24e2794a94d3cf2342c6d9a884888cd96bf
@@ -332,20 +332,20 @@ F src/pager.h 6d435f563b3f7fcae4b84433b76a6ac2730036e2
F src/parse.y f599aa5e871a493330d567ced93de696f61f48f7
F src/pcache.c 24be750c79272e0ca7b6e007bc94999700f3e5ef
F src/pcache.h 9968603796240cdf83da7e7bef76edf90619cea9
F src/pcache1.c bf2afe64a3dedb8643c8dcbd94a145cc80ab2a67
F src/pcache1.c ca0eeaaf9ffab7a9ded47d54639d8ab147d442e6
F src/pragma.c d71b813e67bf03f3116b9dd5164fbfd81ec673a2
F src/pragma.h 631a91c8b0e6ca8f051a1d8a4a0da4150e04620a
F src/prepare.c 82e5db1013846a819f198336fed72c44c974e7b1
F src/printf.c 0c4bcdd1c2e2521024f0a69cb5eb334f86b3652a
F src/random.c ba2679f80ec82c4190062d756f22d0c358180696
F src/resolve.c 47c00ca0ab24d4b8113c6c05aa07bc6cf6eac9af
F src/resolve.c 3126f7694b8ce0f97282d7dd3a5198b8fa18dce9
F src/rowset.c eccf6af6d620aaa4579bd3b72c1b6395d9e9fa1e
F src/select.c c17613385bc6b095c421b1f30548814f5fd8a9b2
F src/shell.c 6332ef06db1390ef812cfdff1fc97b4fd76cdd42
F src/sqlite.h.in 378bebc8fe6a88bade25e5f23b7e6123fdc64b00
F src/sqlite3.rc 992c9f5fb8285ae285d6be28240a7e8d3a7f2bad
F src/sqlite3ext.h f700e6a9dd1fdcccc9951ab022b366fb66b9e413
F src/sqliteInt.h e7e92112a71aeb214c66ebdea1366560535614d1
F src/sqlite3ext.h 5088f0b63491677da848c0d07d5711781302d362
F src/sqliteInt.h 788dc0ea7ba32ec9fec06c628c1792d7b4753d86
F src/sqliteLimit.h 216557999cb45f2e3578ed53ebefe228d779cb46
F src/status.c f266ad8a2892d659b74f0f50cb6a88b6e7c12179
F src/table.c 51b46b2a62d1b3a959633d593b89bab5e2c9155e
@@ -396,8 +396,8 @@ F src/test_vfs.c 3b65d42e18b262805716bd96178c81da8f2d9283
F src/test_vfstrace.c bab9594adc976cbe696ff3970728830b4c5ed698
F src/test_wsd.c 41cadfd9d97fe8e3e4e44f61a4a8ccd6f7ca8fe9
F src/threads.c 6bbcc9fe50c917864d48287b4792d46d6e873481
F src/tokenize.c 57cb3720f53f84d811def2069c2b169b6be539a5
F src/treeview.c 46036cbbceada0836833531b2d963edbca3d9cfa
F src/tokenize.c 83c6ed569423a3af83a83973b444cf7123be33a6
F src/treeview.c 154f0acc622fa3514de8777dcedf4c8a8802b4ce
F src/trigger.c 322f23aad694e8f31d384dcfa386d52a48d3c52f
F src/update.c 3c5bc9570df3bfafa0db36828406a8a14e4c426e
F src/utf.c fc6b889ba0779b7722634cdeaa25f1930d93820c
@@ -406,7 +406,7 @@ F src/vacuum.c 2ddd5cad2a7b9cef7f9e431b8c7771634c6b1701
F src/vdbe.c 6d85be995bd2308a5aa2a68c7b564c5d4cc1a6fb
F src/vdbe.h 4bc88bd0e06f8046ee6ab7487c0015e85ad949ad
F src/vdbeInt.h 8b54e01ad0463590e7cffabce0bc36da9ee4f816
F src/vdbeapi.c bda74ef4b5103d7b4a4be36f936d3cf2b56a7d6f
F src/vdbeapi.c b821d530bcb2900b4604cf5206f2177f3f881d15
F src/vdbeaux.c fd00b489ab3f44f2dca1e4344faf289b7bfcf649
F src/vdbeblob.c 1d7b97115e7bbac4c318db416d2ca83fc779544a
F src/vdbemem.c 19b3036aa4d676e7103b0fb5efd6327da455f915
@@ -414,10 +414,10 @@ F src/vdbesort.c f5009e7a35e3065635d8918b9a31f498a499976b
F src/vdbetrace.c 8befe829faff6d9e6f6e4dee5a7d3f85cc85f1a0
F src/vtab.c 2ecfe020c10e0a0c7b078203fdba2fae844744bc
F src/vxworks.h c18586c8edc1bddbc15c004fa16aeb1e1342b4fb
F src/wal.c 8cd07f1f99e1a81346db1c9da879bef6c6f97cf6
F src/wal.c 18b0ed49830cf04fe2d68224b41838a73ac6cd24
F src/wal.h df01efe09c5cb8c8e391ff1715cca294f89668a4
F src/walker.c 2e14d17f592d176b6dc879c33fbdec4fbccaa2ba
F src/where.c ed1cd1cb0434bca9f4a5379582c637bf393b34ac
F src/where.c 1227687e7892d4009f3c3433e974eb9c9e3c4d6a
F src/whereInt.h 292d3ac90da4eab1e03ac8452f1add746bcafaa1
F src/wherecode.c 6ac8599523f4840d9efac335329f627ebf3f79fd
F src/whereexpr.c 2473e4350e30f9b55d1c6a8f66ca23c689f23f1d
@@ -783,7 +783,7 @@ F test/index5.test 8621491915800ec274609e42e02a97d67e9b13e7
F test/index6.test 7102ec371414c42dfb1d5ca37eb4519aa9edc23a
F test/index7.test 9c6765a74fc3fcde7aebc5b3bd40d98df14a527c
F test/indexedby.test 5f527a78bae74c61b8046ae3037f9dfb0bf0c353
F test/indexexpr1.test 3c5033412f851f225e3a37d6795709df71bea638
F test/indexexpr1.test 4feec154aadacb033b41acc1760a18edc4c60470
F test/indexfault.test 31d4ab9a7d2f6e9616933eb079722362a883eb1d
F test/init.test 15c823093fdabbf7b531fe22cf037134d09587a7
F test/insert.test 38742b5e9601c8f8d76e9b7555f7270288c2d371
@@ -815,6 +815,7 @@ F test/jrnlmode.test 7864d59cf7f6e552b9b99ba0f38acd167edc10fa
F test/jrnlmode2.test 81610545a4e6ed239ea8fa661891893385e23a1d
F test/jrnlmode3.test 556b447a05be0e0963f4311e95ab1632b11c9eaa
F test/json101.test 11535d8986184500f4c30cc2f0b154b4ab05cc4e
F test/json102.test 12ef6d7d7c02c526fa3c2be1e933e7eb2a497cea
F test/keyword1.test 37ef6bba5d2ed5b07ecdd6810571de2956599dff
F test/lastinsert.test 42e948fd6442f07d60acbd15d33fb86473e0ef63
F test/laststmtchanges.test ae613f53819206b3222771828d024154d51db200
@@ -939,7 +940,7 @@ F test/rbu.test 168573d353cd0fd10196b87b0caa322c144ef736
F test/rdonly.test 64e2696c322e3538df0b1ed624e21f9a23ed9ff8
F test/regexp1.test 497ea812f264d12b6198d6e50a76be4a1973a9d8
F test/reindex.test 44edd3966b474468b823d481eafef0c305022254
F test/releasetest.tcl cd2de2749aab7f45b2fe91b4a05431fc08e1692a
F test/releasetest.tcl 5af0ca3d6a12471ffd9993c3efc00a553dfb2d41
F test/resolver01.test f4022acafda7f4d40eca94dbf16bc5fc4ac30ceb
F test/rollback.test 458fe73eb3ffdfdf9f6ba3e9b7350a6220414dea
F test/rollback2.test fc14cf6d1a2b250d2735ef16124b971bce152f14
@@ -1039,8 +1040,8 @@ F test/superlock.test 1cde669f68d2dd37d6c9bd35eee1d95491ae3fc2
F test/sync.test a34cd43e98b7fb84eabbf38f7ed8f7349b3f3d85
F test/syscall.test d2fdaad713f103ac611fe7ef9b724c7b69f8149c
F test/sysfault.test fa776e60bf46bdd3ae69f0b73e46ee3977a58ae6
F test/tabfunc01.test a12eba3f48a03a6626f985734ecc28132381fa9b
F test/table.test 33bf0d1fd07f304582695184b8e6feb017303816
F test/tabfunc01.test fa9d8dfc75747019e0be98d3b6ac68d18632d328
F test/table.test b708f3e5fa2542fa51dfab21fc07b36ea445cb2f
F test/tableapi.test 2674633fa95d80da917571ebdd759a14d9819126
F test/tableopts.test dba698ba97251017b7c80d738c198d39ab747930
F test/tclsqlite.test 7fb866443c7deceed22b63948ccd6f76b52ad054
@@ -1339,8 +1340,8 @@ F tool/fuzzershell.c f2fc86dd22df654b28851b85019d3bd007361751
F tool/genfkey.README cf68fddd4643bbe3ff8e31b8b6d8b0a1b85e20f4
F tool/genfkey.test 4196a8928b78f51d54ef58e99e99401ab2f0a7e5
F tool/getlock.c f4c39b651370156cae979501a7b156bdba50e7ce
F tool/lemon.c b12cb605725dabfa3a8607ec6bd9e978973c7af9
F tool/lempar.c 01ca97f87610d1dac6d8cd96ab109ab1130e76dc
F tool/lemon.c 039f813b520b9395740c52f9cbf36c90b5d8df03
F tool/lempar.c 3617143ddb9b176c3605defe6a9c798793280120
F tool/loadfts.c c3c64e4d5e90e8ba41159232c2189dba4be7b862
F tool/logest.c eef612f8adf4d0993dafed0416064cf50d5d33c6
F tool/mkautoconfamal.sh d1a2da0e15b2ed33d60af35c7e9d483f13a8eb9f
@@ -1366,7 +1367,7 @@ F tool/showstat4.c 9515faa8ec176599d4a8288293ba8ec61f7b728a
F tool/showwal.c 85cb36d4fe3e93e2fbd63e786e0d1ce42d0c4fad
F tool/soak1.tcl 8d407956e1a45b485a8e072470a3e629a27037fe
F tool/space_used.tcl f714c41a59e326b8b9042f415b628b561bafa06b
F tool/spaceanal.tcl 63a415385a66fdbf736bfd204a31c6d851ed8da6
F tool/spaceanal.tcl 93c1fdc9733c525b17a2024c7df193daa002e037
F tool/speedtest.tcl 06c76698485ccf597b9e7dbb1ac70706eb873355
F tool/speedtest16.c c8a9c793df96db7e4933f0852abb7a03d48f2e81
F tool/speedtest2.tcl ee2149167303ba8e95af97873c575c3e0fab58ff
@@ -1384,7 +1385,7 @@ F tool/vdbe_profile.tcl 67746953071a9f8f2f668b73fe899074e2c6d8c1
F tool/warnings-clang.sh f6aa929dc20ef1f856af04a730772f59283631d4
F tool/warnings.sh 48bd54594752d5be3337f12c72f28d2080cb630b
F tool/win/sqlite.vsix deb315d026cc8400325c5863eef847784a219a2f
P 402704b13f1f246c0224f90862bed93a825575f1
R 8542b70a40880b96616f617c0f724216
P 85aac7b8b6731e2f6880b80cfd62d431ea059799 47a46a9fa4a96cdb96a20b6aec802661b1ee4598
R c5f7ba1eb5032deaf906327db459f6d6
U dan
Z bec11568386511f97c280f2faaeb0846
Z 7d64753f9bb762353618192be20f88c2
+1 -1
View File
@@ -1 +1 @@
85aac7b8b6731e2f6880b80cfd62d431ea059799
716e7e747714d6af502f6a87ca8d789bb7ce162a
+11 -7
View File
@@ -357,12 +357,14 @@ Table *sqlite3LocateTable(
if( p==0 ){
const char *zMsg = isView ? "no such view" : "no such table";
#ifndef SQLITE_OMIT_VIRTUALTABLE
/* If zName is the not the name of a table in the schema created using
** CREATE, then check to see if it is the name of an virtual table that
** can be an eponymous virtual table. */
Module *pMod = (Module*)sqlite3HashFind(&pParse->db->aModule, zName);
if( pMod && sqlite3VtabEponymousTableInit(pParse, pMod) ){
return pMod->pEpoTab;
if( sqlite3FindDbName(pParse->db, zDbase)<1 ){
/* If zName is the not the name of a table in the schema created using
** CREATE, then check to see if it is the name of an virtual table that
** can be an eponymous virtual table. */
Module *pMod = (Module*)sqlite3HashFind(&pParse->db->aModule, zName);
if( pMod && sqlite3VtabEponymousTableInit(pParse, pMod) ){
return pMod->pEpoTab;
}
}
#endif
if( zDbase ){
@@ -984,6 +986,8 @@ void sqlite3StartTable(
int j1;
int fileFormat;
int reg1, reg2, reg3;
/* nullRow[] is an OP_Record encoding of a row containing 5 NULLs */
static const char nullRow[] = { 6, 0, 0, 0, 0, 0 };
sqlite3BeginWriteOperation(pParse, 1, iDb);
#ifndef SQLITE_OMIT_VIRTUALTABLE
@@ -1028,7 +1032,7 @@ void sqlite3StartTable(
}
sqlite3OpenMasterTable(pParse, iDb);
sqlite3VdbeAddOp2(v, OP_NewRowid, 0, reg1);
sqlite3VdbeAddOp2(v, OP_Null, 0, reg3);
sqlite3VdbeAddOp4(v, OP_Blob, 6, reg3, 0, nullRow, P4_STATIC);
sqlite3VdbeAddOp3(v, OP_Insert, 0, reg3, reg1);
sqlite3VdbeChangeP5(v, OPFLAG_APPEND);
sqlite3VdbeAddOp0(v, OP_Close);
+77 -28
View File
@@ -16,6 +16,9 @@
** information from an SQLite database in order to implement the
** "sqlite3_analyzer" utility. See the ../tool/spaceanal.tcl script
** for an example implementation.
**
** Additional information is available on the "dbstat.html" page of the
** official SQLite documentation.
*/
#include "sqliteInt.h" /* Requires access to internal data structures */
@@ -64,7 +67,8 @@
" unused INTEGER, /* Bytes of unused space on this page */" \
" mx_payload INTEGER, /* Largest payload size of all cells */" \
" pgoffset INTEGER, /* Offset of page in file */" \
" pgsize INTEGER /* Size of the page */" \
" pgsize INTEGER, /* Size of the page */" \
" schema TEXT HIDDEN /* Database schema being analyzed */" \
");"
@@ -102,6 +106,7 @@ struct StatCursor {
sqlite3_vtab_cursor base;
sqlite3_stmt *pStmt; /* Iterates through set of root pages */
int isEof; /* After pStmt has returned SQLITE_DONE */
int iDb; /* Schema used for this query */
StatPage aPage[32];
int iPage; /* Current entry in aPage[] */
@@ -179,9 +184,32 @@ static int statDisconnect(sqlite3_vtab *pVtab){
/*
** There is no "best-index". This virtual table always does a linear
** scan of the binary VFS log file.
** scan. However, a schema=? constraint should cause this table to
** operate on a different database schema, so check for it.
**
** idxNum is normally 0, but will be 1 if a schema=? constraint exists.
*/
static int statBestIndex(sqlite3_vtab *tab, sqlite3_index_info *pIdxInfo){
int i;
pIdxInfo->estimatedCost = 1.0e6; /* Initial cost estimate */
/* Look for a valid schema=? constraint. If found, change the idxNum to
** 1 and request the value of that constraint be sent to xFilter. And
** lower the cost estimate to encourage the constrained version to be
** used.
*/
for(i=0; i<pIdxInfo->nConstraint; i++){
if( pIdxInfo->aConstraint[i].usable==0 ) continue;
if( pIdxInfo->aConstraint[i].op!=SQLITE_INDEX_CONSTRAINT_EQ ) continue;
if( pIdxInfo->aConstraint[i].iColumn!=10 ) continue;
pIdxInfo->idxNum = 1;
pIdxInfo->estimatedCost = 1.0;
pIdxInfo->aConstraintUsage[i].argvIndex = 1;
pIdxInfo->aConstraintUsage[i].omit = 1;
break;
}
/* Records are always returned in ascending order of (name, path).
** If this will satisfy the client, set the orderByConsumed flag so that
@@ -201,7 +229,6 @@ static int statBestIndex(sqlite3_vtab *tab, sqlite3_index_info *pIdxInfo){
pIdxInfo->orderByConsumed = 1;
}
pIdxInfo->estimatedCost = 10.0;
return SQLITE_OK;
}
@@ -211,36 +238,18 @@ static int statBestIndex(sqlite3_vtab *tab, sqlite3_index_info *pIdxInfo){
static int statOpen(sqlite3_vtab *pVTab, sqlite3_vtab_cursor **ppCursor){
StatTable *pTab = (StatTable *)pVTab;
StatCursor *pCsr;
int rc;
pCsr = (StatCursor *)sqlite3_malloc64(sizeof(StatCursor));
if( pCsr==0 ){
rc = SQLITE_NOMEM;
return SQLITE_NOMEM;
}else{
char *zSql;
memset(pCsr, 0, sizeof(StatCursor));
pCsr->base.pVtab = pVTab;
zSql = sqlite3_mprintf(
"SELECT 'sqlite_master' AS name, 1 AS rootpage, 'table' AS type"
" UNION ALL "
"SELECT name, rootpage, type"
" FROM \"%w\".sqlite_master WHERE rootpage!=0"
" ORDER BY name", pTab->db->aDb[pTab->iDb].zName);
if( zSql==0 ){
rc = SQLITE_NOMEM;
}else{
rc = sqlite3_prepare_v2(pTab->db, zSql, -1, &pCsr->pStmt, 0);
sqlite3_free(zSql);
}
if( rc!=SQLITE_OK ){
sqlite3_free(pCsr);
pCsr = 0;
}
pCsr->iDb = pTab->iDb;
}
*ppCursor = (sqlite3_vtab_cursor *)pCsr;
return rc;
return SQLITE_OK;
}
static void statClearPage(StatPage *p){
@@ -265,6 +274,7 @@ static void statResetCsr(StatCursor *pCsr){
pCsr->iPage = 0;
sqlite3_free(pCsr->zPath);
pCsr->zPath = 0;
pCsr->isEof = 0;
}
/*
@@ -427,7 +437,7 @@ static int statNext(sqlite3_vtab_cursor *pCursor){
char *z;
StatCursor *pCsr = (StatCursor *)pCursor;
StatTable *pTab = (StatTable *)pCursor->pVtab;
Btree *pBt = pTab->db->aDb[pTab->iDb].pBt;
Btree *pBt = pTab->db->aDb[pCsr->iDb].pBt;
Pager *pPager = sqlite3BtreePager(pBt);
sqlite3_free(pCsr->zPath);
@@ -565,9 +575,43 @@ static int statFilter(
int argc, sqlite3_value **argv
){
StatCursor *pCsr = (StatCursor *)pCursor;
StatTable *pTab = (StatTable*)(pCursor->pVtab);
char *zSql;
int rc = SQLITE_OK;
char *zMaster;
if( idxNum==1 ){
const char *zDbase = (const char*)sqlite3_value_text(argv[0]);
pCsr->iDb = sqlite3FindDbName(pTab->db, zDbase);
if( pCsr->iDb<0 ){
sqlite3_free(pCursor->pVtab->zErrMsg);
pCursor->pVtab->zErrMsg = sqlite3_mprintf("no such schema: %s", zDbase);
return pCursor->pVtab->zErrMsg ? SQLITE_ERROR : SQLITE_NOMEM;
}
}else{
pCsr->iDb = pTab->iDb;
}
statResetCsr(pCsr);
return statNext(pCursor);
sqlite3_finalize(pCsr->pStmt);
pCsr->pStmt = 0;
zMaster = pCsr->iDb==1 ? "sqlite_temp_master" : "sqlite_master";
zSql = sqlite3_mprintf(
"SELECT 'sqlite_master' AS name, 1 AS rootpage, 'table' AS type"
" UNION ALL "
"SELECT name, rootpage, type"
" FROM \"%w\".%s WHERE rootpage!=0"
" ORDER BY name", pTab->db->aDb[pCsr->iDb].zName, zMaster);
if( zSql==0 ){
return SQLITE_NOMEM;
}else{
rc = sqlite3_prepare_v2(pTab->db, zSql, -1, &pCsr->pStmt, 0);
sqlite3_free(zSql);
}
if( rc==SQLITE_OK ){
rc = statNext(pCursor);
}
return rc;
}
static int statColumn(
@@ -604,10 +648,15 @@ static int statColumn(
case 8: /* pgoffset */
sqlite3_result_int64(ctx, pCsr->iOffset);
break;
default: /* pgsize */
assert( i==9 );
case 9: /* pgsize */
sqlite3_result_int(ctx, pCsr->szPage);
break;
default: { /* schema */
sqlite3 *db = sqlite3_context_db_handle(ctx);
int iDb = pCsr->iDb;
sqlite3_result_text(ctx, db->aDb[iDb].zName, -1, SQLITE_STATIC);
break;
}
}
return SQLITE_OK;
}
+2 -6
View File
@@ -91,7 +91,7 @@ Expr *sqlite3ExprAddCollateString(Parse *pParse, Expr *pExpr, const char *zC){
}
/*
** Skip over any TK_COLLATE or TK_AS operators and any unlikely()
** Skip over any TK_COLLATE operators and any unlikely()
** or likelihood() function at the root of an expression.
*/
Expr *sqlite3ExprSkipCollate(Expr *pExpr){
@@ -102,7 +102,7 @@ Expr *sqlite3ExprSkipCollate(Expr *pExpr){
assert( pExpr->op==TK_FUNCTION );
pExpr = pExpr->x.pList->a[0].pExpr;
}else{
assert( pExpr->op==TK_COLLATE || pExpr->op==TK_AS );
assert( pExpr->op==TK_COLLATE );
pExpr = pExpr->pLeft;
}
}
@@ -2701,10 +2701,6 @@ int sqlite3ExprCodeTarget(Parse *pParse, Expr *pExpr, int target){
inReg = pExpr->iTable;
break;
}
case TK_AS: {
inReg = sqlite3ExprCodeTarget(pParse, pExpr->pLeft, target);
break;
}
#ifndef SQLITE_OMIT_CAST
case TK_CAST: {
/* Expressions of the form: CAST(pLeft AS token) */
+70 -39
View File
@@ -56,15 +56,19 @@
** ParseARG_PDECL A parameter declaration for the %extra_argument
** ParseARG_STORE Code to store %extra_argument into yypParser
** ParseARG_FETCH Code to extract %extra_argument from yypParser
** YYNSTATE the combined number of states.
** YYNRULE the number of rules in the grammar
** YYERRORSYMBOL is the code number of the error symbol. If not
** defined, then do no error processing.
** YYNSTATE the combined number of states.
** YYNRULE the number of rules in the grammar
** YY_MAX_SHIFT Maximum value for shift actions
** YY_MIN_SHIFTREDUCE Minimum value for shift-reduce actions
** YY_MAX_SHIFTREDUCE Maximum value for shift-reduce actions
** YY_MIN_REDUCE Maximum value for reduce actions
** YY_ERROR_ACTION The yy_action[] code for syntax error
** YY_ACCEPT_ACTION The yy_action[] code for accept
** YY_NO_ACTION The yy_action[] code for no-op
*/
%%
#define YY_NO_ACTION (YYNSTATE+YYNRULE+2)
#define YY_ACCEPT_ACTION (YYNSTATE+YYNRULE+1)
#define YY_ERROR_ACTION (YYNSTATE+YYNRULE)
/* The yyzerominor constant is used to initialize instances of
** YYMINORTYPE objects to zero. */
@@ -91,16 +95,20 @@ static const YYMINORTYPE yyzerominor = { 0 };
** Suppose the action integer is N. Then the action is determined as
** follows
**
** 0 <= N < YYNSTATE Shift N. That is, push the lookahead
** 0 <= N <= YY_MAX_SHIFT Shift N. That is, push the lookahead
** token onto the stack and goto state N.
**
** YYNSTATE <= N < YYNSTATE+YYNRULE Reduce by rule N-YYNSTATE.
** N between YY_MIN_SHIFTREDUCE Shift to an arbitrary state then
** and YY_MAX_SHIFTREDUCE reduce by rule N-YY_MIN_SHIFTREDUCE.
**
** N == YYNSTATE+YYNRULE A syntax error has occurred.
** N between YY_MIN_REDUCE Reduce by rule N-YY_MIN_REDUCE
** and YY_MAX_REDUCE
** N == YY_ERROR_ACTION A syntax error has occurred.
**
** N == YYNSTATE+YYNRULE+1 The parser accepts its input.
** N == YY_ACCEPT_ACTION The parser accepts its input.
**
** N == YYNSTATE+YYNRULE+2 No such action. Denotes unused
** N == YY_NO_ACTION No such action. Denotes unused
** slots in the yy_action[] table.
**
** The action table is constructed as a single large table named yy_action[].
@@ -159,9 +167,13 @@ static const YYCODETYPE yyFallback[] = {
** + The semantic value stored at this level of the stack. This is
** the information used by the action routines in the grammar.
** It is sometimes called the "minor" token.
**
** After the "shift" half of a SHIFTREDUCE action, the stateno field
** actually contains the reduce action for the second half of the
** SHIFTREDUCE.
*/
struct yyStackEntry {
YYACTIONTYPE stateno; /* The state-number */
YYACTIONTYPE stateno; /* The state-number, or reduce action in SHIFTREDUCE */
YYCODETYPE major; /* The major token value. This is the code
** number for the token at this stack level */
YYMINORTYPE minor; /* The user-supplied minor token value. This
@@ -395,10 +407,10 @@ static int yy_find_shift_action(
int i;
int stateno = pParser->yystack[pParser->yyidx].stateno;
if( stateno>YY_SHIFT_COUNT
|| (i = yy_shift_ofst[stateno])==YY_SHIFT_USE_DFLT ){
return yy_default[stateno];
}
if( stateno>=YY_MIN_REDUCE ) return stateno;
assert( stateno <= YY_SHIFT_COUNT );
i = yy_shift_ofst[stateno];
if( i==YY_SHIFT_USE_DFLT ) return yy_default[stateno];
assert( iLookAhead!=YYNOCODE );
i += iLookAhead;
if( i<0 || i>=YY_ACTTAB_COUNT || yy_lookahead[i]!=iLookAhead ){
@@ -499,7 +511,29 @@ static void yyStackOverflow(yyParser *yypParser, YYMINORTYPE *yypMinor){
}
/*
** Perform a shift action.
** Print tracing information for a SHIFT action
*/
#ifndef NDEBUG
static void yyTraceShift(yyParser *yypParser, int yyNewState){
if( yyTraceFILE ){
int i;
if( yyNewState<YYNSTATE ){
fprintf(yyTraceFILE,"%sShift %d\n",yyTracePrompt,yyNewState);
fprintf(yyTraceFILE,"%sStack:",yyTracePrompt);
for(i=1; i<=yypParser->yyidx; i++)
fprintf(yyTraceFILE," %s",yyTokenName[yypParser->yystack[i].major]);
fprintf(yyTraceFILE,"\n");
}else{
fprintf(yyTraceFILE,"%sShift *\n",yyTracePrompt);
}
}
}
#else
# define yyTraceShift(X,Y)
#endif
/*
** Perform a shift action. Return the number of errors.
*/
static void yy_shift(
yyParser *yypParser, /* The parser to be shifted */
@@ -532,16 +566,7 @@ static void yy_shift(
yytos->stateno = (YYACTIONTYPE)yyNewState;
yytos->major = (YYCODETYPE)yyMajor;
yytos->minor = *yypMinor;
#ifndef NDEBUG
if( yyTraceFILE && yypParser->yyidx>0 ){
int i;
fprintf(yyTraceFILE,"%sShift %d\n",yyTracePrompt,yyNewState);
fprintf(yyTraceFILE,"%sStack:",yyTracePrompt);
for(i=1; i<=yypParser->yyidx; i++)
fprintf(yyTraceFILE," %s",yyTokenName[yypParser->yystack[i].major]);
fprintf(yyTraceFILE,"\n");
}
#endif
yyTraceShift(yypParser, yyNewState);
}
/* The following table contains information about every rule that
@@ -574,8 +599,9 @@ static void yy_reduce(
#ifndef NDEBUG
if( yyTraceFILE && yyruleno>=0
&& yyruleno<(int)(sizeof(yyRuleName)/sizeof(yyRuleName[0])) ){
fprintf(yyTraceFILE, "%sReduce [%s].\n", yyTracePrompt,
yyRuleName[yyruleno]);
yysize = yyRuleInfo[yyruleno].nrhs;
fprintf(yyTraceFILE, "%sReduce [%s] -> state %d.\n", yyTracePrompt,
yyRuleName[yyruleno], yymsp[-yysize].stateno);
}
#endif /* NDEBUG */
@@ -613,9 +639,9 @@ static void yy_reduce(
yysize = yyRuleInfo[yyruleno].nrhs;
yypParser->yyidx -= yysize;
yyact = yy_find_reduce_action(yymsp[-yysize].stateno,(YYCODETYPE)yygoto);
if( yyact < YYNSTATE ){
#ifdef NDEBUG
/* If we are not debugging and the reduce action popped at least
if( yyact <= YY_MAX_SHIFTREDUCE ){
if( yyact>YY_MAX_SHIFT ) yyact += YY_MIN_REDUCE - YY_MIN_SHIFTREDUCE;
/* If the reduce action popped at least
** one element off the stack, then we can push the new element back
** onto the stack here, and skip the stack overflow test in yy_shift().
** That gives a significant speed improvement. */
@@ -625,13 +651,12 @@ static void yy_reduce(
yymsp->stateno = (YYACTIONTYPE)yyact;
yymsp->major = (YYCODETYPE)yygoto;
yymsp->minor = yygotominor;
}else
#endif
{
yyTraceShift(yypParser, yyact);
}else{
yy_shift(yypParser,yyact,yygoto,&yygotominor);
}
}else{
assert( yyact == YYNSTATE + YYNRULE + 1 );
assert( yyact == YY_ACCEPT_ACTION );
yy_accept(yypParser);
}
}
@@ -755,12 +780,13 @@ void Parse(
do{
yyact = yy_find_shift_action(yypParser,(YYCODETYPE)yymajor);
if( yyact<YYNSTATE ){
if( yyact <= YY_MAX_SHIFTREDUCE ){
if( yyact > YY_MAX_SHIFT ) yyact += YY_MIN_REDUCE - YY_MIN_SHIFTREDUCE;
yy_shift(yypParser,yyact,yymajor,&yyminorunion);
yypParser->yyerrcnt--;
yymajor = YYNOCODE;
}else if( yyact < YYNSTATE + YYNRULE ){
yy_reduce(yypParser,yyact-YYNSTATE);
}else if( yyact <= YY_MAX_REDUCE ){
yy_reduce(yypParser,yyact-YY_MIN_REDUCE);
}else{
assert( yyact == YY_ERROR_ACTION );
#ifdef YYERRORSYMBOL
@@ -810,7 +836,7 @@ void Parse(
yymx != YYERRORSYMBOL &&
(yyact = yy_find_reduce_action(
yypParser->yystack[yypParser->yyidx].stateno,
YYERRORSYMBOL)) >= YYNSTATE
YYERRORSYMBOL)) >= YY_MIN_REDUCE
){
yy_pop_parser_stack(yypParser);
}
@@ -860,5 +886,10 @@ void Parse(
#endif
}
}while( yymajor!=YYNOCODE && yypParser->yyidx>=0 );
#ifndef NDEBUG
if( yyTraceFILE ){
fprintf(yyTraceFILE,"%sReturn\n",yyTracePrompt);
}
#endif
return;
}
+44 -60
View File
@@ -45,7 +45,7 @@ typedef struct ScratchFreeslot {
*/
static SQLITE_WSD struct Mem0Global {
sqlite3_mutex *mutex; /* Mutex to serialize access */
sqlite3_int64 alarmThreshold; /* The soft heap limit */
sqlite3_int64 alarmThreshold; /* The soft heap limit */
/*
** Pointers to the end of sqlite3GlobalConfig.pScratch memory
@@ -73,59 +73,20 @@ sqlite3_mutex *sqlite3MallocMutex(void){
return mem0.mutex;
}
/*
** Return the amount of memory currently in use.
*/
static sqlite3_int64 memInUse(void){
assert( sqlite3_mutex_held(mem0.mutex) );
return sqlite3StatusValue(SQLITE_STATUS_MEMORY_USED);
}
/*
** Called when the soft heap limit is exceeded for an allocation
** of nBytes.
*/
#ifdef SQLITE_ENABLE_MEMORY_MANAGEMENT
static void sqlite3HeapLimitExceeded(int nByte){
sqlite3_int64 excess = memInUse() + nByte - mem0.alarmThreshold;
sqlite3_mutex_leave(mem0.mutex);
sqlite3_release_memory((int)(excess & 0x7fffffff));
sqlite3_mutex_enter(mem0.mutex);
}
#else
# define sqlite3HeapLimitExceeded(X) /* no-op */
#endif
/*
** Check to see if increasing the total memory usage by nNew bytes
** will exceed the soft heap limit.
**
** If the soft heap limit is exceeded, set the mem0.nearlyFull flag
** and invoke sqlite3HeapLimitExceeded() to try to free up some
** memory.
*/
static void sqlite3CheckSoftHeapLimit(int nNew){
assert( sqlite3_mutex_held(mem0.mutex) );
if( mem0.alarmThreshold>0 ){
if( mem0.alarmThreshold-nNew >= memInUse() ){
mem0.nearlyFull = 1;
sqlite3HeapLimitExceeded(nNew);
}else{
mem0.nearlyFull = 0;
}
}
}
#ifndef SQLITE_OMIT_DEPRECATED
/*
** Deprecated external interface. First deprecated 2007-11-05. Changed
** into a no-op on 2015-09-02.
** Deprecated external interface. It used to set an alarm callback
** that was invoked when memory usage grew too large. Now it is a
** no-op.
*/
int sqlite3_memory_alarm(
void(*xCallback)(void *pArg, sqlite3_int64 used,int N),
void *pArg,
sqlite3_int64 iThreshold
){
(void)xCallback;
(void)pArg;
(void)iThreshold;
return SQLITE_OK;
}
#endif
@@ -136,20 +97,24 @@ int sqlite3_memory_alarm(
*/
sqlite3_int64 sqlite3_soft_heap_limit64(sqlite3_int64 n){
sqlite3_int64 priorLimit;
sqlite3_int64 excess;
sqlite3_int64 nUsed;
#ifndef SQLITE_OMIT_AUTOINIT
int rc = sqlite3_initialize();
if( rc ) return -1;
#endif
sqlite3_mutex_enter(mem0.mutex);
priorLimit = mem0.alarmThreshold;
if( n>0 ){
mem0.alarmThreshold = n;
sqlite3CheckSoftHeapLimit(0);
}else if( n==0 ){
mem0.alarmThreshold = 0;
mem0.nearlyFull = 0;
if( n<0 ){
sqlite3_mutex_leave(mem0.mutex);
return priorLimit;
}
mem0.alarmThreshold = n;
nUsed = sqlite3StatusValue(SQLITE_STATUS_MEMORY_USED);
mem0.nearlyFull = (n>0 && n<=nUsed);
sqlite3_mutex_leave(mem0.mutex);
excess = sqlite3_memory_used() - n;
if( excess>0 ) sqlite3_release_memory((int)(excess & 0x7fffffff));
return priorLimit;
}
void sqlite3_soft_heap_limit(int n){
@@ -240,6 +205,16 @@ sqlite3_int64 sqlite3_memory_highwater(int resetFlag){
return mx;
}
/*
** Trigger the alarm
*/
static void sqlite3MallocAlarm(int nByte){
if( mem0.alarmThreshold<=0 ) return;
sqlite3_mutex_leave(mem0.mutex);
sqlite3_release_memory(nByte);
sqlite3_mutex_enter(mem0.mutex);
}
/*
** Do a memory allocation with statistics and alarms. Assume the
** lock is already held.
@@ -250,11 +225,19 @@ static int mallocWithAlarm(int n, void **pp){
assert( sqlite3_mutex_held(mem0.mutex) );
nFull = sqlite3GlobalConfig.m.xRoundup(n);
sqlite3StatusSet(SQLITE_STATUS_MALLOC_SIZE, n);
sqlite3CheckSoftHeapLimit(nFull);
if( mem0.alarmThreshold>0 ){
sqlite3_int64 nUsed = sqlite3StatusValue(SQLITE_STATUS_MEMORY_USED);
if( nUsed >= mem0.alarmThreshold - nFull ){
mem0.nearlyFull = 1;
sqlite3MallocAlarm(nFull);
}else{
mem0.nearlyFull = 0;
}
}
p = sqlite3GlobalConfig.m.xMalloc(nFull);
#ifdef SQLITE_ENABLE_MEMORY_MANAGEMENT
if( p==0 && mem0.alarmThreshold ){
sqlite3HeapLimitExceeded(nFull);
if( p==0 && mem0.alarmThreshold>0 ){
sqlite3MallocAlarm(nFull);
p = sqlite3GlobalConfig.m.xMalloc(nFull);
}
#endif
@@ -537,14 +520,15 @@ void *sqlite3Realloc(void *pOld, u64 nBytes){
sqlite3_mutex_enter(mem0.mutex);
sqlite3StatusSet(SQLITE_STATUS_MALLOC_SIZE, (int)nBytes);
nDiff = nNew - nOld;
sqlite3CheckSoftHeapLimit(nDiff);
if( sqlite3StatusValue(SQLITE_STATUS_MEMORY_USED) >=
mem0.alarmThreshold-nDiff ){
sqlite3MallocAlarm(nDiff);
}
pNew = sqlite3GlobalConfig.m.xRealloc(pOld, nNew);
#ifdef SQLITE_ENABLE_MEMORY_MANAGEMENT
if( pNew==0 && mem0.alarmThreshold ){
sqlite3HeapLimitExceeded((int)nBytes);
if( pNew==0 && mem0.alarmThreshold>0 ){
sqlite3MallocAlarm((int)nBytes);
pNew = sqlite3GlobalConfig.m.xRealloc(pOld, nNew);
}
#endif
if( pNew ){
nNew = sqlite3MallocSize(pNew);
sqlite3StatusUp(SQLITE_STATUS_MEMORY_USED, nNew-nOld);
+1
View File
@@ -53,6 +53,7 @@ int sqlite3MutexInit(void){
pTo->xMutexLeave = pFrom->xMutexLeave;
pTo->xMutexHeld = pFrom->xMutexHeld;
pTo->xMutexNotheld = pFrom->xMutexNotheld;
sqlite3MemoryBarrier();
pTo->xMutexAlloc = pFrom->xMutexAlloc;
}
rc = sqlite3GlobalConfig.mutex.xMutexInit();
+11
View File
@@ -80,6 +80,17 @@ static int pthreadMutexNotheld(sqlite3_mutex *p){
}
#endif
/*
** Try to provide a memory barrier operation, needed for initialization only.
*/
void sqlite3MemoryBarrier(void){
#if defined(SQLITE_MEMORY_BARRIER)
SQLITE_MEMORY_BARRIER;
#elif defined(__GNUC__)
__sync_synchronize();
#endif
}
/*
** Initialize and deinitialize the mutex subsystem.
*/
+13
View File
@@ -77,6 +77,19 @@ static int winMutexNotheld(sqlite3_mutex *p){
}
#endif
/*
** Try to provide a memory barrier operation, needed for initialization only.
*/
void sqlite3MemoryBarrier(void){
#if defined(SQLITE_MEMORY_BARRIER)
SQLITE_MEMORY_BARRIER;
#elif defined(__GNUC__)
__sync_synchronize();
#else
MemoryBarrier();
#endif
}
/*
** Initialize and deinitialize the mutex subsystem.
*/
+2 -1
View File
@@ -1193,7 +1193,8 @@ int sqlite3PcacheReleaseMemory(int nReq){
PgHdr1 *p;
pcache1EnterMutex(&pcache1.grp);
while( (nReq<0 || nFree<nReq)
&& (p=pcache1.grp.lru.pLruPrev)->isAnchor==0
&& (p=pcache1.grp.lru.pLruPrev)!=0
&& p->isAnchor==0
){
nFree += pcache1MemSize(p->page.pBuf);
#ifdef SQLITE_PCACHE_SEPARATE_HEADER
+3 -35
View File
@@ -45,30 +45,6 @@ static void incrAggFunctionDepth(Expr *pExpr, int N){
** Turn the pExpr expression into an alias for the iCol-th column of the
** result set in pEList.
**
** If the result set column is a simple column reference, then this routine
** makes an exact copy. But for any other kind of expression, this
** routine make a copy of the result set column as the argument to the
** TK_AS operator. The TK_AS operator causes the expression to be
** evaluated just once and then reused for each alias.
**
** The reason for suppressing the TK_AS term when the expression is a simple
** column reference is so that the column reference will be recognized as
** usable by indices within the WHERE clause processing logic.
**
** The TK_AS operator is inhibited if zType[0]=='G'. This means
** that in a GROUP BY clause, the expression is evaluated twice. Hence:
**
** SELECT random()%5 AS x, count(*) FROM tab GROUP BY x
**
** Is equivalent to:
**
** SELECT random()%5 AS x, count(*) FROM tab GROUP BY random()%5
**
** The result of random()%5 in the GROUP BY clause is probably different
** from the result in the result-set. On the other hand Standard SQL does
** not allow the GROUP BY clause to contain references to result-set columns.
** So this should never come up in well-formed queries.
**
** If the reference is followed by a COLLATE operator, then make sure
** the COLLATE operator is preserved. For example:
**
@@ -102,19 +78,11 @@ static void resolveAlias(
db = pParse->db;
pDup = sqlite3ExprDup(db, pOrig, 0);
if( pDup==0 ) return;
if( pOrig->op!=TK_COLUMN && zType[0]!='G' ){
incrAggFunctionDepth(pDup, nSubquery);
pDup = sqlite3PExpr(pParse, TK_AS, pDup, 0, 0);
if( pDup==0 ) return;
ExprSetProperty(pDup, EP_Skip);
if( pEList->a[iCol].u.x.iAlias==0 ){
pEList->a[iCol].u.x.iAlias = (u16)(++pParse->nAlias);
}
pDup->iTable = pEList->a[iCol].u.x.iAlias;
}
if( zType[0]!='G' ) incrAggFunctionDepth(pDup, nSubquery);
if( pExpr->op==TK_COLLATE ){
pDup = sqlite3ExprAddCollateString(pParse, pDup, pExpr->u.zToken);
}
ExprSetProperty(pDup, EP_Alias);
/* Before calling sqlite3ExprDelete(), set the EP_Static flag. This
** prevents ExprDelete() from deleting the Expr structure itself,
@@ -506,7 +474,7 @@ static int lookupName(
lookupname_end:
if( cnt==1 ){
assert( pNC!=0 );
if( pExpr->op!=TK_AS ){
if( !ExprHasProperty(pExpr, EP_Alias) ){
sqlite3AuthRead(pParse, pExpr, pSchema, pNC->pSrcList);
}
/* Increment the nRef value on all name contexts from TopNC up to
+3 -3
View File
@@ -285,7 +285,7 @@ struct sqlite3_api_routines {
** the API. So the redefinition macros are only valid if the
** SQLITE_CORE macros is undefined.
*/
#ifndef SQLITE_CORE
#if !defined(SQLITE_CORE) && !defined(SQLITE_OMIT_LOAD_EXTENSION)
#define sqlite3_aggregate_context sqlite3_api->aggregate_context
#ifndef SQLITE_OMIT_DEPRECATED
#define sqlite3_aggregate_count sqlite3_api->aggregate_count
@@ -508,9 +508,9 @@ struct sqlite3_api_routines {
#define sqlite3_value_free sqlite3_api->value_free
#define sqlite3_result_zeroblob64 sqlite3_api->result_zeroblob64
#define sqlite3_bind_zeroblob64 sqlite3_api->bind_zeroblob64
#endif /* SQLITE_CORE */
#endif /* !defined(SQLITE_CORE) && !defined(SQLITE_OMIT_LOAD_EXTENSION) */
#ifndef SQLITE_CORE
#if !defined(SQLITE_CORE) && !defined(SQLITE_OMIT_LOAD_EXTENSION)
/* This case when the file really is being compiled as a loadable
** extension */
# define SQLITE_EXTENSION_INIT1 const sqlite3_api_routines *sqlite3_api=0;
+6
View File
@@ -2135,6 +2135,7 @@ struct Expr {
#define EP_ConstFunc 0x080000 /* A SQLITE_FUNC_CONSTANT or _SLOCHNG function */
#define EP_CanBeNull 0x100000 /* Can be null despite NOT NULL constraint */
#define EP_Subquery 0x200000 /* Tree contains a TK_SELECT operator */
#define EP_Alias 0x400000 /* Is an alias for a result set column */
/*
** Combinations of two or more EP_* flags
@@ -3191,6 +3192,11 @@ const sqlite3_mem_methods *sqlite3MemGetMemsys5(void);
int sqlite3MutexInit(void);
int sqlite3MutexEnd(void);
#endif
#if !defined(SQLITE_MUTEX_OMIT) && !defined(SQLITE_MUTEX_NOOP)
void sqlite3MemoryBarrier(void);
#else
# define sqlite3MemoryBarrier();
#endif
sqlite3_int64 sqlite3StatusValue(int);
void sqlite3StatusUp(int, int);
+1
View File
@@ -403,6 +403,7 @@ int sqlite3RunParser(Parse *pParse, const char *zSql, char **pzErrMsg){
pParse->zTail = zSql;
i = 0;
assert( pzErrMsg!=0 );
/* sqlite3ParserTrace(stdout, "parser: "); */
pEngine = sqlite3ParserAlloc(sqlite3Malloc);
if( pEngine==0 ){
db->mallocFailed = 1;
-5
View File
@@ -253,11 +253,6 @@ void sqlite3TreeViewExpr(TreeView *pView, const Expr *pExpr, u8 moreToFollow){
sqlite3TreeViewLine(pView,"REGISTER(%d)", pExpr->iTable);
break;
}
case TK_AS: {
sqlite3TreeViewLine(pView,"AS %Q", pExpr->u.zToken);
sqlite3TreeViewExpr(pView, pExpr->pLeft, 0);
break;
}
case TK_ID: {
sqlite3TreeViewLine(pView,"ID \"%w\"", pExpr->u.zToken);
break;
+1 -1
View File
@@ -696,7 +696,7 @@ void *sqlite3_user_data(sqlite3_context *p){
** application defined function.
*/
sqlite3 *sqlite3_context_db_handle(sqlite3_context *p){
assert( p && p->pFunc );
assert( p && p->pOut );
return p->pOut->db;
}
+2 -1
View File
@@ -2462,7 +2462,8 @@ int sqlite3WalFindFrame(
{
u32 iRead2 = 0;
u32 iTest;
for(iTest=iLast; iTest>0; iTest--){
assert( pWal->minFrame>0 );
for(iTest=iLast; iTest>=pWal->minFrame; iTest--){
if( walFramePgno(pWal, iTest)==pgno ){
iRead2 = iTest;
break;
+1 -1
View File
@@ -271,7 +271,7 @@ static WhereTerm *whereScanInit(
u32 opMask, /* Operator(s) to scan for */
Index *pIdx /* Must be compatible with this index */
){
int j;
int j = 0;
/* memset(pScan, 0, sizeof(*pScan)); */
pScan->pOrigWC = pWC;
+21
View File
@@ -198,4 +198,25 @@ do_catchsql_test indexexpr1-410 {
INSERT INTO t3 SELECT * FROM t3 WHERE rowid=10;
} {1 {UNIQUE constraint failed: index 't3abc'}}
do_execsql_test indexexpr1-500 {
CREATE TABLE t5(a);
CREATE TABLE cnt(x);
WITH RECURSIVE
c(x) AS (VALUES(1) UNION ALL SELECT x+1 FROM c WHERE x<5)
INSERT INTO cnt(x) SELECT x FROM c;
INSERT INTO t5(a) SELECT printf('abc%03dxyz',x) FROM cnt;
CREATE INDEX t5ax ON t5( substr(a,4,3) );
} {}
do_execsql_test indexexpr1-510 {
-- The use of the "k" alias in the WHERE clause is technically
-- illegal, but SQLite allows it for historical reasons. In this
-- test and the next, verify that "k" can be used by the t5ax index
SELECT substr(a,4,3) AS k FROM cnt, t5 WHERE k=printf('%03d',x);
} {001 002 003 004 005}
do_execsql_test indexexpr1-510eqp {
EXPLAIN QUERY PLAN
SELECT substr(a,4,3) AS k FROM cnt, t5 WHERE k=printf('%03d',x);
} {/USING INDEX t5ax/}
finish_test
+239
View File
@@ -0,0 +1,239 @@
# 2015-08-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.
#
#***********************************************************************
# This file implements tests for JSON SQL functions extension to the
# SQLite library.
#
# This file contains tests automatically generated from the json1
# documentation.
#
set testdir [file dirname $argv0]
source $testdir/tester.tcl
load_static_extension db json
do_execsql_test json102-100 {
SELECT json_array(1,2,'3',4);
} {{[1,2,"3",4]}}
do_execsql_test json102-110 {
SELECT json_array('[1,2]');
} {{["[1,2]"]}}
do_execsql_test json102-120 {
SELECT json_array(1,null,'3','[4,5]','{"six":7.7}');
} {{[1,null,"3","[4,5]","{\"six\":7.7}"]}}
do_execsql_test json102-130 {
SELECT json_array_length('[1,2,3,4]');
} {{4}}
do_execsql_test json102-140 {
SELECT json_array_length('{"one":[1,2,3]}');
} {{0}}
do_execsql_test json102-150 {
SELECT json_array_length('{"one":[1,2,3]}', '$.one');
} {{3}}
do_execsql_test json102-160 {
SELECT json_extract('{"a":2,"c":[4,5,{"f":7}]}', '$');
} {{{"a":2,"c":[4,5,{"f":7}]}}}
do_execsql_test json102-170 {
SELECT json_extract('{"a":2,"c":[4,5,{"f":7}]}', '$.c');
} {{[4,5,{"f":7}]}}
do_execsql_test json102-180 {
SELECT json_extract('{"a":2,"c":[4,5,{"f":7}]}', '$.c[2]');
} {{{"f":7}}}
do_execsql_test json102-190 {
SELECT json_extract('{"a":2,"c":[4,5,{"f":7}]}', '$.c[2].f');
} {{7}}
do_execsql_test json102-200 {
SELECT json_extract('{"a":2,"c":[4,5],"f":7}','$.c','$.a');
} {{[[4,5],2]}}
do_execsql_test json102-210 {
SELECT json_extract('{"a":2,"c":[4,5,{"f":7}]}', '$.x');
} {{}}
do_execsql_test json102-220 {
SELECT json_insert('{"a":2,"c":4}', '$.a', 99);
} {{{"a":2,"c":4}}}
do_execsql_test json102-230 {
SELECT json_insert('{"a":2,"c":4}', '$.e', 99);
} {{{"a":2,"c":4,"e":99}}}
do_execsql_test json102-240 {
SELECT json_replace('{"a":2,"c":4}', '$.a', 99);
} {{{"a":99,"c":4}}}
do_execsql_test json102-250 {
SELECT json_replace('{"a":2,"c":4}', '$.e', 99);
} {{{"a":2,"c":4}}}
do_execsql_test json102-260 {
SELECT json_set('{"a":2,"c":4}', '$.a', 99);
} {{{"a":99,"c":4}}}
do_execsql_test json102-270 {
SELECT json_set('{"a":2,"c":4}', '$.e', 99);
} {{{"a":2,"c":4,"e":99}}}
do_execsql_test json102-280 {
SELECT json_object('a',2,'c',4);
} {{{"a":2,"c":4}}}
do_execsql_test json102-290 {
SELECT json_object('a',2,'c','{e:5}');
} {{{"a":2,"c":"{e:5}"}}}
do_execsql_test json102-300 {
SELECT json_remove('[0,1,2,3,4]','$[2]');
} {{[0,1,3,4]}}
do_execsql_test json102-310 {
SELECT json_remove('[0,1,2,3,4]','$[2]','$[0]');
} {{[1,3,4]}}
do_execsql_test json102-320 {
SELECT json_remove('[0,1,2,3,4]','$[0]','$[2]');
} {{[1,2,4]}}
do_execsql_test json102-330 {
SELECT json_remove('{"x":25,"y":42}');
} {{{"x":25,"y":42}}}
do_execsql_test json102-340 {
SELECT json_remove('{"x":25,"y":42}','$.z');
} {{{"x":25,"y":42}}}
do_execsql_test json102-350 {
SELECT json_remove('{"x":25,"y":42}','$.y');
} {{{"x":25}}}
do_execsql_test json102-360 {
SELECT json_remove('{"x":25,"y":42}','$');
} {{}}
do_execsql_test json102-370 {
SELECT json_type('{"a":[2,3.5,true,false,null,"x"]}');
} {{object}}
do_execsql_test json102-380 {
SELECT json_type('{"a":[2,3.5,true,false,null,"x"]}','$');
} {{object}}
do_execsql_test json102-390 {
SELECT json_type('{"a":[2,3.5,true,false,null,"x"]}','$.a');
} {{array}}
do_execsql_test json102-400 {
SELECT json_type('{"a":[2,3.5,true,false,null,"x"]}','$.a[0]');
} {{integer}}
do_execsql_test json102-410 {
SELECT json_type('{"a":[2,3.5,true,false,null,"x"]}','$.a[1]');
} {{real}}
do_execsql_test json102-420 {
SELECT json_type('{"a":[2,3.5,true,false,null,"x"]}','$.a[2]');
} {{true}}
do_execsql_test json102-430 {
SELECT json_type('{"a":[2,3.5,true,false,null,"x"]}','$.a[3]');
} {{false}}
do_execsql_test json102-440 {
SELECT json_type('{"a":[2,3.5,true,false,null,"x"]}','$.a[4]');
} {{null}}
do_execsql_test json102-450 {
SELECT json_type('{"a":[2,3.5,true,false,null,"x"]}','$.a[5]');
} {{text}}
do_execsql_test json102-460 {
SELECT json_type('{"a":[2,3.5,true,false,null,"x"]}','$.a[6]');
} {{}}
do_execsql_test json102-470 {
SELECT json_valid('{"x":35}');
} {{1}}
do_execsql_test json102-480 {
SELECT json_valid('{"x":35'); -- }
} {{0}}
ifcapable vtab {
do_execsql_test json102-500 {
CREATE TABLE user(name,phone);
INSERT INTO user(name,phone) VALUES
('Alice','["919-555-2345","804-555-3621"]'),
('Bob','["201-555-8872"]'),
('Cindy','["704-555-9983"]'),
('Dave','["336-555-8421","704-555-4321","803-911-4421"]');
SELECT DISTINCT user.name
FROM user, json_each(user.phone)
WHERE json_each.value LIKE '704-%'
ORDER BY 1;
} {Cindy Dave}
do_execsql_test json102-510 {
UPDATE user
SET phone=json_extract(phone,'$[0]')
WHERE json_array_length(phone)<2;
SELECT name, substr(phone,1,5) FROM user ORDER BY name;
} {Alice {["919} Bob 201-5 Cindy 704-5 Dave {["336}}
do_execsql_test json102-511 {
SELECT name FROM user WHERE phone LIKE '704-%'
UNION
SELECT user.name
FROM user, json_each(user.phone)
WHERE json_valid(user.phone)
AND json_each.value LIKE '704-%';
} {Cindy Dave}
do_execsql_test json102-600 {
CREATE TABLE big(json JSON);
INSERT INTO big(json) VALUES('{
"id":123,
"stuff":[1,2,3,4],
"partlist":[
{"uuid":"bb108722-572e-11e5-9320-7f3b63a4ca74"},
{"uuid":"c690dc14-572e-11e5-95f9-dfc8861fd535"},
{"subassembly":[
{"uuid":"6fa5181e-5721-11e5-a04e-57f3d7b32808"}
]}
]
}');
INSERT INTO big(json) VALUES('{
"id":456,
"stuff":["hello","world","xyzzy"],
"partlist":[
{"uuid":false},
{"uuid":"c690dc14-572e-11e5-95f9-dfc8861fd535"}
]
}');
} {}
set correct_answer [list \
1 {$.id} 123 \
1 {$.stuff[0]} 1 \
1 {$.stuff[1]} 2 \
1 {$.stuff[2]} 3 \
1 {$.stuff[3]} 4 \
1 {$.partlist[0].uuid} bb108722-572e-11e5-9320-7f3b63a4ca74 \
1 {$.partlist[1].uuid} c690dc14-572e-11e5-95f9-dfc8861fd535 \
1 {$.partlist[2].subassembly[0].uuid} 6fa5181e-5721-11e5-a04e-57f3d7b32808 \
2 {$.id} 456 \
2 {$.stuff[0]} hello \
2 {$.stuff[1]} world \
2 {$.stuff[2]} xyzzy \
2 {$.partlist[0].uuid} 0 \
2 {$.partlist[1].uuid} c690dc14-572e-11e5-95f9-dfc8861fd535]
do_execsql_test json102-610 {
SELECT big.rowid, fullkey, value
FROM big, json_tree(big.json)
WHERE json_tree.type NOT IN ('object','array')
ORDER BY +big.rowid, +json_tree.id
} $correct_answer
do_execsql_test json102-620 {
SELECT big.rowid, fullkey, atom
FROM big, json_tree(big.json)
WHERE atom IS NOT NULL
ORDER BY +big.rowid, +json_tree.id
} $correct_answer
do_execsql_test json102-630 {
SELECT DISTINCT json_extract(big.json,'$.id')
FROM big, json_tree(big.json,'$.partlist')
WHERE json_tree.key='uuid'
AND json_tree.value='6fa5181e-5721-11e5-a04e-57f3d7b32808';
} {123}
do_execsql_test json102-631 {
SELECT DISTINCT json_extract(big.json,'$.id')
FROM big, json_tree(big.json,'$')
WHERE json_tree.key='uuid'
AND json_tree.value='6fa5181e-5721-11e5-a04e-57f3d7b32808';
} {123}
do_execsql_test json102-632 {
SELECT DISTINCT json_extract(big.json,'$.id')
FROM big, json_tree(big.json)
WHERE json_tree.key='uuid'
AND json_tree.value='6fa5181e-5721-11e5-a04e-57f3d7b32808';
} {123}
} ;# end ifcapable vtab
finish_test
+2 -1
View File
@@ -292,7 +292,7 @@ set LOG [open releasetest-out.txt w]
proc PUTS {args} {
if {[llength $args]==2} {
puts [lindex $args 0] [lindex $args 1]
puts [lindex $args 0] $::LOG [lindex $args 1]
puts $::LOG [lindex $args 1]
} else {
puts [lindex $args 0]
puts $::LOG [lindex $args 0]
@@ -710,6 +710,7 @@ proc main {argv} {
set sec [expr {$elapsetime%60}]
set etime [format (%02d:%02d:%02d) $hr $min $sec]
PUTS [string repeat * 79]
incr ::NERRCASE $::NERR
PUTS "$::NERRCASE failures out of $::NTESTCASE tests in $etime"
if {$::SQLITE_VERSION ne ""} {
PUTS "SQLite $::SQLITE_VERSION"
+13
View File
@@ -69,5 +69,18 @@ do_execsql_test tabfunc01-3.1 {
SELECT DISTINCT value FROM generate_series(1,x), t1 ORDER BY 1;
} {1 2 3}
# Eponymous virtual table exists in the "main" schema only
#
do_execsql_test tabfunc01-4.1 {
SELECT * FROM main.generate_series(1,4)
} {1 2 3 4}
do_catchsql_test tabfunc01-4.2 {
SELECT * FROM temp.generate_series(1,4)
} {1 {no such table: temp.generate_series}}
do_catchsql_test tabfunc01-4.3 {
ATTACH ':memory:' AS aux1;
CREATE TABLE aux1.t1(a,b,c);
SELECT * FROM aux1.generate_series(1,4)
} {1 {no such table: aux1.generate_series}}
finish_test
+12
View File
@@ -823,5 +823,17 @@ do_execsql_test table-18.2 {
PRAGMA integrity_check;
} {ok}
# 2015-09-09
# Ticket [https://www.sqlite.org/src/info/acd12990885d9276]
# "CREATE TABLE ... AS SELECT ... FROM sqlite_master" fails because the row
# in the sqlite_master table for the next table is initially populated
# with a NULL instead of a record created by OP_Record.
#
do_execsql_test table-19.1 {
CREATE TABLE t19 AS SELECT * FROM sqlite_master;
SELECT name FROM t19 ORDER BY name;
} {{} savepoint t10 t11 t12 t13 t16 t2 t3 t3\"xyz t4\"abc t7 t8 t9 tablet8 test1 weird}
finish_test
+192 -79
View File
@@ -316,7 +316,8 @@ enum e_action {
RRCONFLICT, /* Was a reduce, but part of a conflict */
SH_RESOLVED, /* Was a shift. Precedence resolved conflict */
RD_RESOLVED, /* Was reduce. Precedence resolved conflict */
NOT_USED /* Deleted by compression */
NOT_USED, /* Deleted by compression */
SHIFTREDUCE /* Shift first, then reduce */
};
/* Every shift or reduce operation is stored as one of the following */
@@ -340,7 +341,9 @@ struct state {
struct action *ap; /* Array of actions for this state */
int nTknAct, nNtAct; /* Number of actions on terminals and nonterminals */
int iTknOfst, iNtOfst; /* yy_action[] offset for terminals and nonterms */
int iDflt; /* Default action */
int iDfltReduce; /* Default action is to REDUCE by this rule */
struct rule *pDfltReduce;/* The default REDUCE rule. */
int autoReduce; /* True if this is an auto-reduce state */
};
#define NO_OFFSET (-2147483647)
@@ -360,6 +363,7 @@ struct lemon {
struct state **sorted; /* Table of states sorted by state number */
struct rule *rule; /* List of all rules */
int nstate; /* Number of states */
int nxstate; /* nstate with tail degenerate states removed */
int nrule; /* Number of rules */
int nsymbol; /* Number of terminal and nonterminal symbols */
int nterminal; /* Number of terminal symbols */
@@ -385,7 +389,8 @@ struct lemon {
char *outname; /* Name of the current output file */
char *tokenprefix; /* A prefix added to token names in the .h file */
int nconflict; /* Number of parsing conflicts */
int tablesize; /* Size of the parse tables */
int nactiontab; /* Number of entries in the yy_action[] table */
int tablesize; /* Total table size of all tables in bytes */
int basisflag; /* Print only basis configurations */
int has_fallback; /* True if any %fallback is seen in the grammar */
int nolinenosflag; /* True if #line statements should not be printed */
@@ -483,7 +488,7 @@ static int actioncmp(
if( rc==0 ){
rc = (int)ap1->type - (int)ap2->type;
}
if( rc==0 && ap1->type==REDUCE ){
if( rc==0 && (ap1->type==REDUCE || ap1->type==SHIFTREDUCE) ){
rc = ap1->x.rp->index - ap2->x.rp->index;
}
if( rc==0 ){
@@ -1482,6 +1487,18 @@ static void handle_T_option(char *z){
lemon_strcpy(user_templatename, z);
}
/* forward reference */
static const char *minimum_size_type(int lwr, int upr, int *pnByte);
/* Print a single line of the "Parser Stats" output
*/
static void stats_line(const char *zLabel, int iValue){
int nLabel = lemonStrlen(zLabel);
printf(" %s%.*s %5d\n", zLabel,
35-nLabel, "................................",
iValue);
}
/* The main program. Parse the command line and do it... */
int main(int argc, char **argv)
{
@@ -1613,11 +1630,15 @@ int main(int argc, char **argv)
if( !mhflag ) ReportHeader(&lem);
}
if( statistics ){
printf("Parser statistics: %d terminals, %d nonterminals, %d rules\n",
lem.nterminal, lem.nsymbol - lem.nterminal, lem.nrule);
printf(" %d states, %d parser table entries,"
" %d conflicts\n",
lem.nstate, lem.tablesize, lem.nconflict);
printf("Parser statistics:\n");
stats_line("terminal symbols", lem.nterminal);
stats_line("non-terminal symbols", lem.nsymbol - lem.nterminal);
stats_line("total symbols", lem.nsymbol);
stats_line("rules", lem.nrule);
stats_line("states", lem.nxstate);
stats_line("conflicts", lem.nconflict);
stats_line("action table entries", lem.nactiontab);
stats_line("total table size (bytes)", lem.tablesize);
}
if( lem.nconflict > 0 ){
fprintf(stderr,"%d parsing conflicts.\n",lem.nconflict);
@@ -2943,15 +2964,14 @@ void Reprint(struct lemon *lemp)
}
}
void ConfigPrint(FILE *fp, struct config *cfp)
{
struct rule *rp;
/* Print a single rule.
*/
void RulePrint(FILE *fp, struct rule *rp, int iCursor){
struct symbol *sp;
int i, j;
rp = cfp->rp;
fprintf(fp,"%s ::=",rp->lhs->name);
for(i=0; i<=rp->nrhs; i++){
if( i==cfp->dot ) fprintf(fp," *");
if( i==iCursor ) fprintf(fp," *");
if( i==rp->nrhs ) break;
sp = rp->rhs[i];
if( sp->type==MULTITERMINAL ){
@@ -2965,6 +2985,12 @@ void ConfigPrint(FILE *fp, struct config *cfp)
}
}
/* Print the rule for a configuration.
*/
void ConfigPrint(FILE *fp, struct config *cfp){
RulePrint(fp, cfp->rp, cfp->dot);
}
/* #define TEST */
#if 0
/* Print a set */
@@ -3004,15 +3030,30 @@ char *tag;
/* Print an action to the given file descriptor. Return FALSE if
** nothing was actually printed.
*/
int PrintAction(struct action *ap, FILE *fp, int indent){
int PrintAction(
struct action *ap, /* The action to print */
FILE *fp, /* Print the action here */
int indent /* Indent by this amount */
){
int result = 1;
switch( ap->type ){
case SHIFT:
fprintf(fp,"%*s shift %d",indent,ap->sp->name,ap->x.stp->statenum);
case SHIFT: {
struct state *stp = ap->x.stp;
fprintf(fp,"%*s shift %-7d",indent,ap->sp->name,stp->statenum);
break;
case REDUCE:
fprintf(fp,"%*s reduce %d",indent,ap->sp->name,ap->x.rp->index);
}
case REDUCE: {
struct rule *rp = ap->x.rp;
fprintf(fp,"%*s reduce %-7d",indent,ap->sp->name,rp->index);
RulePrint(fp, rp, -1);
break;
}
case SHIFTREDUCE: {
struct rule *rp = ap->x.rp;
fprintf(fp,"%*s shift-reduce %-7d",indent,ap->sp->name,rp->index);
RulePrint(fp, rp, -1);
break;
}
case ACCEPT:
fprintf(fp,"%*s accept",indent,ap->sp->name);
break;
@@ -3021,16 +3062,16 @@ int PrintAction(struct action *ap, FILE *fp, int indent){
break;
case SRCONFLICT:
case RRCONFLICT:
fprintf(fp,"%*s reduce %-3d ** Parsing conflict **",
fprintf(fp,"%*s reduce %-7d ** Parsing conflict **",
indent,ap->sp->name,ap->x.rp->index);
break;
case SSCONFLICT:
fprintf(fp,"%*s shift %-3d ** Parsing conflict **",
fprintf(fp,"%*s shift %-7d ** Parsing conflict **",
indent,ap->sp->name,ap->x.stp->statenum);
break;
case SH_RESOLVED:
if( showPrecedenceConflict ){
fprintf(fp,"%*s shift %-3d -- dropped by precedence",
fprintf(fp,"%*s shift %-7d -- dropped by precedence",
indent,ap->sp->name,ap->x.stp->statenum);
}else{
result = 0;
@@ -3038,7 +3079,7 @@ int PrintAction(struct action *ap, FILE *fp, int indent){
break;
case RD_RESOLVED:
if( showPrecedenceConflict ){
fprintf(fp,"%*s reduce %-3d -- dropped by precedence",
fprintf(fp,"%*s reduce %-7d -- dropped by precedence",
indent,ap->sp->name,ap->x.rp->index);
}else{
result = 0;
@@ -3051,7 +3092,7 @@ int PrintAction(struct action *ap, FILE *fp, int indent){
return result;
}
/* Generate the "y.output" log file */
/* Generate the "*.out" log file */
void ReportOutput(struct lemon *lemp)
{
int i;
@@ -3062,7 +3103,7 @@ void ReportOutput(struct lemon *lemp)
fp = file_open(lemp,".out","wb");
if( fp==0 ) return;
for(i=0; i<lemp->nstate; i++){
for(i=0; i<lemp->nxstate; i++){
stp = lemp->sorted[i];
fprintf(fp,"State %d:\n",stp->statenum);
if( lemp->basisflag ) cfp=stp->bp;
@@ -3170,10 +3211,11 @@ PRIVATE int compute_action(struct lemon *lemp, struct action *ap)
{
int act;
switch( ap->type ){
case SHIFT: act = ap->x.stp->statenum; break;
case REDUCE: act = ap->x.rp->index + lemp->nstate; break;
case ERROR: act = lemp->nstate + lemp->nrule; break;
case ACCEPT: act = lemp->nstate + lemp->nrule + 1; break;
case SHIFT: act = ap->x.stp->statenum; break;
case SHIFTREDUCE: act = ap->x.rp->index + lemp->nstate; break;
case REDUCE: act = ap->x.rp->index + lemp->nstate+lemp->nrule; break;
case ERROR: act = lemp->nstate + lemp->nrule*2; break;
case ACCEPT: act = lemp->nstate + lemp->nrule*2 + 1; break;
default: act = -1; break;
}
return act;
@@ -3661,24 +3703,32 @@ void print_stack_union(
/*
** Return the name of a C datatype able to represent values between
** lwr and upr, inclusive.
** lwr and upr, inclusive. If pnByte!=NULL then also write the sizeof
** for that type (1, 2, or 4) into *pnByte.
*/
static const char *minimum_size_type(int lwr, int upr){
static const char *minimum_size_type(int lwr, int upr, int *pnByte){
const char *zType = "int";
int nByte = 4;
if( lwr>=0 ){
if( upr<=255 ){
return "unsigned char";
zType = "unsigned char";
nByte = 1;
}else if( upr<65535 ){
return "unsigned short int";
zType = "unsigned short int";
nByte = 2;
}else{
return "unsigned int";
zType = "unsigned int";
nByte = 4;
}
}else if( lwr>=-127 && upr<=127 ){
return "signed char";
zType = "signed char";
nByte = 1;
}else if( lwr>=-32767 && upr<32767 ){
return "short";
}else{
return "int";
zType = "short";
nByte = 2;
}
if( pnByte ) *pnByte = nByte;
return zType;
}
/*
@@ -3703,7 +3753,7 @@ static int axset_compare(const void *a, const void *b){
int c;
c = p2->nAction - p1->nAction;
if( c==0 ){
c = p2->iOrder - p1->iOrder;
c = p1->iOrder - p2->iOrder;
}
assert( c!=0 || p1==p2 );
return c;
@@ -3742,7 +3792,9 @@ void ReportTable(
struct action *ap;
struct rule *rp;
struct acttab *pActtab;
int i, j, n;
int i, j, n, sz;
int szActionType; /* sizeof(YYACTIONTYPE) */
int szCodeType; /* sizeof(YYCODETYPE) */
const char *name;
int mnTknOfst, mxTknOfst;
int mnNtOfst, mxNtOfst;
@@ -3783,10 +3835,10 @@ void ReportTable(
/* Generate the defines */
fprintf(out,"#define YYCODETYPE %s\n",
minimum_size_type(0, lemp->nsymbol+1)); lineno++;
minimum_size_type(0, lemp->nsymbol+1, &szCodeType)); lineno++;
fprintf(out,"#define YYNOCODE %d\n",lemp->nsymbol+1); lineno++;
fprintf(out,"#define YYACTIONTYPE %s\n",
minimum_size_type(0, lemp->nstate+lemp->nrule+5)); lineno++;
minimum_size_type(0,lemp->nstate+lemp->nrule*2+5,&szActionType)); lineno++;
if( lemp->wildcard ){
fprintf(out,"#define YYWILDCARD %d\n",
lemp->wildcard->index); lineno++;
@@ -3822,36 +3874,24 @@ void ReportTable(
if( mhflag ){
fprintf(out,"#endif\n"); lineno++;
}
fprintf(out,"#define YYNSTATE %d\n",lemp->nstate); lineno++;
fprintf(out,"#define YYNRULE %d\n",lemp->nrule); lineno++;
if( lemp->errsym->useCnt ){
fprintf(out,"#define YYERRORSYMBOL %d\n",lemp->errsym->index); lineno++;
fprintf(out,"#define YYERRSYMDT yy%d\n",lemp->errsym->dtnum); lineno++;
fprintf(out,"#define YYERRORSYMBOL %d\n",lemp->errsym->index); lineno++;
fprintf(out,"#define YYERRSYMDT yy%d\n",lemp->errsym->dtnum); lineno++;
}
if( lemp->has_fallback ){
fprintf(out,"#define YYFALLBACK 1\n"); lineno++;
}
tplt_xfer(lemp->name,in,out,&lineno);
/* Generate the action table and its associates:
**
** yy_action[] A single table containing all actions.
** yy_lookahead[] A table containing the lookahead for each entry in
** yy_action. Used to detect hash collisions.
** yy_shift_ofst[] For each state, the offset into yy_action for
** shifting terminals.
** yy_reduce_ofst[] For each state, the offset into yy_action for
** shifting non-terminals after a reduce.
** yy_default[] Default action for each state.
/* Compute the action table, but do not output it yet. The action
** table must be computed before generating the YYNSTATE macro because
** we need to know how many states can be eliminated.
*/
/* Compute the actions on all states and count them up */
ax = (struct axset *) calloc(lemp->nstate*2, sizeof(ax[0]));
ax = (struct axset *) calloc(lemp->nxstate*2, sizeof(ax[0]));
if( ax==0 ){
fprintf(stderr,"malloc failed\n");
exit(1);
}
for(i=0; i<lemp->nstate; i++){
for(i=0; i<lemp->nxstate; i++){
stp = lemp->sorted[i];
ax[i*2].stp = stp;
ax[i*2].isTkn = 1;
@@ -3862,15 +3902,12 @@ void ReportTable(
}
mxTknOfst = mnTknOfst = 0;
mxNtOfst = mnNtOfst = 0;
/* Compute the action table. In order to try to keep the size of the
** action table to a minimum, the heuristic of placing the largest action
** sets first is used.
*/
for(i=0; i<lemp->nstate*2; i++) ax[i].iOrder = i;
qsort(ax, lemp->nstate*2, sizeof(ax[0]), axset_compare);
/* In an effort to minimize the action table size, use the heuristic
** of placing the largest action sets first */
for(i=0; i<lemp->nxstate*2; i++) ax[i].iOrder = i;
qsort(ax, lemp->nxstate*2, sizeof(ax[0]), axset_compare);
pActtab = acttab_alloc();
for(i=0; i<lemp->nstate*2 && ax[i].nAction>0; i++){
for(i=0; i<lemp->nxstate*2 && ax[i].nAction>0; i++){
stp = ax[i].stp;
if( ax[i].isTkn ){
for(ap=stp->ap; ap; ap=ap->next){
@@ -3896,11 +3933,50 @@ void ReportTable(
if( stp->iNtOfst<mnNtOfst ) mnNtOfst = stp->iNtOfst;
if( stp->iNtOfst>mxNtOfst ) mxNtOfst = stp->iNtOfst;
}
#if 0 /* Uncomment for a trace of how the yy_action[] table fills out */
{ int jj, nn;
for(jj=nn=0; jj<pActtab->nAction; jj++){
if( pActtab->aAction[jj].action<0 ) nn++;
}
printf("%4d: State %3d %s n: %2d size: %5d freespace: %d\n",
i, stp->statenum, ax[i].isTkn ? "Token" : "Var ",
ax[i].nAction, pActtab->nAction, nn);
}
#endif
}
free(ax);
/* Finish rendering the constants now that the action table has
** been computed */
fprintf(out,"#define YYNSTATE %d\n",lemp->nxstate); lineno++;
fprintf(out,"#define YYNRULE %d\n",lemp->nrule); lineno++;
fprintf(out,"#define YY_MAX_SHIFT %d\n",lemp->nxstate-1); lineno++;
fprintf(out,"#define YY_MIN_SHIFTREDUCE %d\n",lemp->nstate); lineno++;
i = lemp->nstate + lemp->nrule;
fprintf(out,"#define YY_MAX_SHIFTREDUCE %d\n", i-1); lineno++;
fprintf(out,"#define YY_MIN_REDUCE %d\n", i); lineno++;
i = lemp->nstate + lemp->nrule*2;
fprintf(out,"#define YY_MAX_REDUCE %d\n", i-1); lineno++;
fprintf(out,"#define YY_ERROR_ACTION %d\n", i); lineno++;
fprintf(out,"#define YY_ACCEPT_ACTION %d\n", i+1); lineno++;
fprintf(out,"#define YY_NO_ACTION %d\n", i+2); lineno++;
tplt_xfer(lemp->name,in,out,&lineno);
/* Now output the action table and its associates:
**
** yy_action[] A single table containing all actions.
** yy_lookahead[] A table containing the lookahead for each entry in
** yy_action. Used to detect hash collisions.
** yy_shift_ofst[] For each state, the offset into yy_action for
** shifting terminals.
** yy_reduce_ofst[] For each state, the offset into yy_action for
** shifting non-terminals after a reduce.
** yy_default[] Default action for each state.
*/
/* Output the yy_action table */
n = acttab_size(pActtab);
lemp->nactiontab = n = acttab_size(pActtab);
lemp->tablesize += n*szActionType;
fprintf(out,"#define YY_ACTTAB_COUNT (%d)\n", n); lineno++;
fprintf(out,"static const YYACTIONTYPE yy_action[] = {\n"); lineno++;
for(i=j=0; i<n; i++){
@@ -3918,6 +3994,7 @@ void ReportTable(
fprintf(out, "};\n"); lineno++;
/* Output the yy_lookahead table */
lemp->tablesize += n*szCodeType;
fprintf(out,"static const YYCODETYPE yy_lookahead[] = {\n"); lineno++;
for(i=j=0; i<n; i++){
int la = acttab_yylookahead(pActtab, i);
@@ -3935,13 +4012,14 @@ void ReportTable(
/* Output the yy_shift_ofst[] table */
fprintf(out, "#define YY_SHIFT_USE_DFLT (%d)\n", mnTknOfst-1); lineno++;
n = lemp->nstate;
n = lemp->nxstate;
while( n>0 && lemp->sorted[n-1]->iTknOfst==NO_OFFSET ) n--;
fprintf(out, "#define YY_SHIFT_COUNT (%d)\n", n-1); lineno++;
fprintf(out, "#define YY_SHIFT_MIN (%d)\n", mnTknOfst); lineno++;
fprintf(out, "#define YY_SHIFT_MAX (%d)\n", mxTknOfst); lineno++;
fprintf(out, "static const %s yy_shift_ofst[] = {\n",
minimum_size_type(mnTknOfst-1, mxTknOfst)); lineno++;
minimum_size_type(mnTknOfst-1, mxTknOfst, &sz)); lineno++;
lemp->tablesize += n*sz;
for(i=j=0; i<n; i++){
int ofst;
stp = lemp->sorted[i];
@@ -3960,13 +4038,14 @@ void ReportTable(
/* Output the yy_reduce_ofst[] table */
fprintf(out, "#define YY_REDUCE_USE_DFLT (%d)\n", mnNtOfst-1); lineno++;
n = lemp->nstate;
n = lemp->nxstate;
while( n>0 && lemp->sorted[n-1]->iNtOfst==NO_OFFSET ) n--;
fprintf(out, "#define YY_REDUCE_COUNT (%d)\n", n-1); lineno++;
fprintf(out, "#define YY_REDUCE_MIN (%d)\n", mnNtOfst); lineno++;
fprintf(out, "#define YY_REDUCE_MAX (%d)\n", mxNtOfst); lineno++;
fprintf(out, "static const %s yy_reduce_ofst[] = {\n",
minimum_size_type(mnNtOfst-1, mxNtOfst)); lineno++;
minimum_size_type(mnNtOfst-1, mxNtOfst, &sz)); lineno++;
lemp->tablesize += n*sz;
for(i=j=0; i<n; i++){
int ofst;
stp = lemp->sorted[i];
@@ -3985,11 +4064,12 @@ void ReportTable(
/* Output the default action table */
fprintf(out, "static const YYACTIONTYPE yy_default[] = {\n"); lineno++;
n = lemp->nstate;
n = lemp->nxstate;
lemp->tablesize += n*szActionType;
for(i=j=0; i<n; i++){
stp = lemp->sorted[i];
if( j==0 ) fprintf(out," /* %5d */ ", i);
fprintf(out, " %4d,", stp->iDflt);
fprintf(out, " %4d,", stp->iDfltReduce+lemp->nstate+lemp->nrule);
if( j==9 || i==n-1 ){
fprintf(out, "\n"); lineno++;
j = 0;
@@ -4005,6 +4085,7 @@ void ReportTable(
if( lemp->has_fallback ){
int mx = lemp->nterminal - 1;
while( mx>0 && lemp->symbols[mx]->fallback==0 ){ mx--; }
lemp->tablesize += (mx+1)*szCodeType;
for(i=0; i<=mx; i++){
struct symbol *p = lemp->symbols[i];
if( p->fallback==0 ){
@@ -4269,6 +4350,32 @@ void CompressTables(struct lemon *lemp)
if( ap->type==REDUCE && ap->x.rp==rbest ) ap->type = NOT_USED;
}
stp->ap = Action_sort(stp->ap);
for(ap=stp->ap; ap; ap=ap->next){
if( ap->type==SHIFT ) break;
if( ap->type==REDUCE && ap->x.rp!=rbest ) break;
}
if( ap==0 ){
stp->autoReduce = 1;
stp->pDfltReduce = rbest;
}
}
/* Make a second pass over all states and actions. Convert
** every action that is a SHIFT to an autoReduce state into
** a SHIFTREDUCE action.
*/
for(i=0; i<lemp->nstate; i++){
stp = lemp->sorted[i];
for(ap=stp->ap; ap; ap=ap->next){
struct state *pNextState;
if( ap->type!=SHIFT ) continue;
pNextState = ap->x.stp;
if( pNextState->autoReduce && pNextState->pDfltReduce!=0 ){
ap->type = SHIFTREDUCE;
ap->x.rp = pNextState->pDfltReduce;
}
}
}
}
@@ -4309,17 +4416,19 @@ void ResortStates(struct lemon *lemp)
for(i=0; i<lemp->nstate; i++){
stp = lemp->sorted[i];
stp->nTknAct = stp->nNtAct = 0;
stp->iDflt = lemp->nstate + lemp->nrule;
stp->iDfltReduce = lemp->nrule; /* Init dflt action to "syntax error" */
stp->iTknOfst = NO_OFFSET;
stp->iNtOfst = NO_OFFSET;
for(ap=stp->ap; ap; ap=ap->next){
if( compute_action(lemp,ap)>=0 ){
int iAction = compute_action(lemp,ap);
if( iAction>=0 ){
if( ap->sp->index<lemp->nterminal ){
stp->nTknAct++;
}else if( ap->sp->index<lemp->nsymbol ){
stp->nNtAct++;
}else{
stp->iDflt = compute_action(lemp, ap);
assert( stp->autoReduce==0 || stp->pDfltReduce==ap->x.rp );
stp->iDfltReduce = iAction - lemp->nstate - lemp->nrule;
}
}
}
@@ -4329,6 +4438,10 @@ void ResortStates(struct lemon *lemp)
for(i=0; i<lemp->nstate; i++){
lemp->sorted[i]->statenum = i;
}
lemp->nxstate = lemp->nstate;
while( lemp->nxstate>1 && lemp->sorted[lemp->nxstate-1]->autoReduce ){
lemp->nxstate--;
}
}
+71 -41
View File
@@ -50,15 +50,19 @@
** ParseARG_PDECL A parameter declaration for the %extra_argument
** ParseARG_STORE Code to store %extra_argument into yypParser
** ParseARG_FETCH Code to extract %extra_argument from yypParser
** YYNSTATE the combined number of states.
** YYNRULE the number of rules in the grammar
** YYERRORSYMBOL is the code number of the error symbol. If not
** defined, then do no error processing.
** YYNSTATE the combined number of states.
** YYNRULE the number of rules in the grammar
** YY_MAX_SHIFT Maximum value for shift actions
** YY_MIN_SHIFTREDUCE Minimum value for shift-reduce actions
** YY_MAX_SHIFTREDUCE Maximum value for shift-reduce actions
** YY_MIN_REDUCE Maximum value for reduce actions
** YY_ERROR_ACTION The yy_action[] code for syntax error
** YY_ACCEPT_ACTION The yy_action[] code for accept
** YY_NO_ACTION The yy_action[] code for no-op
*/
%%
#define YY_NO_ACTION (YYNSTATE+YYNRULE+2)
#define YY_ACCEPT_ACTION (YYNSTATE+YYNRULE+1)
#define YY_ERROR_ACTION (YYNSTATE+YYNRULE)
/* The yyzerominor constant is used to initialize instances of
** YYMINORTYPE objects to zero. */
@@ -85,16 +89,20 @@ static const YYMINORTYPE yyzerominor = { 0 };
** Suppose the action integer is N. Then the action is determined as
** follows
**
** 0 <= N < YYNSTATE Shift N. That is, push the lookahead
** 0 <= N <= YY_MAX_SHIFT Shift N. That is, push the lookahead
** token onto the stack and goto state N.
**
** YYNSTATE <= N < YYNSTATE+YYNRULE Reduce by rule N-YYNSTATE.
** N between YY_MIN_SHIFTREDUCE Shift to an arbitrary state then
** and YY_MAX_SHIFTREDUCE reduce by rule N-YY_MIN_SHIFTREDUCE.
**
** N == YYNSTATE+YYNRULE A syntax error has occurred.
** N between YY_MIN_REDUCE Reduce by rule N-YY_MIN_REDUCE
** and YY_MAX_REDUCE
** N == YY_ERROR_ACTION A syntax error has occurred.
**
** N == YYNSTATE+YYNRULE+1 The parser accepts its input.
** N == YY_ACCEPT_ACTION The parser accepts its input.
**
** N == YYNSTATE+YYNRULE+2 No such action. Denotes unused
** N == YY_NO_ACTION No such action. Denotes unused
** slots in the yy_action[] table.
**
** The action table is constructed as a single large table named yy_action[].
@@ -153,9 +161,13 @@ static const YYCODETYPE yyFallback[] = {
** + The semantic value stored at this level of the stack. This is
** the information used by the action routines in the grammar.
** It is sometimes called the "minor" token.
**
** After the "shift" half of a SHIFTREDUCE action, the stateno field
** actually contains the reduce action for the second half of the
** SHIFTREDUCE.
*/
struct yyStackEntry {
YYACTIONTYPE stateno; /* The state-number */
YYACTIONTYPE stateno; /* The state-number, or reduce action in SHIFTREDUCE */
YYCODETYPE major; /* The major token value. This is the code
** number for the token at this stack level */
YYMINORTYPE minor; /* The user-supplied minor token value. This
@@ -384,11 +396,11 @@ static int yy_find_shift_action(
){
int i;
int stateno = pParser->yystack[pParser->yyidx].stateno;
if( stateno>YY_SHIFT_COUNT
|| (i = yy_shift_ofst[stateno])==YY_SHIFT_USE_DFLT ){
return yy_default[stateno];
}
if( stateno>=YY_MIN_REDUCE ) return stateno;
assert( stateno <= YY_SHIFT_COUNT );
i = yy_shift_ofst[stateno];
if( i==YY_SHIFT_USE_DFLT ) return yy_default[stateno];
assert( iLookAhead!=YYNOCODE );
i += iLookAhead;
if( i<0 || i>=YY_ACTTAB_COUNT || yy_lookahead[i]!=iLookAhead ){
@@ -489,7 +501,29 @@ static void yyStackOverflow(yyParser *yypParser, YYMINORTYPE *yypMinor){
}
/*
** Perform a shift action.
** Print tracing information for a SHIFT action
*/
#ifndef NDEBUG
static void yyTraceShift(yyParser *yypParser, int yyNewState){
if( yyTraceFILE ){
int i;
if( yyNewState<YYNSTATE ){
fprintf(yyTraceFILE,"%sShift %d\n",yyTracePrompt,yyNewState);
fprintf(yyTraceFILE,"%sStack:",yyTracePrompt);
for(i=1; i<=yypParser->yyidx; i++)
fprintf(yyTraceFILE," %s",yyTokenName[yypParser->yystack[i].major]);
fprintf(yyTraceFILE,"\n");
}else{
fprintf(yyTraceFILE,"%sShift *\n",yyTracePrompt);
}
}
}
#else
# define yyTraceShift(X,Y)
#endif
/*
** Perform a shift action. Return the number of errors.
*/
static void yy_shift(
yyParser *yypParser, /* The parser to be shifted */
@@ -522,16 +556,7 @@ static void yy_shift(
yytos->stateno = (YYACTIONTYPE)yyNewState;
yytos->major = (YYCODETYPE)yyMajor;
yytos->minor = *yypMinor;
#ifndef NDEBUG
if( yyTraceFILE && yypParser->yyidx>0 ){
int i;
fprintf(yyTraceFILE,"%sShift %d\n",yyTracePrompt,yyNewState);
fprintf(yyTraceFILE,"%sStack:",yyTracePrompt);
for(i=1; i<=yypParser->yyidx; i++)
fprintf(yyTraceFILE," %s",yyTokenName[yypParser->yystack[i].major]);
fprintf(yyTraceFILE,"\n");
}
#endif
yyTraceShift(yypParser, yyNewState);
}
/* The following table contains information about every rule that
@@ -564,8 +589,9 @@ static void yy_reduce(
#ifndef NDEBUG
if( yyTraceFILE && yyruleno>=0
&& yyruleno<(int)(sizeof(yyRuleName)/sizeof(yyRuleName[0])) ){
fprintf(yyTraceFILE, "%sReduce [%s].\n", yyTracePrompt,
yyRuleName[yyruleno]);
yysize = yyRuleInfo[yyruleno].nrhs;
fprintf(yyTraceFILE, "%sReduce [%s] -> state %d.\n", yyTracePrompt,
yyRuleName[yyruleno], yymsp[-yysize].stateno);
}
#endif /* NDEBUG */
@@ -602,9 +628,9 @@ static void yy_reduce(
yysize = yyRuleInfo[yyruleno].nrhs;
yypParser->yyidx -= yysize;
yyact = yy_find_reduce_action(yymsp[-yysize].stateno,(YYCODETYPE)yygoto);
if( yyact < YYNSTATE ){
#ifdef NDEBUG
/* If we are not debugging and the reduce action popped at least
if( yyact <= YY_MAX_SHIFTREDUCE ){
if( yyact>YY_MAX_SHIFT ) yyact += YY_MIN_REDUCE - YY_MIN_SHIFTREDUCE;
/* If the reduce action popped at least
** one element off the stack, then we can push the new element back
** onto the stack here, and skip the stack overflow test in yy_shift().
** That gives a significant speed improvement. */
@@ -614,13 +640,12 @@ static void yy_reduce(
yymsp->stateno = (YYACTIONTYPE)yyact;
yymsp->major = (YYCODETYPE)yygoto;
yymsp->minor = yygotominor;
}else
#endif
{
yyTraceShift(yypParser, yyact);
}else{
yy_shift(yypParser,yyact,yygoto,&yygotominor);
}
}else{
assert( yyact == YYNSTATE + YYNRULE + 1 );
assert( yyact == YY_ACCEPT_ACTION );
yy_accept(yypParser);
}
}
@@ -740,13 +765,13 @@ void Parse(
do{
yyact = yy_find_shift_action(yypParser,(YYCODETYPE)yymajor);
if( yyact<YYNSTATE ){
assert( !yyendofinput ); /* Impossible to shift the $ token */
if( yyact <= YY_MAX_SHIFTREDUCE ){
if( yyact > YY_MAX_SHIFT ) yyact += YY_MIN_REDUCE - YY_MIN_SHIFTREDUCE;
yy_shift(yypParser,yyact,yymajor,&yyminorunion);
yypParser->yyerrcnt--;
yymajor = YYNOCODE;
}else if( yyact < YYNSTATE + YYNRULE ){
yy_reduce(yypParser,yyact-YYNSTATE);
}else if( yyact <= YY_MAX_REDUCE ){
yy_reduce(yypParser,yyact-YY_MIN_REDUCE);
}else{
assert( yyact == YY_ERROR_ACTION );
#ifdef YYERRORSYMBOL
@@ -796,7 +821,7 @@ void Parse(
yymx != YYERRORSYMBOL &&
(yyact = yy_find_reduce_action(
yypParser->yystack[yypParser->yyidx].stateno,
YYERRORSYMBOL)) >= YYNSTATE
YYERRORSYMBOL)) >= YY_MIN_REDUCE
){
yy_pop_parser_stack(yypParser);
}
@@ -846,5 +871,10 @@ void Parse(
#endif
}
}while( yymajor!=YYNOCODE && yypParser->yyidx>=0 );
#ifndef NDEBUG
if( yyTraceFILE ){
fprintf(yyTraceFILE,"%sReturn\n",yyTracePrompt);
}
#endif
return;
}
+13 -1
View File
@@ -26,7 +26,19 @@ proc is_without_rowid {tname} {
#
proc usage {} {
set argv0 [file rootname [file tail [info nameofexecutable]]]
puts stderr "Usage: $argv0 \[--pageinfo] \[--stats] database-name"
puts stderr "Usage: $argv0 ?--pageinfo? ?--stats? database-filename"
puts stderr {
Analyze the SQLite3 database file specified by the "database-filename"
argument and output a report detailing size and storage efficiency
information for the database and its constituent tables and indexes.
Options:
--stats Output SQL text that creates a new database containing
statistics about the database that was analyzed
--pageinfo Show how each page of the database-file is used
}
exit 1
}
set file_to_analyze {}