SQLite

Check-in [03b32be4]
Login

Many hyperlinks are disabled.
Use anonymous login to enable hyperlinks.

Overview
Comment:In the query flattener, defer deleting content until after associated Parse object is destroyed, in case some of the deleted expressions have been collected for use by sAggInfo.
Downloads: Tarball | ZIP archive | SQL archive
Timelines: family | ancestors | descendants | both | early-winfunc-rewrite-dev
Files: files | file ages | folders
SHA3-256: 03b32be44d9d278397d50c9a8d7aad7c07b92c10375113b261c7f610646d0717
User & Date: drh 2020-06-06 18:34:12
Context
2020-06-06
20:48
Merge multiple changes from trunk to address concerns with window-function parse-tree rewriting. (check-in: 05418b2a user: drh tags: branch-3.32-early-winfunc-rewrite)
18:45
Clearly distinguish between window functions and scalar functions in the debugging TreeView output. (check-in: 15babdcb user: drh tags: early-winfunc-rewrite-dev)
18:34
In the query flattener, defer deleting content until after associated Parse object is destroyed, in case some of the deleted expressions have been collected for use by sAggInfo. (check-in: 03b32be4 user: drh tags: early-winfunc-rewrite-dev)
14:58
Remove an incorrect assert() added earlier today. (check-in: 3926ff17 user: drh tags: early-winfunc-rewrite-dev)
Changes
Hide Diffs Unified Diffs Ignore Whitespace Patch

Changes to src/build.c.

208
209
210
211
212
213
214


215

216
217
218
219
220
221
222
      sqlite3AutoincrementBegin(pParse);

      /* Code constant expressions that where factored out of inner loops */
      if( pParse->pConstExpr ){
        ExprList *pEL = pParse->pConstExpr;
        pParse->okConstFactor = 0;
        for(i=0; i<pEL->nExpr; i++){


          sqlite3ExprCode(pParse, pEL->a[i].pExpr, pEL->a[i].u.iConstExprReg);

        }
      }

      /* Finally, jump back to the beginning of the executable code. */
      sqlite3VdbeGoto(v, 1);
    }
  }







>
>
|
>







208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
      sqlite3AutoincrementBegin(pParse);

      /* Code constant expressions that where factored out of inner loops */
      if( pParse->pConstExpr ){
        ExprList *pEL = pParse->pConstExpr;
        pParse->okConstFactor = 0;
        for(i=0; i<pEL->nExpr; i++){
          int iReg = pEL->a[i].u.iConstExprReg;
          if( iReg>0 ){
            sqlite3ExprCode(pParse, pEL->a[i].pExpr, iReg);
          }
        }
      }

      /* Finally, jump back to the beginning of the executable code. */
      sqlite3VdbeGoto(v, 1);
    }
  }

Changes to src/select.c.

163
164
165
166
167
168
169
170
171
172
173
174
175
176





























177
178
179
180
181
182
183
    pAllocated = 0;
  }else{
    assert( pNew->pSrc!=0 || pParse->nErr>0 );
  }
  return pAllocated;
}


/*
** Delete the given Select structure and all of its substructures.
*/
void sqlite3SelectDelete(sqlite3 *db, Select *p){
  if( OK_IF_ALWAYS_TRUE(p) ) clearSelect(db, p, 1);
}






























/*
** Delete all the substructure for p, but keep p allocated.  Redefine
** p to be a single SELECT where every column of the result set has a
** value of NULL.
*/
void sqlite3SelectReset(Parse *pParse, Select *p){







<






>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>







163
164
165
166
167
168
169

170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
    pAllocated = 0;
  }else{
    assert( pNew->pSrc!=0 || pParse->nErr>0 );
  }
  return pAllocated;
}


/*
** Delete the given Select structure and all of its substructures.
*/
void sqlite3SelectDelete(sqlite3 *db, Select *p){
  if( OK_IF_ALWAYS_TRUE(p) ) clearSelect(db, p, 1);
}

/*
** Make arrangements to delete a subquery when the Parse object is
** destroyed.
**
** This works by adding the subquery to the Parse.pConstExpr list, but
** with a register number of zero.  The pConstExpr list is destroyed
** when the Parse object is destroyed.  And the zero register means
** that the expression is not coded.
*/
void sqlite3SelectDeferredDelete(Parse *pParse, Select *p){
  Expr *pNew = sqlite3PExpr(pParse, TK_SELECT, 0, 0);
  if( pNew==0 ){
    clearSelect(pParse->db, p, 1);
  }else{
    sqlite3PExprAddSelect(pParse, pNew, p);
    pParse->pConstExpr =
      sqlite3ExprListAppend(pParse, pParse->pConstExpr, pNew);
    testcase( pParse->pConstExpr==0 ); /* Only true following OOM */
#ifdef SQLITE_DEBUG
    if( pParse->pConstExpr ){
      ExprList *p = pParse->pConstExpr;
      struct ExprList_item *pItem = &p->a[p->nExpr-1];
      assert( pItem->reusable==0 );
      assert( pItem->u.iConstExprReg==0 );
    }
#endif
  }
}

