Merge latest changes from trunk. Including fts5_expr.c fixes.
FossilOrigin-Name: 716e7e747714d6af502f6a87ca8d789bb7ce162a
This commit is contained in:
@@ -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
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -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
@@ -1 +1 @@
|
||||
85aac7b8b6731e2f6880b80cfd62d431ea059799
|
||||
716e7e747714d6af502f6a87ca8d789bb7ce162a
|
||||
+11
-7
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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);
|
||||
|
||||
@@ -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();
|
||||
|
||||
@@ -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.
|
||||
*/
|
||||
|
||||
@@ -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
@@ -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
@@ -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
@@ -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;
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
@@ -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
@@ -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;
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
@@ -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"
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
@@ -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
@@ -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
@@ -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 {}
|
||||
|
||||
Reference in New Issue
Block a user