Update bundled library to version 2.8.2.

Make OnUpdateInt compatible with ZE2.
Fix the makefile fragment for non-gnu makes
This commit is contained in:
Wez Furlong 2003-06-04 22:40:00 +00:00
parent 82a1818fde
commit 80e7f7001d
42 changed files with 11143 additions and 7558 deletions

View file

@ -120,9 +120,8 @@ int sqliteJoinType(Parse *pParse, Token *pA, Token *pB, Token *pC){
pParse->nErr++;
jointype = JT_INNER;
}else if( jointype & JT_RIGHT ){
sqliteSetString(&pParse->zErrMsg,
"RIGHT and FULL OUTER JOINs are not currently supported", 0);
pParse->nErr++;
sqliteErrorMsg(pParse,
"RIGHT and FULL OUTER JOINs are not currently supported");
jointype = JT_INNER;
}
return jointype;
@ -218,9 +217,8 @@ static int sqliteProcessJoin(Parse *pParse, Select *p){
if( pTerm->jointype & JT_NATURAL ){
Table *pTab;
if( pTerm->pOn || pTerm->pUsing ){
sqliteSetString(&pParse->zErrMsg, "a NATURAL join may not have "
sqliteErrorMsg(pParse, "a NATURAL join may not have "
"an ON or USING clause", 0);
pParse->nErr++;
return 1;
}
pTab = pTerm->pTab;
@ -234,9 +232,8 @@ static int sqliteProcessJoin(Parse *pParse, Select *p){
/* Disallow both ON and USING clauses in the same join
*/
if( pTerm->pOn && pTerm->pUsing ){
sqliteSetString(&pParse->zErrMsg, "cannot have both ON and USING "
"clauses in the same join", 0);
pParse->nErr++;
sqliteErrorMsg(pParse, "cannot have both ON and USING "
"clauses in the same join");
return 1;
}
@ -268,9 +265,8 @@ static int sqliteProcessJoin(Parse *pParse, Select *p){
for(j=0; j<pList->nId; j++){
if( columnIndex(pTerm->pTab, pList->a[j].zName)<0 ||
columnIndex(pOther->pTab, pList->a[j].zName)<0 ){
sqliteSetString(&pParse->zErrMsg, "cannot join using column ",
pList->a[j].zName, " - column not present in both tables", 0);
pParse->nErr++;
sqliteErrorMsg(pParse, "cannot join using column %s - column "
"not present in both tables", pList->a[j].zName);
return 1;
}
addWhereTerm(pList->a[j].zName, pTerm->pTab, pOther->pTab, &p->pWhere);
@ -300,13 +296,15 @@ static int sqliteProcessJoin(Parse *pParse, Select *p){
** will work correctly for both SQLite and Oracle8.
*/
static int sqliteOracle8JoinFixup(
int base, /* VDBE cursor number for first table in pSrc */
SrcList *pSrc, /* List of tables being joined */
Expr *pWhere /* The WHERE clause of the SELECT statement */
){
int rc = 0;
if( ExprHasProperty(pWhere, EP_Oracle8Join) && pWhere->op==TK_COLUMN ){
int idx = pWhere->iTable - base;
int idx;
for(idx=0; idx<pSrc->nSrc; idx++){
if( pSrc->a[idx].iCursor==pWhere->iTable ) break;
}
assert( idx>=0 && idx<pSrc->nSrc );
if( idx>0 ){
pSrc->a[idx-1].jointype &= ~JT_INNER;
@ -315,16 +313,16 @@ static int sqliteOracle8JoinFixup(
}
}
if( pWhere->pRight ){
rc = sqliteOracle8JoinFixup(base, pSrc, pWhere->pRight);
rc = sqliteOracle8JoinFixup(pSrc, pWhere->pRight);
}
if( pWhere->pLeft ){
rc |= sqliteOracle8JoinFixup(base, pSrc, pWhere->pLeft);
rc |= sqliteOracle8JoinFixup(pSrc, pWhere->pLeft);
}
if( pWhere->pList ){
int i;
ExprList *pList = pWhere->pList;
for(i=0; i<pList->nExpr && rc==0; i++){
rc |= sqliteOracle8JoinFixup(base, pSrc, pList->a[i].pExpr);
rc |= sqliteOracle8JoinFixup(pSrc, pList->a[i].pExpr);
}
}
if( rc==1 && (pWhere->op==TK_AND || pWhere->op==TK_EQ) ){
@ -691,12 +689,11 @@ static void generateSortTail(
*/
static void generateColumnTypes(
Parse *pParse, /* Parser context */
int base, /* VDBE cursor corresponding to first entry in pTabList */
SrcList *pTabList, /* List of tables */
ExprList *pEList /* Expressions defining the result set */
){
Vdbe *v = pParse->pVdbe;
int i;
int i, j;
if( pParse->useCallback && (pParse->db->flags & SQLITE_ReportTypes)==0 ){
return;
}
@ -705,8 +702,11 @@ static void generateColumnTypes(
char *zType = 0;
if( p==0 ) continue;
if( p->op==TK_COLUMN && pTabList ){
Table *pTab = pTabList->a[p->iTable - base].pTab;
Table *pTab;
int iCol = p->iColumn;
for(j=0; j<pTabList->nSrc && pTabList->a[j].iCursor!=p->iTable; j++){}
assert( j<pTabList->nSrc );
pTab = pTabList->a[j].pTab;
if( iCol<0 ) iCol = pTab->iPKey;
assert( iCol==-1 || (iCol>=0 && iCol<pTab->nCol) );
if( iCol<0 ){
@ -733,12 +733,11 @@ static void generateColumnTypes(
*/
static void generateColumnNames(
Parse *pParse, /* Parser context */
int base, /* VDBE cursor corresponding to first entry in pTabList */
SrcList *pTabList, /* List of tables */
ExprList *pEList /* Expressions defining the result set */
){
Vdbe *v = pParse->pVdbe;
int i;
int i, j;
if( pParse->colNamesSet || v==0 || sqlite_malloc_failed ) return;
pParse->colNamesSet = 1;
for(i=0; i<pEList->nExpr; i++){
@ -755,9 +754,12 @@ static void generateColumnNames(
}
showFullNames = (pParse->db->flags & SQLITE_FullColNames)!=0;
if( p->op==TK_COLUMN && pTabList ){
Table *pTab = pTabList->a[p->iTable - base].pTab;
Table *pTab;
char *zCol;
int iCol = p->iColumn;
for(j=0; j<pTabList->nSrc && pTabList->a[j].iCursor!=p->iTable; j++){}
assert( j<pTabList->nSrc );
pTab = pTabList->a[j].pTab;
if( iCol<0 ) iCol = pTab->iPKey;
assert( iCol==-1 || (iCol>=0 && iCol<pTab->nCol) );
if( iCol<0 ){
@ -775,7 +777,7 @@ static void generateColumnNames(
char *zName = 0;
char *zTab;
zTab = pTabList->a[p->iTable - base].zAlias;
zTab = pTabList->a[j].zAlias;
if( showFullNames || zTab==0 ) zTab = pTab->zName;
sqliteSetString(&zName, zTab, ".", zCol, 0);
sqliteVdbeAddOp(v, OP_ColumnName, i, 0);
@ -863,7 +865,12 @@ Table *sqliteResultSetOfSelect(Parse *pParse, char *zTabName, Select *pSelect){
** For the given SELECT statement, do three things.
**
** (1) Fill in the pTabList->a[].pTab fields in the SrcList that
** defines the set of tables that should be scanned.
** defines the set of tables that should be scanned. For views,
** fill pTabList->a[].pSelect with a copy of the SELECT statement
** that implements the view. A copy is made of the view's SELECT
** statement so that we can freely modify or delete that statement
** without worrying about messing up the presistent representation
** of the view.
**
** (2) Add terms to the WHERE clause to accomodate the NATURAL keyword
** on joins and the ON and USING clause of joins.
@ -908,23 +915,31 @@ static int fillInColumnList(Parse *pParse, Select *p){
if( pTab==0 ){
return 1;
}
/* The isTransient flag indicates that the Table structure has been
** dynamically allocated and may be freed at any time. In other words,
** pTab is not pointing to a persistent table structure that defines
** part of the schema. */
pTab->isTransient = 1;
}else{
/* An ordinary table or view name in the FROM clause */
pTabList->a[i].pTab = pTab =
sqliteFindTable(pParse->db, pTabList->a[i].zName);
sqliteLocateTable(pParse,pTabList->a[i].zName,pTabList->a[i].zDatabase);
if( pTab==0 ){
sqliteSetString(&pParse->zErrMsg, "no such table: ",
pTabList->a[i].zName, 0);
pParse->nErr++;
return 1;
}
if( pTab->pSelect ){
/* We reach here if the named table is a really a view */
if( sqliteViewGetColumnNames(pParse, pTab) ){
return 1;
}
sqliteSelectDelete(pTabList->a[i].pSelect);
pTabList->a[i].pSelect = sqliteSelectDup(pTab->pSelect);
/* If pTabList->a[i].pSelect!=0 it means we are dealing with a
** view within a view. The SELECT structure has already been
** copied by the outer view so we can skip the copy step here
** in the inner view.
*/
if( pTabList->a[i].pSelect==0 ){
pTabList->a[i].pSelect = sqliteSelectDup(pTab->pSelect);
}
}
}
}
@ -1032,10 +1047,9 @@ static int fillInColumnList(Parse *pParse, Select *p){
}
if( !tableSeen ){
if( pName ){
sqliteSetNString(&pParse->zErrMsg, "no such table: ", -1,
pName->z, pName->n, 0);
sqliteErrorMsg(pParse, "no such table: %T", pName);
}else{
sqliteSetString(&pParse->zErrMsg, "no tables specified", 0);
sqliteErrorMsg(pParse, "no tables specified");
}
rc = 1;
}
@ -1056,6 +1070,9 @@ static int fillInColumnList(Parse *pParse, Select *p){
** 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.
** If the bindings are not removed, then the Select.pSrc->a[].pTab field
** will be left pointing to a deallocated Table structure after the
** DROP and a coredump will occur the next time the VIEW is used.
*/
void sqliteSelectUnbind(Select *p){
int i;
@ -1066,10 +1083,6 @@ void sqliteSelectUnbind(Select *p){
if( (pTab = pSrc->a[i].pTab)!=0 ){
if( pTab->isTransient ){
sqliteDeleteTable(0, pTab);
#if 0
sqliteSelectDelete(pSrc->a[i].pSelect);
pSrc->a[i].pSelect = 0;
#endif
}
pSrc->a[i].pTab = 0;
if( pSrc->a[i].pSelect ){
@ -1129,11 +1142,9 @@ static int matchOrderbyToColumn(
if( pOrderBy->a[i].done ) continue;
if( sqliteExprIsInteger(pE, &iCol) ){
if( iCol<=0 || iCol>pEList->nExpr ){
char zBuf[200];
sprintf(zBuf,"ORDER BY position %d should be between 1 and %d",
iCol, pEList->nExpr);
sqliteSetString(&pParse->zErrMsg, zBuf, 0);
pParse->nErr++;
sqliteErrorMsg(pParse,
"ORDER BY position %d should be between 1 and %d",
iCol, pEList->nExpr);
nErr++;
break;
}
@ -1163,11 +1174,8 @@ static int matchOrderbyToColumn(
pOrderBy->a[i].done = 1;
}
if( iCol<0 && mustComplete ){
char zBuf[30];
sprintf(zBuf,"%d",i+1);
sqliteSetString(&pParse->zErrMsg, "ORDER BY term number ", zBuf,
" does not match any result column", 0);
pParse->nErr++;
sqliteErrorMsg(pParse,
"ORDER BY term number %d does not match any result column", i+1);
nErr++;
break;
}
@ -1277,9 +1285,8 @@ static int multiSelect(Parse *pParse, Select *p, int eDest, int iParm){
if( p==0 || p->pPrior==0 ) return 1;
pPrior = p->pPrior;
if( pPrior->pOrderBy ){
sqliteSetString(&pParse->zErrMsg,"ORDER BY clause should come after ",
selectOpName(p->op), " not before", 0);
pParse->nErr++;
sqliteErrorMsg(pParse,"ORDER BY clause should come after %s not before",
selectOpName(p->op));
return 1;
}
@ -1367,8 +1374,8 @@ static int multiSelect(Parse *pParse, Select *p, int eDest, int iParm){
int iCont, iBreak, iStart;
assert( p->pEList );
if( eDest==SRT_Callback ){
generateColumnNames(pParse, p->base, 0, p->pEList);
generateColumnTypes(pParse, p->base, p->pSrc, p->pEList);
generateColumnNames(pParse, 0, p->pEList);
generateColumnTypes(pParse, p->pSrc, p->pEList);
}
iBreak = sqliteVdbeMakeLabel(v);
iCont = sqliteVdbeMakeLabel(v);
@ -1424,8 +1431,8 @@ static int multiSelect(Parse *pParse, Select *p, int eDest, int iParm){
*/
assert( p->pEList );
if( eDest==SRT_Callback ){
generateColumnNames(pParse, p->base, 0, p->pEList);
generateColumnTypes(pParse, p->base, p->pSrc, p->pEList);
generateColumnNames(pParse, 0, p->pEList);
generateColumnTypes(pParse, p->pSrc, p->pEList);
}
iBreak = sqliteVdbeMakeLabel(v);
iCont = sqliteVdbeMakeLabel(v);
@ -1450,9 +1457,8 @@ static int multiSelect(Parse *pParse, Select *p, int eDest, int iParm){
}
assert( p->pEList && pPrior->pEList );
if( p->pEList->nExpr!=pPrior->pEList->nExpr ){
sqliteSetString(&pParse->zErrMsg, "SELECTs to the left and right of ",
selectOpName(p->op), " do not have the same number of result columns", 0);
pParse->nErr++;
sqliteErrorMsg(pParse, "SELECTs to the left and right of %s"
" do not have the same number of result columns", selectOpName(p->op));
return 1;
}
@ -1466,37 +1472,11 @@ static int multiSelect(Parse *pParse, Select *p, int eDest, int iParm){
return 0;
}
/*
** Recursively scan through an expression tree. For every reference
** to a column in table number iFrom, change that reference to the
** same column in table number iTo.
*/
static void changeTablesInList(ExprList*, int, int); /* Forward Declaration */
static void changeTables(Expr *pExpr, int iFrom, int iTo){
if( pExpr==0 ) return;
if( pExpr->op==TK_COLUMN && pExpr->iTable==iFrom ){
pExpr->iTable = iTo;
}else{
changeTables(pExpr->pLeft, iFrom, iTo);
changeTables(pExpr->pRight, iFrom, iTo);
changeTablesInList(pExpr->pList, iFrom, iTo);
}
}
static void changeTablesInList(ExprList *pList, int iFrom, int iTo){
if( pList ){
int i;
for(i=0; i<pList->nExpr; i++){
changeTables(pList->a[i].pExpr, iFrom, iTo);
}
}
}
/*
** Scan through the expression pExpr. Replace every reference to
** a column in table number iTable with a copy of the corresponding
** a column in table number iTable with a copy of the iColumn-th
** entry in pEList. (But leave references to the ROWID column
** unchanged.) When making a copy of an expression in pEList, change
** references to columns in table iSub into references to table iTable.
** unchanged.)
**
** This routine is part of the flattening procedure. A subquery
** whose result set is defined by pEList appears as entry in the
@ -1505,8 +1485,8 @@ static void changeTablesInList(ExprList *pList, int iFrom, int iTo){
** changes to pExpr so that it refers directly to the source table
** of the subquery rather the result set of the subquery.
*/
static void substExprList(ExprList*,int,ExprList*,int); /* Forward Decl */
static void substExpr(Expr *pExpr, int iTable, ExprList *pEList, int iSub){
static void substExprList(ExprList*,int,ExprList*); /* Forward Decl */
static void substExpr(Expr *pExpr, int iTable, ExprList *pEList){
if( pExpr==0 ) return;
if( pExpr->op==TK_COLUMN && pExpr->iTable==iTable && pExpr->iColumn>=0 ){
Expr *pNew;
@ -1527,21 +1507,18 @@ static void substExpr(Expr *pExpr, int iTable, ExprList *pEList, int iSub){
pExpr->iAgg = pNew->iAgg;
sqliteTokenCopy(&pExpr->token, &pNew->token);
sqliteTokenCopy(&pExpr->span, &pNew->span);
if( iSub!=iTable ){
changeTables(pExpr, iSub, iTable);
}
}else{
substExpr(pExpr->pLeft, iTable, pEList, iSub);
substExpr(pExpr->pRight, iTable, pEList, iSub);
substExprList(pExpr->pList, iTable, pEList, iSub);
substExpr(pExpr->pLeft, iTable, pEList);
substExpr(pExpr->pRight, iTable, pEList);
substExprList(pExpr->pList, iTable, pEList);
}
}
static void
substExprList(ExprList *pList, int iTable, ExprList *pEList, int iSub){
substExprList(ExprList *pList, int iTable, ExprList *pEList){
int i;
if( pList==0 ) return;
for(i=0; i<pList->nExpr; i++){
substExpr(pList->a[i].pExpr, iTable, pEList, iSub);
substExpr(pList->a[i].pExpr, iTable, pEList);
}
}
@ -1578,7 +1555,8 @@ substExprList(ExprList *pList, int iTable, ExprList *pEList, int iSub){
**
** (2) The subquery is not an aggregate or the outer query is not a join.
**
** (3) The subquery is not a join.
** (3) The subquery is not the right operand of a left outer join, or
** the subquery is not itself a join. (Ticket #306)
**
** (4) The subquery is not DISTINCT or the outer query is not a join.
**
@ -1604,7 +1582,7 @@ substExprList(ExprList *pList, int iTable, ExprList *pEList, int iSub){
** The subquery is p->pSrc->a[iFrom]. isAgg is true if the outer query
** uses aggregates and subqueryIsAgg is true if the subquery uses aggregates.
**
** If flattening is not attempted, this routine is a no-op and return 0.
** If flattening is not attempted, this routine is a no-op and returns 0.
** If flattening is attempted this routine returns 1.
**
** All of the expression analysis must occur on both the outer query and
@ -1621,8 +1599,8 @@ static int flattenSubquery(
SrcList *pSrc; /* The FROM clause of the outer query */
SrcList *pSubSrc; /* The FROM clause of the subquery */
ExprList *pList; /* The result set of the outer query */
int iParent; /* VDBE cursor number of the pSub result set temp table */
int i;
int iParent, iSub;
Expr *pWhere;
/* Check to see if flattening is permitted. Return 0 if not.
@ -1636,19 +1614,81 @@ static int flattenSubquery(
if( subqueryIsAgg && pSrc->nSrc>1 ) return 0;
pSubSrc = pSub->pSrc;
assert( pSubSrc );
if( pSubSrc->nSrc!=1 ) return 0;
if( pSubSrc->nSrc==0 ) return 0;
if( (pSub->isDistinct || pSub->nLimit>=0) && (pSrc->nSrc>1 || isAgg) ){
return 0;
}
if( (p->isDistinct || p->nLimit>=0) && subqueryIsAgg ) return 0;
if( p->pOrderBy && pSub->pOrderBy ) return 0;
/* If we reach this point, it means flattening is permitted for the
** i-th entry of the FROM clause in the outer query.
/* Restriction 3: If the subquery is a join, make sure the subquery is
** not used as the right operand of an outer join. Examples of why this
** is not allowed:
**
** t1 LEFT OUTER JOIN (t2 JOIN t3)
**
** If we flatten the above, we would get
**
** (t1 LEFT OUTER JOIN t2) JOIN t3
**
** which is not at all the same thing.
*/
iParent = p->base + iFrom;
iSub = pSub->base;
substExprList(p->pEList, iParent, pSub->pEList, iSub);
if( pSubSrc->nSrc>1 && iFrom>0 && (pSrc->a[iFrom-1].jointype & JT_OUTER)!=0 ){
return 0;
}
/* If we reach this point, it means flattening is permitted for the
** iFrom-th entry of the FROM clause in the outer query.
*/
/* Move all of the FROM elements of the subquery into the
** the FROM clause of the outer query. Before doing this, remember
** the cursor number for the original outer query FROM element in
** iParent. The iParent cursor will never be used. Subsequent code
** will scan expressions looking for iParent references and replace
** those references with expressions that resolve to the subquery FROM
** elements we are now copying in.
*/
iParent = pSrc->a[iFrom].iCursor;
{
int nSubSrc = pSubSrc->nSrc;
int jointype = pSrc->a[iFrom].jointype;
if( pSrc->a[iFrom].pTab && pSrc->a[iFrom].pTab->isTransient ){
sqliteDeleteTable(0, pSrc->a[iFrom].pTab);
}
sqliteFree(pSrc->a[iFrom].zName);
sqliteFree(pSrc->a[iFrom].zAlias);
if( nSubSrc>1 ){
int extra = nSubSrc - 1;
for(i=1; i<nSubSrc; i++){
pSrc = sqliteSrcListAppend(pSrc, 0, 0);
}
p->pSrc = pSrc;
for(i=pSrc->nSrc-1; i-extra>=iFrom; i--){
pSrc->a[i] = pSrc->a[i-extra];
}
}
for(i=0; i<nSubSrc; i++){
pSrc->a[i+iFrom] = pSubSrc->a[i];
memset(&pSubSrc->a[i], 0, sizeof(pSubSrc->a[i]));
}
pSrc->a[iFrom+nSubSrc-1].jointype = jointype;
}
/* Now begin substituting subquery result set expressions for
** references to the iParent in the outer query.
**
** Example:
**
** SELECT a+5, b*10 FROM (SELECT x*3 AS a, y+10 AS b FROM t1) WHERE a>b;
** \ \_____________ subquery __________/ /
** \_____________________ outer query ______________________________/
**
** We look at every expression in the outer query and every place we see
** "a" we substitute "x*3" and every place we see "b" we substitute "y+10".
*/
substExprList(p->pEList, iParent, pSub->pEList);
pList = p->pEList;
for(i=0; i<pList->nExpr; i++){
Expr *pExpr;
@ -1657,22 +1697,18 @@ static int flattenSubquery(
}
}
if( isAgg ){
substExprList(p->pGroupBy, iParent, pSub->pEList, iSub);
substExpr(p->pHaving, iParent, pSub->pEList, iSub);
substExprList(p->pGroupBy, iParent, pSub->pEList);
substExpr(p->pHaving, iParent, pSub->pEList);
}
if( pSub->pOrderBy ){
assert( p->pOrderBy==0 );
p->pOrderBy = pSub->pOrderBy;
pSub->pOrderBy = 0;
changeTablesInList(p->pOrderBy, iSub, iParent);
}else if( p->pOrderBy ){
substExprList(p->pOrderBy, iParent, pSub->pEList, iSub);
substExprList(p->pOrderBy, iParent, pSub->pEList);
}
if( pSub->pWhere ){
pWhere = sqliteExprDup(pSub->pWhere);
if( iParent!=iSub ){
changeTables(pWhere, iSub, iParent);
}
}else{
pWhere = 0;
}
@ -1680,12 +1716,9 @@ static int flattenSubquery(
assert( p->pHaving==0 );
p->pHaving = p->pWhere;
p->pWhere = pWhere;
substExpr(p->pHaving, iParent, pSub->pEList, iSub);
substExpr(p->pHaving, iParent, pSub->pEList);
if( pSub->pHaving ){
Expr *pHaving = sqliteExprDup(pSub->pHaving);
if( iParent!=iSub ){
changeTables(pHaving, iSub, iParent);
}
if( p->pHaving ){
p->pHaving = sqliteExpr(TK_AND, p->pHaving, pHaving, 0);
}else{
@ -1694,19 +1727,23 @@ static int flattenSubquery(
}
assert( p->pGroupBy==0 );
p->pGroupBy = sqliteExprListDup(pSub->pGroupBy);
if( iParent!=iSub ){
changeTablesInList(p->pGroupBy, iSub, iParent);
}
}else if( p->pWhere==0 ){
p->pWhere = pWhere;
}else{
substExpr(p->pWhere, iParent, pSub->pEList, iSub);
substExpr(p->pWhere, iParent, pSub->pEList);
if( pWhere ){
p->pWhere = sqliteExpr(TK_AND, p->pWhere, pWhere, 0);
}
}
/* The flattened query is distinct if either the inner or the
** outer query is distinct.
*/
p->isDistinct = p->isDistinct || pSub->isDistinct;
/* Transfer the limit expression from the subquery to the outer
** query.
*/
if( pSub->nLimit>=0 ){
if( p->nLimit<0 ){
p->nLimit = pSub->nLimit;
@ -1716,27 +1753,9 @@ static int flattenSubquery(
}
p->nOffset += pSub->nOffset;
/* If the subquery contains subqueries of its own, that were not
** flattened, then code will have already been generated to put
** the results of those sub-subqueries into VDBE cursors relative
** to the subquery. We must translate the cursor number into values
** suitable for use by the outer query.
/* Finially, delete what is left of the subquery and return
** success.
*/
for(i=0; i<pSubSrc->nSrc; i++){
Vdbe *v;
if( pSubSrc->a[i].pSelect==0 ) continue;
v = sqliteGetVdbe(pParse);
sqliteVdbeAddOp(v, OP_RenameCursor, pSub->base+i, p->base+i);
}
if( pSrc->a[iFrom].pTab && pSrc->a[iFrom].pTab->isTransient ){
sqliteDeleteTable(0, pSrc->a[iFrom].pTab);
}
pSrc->a[iFrom].pTab = pSubSrc->a[0].pTab;
pSubSrc->a[0].pTab = 0;
assert( pSrc->a[iFrom].pSelect==pSub );
pSrc->a[iFrom].pSelect = pSubSrc->a[0].pSelect;
pSubSrc->a[0].pSelect = 0;
sqliteSelectDelete(pSub);
return 1;
}
@ -1768,7 +1787,6 @@ static int simpleMinMaxQuery(Parse *pParse, Select *p, int eDest, int iParm){
Index *pIdx;
int base;
Vdbe *v;
int openOp;
int seekOp;
int cont;
ExprList eList;
@ -1818,8 +1836,8 @@ static int simpleMinMaxQuery(Parse *pParse, Select *p, int eDest, int iParm){
v = sqliteGetVdbe(pParse);
if( v==0 ) return 0;
if( eDest==SRT_Callback ){
generateColumnNames(pParse, p->base, p->pSrc, p->pEList);
generateColumnTypes(pParse, p->base, p->pSrc, p->pEList);
generateColumnNames(pParse, p->pSrc, p->pEList);
generateColumnTypes(pParse, p->pSrc, p->pEList);
}
/* Generating code to find the min or the max. Basically all we have
@ -1827,18 +1845,17 @@ static int simpleMinMaxQuery(Parse *pParse, Select *p, int eDest, int iParm){
** the min() or max() is on the INTEGER PRIMARY KEY, then find the first
** or last entry in the main table.
*/
if( !pParse->schemaVerified && (pParse->db->flags & SQLITE_InTrans)==0 ){
sqliteVdbeAddOp(v, OP_VerifyCookie, pParse->db->schema_cookie, 0);
pParse->schemaVerified = 1;
}
openOp = pTab->isTemp ? OP_OpenAux : OP_Open;
base = p->base;
sqliteVdbeAddOp(v, openOp, base, pTab->tnum);
sqliteCodeVerifySchema(pParse, pTab->iDb);
base = p->pSrc->a[0].iCursor;
sqliteVdbeAddOp(v, OP_Integer, pTab->iDb, 0);
sqliteVdbeAddOp(v, OP_OpenRead, base, pTab->tnum);
sqliteVdbeChangeP3(v, -1, pTab->zName, P3_STATIC);
cont = sqliteVdbeMakeLabel(v);
if( pIdx==0 ){
sqliteVdbeAddOp(v, seekOp, base, 0);
}else{
sqliteVdbeAddOp(v, openOp, base+1, pIdx->tnum);
sqliteVdbeAddOp(v, OP_Integer, pIdx->iDb, 0);
sqliteVdbeAddOp(v, OP_OpenRead, base+1, pIdx->tnum);
sqliteVdbeChangeP3(v, -1, pIdx->zName, P3_STATIC);
sqliteVdbeAddOp(v, seekOp, base+1, 0);
sqliteVdbeAddOp(v, OP_IdxRecno, base+1, 0);
@ -1849,7 +1866,6 @@ static int simpleMinMaxQuery(Parse *pParse, Select *p, int eDest, int iParm){
memset(&eListItem, 0, sizeof(eListItem));
eList.a = &eListItem;
eList.a[0].pExpr = pExpr;
cont = sqliteVdbeMakeLabel(v);
selectInnerLoop(pParse, p, &eList, 0, 0, 0, -1, eDest, iParm, cont, cont);
sqliteVdbeResolveLabel(v, cont);
sqliteVdbeAddOp(v, OP_Close, base, 0);
@ -1929,11 +1945,10 @@ int sqliteSelect(
Expr *pHaving; /* The HAVING clause. May be NULL */
int isDistinct; /* True if the DISTINCT keyword is present */
int distinct; /* Table to use for the distinct set */
int base; /* First cursor available for use */
int rc = 1; /* Value to return from this function */
if( sqlite_malloc_failed || pParse->nErr || p==0 ) return 1;
if( sqliteAuthCheck(pParse, SQLITE_SELECT, 0, 0) ) return 1;
if( sqliteAuthCheck(pParse, SQLITE_SELECT, 0, 0, 0) ) return 1;
/* If there is are a sequence of queries, do the earlier ones first.
*/
@ -1950,12 +1965,9 @@ int sqliteSelect(
pHaving = p->pHaving;
isDistinct = p->isDistinct;
/* Allocate a block of VDBE cursors, one for each table in the FROM clause.
** The WHERE processing requires that the cursors for the tables in the
** FROM clause be consecutive.
/* Allocate VDBE cursors for each table in the FROM clause
*/
base = p->base = pParse->nTab;
pParse->nTab += pTabList->nSrc;
sqliteSrcListAssignCursors(pParse, pTabList);
/*
** Do not even attempt to generate any code if we have already seen
@ -1978,9 +1990,8 @@ int sqliteSelect(
** only a single column may be output.
*/
if( (eDest==SRT_Mem || eDest==SRT_Set) && pEList->nExpr>1 ){
sqliteSetString(&pParse->zErrMsg, "only a single result allowed for "
"a SELECT that is part of an expression", 0);
pParse->nErr++;
sqliteErrorMsg(pParse, "only a single result allowed for "
"a SELECT that is part of an expression");
goto select_end;
}
@ -2002,7 +2013,7 @@ int sqliteSelect(
** Resolve the column names and do a semantics check on all the expressions.
*/
for(i=0; i<pEList->nExpr; i++){
if( sqliteExprResolveIds(pParse, base, pTabList, 0, pEList->a[i].pExpr) ){
if( sqliteExprResolveIds(pParse, pTabList, 0, pEList->a[i].pExpr) ){
goto select_end;
}
if( sqliteExprCheck(pParse, pEList->a[i].pExpr, 1, &isAgg) ){
@ -2010,22 +2021,20 @@ int sqliteSelect(
}
}
if( pWhere ){
if( sqliteExprResolveIds(pParse, base, pTabList, pEList, pWhere) ){
if( sqliteExprResolveIds(pParse, pTabList, pEList, pWhere) ){
goto select_end;
}
if( sqliteExprCheck(pParse, pWhere, 0, 0) ){
goto select_end;
}
sqliteOracle8JoinFixup(base, pTabList, pWhere);
sqliteOracle8JoinFixup(pTabList, pWhere);
}
if( pHaving ){
if( pGroupBy==0 ){
sqliteSetString(&pParse->zErrMsg, "a GROUP BY clause is required "
"before HAVING", 0);
pParse->nErr++;
sqliteErrorMsg(pParse, "a GROUP BY clause is required before HAVING");
goto select_end;
}
if( sqliteExprResolveIds(pParse, base, pTabList, pEList, pHaving) ){
if( sqliteExprResolveIds(pParse, pTabList, pEList, pHaving) ){
goto select_end;
}
if( sqliteExprCheck(pParse, pHaving, 1, &isAgg) ){
@ -2040,7 +2049,7 @@ int sqliteSelect(
sqliteExprDelete(pE);
pE = pOrderBy->a[i].pExpr = sqliteExprDup(pEList->a[iCol-1].pExpr);
}
if( sqliteExprResolveIds(pParse, base, pTabList, pEList, pE) ){
if( sqliteExprResolveIds(pParse, pTabList, pEList, pE) ){
goto select_end;
}
if( sqliteExprCheck(pParse, pE, isAgg, 0) ){
@ -2048,16 +2057,13 @@ int sqliteSelect(
}
if( sqliteExprIsConstant(pE) ){
if( sqliteExprIsInteger(pE, &iCol)==0 ){
sqliteSetString(&pParse->zErrMsg,
"ORDER BY terms must not be non-integer constants", 0);
pParse->nErr++;
sqliteErrorMsg(pParse,
"ORDER BY terms must not be non-integer constants");
goto select_end;
}else if( iCol<=0 || iCol>pEList->nExpr ){
char zBuf[2000];
sprintf(zBuf,"ORDER BY column number %d out of range - should be "
sqliteErrorMsg(pParse,
"ORDER BY column number %d out of range - should be "
"between 1 and %d", iCol, pEList->nExpr);
sqliteSetString(&pParse->zErrMsg, zBuf, 0);
pParse->nErr++;
goto select_end;
}
}
@ -2071,7 +2077,7 @@ int sqliteSelect(
sqliteExprDelete(pE);
pE = pGroupBy->a[i].pExpr = sqliteExprDup(pEList->a[iCol-1].pExpr);
}
if( sqliteExprResolveIds(pParse, base, pTabList, pEList, pE) ){
if( sqliteExprResolveIds(pParse, pTabList, pEList, pE) ){
goto select_end;
}
if( sqliteExprCheck(pParse, pE, isAgg, 0) ){
@ -2079,16 +2085,13 @@ int sqliteSelect(
}
if( sqliteExprIsConstant(pE) ){
if( sqliteExprIsInteger(pE, &iCol)==0 ){
sqliteSetString(&pParse->zErrMsg,
"GROUP BY terms must not be non-integer constants", 0);
pParse->nErr++;
sqliteErrorMsg(pParse,
"GROUP BY terms must not be non-integer constants");
goto select_end;
}else if( iCol<=0 || iCol>pEList->nExpr ){
char zBuf[2000];
sprintf(zBuf,"GROUP BY column number %d out of range - should be "
sqliteErrorMsg(pParse,
"GROUP BY column number %d out of range - should be "
"between 1 and %d", iCol, pEList->nExpr);
sqliteSetString(&pParse->zErrMsg, zBuf, 0);
pParse->nErr++;
goto select_end;
}
}
@ -2112,7 +2115,7 @@ int sqliteSelect(
** step is skipped if the output is going to some other destination.
*/
if( eDest==SRT_Callback ){
generateColumnNames(pParse, p->base, pTabList, pEList);
generateColumnNames(pParse, pTabList, pEList);
}
/* Set the limiter
@ -2138,12 +2141,25 @@ int sqliteSelect(
/* Generate code for all sub-queries in the FROM clause
*/
for(i=0; i<pTabList->nSrc; i++){
const char *zSavedAuthContext;
int needRestoreContext;
if( pTabList->a[i].pSelect==0 ) continue;
sqliteSelect(pParse, pTabList->a[i].pSelect, SRT_TempTable, base+i,
p, i, &isAgg);
if( pTabList->a[i].zName!=0 ){
zSavedAuthContext = pParse->zAuthContext;
pParse->zAuthContext = pTabList->a[i].zName;
needRestoreContext = 1;
}else{
needRestoreContext = 0;
}
sqliteSelect(pParse, pTabList->a[i].pSelect, SRT_TempTable,
pTabList->a[i].iCursor, p, i, &isAgg);
if( needRestoreContext ){
pParse->zAuthContext = zSavedAuthContext;
}
pTabList = p->pSrc;
pWhere = p->pWhere;
if( eDest==SRT_Callback ){
if( eDest!=SRT_Union && eDest!=SRT_Except && eDest!=SRT_Discard ){
pOrderBy = p->pOrderBy;
}
pGroupBy = p->pGroupBy;
@ -2165,7 +2181,7 @@ int sqliteSelect(
** than a callback.
*/
if( eDest==SRT_Callback ){
generateColumnTypes(pParse, p->base, pTabList, pEList);
generateColumnTypes(pParse, pTabList, pEList);
}
/* If the output is destined for a temporary table, open that table.
@ -2239,7 +2255,7 @@ int sqliteSelect(
/* Begin the database scan
*/
pWInfo = sqliteWhereBegin(pParse, p->base, pTabList, pWhere, 0,
pWInfo = sqliteWhereBegin(pParse, pTabList, pWhere, 0,
pGroupBy ? 0 : &pOrderBy);
if( pWInfo==0 ) goto select_end;