/*
** Delete all the substructure for p, but keep p allocated.  Redefine
** p to be a single SELECT where every column of the result set has a
** value of NULL.
*/
void sqlite3SelectReset(Parse *pParse, Select *p){
4147
4148
4149
4150
4151
4152
4153
4154
4155
4156
4157
4158
4159
4160
4161
      recomputeColumnsUsed(pParent, &pSrc->a[i+iFrom]);
    }
  }

  /* Finially, delete what is left of the subquery and return
  ** success.
  */
  sqlite3SelectDelete(db, pSub1);

#if SELECTTRACE_ENABLED
  if( sqlite3SelectTrace & 0x100 ){
    SELECTTRACE(0x100,pParse,p,("After flattening:\n"));
    sqlite3TreeViewSelect(0, p, 0);
  }
#endif







|







4175
4176
4177
4178
4179
4180
4181
4182
4183
4184
4185
4186
4187
4188
4189
      recomputeColumnsUsed(pParent, &pSrc->a[i+iFrom]);
    }
  }

  /* Finially, delete what is left of the subquery and return
  ** success.
  */
  sqlite3SelectDeferredDelete(pParse, pSub1);

#if SELECTTRACE_ENABLED
  if( sqlite3SelectTrace & 0x100 ){
    SELECTTRACE(0x100,pParse,p,("After flattening:\n"));
    sqlite3TreeViewSelect(0, p, 0);
  }
#endif

Changes to src/sqliteInt.h.

4242
4243
4244
4245
4246
4247
4248

4249
4250
4251
4252
4253
4254
4255
void sqlite3CreateIndex(Parse*,Token*,Token*,SrcList*,ExprList*,int,Token*,
                          Expr*, int, int, u8);
void sqlite3DropIndex(Parse*, SrcList*, int);
int sqlite3Select(Parse*, Select*, SelectDest*);
Select *sqlite3SelectNew(Parse*,ExprList*,SrcList*,Expr*,ExprList*,
                         Expr*,ExprList*,u32,Expr*);
void sqlite3SelectDelete(sqlite3*, Select*);

void sqlite3SelectReset(Parse*, Select*);
Table *sqlite3SrcListLookup(Parse*, SrcList*);
int sqlite3IsReadOnly(Parse*, Table*, int);
void sqlite3OpenTable(Parse*, int iCur, int iDb, Table*, int);
#if defined(SQLITE_ENABLE_UPDATE_DELETE_LIMIT) && !defined(SQLITE_OMIT_SUBQUERY)
Expr *sqlite3LimitWhere(Parse*,SrcList*,Expr*,ExprList*,Expr*,char*);
#endif







>







4242
4243
4244
4245
4246
4247
4248
4249
4250
4251
4252
4253
4254
4255
4256
void sqlite3CreateIndex(Parse*,Token*,Token*,SrcList*,ExprList*,int,Token*,
                          Expr*, int, int, u8);
void sqlite3DropIndex(Parse*, SrcList*, int);
int sqlite3Select(Parse*, Select*, SelectDest*);
Select *sqlite3SelectNew(Parse*,ExprList*,SrcList*,Expr*,ExprList*,
                         Expr*,ExprList*,u32,Expr*);
void sqlite3SelectDelete(sqlite3*, Select*);
void sqlite3SelectDeferredDelete(Parse*, Select*);
void sqlite3SelectReset(Parse*, Select*);
Table *sqlite3SrcListLookup(Parse*, SrcList*);
int sqlite3IsReadOnly(Parse*, Table*, int);
void sqlite3OpenTable(Parse*, int iCur, int iDb, Table*, int);
#if defined(SQLITE_ENABLE_UPDATE_DELETE_LIMIT) && !defined(SQLITE_OMIT_SUBQUERY)
Expr *sqlite3LimitWhere(Parse*,SrcList*,Expr*,ExprList*,Expr*,char*);
#endif

Changes to test/window1.test.

1832
1833
1834
1835
1836
1837
1838











1839
1840
  FROM t1;
} {{} {} 0}
do_execsql_test 57.2 {
  CREATE TABLE v0 ( v1 INTEGER PRIMARY KEY ) ; 
  INSERT INTO v0 VALUES ( 10 ) ; 
  SELECT DISTINCT v1, lead(v1) OVER() FROM v0 GROUP BY v1 ORDER BY 2;
} {10 {}}












finish_test







>
>
>
>
>
>
>
>
>
>
>


1832
1833
1834
1835
1836
1837
1838
1839
1840
1841
1842
1843
1844
1845
1846
1847
1848
1849
1850
1851
  FROM t1;
} {{} {} 0}
do_execsql_test 57.2 {
  CREATE TABLE v0 ( v1 INTEGER PRIMARY KEY ) ; 
  INSERT INTO v0 VALUES ( 10 ) ; 
  SELECT DISTINCT v1, lead(v1) OVER() FROM v0 GROUP BY v1 ORDER BY 2;
} {10 {}}
do_execsql_test 57.3 {
  DROP TABLE t1;
  CREATE TABLE t1(a);
  INSERT INTO t1(a) VALUES(22);
  CREATE TABLE t3(y);
  INSERT INTO t3(y) VALUES(5),(11),(-9);
  SELECT (
    SELECT max(y) OVER( ORDER BY (SELECT x FROM (SELECT sum(y) AS x FROM t1)))
  )
  FROM t3;
} {5}

finish_test