mirror of
https://github.com/sqlite/sqlite.git
synced 2025-11-08 03:22:21 +03:00
Improvements to the data-structure explain subsystem. Most queries now
give a reasonably detailed graph of their parse tree. FossilOrigin-Name: 0aa7d3d2346bdddcc4e1e25ee26d13c8594885e5
This commit is contained in:
14
manifest
14
manifest
@@ -1,5 +1,5 @@
|
|||||||
C Begin\sadding\sthe\sdata-structure\sexplaining\ssubsystem.\s\sAll\sis\scontained\swithin
|
C Improvements\sto\sthe\sdata-structure\sexplain\ssubsystem.\s\sMost\squeries\snow\ngive\sa\sreasonably\sdetailed\sgraph\sof\stheir\sparse\stree.
|
||||||
D 2011-12-06T19:44:51.212
|
D 2011-12-07T01:23:51.800
|
||||||
F Makefile.arm-wince-mingw32ce-gcc d6df77f1f48d690bd73162294bbba7f59507c72f
|
F Makefile.arm-wince-mingw32ce-gcc d6df77f1f48d690bd73162294bbba7f59507c72f
|
||||||
F Makefile.in 5b4a3e12a850b021547e43daf886b25133b44c07
|
F Makefile.in 5b4a3e12a850b021547e43daf886b25133b44c07
|
||||||
F Makefile.linux-gcc 91d710bdc4998cb015f39edf3cb314ec4f4d7e23
|
F Makefile.linux-gcc 91d710bdc4998cb015f39edf3cb314ec4f4d7e23
|
||||||
@@ -134,7 +134,7 @@ F src/complete.c dc1d136c0feee03c2f7550bafc0d29075e36deac
|
|||||||
F src/ctime.c a9c26822515f81ec21588cbb482ca6724be02e33
|
F src/ctime.c a9c26822515f81ec21588cbb482ca6724be02e33
|
||||||
F src/date.c 067a81c9942c497aafd2c260e13add8a7d0c7dd4
|
F src/date.c 067a81c9942c497aafd2c260e13add8a7d0c7dd4
|
||||||
F src/delete.c 51d32f0a9c880663e54ce309f52e40c325d5e112
|
F src/delete.c 51d32f0a9c880663e54ce309f52e40c325d5e112
|
||||||
F src/expr.c 942171222a30af8cf4f9504a43ef6cadaf993dae
|
F src/expr.c 62f6ad2a1dcfbf684e6916c0662d5b4f28b98346
|
||||||
F src/fault.c 160a0c015b6c2629d3899ed2daf63d75754a32bb
|
F src/fault.c 160a0c015b6c2629d3899ed2daf63d75754a32bb
|
||||||
F src/fkey.c 657212460bf5cfd3ae607d12ea62092844c227b5
|
F src/fkey.c 657212460bf5cfd3ae607d12ea62092844c227b5
|
||||||
F src/func.c 6261ce00aad9c63cd5b4219249b05683979060e9
|
F src/func.c 6261ce00aad9c63cd5b4219249b05683979060e9
|
||||||
@@ -180,7 +180,7 @@ F src/printf.c 7ffb4ebb8b341f67e049695ba031da717b3d2699
|
|||||||
F src/random.c cd4a67b3953b88019f8cd4ccd81394a8ddfaba50
|
F src/random.c cd4a67b3953b88019f8cd4ccd81394a8ddfaba50
|
||||||
F src/resolve.c 365ab1c870e38596d6869e76fb544fe6e4ffc809
|
F src/resolve.c 365ab1c870e38596d6869e76fb544fe6e4ffc809
|
||||||
F src/rowset.c 69afa95a97c524ba6faf3805e717b5b7ae85a697
|
F src/rowset.c 69afa95a97c524ba6faf3805e717b5b7ae85a697
|
||||||
F src/select.c 2923f3129afcddb8023971ab591b07cdc868c163
|
F src/select.c 352ac58d6070f9a5564e9648bc2202b9d6339747
|
||||||
F src/shell.c a1eadb2fdbfa45e54307263f0c8da8ee8cd61b8b
|
F src/shell.c a1eadb2fdbfa45e54307263f0c8da8ee8cd61b8b
|
||||||
F src/sqlite.h.in 1dc07194eb1a2c69c8ef75f88022b170be08024a
|
F src/sqlite.h.in 1dc07194eb1a2c69c8ef75f88022b170be08024a
|
||||||
F src/sqlite3ext.h 6904f4aadf976f95241311fbffb00823075d9477
|
F src/sqlite3ext.h 6904f4aadf976f95241311fbffb00823075d9477
|
||||||
@@ -977,7 +977,7 @@ F tool/tostr.awk e75472c2f98dd76e06b8c9c1367f4ab07e122d06
|
|||||||
F tool/vdbe-compress.tcl d70ea6d8a19e3571d7ab8c9b75cba86d1173ff0f
|
F tool/vdbe-compress.tcl d70ea6d8a19e3571d7ab8c9b75cba86d1173ff0f
|
||||||
F tool/warnings-clang.sh 9f406d66e750e8ac031c63a9ef3248aaa347ef2a
|
F tool/warnings-clang.sh 9f406d66e750e8ac031c63a9ef3248aaa347ef2a
|
||||||
F tool/warnings.sh fbc018d67fd7395f440c28f33ef0f94420226381
|
F tool/warnings.sh fbc018d67fd7395f440c28f33ef0f94420226381
|
||||||
P 162421dadf93e9201c3290d800c597cbeeacdb40
|
P 79ae51c5b1b20ed0a425a87e65a32a096a80b7e1
|
||||||
R ddbfe0a87d25503aebbe5e810f678862
|
R 33f29d39c143746ce94119c4aaec65fd
|
||||||
U drh
|
U drh
|
||||||
Z ed29fdae1618daadbff0e860a54f25e4
|
Z 8a3e65c823a12538f790d9d174308040
|
||||||
|
|||||||
@@ -1 +1 @@
|
|||||||
79ae51c5b1b20ed0a425a87e65a32a096a80b7e1
|
0aa7d3d2346bdddcc4e1e25ee26d13c8594885e5
|
||||||
266
src/expr.c
266
src/expr.c
@@ -2943,25 +2943,238 @@ int sqlite3ExprCodeAndCache(Parse *pParse, Expr *pExpr, int target){
|
|||||||
/*
|
/*
|
||||||
** Generate a human-readable explanation of an expression tree.
|
** Generate a human-readable explanation of an expression tree.
|
||||||
*/
|
*/
|
||||||
void sqlite3ExplainExpr(Vdbe *pOut, Expr *p){
|
void sqlite3ExplainExpr(Vdbe *pOut, Expr *pExpr){
|
||||||
if( p==0 ){
|
int op; /* The opcode being coded */
|
||||||
sqlite3ExplainPrintf(pOut, "(C-null)");
|
const char *zBinOp = 0; /* Binary operator */
|
||||||
return;
|
const char *zUniOp = 0; /* Unary operator */
|
||||||
}
|
if( pExpr==0 ){
|
||||||
if( !ExprHasProperty(p, EP_IntValue) && p->u.zToken ){
|
op = TK_NULL;
|
||||||
sqlite3ExplainPrintf(pOut, "(%s", p->u.zToken);
|
|
||||||
}else{
|
}else{
|
||||||
sqlite3ExplainPrintf(pOut, "(op=%d", p->op);
|
op = pExpr->op;
|
||||||
}
|
}
|
||||||
if( p->pLeft ){
|
switch( op ){
|
||||||
sqlite3ExplainPrintf(pOut, " left=");
|
case TK_AGG_COLUMN: {
|
||||||
sqlite3ExplainExpr(pOut, p->pLeft);
|
sqlite3ExplainPrintf(pOut, "AGG_COLUMN(%s:%d:%d)",
|
||||||
|
pExpr->pTab->zName, pExpr->iTable, pExpr->iColumn);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case TK_COLUMN: {
|
||||||
|
if( pExpr->iTable<0 ){
|
||||||
|
/* This only happens when coding check constraints */
|
||||||
|
sqlite3ExplainPrintf(pOut, "COLUMN(%d)", pExpr->iColumn);
|
||||||
|
}else{
|
||||||
|
sqlite3ExplainPrintf(pOut, "COLUMN(%s:%d:%d)",
|
||||||
|
pExpr->pTab->zName, pExpr->iTable, pExpr->iColumn);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case TK_INTEGER: {
|
||||||
|
if( pExpr->flags & EP_IntValue ){
|
||||||
|
sqlite3ExplainPrintf(pOut, "INTEGER(%d)", pExpr->u.iValue);
|
||||||
|
}else{
|
||||||
|
sqlite3ExplainPrintf(pOut, "INTEGER(%s)", pExpr->u.zToken);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
#ifndef SQLITE_OMIT_FLOATING_POINT
|
||||||
|
case TK_FLOAT: {
|
||||||
|
sqlite3ExplainPrintf(pOut,"REAL(%s)", pExpr->u.zToken);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
case TK_STRING: {
|
||||||
|
sqlite3ExplainPrintf(pOut,"STRING(%s)", pExpr->u.zToken);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case TK_NULL: {
|
||||||
|
sqlite3ExplainPrintf(pOut,"NULL");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
#ifndef SQLITE_OMIT_BLOB_LITERAL
|
||||||
|
case TK_BLOB: {
|
||||||
|
int n;
|
||||||
|
const char *z;
|
||||||
|
assert( !ExprHasProperty(pExpr, EP_IntValue) );
|
||||||
|
assert( pExpr->u.zToken[0]=='x' || pExpr->u.zToken[0]=='X' );
|
||||||
|
assert( pExpr->u.zToken[1]=='\'' );
|
||||||
|
z = &pExpr->u.zToken[2];
|
||||||
|
n = sqlite3Strlen30(z) - 1;
|
||||||
|
assert( z[n]=='\'' );
|
||||||
|
sqlite3ExplainPrintf(pOut,"BLOB(%.*s)", n, z);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
case TK_VARIABLE: {
|
||||||
|
sqlite3ExplainPrintf(pOut,"VARIABLE(%s,%d)",
|
||||||
|
pExpr->u.zToken, pExpr->iColumn);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case TK_REGISTER: {
|
||||||
|
sqlite3ExplainPrintf(pOut,"REGISTER(%d)", pExpr->iTable);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case TK_AS: {
|
||||||
|
sqlite3ExplainExpr(pOut, pExpr->pLeft);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
#ifndef SQLITE_OMIT_CAST
|
||||||
|
case TK_CAST: {
|
||||||
|
/* Expressions of the form: CAST(pLeft AS token) */
|
||||||
|
const char *zAff = "unk";
|
||||||
|
switch( sqlite3AffinityType(pExpr->u.zToken) ){
|
||||||
|
case SQLITE_AFF_TEXT: zAff = "TEXT"; break;
|
||||||
|
case SQLITE_AFF_NONE: zAff = "NONE"; break;
|
||||||
|
case SQLITE_AFF_NUMERIC: zAff = "NUMERIC"; break;
|
||||||
|
case SQLITE_AFF_INTEGER: zAff = "INTEGER"; break;
|
||||||
|
case SQLITE_AFF_REAL: zAff = "REAL"; break;
|
||||||
|
}
|
||||||
|
sqlite3ExplainPrintf(pOut, "CAST-%s(", zAff);
|
||||||
|
sqlite3ExplainExpr(pOut, pExpr->pLeft);
|
||||||
|
sqlite3ExplainPrintf(pOut, ")");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
#endif /* SQLITE_OMIT_CAST */
|
||||||
|
case TK_LT: zBinOp = "LT"; break;
|
||||||
|
case TK_LE: zBinOp = "LE"; break;
|
||||||
|
case TK_GT: zBinOp = "GT"; break;
|
||||||
|
case TK_GE: zBinOp = "GE"; break;
|
||||||
|
case TK_NE: zBinOp = "NE"; break;
|
||||||
|
case TK_EQ: zBinOp = "EQ"; break;
|
||||||
|
case TK_IS: zBinOp = "IS"; break;
|
||||||
|
case TK_ISNOT: zBinOp = "ISNOT"; break;
|
||||||
|
case TK_AND: zBinOp = "AND"; break;
|
||||||
|
case TK_OR: zBinOp = "OR"; break;
|
||||||
|
case TK_PLUS: zBinOp = "ADD"; break;
|
||||||
|
case TK_STAR: zBinOp = "MUL"; break;
|
||||||
|
case TK_MINUS: zBinOp = "SUB"; break;
|
||||||
|
case TK_REM: zBinOp = "REM"; break;
|
||||||
|
case TK_BITAND: zBinOp = "BITAND"; break;
|
||||||
|
case TK_BITOR: zBinOp = "BITOR"; break;
|
||||||
|
case TK_SLASH: zBinOp = "DIV"; break;
|
||||||
|
case TK_LSHIFT: zBinOp = "LSHIFT"; break;
|
||||||
|
case TK_RSHIFT: zBinOp = "RSHIFT"; break;
|
||||||
|
case TK_CONCAT: zBinOp = "CONCAT"; break;
|
||||||
|
|
||||||
|
case TK_UMINUS: zUniOp = "UMINUS"; break;
|
||||||
|
case TK_UPLUS: zUniOp = "UPLUS"; break;
|
||||||
|
case TK_BITNOT: zUniOp = "BITNOT"; break;
|
||||||
|
case TK_NOT: zUniOp = "NOT"; break;
|
||||||
|
case TK_ISNULL: zUniOp = "ISNULL"; break;
|
||||||
|
case TK_NOTNULL: zUniOp = "NOTNULL"; break;
|
||||||
|
|
||||||
|
case TK_AGG_FUNCTION:
|
||||||
|
case TK_CONST_FUNC:
|
||||||
|
case TK_FUNCTION: {
|
||||||
|
ExprList *pFarg; /* List of function arguments */
|
||||||
|
if( ExprHasAnyProperty(pExpr, EP_TokenOnly) ){
|
||||||
|
pFarg = 0;
|
||||||
|
}else{
|
||||||
|
pFarg = pExpr->x.pList;
|
||||||
|
}
|
||||||
|
sqlite3ExplainPrintf(pOut, "%sFUNCTION:%s(",
|
||||||
|
op==TK_AGG_FUNCTION ? "AGG_" : "",
|
||||||
|
pExpr->u.zToken);
|
||||||
|
if( pFarg ){
|
||||||
|
sqlite3ExplainExprList(pOut, pFarg);
|
||||||
|
}
|
||||||
|
sqlite3ExplainPrintf(pOut, ")");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
#ifndef SQLITE_OMIT_SUBQUERY
|
||||||
|
case TK_EXISTS: {
|
||||||
|
sqlite3ExplainPrintf(pOut, "EXISTS(");
|
||||||
|
sqlite3ExplainSelect(pOut, pExpr->x.pSelect);
|
||||||
|
sqlite3ExplainPrintf(pOut,")");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case TK_SELECT: {
|
||||||
|
sqlite3ExplainPrintf(pOut, "(");
|
||||||
|
sqlite3ExplainSelect(pOut, pExpr->x.pSelect);
|
||||||
|
sqlite3ExplainPrintf(pOut, ")");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case TK_IN: {
|
||||||
|
sqlite3ExplainPrintf(pOut, "IN(");
|
||||||
|
sqlite3ExplainExpr(pOut, pExpr->pLeft);
|
||||||
|
sqlite3ExplainPrintf(pOut, ",");
|
||||||
|
if( ExprHasProperty(pExpr, EP_xIsSelect) ){
|
||||||
|
sqlite3ExplainSelect(pOut, pExpr->x.pSelect);
|
||||||
|
}else{
|
||||||
|
sqlite3ExplainExprList(pOut, pExpr->x.pList);
|
||||||
|
}
|
||||||
|
sqlite3ExplainPrintf(pOut, ")");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
#endif /* SQLITE_OMIT_SUBQUERY */
|
||||||
|
|
||||||
|
/*
|
||||||
|
** x BETWEEN y AND z
|
||||||
|
**
|
||||||
|
** This is equivalent to
|
||||||
|
**
|
||||||
|
** x>=y AND x<=z
|
||||||
|
**
|
||||||
|
** X is stored in pExpr->pLeft.
|
||||||
|
** Y is stored in pExpr->pList->a[0].pExpr.
|
||||||
|
** Z is stored in pExpr->pList->a[1].pExpr.
|
||||||
|
*/
|
||||||
|
case TK_BETWEEN: {
|
||||||
|
Expr *pX = pExpr->pLeft;
|
||||||
|
Expr *pY = pExpr->x.pList->a[0].pExpr;
|
||||||
|
Expr *pZ = pExpr->x.pList->a[1].pExpr;
|
||||||
|
sqlite3ExplainPrintf(pOut, "BETWEEN(");
|
||||||
|
sqlite3ExplainExpr(pOut, pX);
|
||||||
|
sqlite3ExplainPrintf(pOut, ",");
|
||||||
|
sqlite3ExplainExpr(pOut, pY);
|
||||||
|
sqlite3ExplainPrintf(pOut, ",");
|
||||||
|
sqlite3ExplainExpr(pOut, pZ);
|
||||||
|
sqlite3ExplainPrintf(pOut, ")");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case TK_TRIGGER: {
|
||||||
|
/* If the opcode is TK_TRIGGER, then the expression is a reference
|
||||||
|
** to a column in the new.* or old.* pseudo-tables available to
|
||||||
|
** trigger programs. In this case Expr.iTable is set to 1 for the
|
||||||
|
** new.* pseudo-table, or 0 for the old.* pseudo-table. Expr.iColumn
|
||||||
|
** is set to the column of the pseudo-table to read, or to -1 to
|
||||||
|
** read the rowid field.
|
||||||
|
*/
|
||||||
|
sqlite3ExplainPrintf(pOut, "%s(%d)",
|
||||||
|
pExpr->iTable ? "NEW" : "OLD", pExpr->iColumn);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case TK_CASE: {
|
||||||
|
sqlite3ExplainPrintf(pOut, "CASE(");
|
||||||
|
sqlite3ExplainExpr(pOut, pExpr->pLeft);
|
||||||
|
sqlite3ExplainPrintf(pOut, ",");
|
||||||
|
sqlite3ExplainExprList(pOut, pExpr->x.pList);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
#ifndef SQLITE_OMIT_TRIGGER
|
||||||
|
case TK_RAISE: {
|
||||||
|
const char *zType = "unk";
|
||||||
|
switch( pExpr->affinity ){
|
||||||
|
case OE_Rollback: zType = "rollback"; break;
|
||||||
|
case OE_Abort: zType = "abort"; break;
|
||||||
|
case OE_Fail: zType = "fail"; break;
|
||||||
|
case OE_Ignore: zType = "ignore"; break;
|
||||||
|
}
|
||||||
|
sqlite3ExplainPrintf(pOut, "RAISE-%s(%s)", zType, pExpr->u.zToken);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
if( p->pRight ){
|
if( zBinOp ){
|
||||||
sqlite3ExplainPrintf(pOut, " right=");
|
sqlite3ExplainPrintf(pOut,"%s(", zBinOp);
|
||||||
sqlite3ExplainExpr(pOut, p->pRight);
|
sqlite3ExplainExpr(pOut, pExpr->pLeft);
|
||||||
|
sqlite3ExplainPrintf(pOut,",");
|
||||||
|
sqlite3ExplainExpr(pOut, pExpr->pRight);
|
||||||
|
sqlite3ExplainPrintf(pOut,")");
|
||||||
|
}else if( zUniOp ){
|
||||||
|
sqlite3ExplainPrintf(pOut,"%s(", zUniOp);
|
||||||
|
sqlite3ExplainExpr(pOut, pExpr->pLeft);
|
||||||
|
sqlite3ExplainPrintf(pOut,")");
|
||||||
}
|
}
|
||||||
sqlite3ExplainPrintf(pOut, ")");
|
|
||||||
}
|
}
|
||||||
#endif /* defined(SQLITE_DEBUG) */
|
#endif /* defined(SQLITE_DEBUG) */
|
||||||
|
|
||||||
@@ -2971,21 +3184,24 @@ void sqlite3ExplainExpr(Vdbe *pOut, Expr *p){
|
|||||||
*/
|
*/
|
||||||
void sqlite3ExplainExprList(Vdbe *pOut, ExprList *pList){
|
void sqlite3ExplainExprList(Vdbe *pOut, ExprList *pList){
|
||||||
int i;
|
int i;
|
||||||
if( pList==0 ){
|
if( pList==0 || pList->nExpr==0 ){
|
||||||
sqlite3ExplainPrintf(pOut, "(empty-list)");
|
sqlite3ExplainPrintf(pOut, "(empty-list)");
|
||||||
return;
|
return;
|
||||||
}
|
}else if( pList->nExpr==1 ){
|
||||||
sqlite3ExplainPush(pOut);
|
sqlite3ExplainExpr(pOut, pList->a[0].pExpr);
|
||||||
for(i=0; i<pList->nExpr; i++){
|
}else{
|
||||||
sqlite3ExplainPrintf(pOut, "%02d: ", i);
|
|
||||||
sqlite3ExplainPush(pOut);
|
sqlite3ExplainPush(pOut);
|
||||||
sqlite3ExplainExpr(pOut, pList->a[i].pExpr);
|
for(i=0; i<pList->nExpr; i++){
|
||||||
sqlite3ExplainPop(pOut);
|
sqlite3ExplainPrintf(pOut, "item[%d] = ", i);
|
||||||
if( i<pList->nExpr-1 ){
|
sqlite3ExplainPush(pOut);
|
||||||
sqlite3ExplainNL(pOut);
|
sqlite3ExplainExpr(pOut, pList->a[i].pExpr);
|
||||||
|
sqlite3ExplainPop(pOut);
|
||||||
|
if( i<pList->nExpr-1 ){
|
||||||
|
sqlite3ExplainNL(pOut);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
sqlite3ExplainPop(pOut);
|
||||||
}
|
}
|
||||||
sqlite3ExplainPop(pOut);
|
|
||||||
}
|
}
|
||||||
#endif /* SQLITE_DEBUG */
|
#endif /* SQLITE_DEBUG */
|
||||||
|
|
||||||
|
|||||||
54
src/select.c
54
src/select.c
@@ -4498,47 +4498,43 @@ select_end:
|
|||||||
/*
|
/*
|
||||||
** Generate a human-readable description of a the Select object.
|
** Generate a human-readable description of a the Select object.
|
||||||
*/
|
*/
|
||||||
void sqlite3ExplainSelect(Vdbe *pVdbe, Select *p){
|
static void explainOneSelect(Vdbe *pVdbe, Select *p){
|
||||||
if( p==0 ){
|
|
||||||
sqlite3ExplainPrintf(pVdbe, "(empty-select)");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
sqlite3ExplainPrintf(pVdbe, "SELECT ");
|
sqlite3ExplainPrintf(pVdbe, "SELECT ");
|
||||||
sqlite3ExplainPush(pVdbe);
|
|
||||||
sqlite3ExplainExprList(pVdbe, p->pEList);
|
sqlite3ExplainExprList(pVdbe, p->pEList);
|
||||||
sqlite3ExplainNL(pVdbe);
|
sqlite3ExplainNL(pVdbe);
|
||||||
sqlite3ExplainPop(pVdbe);
|
|
||||||
if( p->pSrc && p->pSrc->nSrc ){
|
if( p->pSrc && p->pSrc->nSrc ){
|
||||||
int i;
|
int i;
|
||||||
sqlite3ExplainPrintf(pVdbe, " FROM ");
|
sqlite3ExplainPrintf(pVdbe, "FROM ");
|
||||||
sqlite3ExplainPush(pVdbe);
|
sqlite3ExplainPush(pVdbe);
|
||||||
for(i=0; i<p->pSrc->nSrc; i++){
|
for(i=0; i<p->pSrc->nSrc; i++){
|
||||||
struct SrcList_item *pItem = &p->pSrc->a[i];
|
struct SrcList_item *pItem = &p->pSrc->a[i];
|
||||||
sqlite3ExplainPrintf(pVdbe, "%02d: ", i);
|
sqlite3ExplainPrintf(pVdbe, "src[%d] = ", i);
|
||||||
sqlite3ExplainPush(pVdbe);
|
|
||||||
if( pItem->pSelect ){
|
if( pItem->pSelect ){
|
||||||
sqlite3ExplainSelect(pVdbe, pItem->pSelect);
|
sqlite3ExplainSelect(pVdbe, pItem->pSelect);
|
||||||
}else if( pItem->zName ){
|
}else if( pItem->zName ){
|
||||||
sqlite3ExplainPrintf(pVdbe, "%s", pItem->zName);
|
sqlite3ExplainPrintf(pVdbe, "%s", pItem->zName);
|
||||||
}
|
}
|
||||||
if( pItem->pTab ){
|
if( pItem->pTab ){
|
||||||
sqlite3ExplainPrintf(pVdbe, " (table: %s)", pItem->pTab->zName);
|
sqlite3ExplainPrintf(pVdbe, " (name=%s:%d)",
|
||||||
|
pItem->pTab->zName, pItem->iCursor);
|
||||||
|
}
|
||||||
|
if( pItem->jointype & JT_LEFT ){
|
||||||
|
sqlite3ExplainPrintf(pVdbe, " LEFT-JOIN");
|
||||||
}
|
}
|
||||||
if( pItem->zAlias ){
|
if( pItem->zAlias ){
|
||||||
sqlite3ExplainPrintf(pVdbe, " (AS %s)", pItem->zAlias);
|
sqlite3ExplainPrintf(pVdbe, " (AS %s)", pItem->zAlias);
|
||||||
}
|
}
|
||||||
sqlite3ExplainNL(pVdbe);
|
sqlite3ExplainNL(pVdbe);
|
||||||
sqlite3ExplainPop(pVdbe);
|
|
||||||
}
|
}
|
||||||
sqlite3ExplainPop(pVdbe);
|
sqlite3ExplainPop(pVdbe);
|
||||||
}
|
}
|
||||||
if( p->pWhere ){
|
if( p->pWhere ){
|
||||||
sqlite3ExplainPrintf(pVdbe, " WHERE ");
|
sqlite3ExplainPrintf(pVdbe, "WHERE ");
|
||||||
sqlite3ExplainExpr(pVdbe, p->pWhere);
|
sqlite3ExplainExpr(pVdbe, p->pWhere);
|
||||||
sqlite3ExplainNL(pVdbe);
|
sqlite3ExplainNL(pVdbe);
|
||||||
}
|
}
|
||||||
if( p->pGroupBy ){
|
if( p->pGroupBy ){
|
||||||
sqlite3ExplainPrintf(pVdbe, " GROUP BY ");
|
sqlite3ExplainPrintf(pVdbe, "GROUPBY ");
|
||||||
sqlite3ExplainExprList(pVdbe, p->pGroupBy);
|
sqlite3ExplainExprList(pVdbe, p->pGroupBy);
|
||||||
sqlite3ExplainNL(pVdbe);
|
sqlite3ExplainNL(pVdbe);
|
||||||
}
|
}
|
||||||
@@ -4548,11 +4544,37 @@ void sqlite3ExplainSelect(Vdbe *pVdbe, Select *p){
|
|||||||
sqlite3ExplainNL(pVdbe);
|
sqlite3ExplainNL(pVdbe);
|
||||||
}
|
}
|
||||||
if( p->pOrderBy ){
|
if( p->pOrderBy ){
|
||||||
sqlite3ExplainPrintf(pVdbe, " ORDER BY ");
|
sqlite3ExplainPrintf(pVdbe, "ORDERBY ");
|
||||||
sqlite3ExplainExprList(pVdbe, p->pOrderBy);
|
sqlite3ExplainExprList(pVdbe, p->pOrderBy);
|
||||||
sqlite3ExplainNL(pVdbe);
|
sqlite3ExplainNL(pVdbe);
|
||||||
}
|
}
|
||||||
sqlite3ExplainPrintf(pVdbe, " END");
|
if( p->pLimit ){
|
||||||
|
sqlite3ExplainPrintf(pVdbe, "LIMIT ");
|
||||||
|
sqlite3ExplainExpr(pVdbe, p->pLimit);
|
||||||
|
sqlite3ExplainNL(pVdbe);
|
||||||
|
}
|
||||||
|
if( p->pOffset ){
|
||||||
|
sqlite3ExplainPrintf(pVdbe, "OFFSET ");
|
||||||
|
sqlite3ExplainExpr(pVdbe, p->pOffset);
|
||||||
|
sqlite3ExplainNL(pVdbe);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
void sqlite3ExplainSelect(Vdbe *pVdbe, Select *p){
|
||||||
|
if( p==0 ){
|
||||||
|
sqlite3ExplainPrintf(pVdbe, "(null-select)");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
while( p->pPrior ) p = p->pPrior;
|
||||||
|
sqlite3ExplainPush(pVdbe);
|
||||||
|
while( p ){
|
||||||
|
explainOneSelect(pVdbe, p);
|
||||||
|
p = p->pNext;
|
||||||
|
if( p==0 ) break;
|
||||||
|
sqlite3ExplainNL(pVdbe);
|
||||||
|
sqlite3ExplainPrintf(pVdbe, "%s\n", selectOpName(p->op));
|
||||||
|
}
|
||||||
|
sqlite3ExplainPrintf(pVdbe, "END");
|
||||||
|
sqlite3ExplainPop(pVdbe);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* End of the structure debug printing code
|
/* End of the structure debug printing code
|
||||||
|
|||||||
Reference in New Issue
Block a user