aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authordrh <drh@noemail.net>2015-11-07 15:19:59 +0000
committerdrh <drh@noemail.net>2015-11-07 15:19:59 +0000
commit2476a6f2cb071b4ea17a99b1ddc05111cd1422f4 (patch)
treef15b211d55a45a22543eea8c46c0150153f7e851 /src
parentd6b7946c32ec1cf4b77f51ab82db553cf466c488 (diff)
downloadsqlite-2476a6f2cb071b4ea17a99b1ddc05111cd1422f4.tar.gz
sqlite-2476a6f2cb071b4ea17a99b1ddc05111cd1422f4.zip
Enhance TreeView to show WITH clauses. Add an assert to detect the
infinite loop behavior when certain kinds of errors occur on a nested WITH clause. FossilOrigin-Name: 2040d88e877bdb69de125a047cefb4a1558e89e8
Diffstat (limited to 'src')
-rw-r--r--src/select.c3
-rw-r--r--src/sqliteInt.h1
-rw-r--r--src/treeview.c44
3 files changed, 47 insertions, 1 deletions
diff --git a/src/select.c b/src/select.c
index 8db983891..456271365 100644
--- a/src/select.c
+++ b/src/select.c
@@ -3972,7 +3972,7 @@ static int convertCompoundSelectToSubquery(Walker *pWalker, Select *p){
** object that the returned CTE belongs to.
*/
static struct Cte *searchWith(
- With *pWith, /* Current outermost WITH clause */
+ With *pWith, /* Current innermost WITH clause */
struct SrcList_item *pItem, /* FROM clause element to resolve */
With **ppContext /* OUT: WITH clause return value belongs to */
){
@@ -4005,6 +4005,7 @@ static struct Cte *searchWith(
void sqlite3WithPush(Parse *pParse, With *pWith, u8 bFree){
assert( bFree==0 || pParse->pWith==0 );
if( pWith ){
+ assert( pParse->pWith!=pWith );
pWith->pOuter = pParse->pWith;
pParse->pWith = pWith;
pParse->bFreeWith = bFree;
diff --git a/src/sqliteInt.h b/src/sqliteInt.h
index 2b9ece78e..8956c43b0 100644
--- a/src/sqliteInt.h
+++ b/src/sqliteInt.h
@@ -3271,6 +3271,7 @@ char *sqlite3VMPrintf(sqlite3*,const char*, va_list);
void sqlite3TreeViewExpr(TreeView*, const Expr*, u8);
void sqlite3TreeViewExprList(TreeView*, const ExprList*, u8, const char*);
void sqlite3TreeViewSelect(TreeView*, const Select*, u8);
+ void sqlite3TreeViewWith(TreeView*, const With*, u8);
#endif
diff --git a/src/treeview.c b/src/treeview.c
index 971de4e8b..a26e9e2b9 100644
--- a/src/treeview.c
+++ b/src/treeview.c
@@ -79,6 +79,45 @@ static void sqlite3TreeViewItem(TreeView *p, const char *zLabel,u8 moreFollows){
sqlite3TreeViewLine(p, "%s", zLabel);
}
+/*
+** Generate a human-readable description of a WITH clause.
+*/
+void sqlite3TreeViewWith(TreeView *pView, const With *pWith, u8 moreToFollow){
+ int i;
+ if( pWith==0 ) return;
+ if( pWith->nCte==0 ) return;
+ if( pWith->pOuter ){
+ sqlite3TreeViewLine(pView, "WITH (0x%p, pOuter=0x%p)",pWith,pWith->pOuter);
+ }else{
+ sqlite3TreeViewLine(pView, "WITH (0x%p)", pWith);
+ }
+ if( pWith->nCte>0 ){
+ pView = sqlite3TreeViewPush(pView, 1);
+ for(i=0; i<pWith->nCte; i++){
+ StrAccum x;
+ char zLine[1000];
+ const struct Cte *pCte = &pWith->a[i];
+ sqlite3StrAccumInit(&x, 0, zLine, sizeof(zLine), 0);
+ sqlite3XPrintf(&x, 0, "%s", pCte->zName);
+ if( pCte->pCols && pCte->pCols->nExpr>0 ){
+ char cSep = '(';
+ int j;
+ for(j=0; j<pCte->pCols->nExpr; j++){
+ sqlite3XPrintf(&x, 0, "%c%s", cSep, pCte->pCols->a[j].zName);
+ cSep = ',';
+ }
+ sqlite3XPrintf(&x, 0, ")");
+ }
+ sqlite3XPrintf(&x, 0, " AS");
+ sqlite3StrAccumFinish(&x);
+ sqlite3TreeViewItem(pView, zLine, i<pWith->nCte-1);
+ sqlite3TreeViewSelect(pView, pCte->pSelect, 0);
+ sqlite3TreeViewPop(pView);
+ }
+ sqlite3TreeViewPop(pView);
+ }
+}
+
/*
** Generate a human-readable description of a the Select object.
@@ -87,6 +126,11 @@ void sqlite3TreeViewSelect(TreeView *pView, const Select *p, u8 moreToFollow){
int n = 0;
int cnt = 0;
pView = sqlite3TreeViewPush(pView, moreToFollow);
+ if( p->pWith ){
+ sqlite3TreeViewWith(pView, p->pWith, 1);
+ cnt = 1;
+ sqlite3TreeViewPush(pView, 1);
+ }
do{
sqlite3TreeViewLine(pView, "SELECT%s%s (0x%p) selFlags=0x%x",
((p->selFlags & SF_Distinct) ? " DISTINCT" : ""),