1
0
mirror of https://github.com/sqlite/sqlite.git synced 2025-07-30 19:03:16 +03:00

Bug fixes in the VIEW implementation. (CVS 396)

FossilOrigin-Name: 668ef6380eba256ef82477b63aef850249a619a0
This commit is contained in:
drh
2002-02-27 01:47:11 +00:00
parent a2ed56016f
commit ff78bd2f07
8 changed files with 222 additions and 28 deletions

View File

@ -25,7 +25,7 @@
** ROLLBACK
** PRAGMA
**
** $Id: build.c,v 1.79 2002/02/23 02:32:10 drh Exp $
** $Id: build.c,v 1.80 2002/02/27 01:47:12 drh Exp $
*/
#include "sqliteInt.h"
#include <ctype.h>
@ -824,6 +824,7 @@ void sqliteCreateView(
pSelTab->nCol = 0;
pSelTab->aCol = 0;
sqliteDeleteTable(0, pSelTab);
sqliteSelectUnbind(pSelect);
sEnd = pParse->sLastToken;
if( sEnd.z[0]!=0 && sEnd.z[0]!=';' ){
sEnd.z += sEnd.n;
@ -1341,22 +1342,15 @@ void sqliteIdListDelete(IdList *pList){
for(i=0; i<pList->nId; i++){
sqliteFree(pList->a[i].zName);
sqliteFree(pList->a[i].zAlias);
/* If the pSelect field is set and is not pointing to the Select
** structure that defines a VIEW, then the Select is for a subquery
** and should be deleted. Do not delete VIEWs, however.
*/
if( pList->a[i].pSelect &&
(pList->a[i].pTab==0 || pList->a[i].pTab->pSelect==0) ){
sqliteSelectDelete(pList->a[i].pSelect);
if( pList->a[i].pTab && pList->a[i].pTab->isTransient ){
sqliteDeleteTable(0, pList->a[i].pTab);
}
sqliteSelectDelete(pList->a[i].pSelect);
}
sqliteFree(pList->a);
sqliteFree(pList);
}
/*
** The COPY command is for compatibility with PostgreSQL and specificially
** for the ability to read the output of pg_dump. The format is as

View File

@ -12,7 +12,7 @@
** This file contains routines used for analyzing expressions and
** for generating VDBE code that evaluates expressions in SQLite.
**
** $Id: expr.c,v 1.45 2002/02/26 23:55:31 drh Exp $
** $Id: expr.c,v 1.46 2002/02/27 01:47:12 drh Exp $
*/
#include "sqliteInt.h"
@ -147,6 +147,91 @@ void sqliteSelectMoveStrings(Select *pSelect, int offset){
sqliteSelectMoveStrings(pSelect->pPrior, offset);
}
/*
** The following group of routines make deep copies of expressions,
** expression lists, ID lists, and select statements. The copies can
** be deleted (by being passed to their respective ...Delete() routines)
** without effecting the originals.
**
** Note, however, that the Expr.token.z and Expr.span.z fields point to
** string space that is allocated separately from the expression tree
** itself. These routines do NOT duplicate that string space.
**
** The expression list and ID list return by sqliteExprListDup() and
** sqliteIdListDup() can not be further expanded by subsequent calls
** to sqliteExprListAppend() or sqliteIdListAppend().
**
** Any tables that the ID list might point to are not duplicated.
*/
Expr *sqliteExprDup(Expr *p){
Expr *pNew;
if( p==0 ) return 0;
pNew = sqliteMalloc( sizeof(*p) );
if( pNew==0 ) return 0;
pNew->op = p->op;
pNew->pLeft = sqliteExprDup(p->pLeft);
pNew->pRight = sqliteExprDup(p->pRight);
pNew->pList = sqliteExprListDup(p->pList);
pNew->token = p->token;
pNew->span = p->span;
pNew->pSelect = sqliteSelectDup(p->pSelect);
return pNew;
}
ExprList *sqliteExprListDup(ExprList *p){
ExprList *pNew;
int i;
if( p==0 ) return 0;
pNew = sqliteMalloc( sizeof(*pNew) );
if( pNew==0 ) return 0;
pNew->nExpr = p->nExpr;
pNew->a = sqliteMalloc( p->nExpr*sizeof(p->a[0]) );
for(i=0; i<p->nExpr; i++){
pNew->a[i].pExpr = sqliteExprDup(p->a[i].pExpr);
pNew->a[i].zName = sqliteStrDup(p->a[i].zName);
pNew->a[i].sortOrder = p->a[i].sortOrder;
pNew->a[i].isAgg = p->a[i].isAgg;
pNew->a[i].done = 0;
}
return pNew;
}
IdList *sqliteIdListDup(IdList *p){
IdList *pNew;
int i;
if( p==0 ) return 0;
pNew = sqliteMalloc( sizeof(*pNew) );
if( pNew==0 ) return 0;
pNew->nId = p->nId;
pNew->a = sqliteMalloc( p->nId*sizeof(p->a[0]) );
for(i=0; i<p->nId; i++){
pNew->a[i].zName = sqliteStrDup(p->a[i].zName);
pNew->a[i].zAlias = sqliteStrDup(p->a[i].zAlias);
pNew->a[i].idx = p->a[i].idx;
pNew->a[i].pTab = 0;
pNew->a[i].pSelect = sqliteSelectDup(p->a[i].pSelect);
}
return pNew;
}
Select *sqliteSelectDup(Select *p){
Select *pNew;
if( p==0 ) return 0;
pNew = sqliteMalloc( sizeof(*p) );
if( pNew==0 ) return 0;
pNew->isDistinct = p->isDistinct;
pNew->pEList = sqliteExprListDup(p->pEList);
pNew->pSrc = sqliteIdListDup(p->pSrc);
pNew->pWhere = sqliteExprDup(p->pWhere);
pNew->pGroupBy = sqliteExprListDup(p->pGroupBy);
pNew->pHaving = sqliteExprDup(p->pHaving);
pNew->pOrderBy = sqliteExprListDup(p->pOrderBy);
pNew->op = p->op;
pNew->pPrior = sqliteSelectDup(p->pPrior);
pNew->nLimit = p->nLimit;
pNew->nOffset = p->nOffset;
pNew->zSelect = 0;
return pNew;
}
/*
** Add a new element to the end of an expression list. If pList is
** initially NULL, then create a new expression list.

View File

@ -12,7 +12,7 @@
** This file contains C code routines that are called by the parser
** to handle SELECT statements in SQLite.
**
** $Id: select.c,v 1.66 2002/02/24 03:25:16 drh Exp $
** $Id: select.c,v 1.67 2002/02/27 01:47:12 drh Exp $
*/
#include "sqliteInt.h"
@ -397,7 +397,7 @@ static int fillInColumnList(Parse *pParse, Select *p){
return 1;
}
if( pTab->pSelect ){
pTabList->a[i].pSelect = pTab->pSelect;
pTabList->a[i].pSelect = sqliteSelectDup(pTab->pSelect);
}
}
}
@ -456,6 +456,36 @@ static int fillInColumnList(Parse *pParse, Select *p){
return 0;
}
/*
** This routine recursively unlinks the Select.pSrc.a[].pTab pointers
** in a select structure. It just sets the pointers to NULL. This
** routine is recursive in the sense that if the Select.pSrc.a[].pSelect
** pointer is not NULL, this routine is called recursively on that pointer.
**
** This routine is called on the Select structure that defines a
** VIEW in order to undo any bindings to tables. This is necessary
** because those tables might be DROPed by a subsequent SQL command.
*/
void sqliteSelectUnbind(Select *p){
int i;
IdList *pSrc = p->pSrc;
Table *pTab;
if( p==0 ) return;
for(i=0; i<pSrc->nId; i++){
if( (pTab = pSrc->a[i].pTab)!=0 ){
if( pTab->isTransient ){
sqliteDeleteTable(0, pTab);
sqliteSelectDelete(pSrc->a[i].pSelect);
pSrc->a[i].pSelect = 0;
}
pSrc->a[i].pTab = 0;
if( pSrc->a[i].pSelect ){
sqliteSelectUnbind(pSrc->a[i].pSelect);
}
}
}
}
/*
** This routine associates entries in an ORDER BY expression list with
** columns in a result. For each ORDER BY expression, the opcode of

View File

@ -11,7 +11,7 @@
*************************************************************************
** Internal interface definitions for SQLite.
**
** @(#) $Id: sqliteInt.h,v 1.93 2002/02/24 03:25:16 drh Exp $
** @(#) $Id: sqliteInt.h,v 1.94 2002/02/27 01:47:12 drh Exp $
*/
#include "sqlite.h"
#include "hash.h"
@ -605,6 +605,7 @@ int sqliteSelect(Parse*, Select*, int, int);
Select *sqliteSelectNew(ExprList*,IdList*,Expr*,ExprList*,Expr*,ExprList*,
int,int,int);
void sqliteSelectDelete(Select*);
void sqliteSelectUnbind(Select*);
Table *sqliteTableNameToTable(Parse*, const char*);
IdList *sqliteTableTokenToIdList(Parse*, Token*);
void sqliteDeleteFrom(Parse*, Token*, Expr*);
@ -646,5 +647,9 @@ void sqliteEndWriteOperation(Parse*);
void sqliteExprMoveStrings(Expr*, int);
void sqliteExprListMoveStrings(ExprList*, int);
void sqliteSelectMoveStrings(Select*, int);
Expr *sqliteExprDup(Expr*);
ExprList *sqliteExprListDup(ExprList*);
IdList *sqliteIdListDup(IdList*);
Select *sqliteSelectDup(Select*);
UserFunc *sqliteFindUserFunction(sqlite*,const char*,int,int,int);
void sqliteRegisterBuildinFunctions(sqlite*);

View File

@ -14,7 +14,7 @@
** This file contains functions for allocating memory, comparing
** strings, and stuff like that.
**
** $Id: util.c,v 1.37 2002/02/14 21:42:51 drh Exp $
** $Id: util.c,v 1.38 2002/02/27 01:47:12 drh Exp $
*/
#include "sqliteInt.h"
#include <stdarg.h>
@ -183,12 +183,16 @@ void sqliteStrRealloc(char **pz){
** Make a copy of a string in memory obtained from sqliteMalloc()
*/
char *sqliteStrDup_(const char *z, char *zFile, int line){
char *zNew = sqliteMalloc_(strlen(z)+1, zFile, line);
char *zNew;
if( z==0 ) return 0;
zNew = sqliteMalloc_(strlen(z)+1, zFile, line);
if( zNew ) strcpy(zNew, z);
return zNew;
}
char *sqliteStrNDup_(const char *z, int n, char *zFile, int line){
char *zNew = sqliteMalloc_(n+1, zFile, line);
char *zNew;
if( z==0 ) return 0;
zNew = sqliteMalloc_(n+1, zFile, line);
if( zNew ){
memcpy(zNew, z, n);
zNew[n] = 0;