Many hyperlinks are disabled.
Use anonymous login
to enable hyperlinks.
Overview
Comment: | Modify sub-query handling. Tickets #1083 and #1084. (CVS 2286) |
---|---|
Downloads: | Tarball | ZIP archive |
Timelines: | family | ancestors | descendants | both | trunk |
Files: | files | file ages | folders |
SHA1: |
b1b50f315873a8614920d1e3af4a07fb |
User & Date: | danielk1977 2005-01-29 08:32:44.000 |
Context
2005-01-29
| ||
08:36 | Update ioerr.test to be more deterministic. (CVS 2287) (check-in: d0b16bae65 user: danielk1977 tags: trunk) | |
08:32 | Modify sub-query handling. Tickets #1083 and #1084. (CVS 2286) (check-in: b1b50f3158 user: danielk1977 tags: trunk) | |
01:54 | Modification to schema.test so that it works with SQLITE_OMIT_TRIGGER and SQLITE_OMIT_UTF16 defined. (CVS 2285) (check-in: 95ecb2745f user: danielk1977 tags: trunk) | |
Changes
Changes to src/auth.c.
︙ | ︙ | |||
10 11 12 13 14 15 16 | ** ************************************************************************* ** This file contains code used to implement the sqlite3_set_authorizer() ** API. This facility is an optional feature of the library. Embedded ** systems that do not need this facility may omit it by recompiling ** the library with -DSQLITE_OMIT_AUTHORIZATION=1 ** | | | 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 | ** ************************************************************************* ** This file contains code used to implement the sqlite3_set_authorizer() ** API. This facility is an optional feature of the library. Embedded ** systems that do not need this facility may omit it by recompiling ** the library with -DSQLITE_OMIT_AUTHORIZATION=1 ** ** $Id: auth.c,v 1.21 2005/01/29 08:32:44 danielk1977 Exp $ */ #include "sqliteInt.h" /* ** All of the code in this file may be omitted by defining a single ** macro. */ |
︙ | ︙ | |||
111 112 113 114 115 116 117 | const char *zCol; /* Name of the column of the table */ int iSrc; /* Index in pTabList->a[] of table being read */ const char *zDBase; /* Name of database being accessed */ TriggerStack *pStack; /* The stack of current triggers */ if( db->xAuth==0 ) return; assert( pExpr->op==TK_COLUMN ); | | | | 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 | const char *zCol; /* Name of the column of the table */ int iSrc; /* Index in pTabList->a[] of table being read */ const char *zDBase; /* Name of database being accessed */ TriggerStack *pStack; /* The stack of current triggers */ if( db->xAuth==0 ) return; assert( pExpr->op==TK_COLUMN ); for(iSrc=0; pTabList && iSrc<pTabList->nSrc; iSrc++){ if( pExpr->iTable==pTabList->a[iSrc].iCursor ) break; } if( iSrc>=0 && pTabList && iSrc<pTabList->nSrc ){ pTab = pTabList->a[iSrc].pTab; }else if( (pStack = pParse->trigStack)!=0 ){ /* This must be an attempt to read the NEW or OLD pseudo-tables ** of a trigger. */ assert( pExpr->iTable==pStack->newIdx || pExpr->iTable==pStack->oldIdx ); pTab = pStack->pTab; |
︙ | ︙ |
Changes to src/build.c.
︙ | ︙ | |||
18 19 20 21 22 23 24 | ** CREATE INDEX ** DROP INDEX ** creating ID lists ** BEGIN TRANSACTION ** COMMIT ** ROLLBACK ** | | | 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 | ** CREATE INDEX ** DROP INDEX ** creating ID lists ** BEGIN TRANSACTION ** COMMIT ** ROLLBACK ** ** $Id: build.c,v 1.301 2005/01/29 08:32:45 danielk1977 Exp $ */ #include "sqliteInt.h" #include <ctype.h> /* ** This routine is called when a new SQL statement is beginning to ** be parsed. Initialize the pParse structure as needed. |
︙ | ︙ | |||
91 92 93 94 95 96 97 | /* Get the VDBE program ready for execution */ if( v && pParse->nErr==0 ){ FILE *trace = (db->flags & SQLITE_VdbeTrace)!=0 ? stdout : 0; sqlite3VdbeTrace(v, trace); sqlite3VdbeMakeReady(v, pParse->nVar, pParse->nMem+3, | | < | 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 | /* Get the VDBE program ready for execution */ if( v && pParse->nErr==0 ){ FILE *trace = (db->flags & SQLITE_VdbeTrace)!=0 ? stdout : 0; sqlite3VdbeTrace(v, trace); sqlite3VdbeMakeReady(v, pParse->nVar, pParse->nMem+3, pParse->nTab+3, pParse->nMaxDepth+1, pParse->explain); pParse->rc = pParse->nErr ? SQLITE_ERROR : SQLITE_DONE; pParse->colNamesSet = 0; }else if( pParse->rc==SQLITE_OK ){ pParse->rc = SQLITE_ERROR; } pParse->nTab = 0; pParse->nMem = 0; pParse->nSet = 0; pParse->nVar = 0; pParse->cookieMask = 0; pParse->cookieGoto = 0; } /* ** Run the parser and code generator recursively in order to generate |
︙ | ︙ | |||
892 893 894 895 896 897 898 | pCol = &(p->aCol[p->nCol-1]); if( !sqlite3ExprIsConstant(pExpr) ){ sqlite3ErrorMsg(pParse, "default value of column [%s] is not constant", pCol->zName); }else{ sqlite3ExprDelete(pCol->pDflt); pCol->pDflt = sqlite3ExprDup(pExpr); | < | 891 892 893 894 895 896 897 898 899 900 901 902 903 904 | pCol = &(p->aCol[p->nCol-1]); if( !sqlite3ExprIsConstant(pExpr) ){ sqlite3ErrorMsg(pParse, "default value of column [%s] is not constant", pCol->zName); }else{ sqlite3ExprDelete(pCol->pDflt); pCol->pDflt = sqlite3ExprDup(pExpr); } sqlite3ExprDelete(pExpr); } /* ** Designate the PRIMARY KEY for the table. pList is a list of names ** of columns that form the primary key. If pList is NULL, then the |
︙ | ︙ | |||
1435 1436 1437 1438 1439 1440 1441 | */ if( pSelect ){ Table *pSelTab; sqlite3VdbeAddOp(v, OP_Dup, 0, 0); sqlite3VdbeAddOp(v, OP_Integer, p->iDb, 0); sqlite3VdbeAddOp(v, OP_OpenWrite, 1, 0); pParse->nTab = 2; | | | 1433 1434 1435 1436 1437 1438 1439 1440 1441 1442 1443 1444 1445 1446 1447 | */ if( pSelect ){ Table *pSelTab; sqlite3VdbeAddOp(v, OP_Dup, 0, 0); sqlite3VdbeAddOp(v, OP_Integer, p->iDb, 0); sqlite3VdbeAddOp(v, OP_OpenWrite, 1, 0); pParse->nTab = 2; sqlite3Select(pParse, pSelect, SRT_Table, 1, 0, 0, 0, 0); sqlite3VdbeAddOp(v, OP_Close, 1, 0); if( pParse->nErr==0 ){ pSelTab = sqlite3ResultSetOfSelect(pParse, 0, pSelect); if( pSelTab==0 ) return; assert( p->aCol==0 ); p->nCol = pSelTab->nCol; p->aCol = pSelTab->aCol; |
︙ | ︙ |
Changes to src/delete.c.
︙ | ︙ | |||
8 9 10 11 12 13 14 | ** May you find forgiveness for yourself and forgive others. ** May you share freely, never taking more than you give. ** ************************************************************************* ** This file contains C code routines that are called by the parser ** in order to generate code for DELETE FROM statements. ** | | | 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 | ** May you find forgiveness for yourself and forgive others. ** May you share freely, never taking more than you give. ** ************************************************************************* ** This file contains C code routines that are called by the parser ** in order to generate code for DELETE FROM statements. ** ** $Id: delete.c,v 1.100 2005/01/29 08:32:45 danielk1977 Exp $ */ #include "sqliteInt.h" /* ** Look up every table that is named in pSrc. If any table is not found, ** add an error message to pParse->zErrMsg and return NULL. If all tables ** are found, return a pointer to the last table. |
︙ | ︙ | |||
86 87 88 89 90 91 92 93 94 95 96 97 98 99 | int i; /* Loop counter */ WhereInfo *pWInfo; /* Information about the WHERE clause */ Index *pIdx; /* For looping over indices of the table */ int iCur; /* VDBE Cursor number for pTab */ sqlite3 *db; /* Main database structure */ AuthContext sContext; /* Authorization context */ int oldIdx = -1; /* Cursor for the OLD table of AFTER triggers */ #ifndef SQLITE_OMIT_TRIGGER int isView; /* True if attempting to delete from a view */ int triggers_exist = 0; /* True if any triggers exist */ #endif sContext.pParse = 0; | > | 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 | int i; /* Loop counter */ WhereInfo *pWInfo; /* Information about the WHERE clause */ Index *pIdx; /* For looping over indices of the table */ int iCur; /* VDBE Cursor number for pTab */ sqlite3 *db; /* Main database structure */ AuthContext sContext; /* Authorization context */ int oldIdx = -1; /* Cursor for the OLD table of AFTER triggers */ NameContext sNC; /* Name context to resolve expressions in */ #ifndef SQLITE_OMIT_TRIGGER int isView; /* True if attempting to delete from a view */ int triggers_exist = 0; /* True if any triggers exist */ #endif sContext.pParse = 0; |
︙ | ︙ | |||
144 145 146 147 148 149 150 | /* Allocate a cursor used to store the old.* data for a trigger. */ if( triggers_exist ){ oldIdx = pParse->nTab++; } | | > > > | | 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 | /* Allocate a cursor used to store the old.* data for a trigger. */ if( triggers_exist ){ oldIdx = pParse->nTab++; } /* Resolve the column names in the WHERE clause. */ assert( pTabList->nSrc==1 ); iCur = pTabList->a[0].iCursor = pParse->nTab++; memset(&sNC, 0, sizeof(sNC)); sNC.pParse = pParse; sNC.pSrcList = pTabList; if( sqlite3ExprResolveNames(&sNC, pWhere) ){ goto delete_from_cleanup; } /* Start the view context */ if( isView ){ sqlite3AuthContextPush(pParse, &sContext, pTab->zName); |
︙ | ︙ | |||
172 173 174 175 176 177 178 | sqlite3BeginWriteOperation(pParse, triggers_exist, pTab->iDb); /* If we are trying to delete from a view, construct that view into ** a temporary table. */ if( isView ){ Select *pView = sqlite3SelectDup(pTab->pSelect); | | | 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 | sqlite3BeginWriteOperation(pParse, triggers_exist, pTab->iDb); /* If we are trying to delete from a view, construct that view into ** a temporary table. */ if( isView ){ Select *pView = sqlite3SelectDup(pTab->pSelect); sqlite3Select(pParse, pView, SRT_TempTable, iCur, 0, 0, 0, 0); sqlite3SelectDelete(pView); } /* Initialize the counter of the number of rows deleted, if ** we are counting rows. */ if( db->flags & SQLITE_CountRows ){ |
︙ | ︙ |
Changes to src/expr.c.
︙ | ︙ | |||
8 9 10 11 12 13 14 | ** May you find forgiveness for yourself and forgive others. ** May you share freely, never taking more than you give. ** ************************************************************************* ** This file contains routines used for analyzing expressions and ** for generating VDBE code that evaluates expressions in SQLite. ** | | | 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 | ** May you find forgiveness for yourself and forgive others. ** May you share freely, never taking more than you give. ** ************************************************************************* ** This file contains routines used for analyzing expressions and ** for generating VDBE code that evaluates expressions in SQLite. ** ** $Id: expr.c,v 1.189 2005/01/29 08:32:45 danielk1977 Exp $ */ #include "sqliteInt.h" #include <ctype.h> /* ** Return the 'affinity' of the expression pExpr if any. ** |
︙ | ︙ | |||
512 513 514 515 516 517 518 519 520 521 522 523 524 525 | pNew->pPrior = sqlite3SelectDup(p->pPrior); pNew->nLimit = p->nLimit; pNew->nOffset = p->nOffset; pNew->iLimit = -1; pNew->iOffset = -1; pNew->ppOpenTemp = 0; pNew->pFetch = 0; return pNew; } #else Select *sqlite3SelectDup(Select *p){ assert( p==0 ); return 0; } | > > | 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 | pNew->pPrior = sqlite3SelectDup(p->pPrior); pNew->nLimit = p->nLimit; pNew->nOffset = p->nOffset; pNew->iLimit = -1; pNew->iOffset = -1; pNew->ppOpenTemp = 0; pNew->pFetch = 0; pNew->isResolved = 0; pNew->isAgg = 0; return pNew; } #else Select *sqlite3SelectDup(Select *p){ assert( p==0 ); return 0; } |
︙ | ︙ | |||
746 747 748 749 750 751 752 | pExpr->iTable = -1; while( pNC && cnt==0 ){ SrcList *pSrcList = pNC->pSrcList; ExprList *pEList = pNC->pEList; pNC->nRef++; /* assert( zTab==0 || pEList==0 ); */ | > | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | > | 748 749 750 751 752 753 754 755 756 757 758 759 760 761 762 763 764 765 766 767 768 769 770 771 772 773 774 775 776 777 778 779 780 781 782 783 784 785 786 787 788 789 790 791 792 793 794 795 796 797 | pExpr->iTable = -1; while( pNC && cnt==0 ){ SrcList *pSrcList = pNC->pSrcList; ExprList *pEList = pNC->pEList; pNC->nRef++; /* assert( zTab==0 || pEList==0 ); */ if( pSrcList ){ for(i=0, pItem=pSrcList->a; i<pSrcList->nSrc; i++, pItem++){ Table *pTab = pItem->pTab; Column *pCol; if( pTab==0 ) continue; assert( pTab->nCol>0 ); if( zTab ){ if( pItem->zAlias ){ char *zTabName = pItem->zAlias; if( sqlite3StrICmp(zTabName, zTab)!=0 ) continue; }else{ char *zTabName = pTab->zName; if( zTabName==0 || sqlite3StrICmp(zTabName, zTab)!=0 ) continue; if( zDb!=0 && sqlite3StrICmp(db->aDb[pTab->iDb].zName, zDb)!=0 ){ continue; } } } if( 0==(cntTab++) ){ pExpr->iTable = pItem->iCursor; pExpr->iDb = pTab->iDb; pMatch = pItem; } for(j=0, pCol=pTab->aCol; j<pTab->nCol; j++, pCol++){ if( sqlite3StrICmp(pCol->zName, zCol)==0 ){ cnt++; pExpr->iTable = pItem->iCursor; pMatch = pItem; pExpr->iDb = pTab->iDb; /* Substitute the rowid (column -1) for the INTEGER PRIMARY KEY */ pExpr->iColumn = j==pTab->iPKey ? -1 : j; pExpr->affinity = pTab->aCol[j].affinity; pExpr->pColl = pTab->aCol[j].pColl; break; } } } } #ifndef SQLITE_OMIT_TRIGGER /* If we have not already resolved the name, then maybe ** it is a new.* or old.* trigger argument reference |
︙ | ︙ | |||
922 923 924 925 926 927 928 | sqliteFree(zCol); sqlite3ExprDelete(pExpr->pLeft); pExpr->pLeft = 0; sqlite3ExprDelete(pExpr->pRight); pExpr->pRight = 0; pExpr->op = TK_COLUMN; if( cnt==1 ){ | | | 926 927 928 929 930 931 932 933 934 935 936 937 938 939 940 | sqliteFree(zCol); sqlite3ExprDelete(pExpr->pLeft); pExpr->pLeft = 0; sqlite3ExprDelete(pExpr->pRight); pExpr->pRight = 0; pExpr->op = TK_COLUMN; if( cnt==1 ){ assert( pNC!=0 ); sqlite3AuthRead(pParse, pExpr, pNC->pSrcList); } return cnt!=1; } /* ** pExpr is a node that defines a function of some kind. It might |
︙ | ︙ | |||
987 988 989 990 991 992 993 994 995 996 | ** to TK_AGG_FUNCTION. */ static int nameResolverStep(void *pArg, Expr *pExpr){ NameContext *pNC = (NameContext*)pArg; SrcList *pSrcList; Parse *pParse; assert( pNC!=0 ); pSrcList = pNC->pSrcList; pParse = pNC->pParse; | > | | 991 992 993 994 995 996 997 998 999 1000 1001 1002 1003 1004 1005 1006 1007 1008 1009 | ** to TK_AGG_FUNCTION. */ static int nameResolverStep(void *pArg, Expr *pExpr){ NameContext *pNC = (NameContext*)pArg; SrcList *pSrcList; Parse *pParse; if( pExpr==0 ) return 1; assert( pNC!=0 ); pSrcList = pNC->pSrcList; pParse = pNC->pParse; if( ExprHasAnyProperty(pExpr, EP_Resolved) ) return 1; ExprSetProperty(pExpr, EP_Resolved); #ifndef NDEBUG if( pSrcList ){ int i; for(i=0; i<pSrcList->nSrc; i++){ assert( pSrcList->a[i].iCursor>=0 && pSrcList->a[i].iCursor<pParse->nTab); |
︙ | ︙ | |||
1013 1014 1015 1016 1017 1018 1019 | case TK_STRING: { if( pExpr->token.z[0]=='\'' ) break; /* Fall thru into the TK_ID case if this is a double-quoted string */ } /* A lone identifier is the name of a column. */ case TK_ID: { | < | < | 1018 1019 1020 1021 1022 1023 1024 1025 1026 1027 1028 1029 1030 1031 1032 1033 1034 1035 1036 1037 1038 1039 1040 1041 1042 1043 1044 1045 1046 1047 1048 1049 1050 1051 1052 1053 1054 1055 1056 1057 1058 1059 1060 1061 1062 1063 1064 1065 | case TK_STRING: { if( pExpr->token.z[0]=='\'' ) break; /* Fall thru into the TK_ID case if this is a double-quoted string */ } /* A lone identifier is the name of a column. */ case TK_ID: { lookupName(pParse, 0, 0, &pExpr->token, pNC, pExpr); return 1; } /* A table name and column name: ID.ID ** Or a database, table and column: ID.ID.ID */ case TK_DOT: { Token *pColumn; Token *pTable; Token *pDb; Expr *pRight; /* if( pSrcList==0 ) break; */ pRight = pExpr->pRight; if( pRight->op==TK_ID ){ pDb = 0; pTable = &pExpr->pLeft->token; pColumn = &pRight->token; }else{ assert( pRight->op==TK_DOT ); pDb = &pExpr->pLeft->token; pTable = &pRight->pLeft->token; pColumn = &pRight->pRight->token; } lookupName(pParse, pDb, pTable, pColumn, pNC, pExpr); return 1; } /* Resolve function names */ case TK_CTIME: case TK_CTIMESTAMP: case TK_CDATE: case TK_GLOB: case TK_LIKE: case TK_FUNCTION: { ExprList *pList = pExpr->pList; /* The argument list */ int n = pList ? pList->nExpr : 0; /* Number of arguments */ int no_such_func = 0; /* True if no such function exists */ int wrong_num_args = 0; /* True if wrong number of arguments */ |
︙ | ︙ | |||
1101 1102 1103 1104 1105 1106 1107 1108 1109 1110 1111 | } if( is_agg ) pNC->allowAgg = 1; /* FIX ME: Compute pExpr->affinity based on the expected return ** type of the function */ return is_agg; } } return 0; } | > > > > > > > > > > > > > > < < < | 1104 1105 1106 1107 1108 1109 1110 1111 1112 1113 1114 1115 1116 1117 1118 1119 1120 1121 1122 1123 1124 1125 1126 1127 1128 1129 1130 1131 1132 1133 1134 1135 | } if( is_agg ) pNC->allowAgg = 1; /* FIX ME: Compute pExpr->affinity based on the expected return ** type of the function */ return is_agg; } #ifndef SQLITE_OMIT_SUBQUERY case TK_SELECT: case TK_EXISTS: #endif case TK_IN: { if( pExpr->pSelect ){ int nRef = pNC->nRef; sqlite3SelectResolve(pParse, pExpr->pSelect, pNC); assert( pNC->nRef>=nRef ); if( nRef!=pNC->nRef ){ ExprSetProperty(pExpr, EP_VarSelect); } } } } return 0; } /* ** This routine walks an expression tree and resolves references to ** table columns. Nodes of the form ID.ID or ID resolve into an ** index to the table in the table list and a column offset. The ** Expr.opcode for such nodes is changed to TK_COLUMN. The Expr.iTable ** value is changed to the index of the referenced table in pTabList ** plus the "base" value. The base value will ultimately become the |
︙ | ︙ | |||
1130 1131 1132 1133 1134 1135 1136 | ** have the correct number of arguments. Leave an error message ** in pParse->zErrMsg if anything is amiss. Return the number of errors. ** ** If the expression contains aggregate functions then set the EP_Agg ** property on the expression. */ int sqlite3ExprResolveNames( | < < < | | < < < < < < < < < < | < < < | < < | 1144 1145 1146 1147 1148 1149 1150 1151 1152 1153 1154 1155 1156 1157 1158 1159 1160 1161 1162 1163 1164 | ** have the correct number of arguments. Leave an error message ** in pParse->zErrMsg if anything is amiss. Return the number of errors. ** ** If the expression contains aggregate functions then set the EP_Agg ** property on the expression. */ int sqlite3ExprResolveNames( NameContext *pNC, /* Namespace to resolve expressions in. */ Expr *pExpr /* The expression to be analyzed. */ ){ if( pExpr==0 ) return 0; walkExprTree(pExpr, nameResolverStep, pNC); if( pNC->nErr>0 ){ ExprSetProperty(pExpr, EP_Error); } return ExprHasProperty(pExpr, EP_Error); } /* ** A pointer instance of this structure is used to pass information ** through walkExprTree into codeSubqueryStep(). |
︙ | ︙ | |||
1182 1183 1184 1185 1186 1187 1188 | ** expr IN (exprlist) ** and ** expr IN (SELECT ...) ** ** The first form is handled by creating a set holding the list ** of allowed values. The second form causes the SELECT to generate ** a temporary table. | < < < < < < < < | > > > | > > > > > > > > > > > > | > > > < < | 1178 1179 1180 1181 1182 1183 1184 1185 1186 1187 1188 1189 1190 1191 1192 1193 1194 1195 1196 1197 1198 1199 1200 1201 1202 1203 1204 1205 1206 1207 1208 1209 1210 1211 1212 1213 1214 1215 1216 1217 1218 1219 1220 1221 | ** expr IN (exprlist) ** and ** expr IN (SELECT ...) ** ** The first form is handled by creating a set holding the list ** of allowed values. The second form causes the SELECT to generate ** a temporary table. */ #ifndef SQLITE_OMIT_SUBQUERY void sqlite3CodeSubselect(Parse *pParse, Expr *pExpr){ int label = 0; /* Address after sub-select code */ Vdbe *v = sqlite3GetVdbe(pParse); if( v==0 ) return; /* If this is not a variable (correlated) select, then execute ** it only once. Unless this is part of a trigger program. In ** that case re-execute every time (this could be optimized). */ if( !ExprHasAnyProperty(pExpr, EP_VarSelect) && !pParse->trigStack ){ int mem = pParse->nMem++; sqlite3VdbeAddOp(v, OP_MemLoad, mem, 0); label = sqlite3VdbeMakeLabel(v); sqlite3VdbeAddOp(v, OP_If, 0, label); sqlite3VdbeAddOp(v, OP_Integer, 1, 0); sqlite3VdbeAddOp(v, OP_MemStore, mem, 1); } if( pExpr->pSelect ){ sqlite3VdbeAddOp(v, OP_AggContextPush, 0, 0); } switch( pExpr->op ){ case TK_IN: { char affinity; KeyInfo keyInfo; int addr; /* Address of OP_OpenTemp instruction */ affinity = sqlite3ExprAffinity(pExpr->pLeft); /* Whether this is an 'x IN(SELECT...)' or an 'x IN(<exprlist>)' ** expression it is handled the same way. A temporary table is ** filled with single-field index keys representing the results ** from the SELECT or the <exprlist>. ** |
︙ | ︙ | |||
1234 1235 1236 1237 1238 1239 1240 | ** ** Generate code to write the results of the select into the temporary ** table allocated and opened above. */ int iParm = pExpr->iTable + (((int)affinity)<<16); ExprList *pEList; assert( (pExpr->iTable&0x0000FFFF)==pExpr->iTable ); | | | 1238 1239 1240 1241 1242 1243 1244 1245 1246 1247 1248 1249 1250 1251 1252 | ** ** Generate code to write the results of the select into the temporary ** table allocated and opened above. */ int iParm = pExpr->iTable + (((int)affinity)<<16); ExprList *pEList; assert( (pExpr->iTable&0x0000FFFF)==pExpr->iTable ); sqlite3Select(pParse, pExpr->pSelect, SRT_Set, iParm, 0, 0, 0, 0); pEList = pExpr->pSelect->pEList; if( pEList && pEList->nExpr>0 ){ keyInfo.aColl[0] = binaryCompareCollSeq(pParse, pExpr->pLeft, pEList->a[0].pExpr); } }else if( pExpr->pList ){ /* Case 2: expr IN (exprlist) |
︙ | ︙ | |||
1262 1263 1264 1265 1266 1267 1268 | for(i=0; i<pExpr->pList->nExpr; i++){ Expr *pE2 = pExpr->pList->a[i].pExpr; /* Check that the expression is constant and valid. */ if( !sqlite3ExprIsConstant(pE2) ){ sqlite3ErrorMsg(pParse, "right-hand side of IN operator must be constant"); | | < < < | < < < < < < < < < | < < < < < | < < < | < | | < > > | < > > | < < < < < < < < < < < < < < < | > | 1266 1267 1268 1269 1270 1271 1272 1273 1274 1275 1276 1277 1278 1279 1280 1281 1282 1283 1284 1285 1286 1287 1288 1289 1290 1291 1292 1293 1294 1295 1296 1297 1298 1299 1300 1301 1302 1303 1304 1305 1306 1307 1308 1309 1310 1311 1312 1313 1314 1315 1316 1317 1318 1319 1320 1321 1322 1323 1324 1325 1326 1327 1328 | for(i=0; i<pExpr->pList->nExpr; i++){ Expr *pE2 = pExpr->pList->a[i].pExpr; /* Check that the expression is constant and valid. */ if( !sqlite3ExprIsConstant(pE2) ){ sqlite3ErrorMsg(pParse, "right-hand side of IN operator must be constant"); return; } /* Evaluate the expression and insert it into the temp table */ sqlite3ExprCode(pParse, pE2); sqlite3VdbeOp3(v, OP_MakeRecord, 1, 0, &affinity, 1); sqlite3VdbeAddOp(v, OP_String8, 0, 0); sqlite3VdbeAddOp(v, OP_PutStrKey, pExpr->iTable, 0); } } sqlite3VdbeChangeP3(v, addr, (void *)&keyInfo, P3_KEYINFO); break; } case TK_EXISTS: case TK_SELECT: { /* This has to be a scalar SELECT. Generate code to put the ** value of this select in a memory cell and record the number ** of the memory cell in iColumn. */ int sop; Select *pSel; pExpr->iColumn = pParse->nMem++; pSel = pExpr->pSelect; if( pExpr->op==TK_SELECT ){ sop = SRT_Mem; }else{ static const Token one = { "1", 0, 1 }; sop = SRT_Exists; sqlite3ExprListDelete(pSel->pEList); pSel->pEList = sqlite3ExprListAppend(0, sqlite3Expr(TK_INTEGER, 0, 0, &one), 0); } sqlite3Select(pParse, pSel, sop, pExpr->iColumn, 0, 0, 0, 0); break; } } if( pExpr->pSelect ){ sqlite3VdbeAddOp(v, OP_AggContextPop, 0, 0); } if( label<0 ){ sqlite3VdbeResolveLabel(v, label); } return; } #endif /* SQLITE_OMIT_SUBQUERY */ /* ** Generate an instruction that will put the integer describe by ** text z[0..n-1] on the stack. */ static void codeInteger(Vdbe *v, const char *z, int n){ int i; if( sqlite3GetInt32(z, &i) ){ |
︙ | ︙ | |||
1552 1553 1554 1555 1556 1557 1558 | } sqlite3VdbeOp3(v, OP_Function, nExpr, p2, (char*)pDef, P3_FUNCDEF); break; } #ifndef SQLITE_OMIT_SUBQUERY case TK_EXISTS: case TK_SELECT: { | | < < < > | 1523 1524 1525 1526 1527 1528 1529 1530 1531 1532 1533 1534 1535 1536 1537 1538 1539 1540 1541 1542 1543 1544 1545 | } sqlite3VdbeOp3(v, OP_Function, nExpr, p2, (char*)pDef, P3_FUNCDEF); break; } #ifndef SQLITE_OMIT_SUBQUERY case TK_EXISTS: case TK_SELECT: { sqlite3CodeSubselect(pParse, pExpr); sqlite3VdbeAddOp(v, OP_MemLoad, pExpr->iColumn, 0); VdbeComment((v, "# load subquery result")); break; } case TK_IN: { int addr; char affinity; sqlite3CodeSubselect(pParse, pExpr); /* Figure out the affinity to use to create a key from the results ** of the expression. affinityStr stores a static string suitable for ** P3 of OP_MakeRecord. */ affinity = comparisonAffinity(pExpr); |
︙ | ︙ |
Changes to src/insert.c.
︙ | ︙ | |||
8 9 10 11 12 13 14 | ** May you find forgiveness for yourself and forgive others. ** May you share freely, never taking more than you give. ** ************************************************************************* ** This file contains C code routines that are called by the parser ** to handle INSERT statements in SQLite. ** | | | 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 | ** May you find forgiveness for yourself and forgive others. ** May you share freely, never taking more than you give. ** ************************************************************************* ** This file contains C code routines that are called by the parser ** to handle INSERT statements in SQLite. ** ** $Id: insert.c,v 1.135 2005/01/29 08:32:45 danielk1977 Exp $ */ #include "sqliteInt.h" /* ** Set P3 of the most recently inserted opcode to a column affinity ** string for index pIdx. A column affinity string has one character ** for each column in the table, according to the affinity of the column: |
︙ | ︙ | |||
308 309 310 311 312 313 314 | if( pSelect ){ /* Data is coming from a SELECT. Generate code to implement that SELECT */ int rc, iInitCode; iInitCode = sqlite3VdbeAddOp(v, OP_Goto, 0, 0); iSelectLoop = sqlite3VdbeCurrentAddr(v); iInsertBlock = sqlite3VdbeMakeLabel(v); | > > | > | 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 | if( pSelect ){ /* Data is coming from a SELECT. Generate code to implement that SELECT */ int rc, iInitCode; iInitCode = sqlite3VdbeAddOp(v, OP_Goto, 0, 0); iSelectLoop = sqlite3VdbeCurrentAddr(v); iInsertBlock = sqlite3VdbeMakeLabel(v); /* Resolve the expressions in the SELECT statement and execute it. */ rc = sqlite3Select(pParse, pSelect, SRT_Subroutine, iInsertBlock,0,0,0,0); if( rc || pParse->nErr || sqlite3_malloc_failed ) goto insert_cleanup; iCleanup = sqlite3VdbeMakeLabel(v); sqlite3VdbeAddOp(v, OP_Goto, 0, iCleanup); assert( pSelect->pEList ); nColumn = pSelect->pEList->nExpr; /* Set useTempTable to TRUE if the result of the SELECT statement ** should be written into a temporary table. Set to FALSE if each |
︙ | ︙ | |||
368 369 370 371 372 373 374 | }else{ sqlite3VdbeChangeP2(v, iInitCode, sqlite3VdbeCurrentAddr(v)); } }else{ /* This is the case if the data for the INSERT is coming from a VALUES ** clause */ | | > > < | | 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 | }else{ sqlite3VdbeChangeP2(v, iInitCode, sqlite3VdbeCurrentAddr(v)); } }else{ /* This is the case if the data for the INSERT is coming from a VALUES ** clause */ NameContext sNC; memset(&sNC, 0, sizeof(sNC)); sNC.pParse = pParse; assert( pList!=0 ); srcTab = -1; useTempTable = 0; assert( pList ); nColumn = pList->nExpr; for(i=0; i<nColumn; i++){ if( sqlite3ExprResolveNames(&sNC, pList->a[i].pExpr) ){ goto insert_cleanup; } } } /* Make sure the number of columns in the source data matches the number ** of columns to be inserted into the table. |
︙ | ︙ |
Changes to src/main.c.
︙ | ︙ | |||
10 11 12 13 14 15 16 | ** ************************************************************************* ** Main file for the SQLite library. The routines in this file ** implement the programmer interface to the library. Routines in ** other files are for internal use by SQLite and should not be ** accessed by users of the library. ** | | | 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 | ** ************************************************************************* ** Main file for the SQLite library. The routines in this file ** implement the programmer interface to the library. Routines in ** other files are for internal use by SQLite and should not be ** accessed by users of the library. ** ** $Id: main.c,v 1.276 2005/01/29 08:32:45 danielk1977 Exp $ */ #include "sqliteInt.h" #include "os.h" #include <ctype.h> /* ** The following constant value is used by the SQLITE_BIGENDIAN and |
︙ | ︙ | |||
1262 1263 1264 1265 1266 1267 1268 | */ int sqlite3_reset(sqlite3_stmt *pStmt){ int rc; if( pStmt==0 ){ rc = SQLITE_OK; }else{ rc = sqlite3VdbeReset((Vdbe*)pStmt); | | | 1262 1263 1264 1265 1266 1267 1268 1269 1270 1271 1272 1273 1274 1275 1276 | */ int sqlite3_reset(sqlite3_stmt *pStmt){ int rc; if( pStmt==0 ){ rc = SQLITE_OK; }else{ rc = sqlite3VdbeReset((Vdbe*)pStmt); sqlite3VdbeMakeReady((Vdbe*)pStmt, -1, 0, 0, 0, 0); } return rc; } /* ** Register a new collation sequence with the database handle db. */ |
︙ | ︙ |
Changes to src/pager.c.
︙ | ︙ | |||
14 15 16 17 18 19 20 | ** The pager is used to access a database disk file. It implements ** atomic commit and rollback through the use of a journal file that ** is separate from the database file. The pager also implements file ** locking to prevent two processes from writing the same database ** file simultaneously, or one process from reading the database while ** another is writing. ** | | | 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 | ** The pager is used to access a database disk file. It implements ** atomic commit and rollback through the use of a journal file that ** is separate from the database file. The pager also implements file ** locking to prevent two processes from writing the same database ** file simultaneously, or one process from reading the database while ** another is writing. ** ** @(#) $Id: pager.c,v 1.187 2005/01/29 08:32:45 danielk1977 Exp $ */ #include "sqliteInt.h" #include "os.h" #include "pager.h" #include <assert.h> #include <string.h> |
︙ | ︙ | |||
1798 1799 1800 1801 1802 1803 1804 1805 1806 1807 1808 1809 1810 1811 1812 | */ int sqlite3pager_close(Pager *pPager){ PgHdr *pPg, *pNext; switch( pPager->state ){ case PAGER_RESERVED: case PAGER_SYNCED: case PAGER_EXCLUSIVE: { sqlite3pager_rollback(pPager); if( !MEMDB ){ sqlite3OsUnlock(&pPager->fd, NO_LOCK); } assert( pPager->journalOpen==0 ); break; } case PAGER_SHARED: { | > > > > > > > > > > > > | 1798 1799 1800 1801 1802 1803 1804 1805 1806 1807 1808 1809 1810 1811 1812 1813 1814 1815 1816 1817 1818 1819 1820 1821 1822 1823 1824 | */ int sqlite3pager_close(Pager *pPager){ PgHdr *pPg, *pNext; switch( pPager->state ){ case PAGER_RESERVED: case PAGER_SYNCED: case PAGER_EXCLUSIVE: { /* We ignore any IO errors that occur during the rollback ** operation. So disable IO error simulation so that testing ** works more easily. */ #if defined(SQLITE_TEST) && (defined(OS_UNIX) || defined(OS_WIN)) extern int sqlite3_io_error_pending; int ioerr_cnt = sqlite3_io_error_pending; sqlite3_io_error_pending = -1; #endif sqlite3pager_rollback(pPager); #if defined(SQLITE_TEST) && (defined(OS_UNIX) || defined(OS_WIN)) sqlite3_io_error_pending = ioerr_cnt; #endif if( !MEMDB ){ sqlite3OsUnlock(&pPager->fd, NO_LOCK); } assert( pPager->journalOpen==0 ); break; } case PAGER_SHARED: { |
︙ | ︙ |
Changes to src/parse.y.
︙ | ︙ | |||
10 11 12 13 14 15 16 | ** ************************************************************************* ** This file contains SQLite's grammar for SQL. Process this file ** using the lemon parser generator to generate C code that runs ** the parser. Lemon will also generate a header file containing ** numeric codes for all of the tokens. ** | | | 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 | ** ************************************************************************* ** This file contains SQLite's grammar for SQL. Process this file ** using the lemon parser generator to generate C code that runs ** the parser. Lemon will also generate a header file containing ** numeric codes for all of the tokens. ** ** @(#) $Id: parse.y,v 1.163 2005/01/29 08:32:45 danielk1977 Exp $ */ %token_prefix TK_ %token_type {Token} %default_type {Token} %extra_argument {Parse *pParse} %syntax_error { if( pParse->zErrMsg==0 ){ |
︙ | ︙ | |||
313 314 315 316 317 318 319 | sqlite3DropTable(pParse, X, 1); } %endif // SQLITE_OMIT_VIEW //////////////////////// The SELECT statement ///////////////////////////////// // cmd ::= select(X). { | | | 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 | sqlite3DropTable(pParse, X, 1); } %endif // SQLITE_OMIT_VIEW //////////////////////// The SELECT statement ///////////////////////////////// // cmd ::= select(X). { sqlite3Select(pParse, X, SRT_Callback, 0, 0, 0, 0, 0); sqlite3SelectDelete(X); } %type select {Select*} %destructor select {sqlite3SelectDelete($$);} %type oneselect {Select*} %destructor oneselect {sqlite3SelectDelete($$);} |
︙ | ︙ | |||
605 606 607 608 609 610 611 | %endif expr(A) ::= REGISTER(X). {A = sqlite3RegisterExpr(pParse, &X);} expr(A) ::= VARIABLE(X). { Token *pToken = &X; Expr *pExpr = A = sqlite3Expr(TK_VARIABLE, 0, 0, pToken); sqlite3ExprAssignVarNumber(pParse, pExpr); } | | | 605 606 607 608 609 610 611 612 613 614 615 616 617 618 619 | %endif expr(A) ::= REGISTER(X). {A = sqlite3RegisterExpr(pParse, &X);} expr(A) ::= VARIABLE(X). { Token *pToken = &X; Expr *pExpr = A = sqlite3Expr(TK_VARIABLE, 0, 0, pToken); sqlite3ExprAssignVarNumber(pParse, pExpr); } expr(A) ::= ID(X) LP exprlist(Y) RP(E). { A = sqlite3ExprFunction(Y, &X); sqlite3ExprSpan(A,&X,&E); } expr(A) ::= ID(X) LP STAR RP(E). { A = sqlite3ExprFunction(0, &X); sqlite3ExprSpan(A,&X,&E); } |
︙ | ︙ |
Changes to src/select.c.
︙ | ︙ | |||
8 9 10 11 12 13 14 | ** May you find forgiveness for yourself and forgive others. ** May you share freely, never taking more than you give. ** ************************************************************************* ** This file contains C code routines that are called by the parser ** to handle SELECT statements in SQLite. ** | | | 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 | ** May you find forgiveness for yourself and forgive others. ** May you share freely, never taking more than you give. ** ************************************************************************* ** This file contains C code routines that are called by the parser ** to handle SELECT statements in SQLite. ** ** $Id: select.c,v 1.235 2005/01/29 08:32:45 danielk1977 Exp $ */ #include "sqliteInt.h" /* ** Allocate a new Select structure and return a pointer to that ** structure. |
︙ | ︙ | |||
310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 | sqlite3SelectDelete(p->pPrior); sqliteFree(p); } /* ** Delete the aggregate information from the parse structure. */ static void sqliteAggregateInfoReset(Parse *pParse){ sqliteFree(pParse->aAgg); pParse->aAgg = 0; pParse->nAgg = 0; pParse->useAgg = 0; } /* ** Insert code into "v" that will push the record on the top of the ** stack into the sorter. */ static void pushOntoSorter(Parse *pParse, Vdbe *v, ExprList *pOrderBy){ int i; | > > | 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 | sqlite3SelectDelete(p->pPrior); sqliteFree(p); } /* ** Delete the aggregate information from the parse structure. */ #if 0 static void sqliteAggregateInfoReset(Parse *pParse){ sqliteFree(pParse->aAgg); pParse->aAgg = 0; pParse->nAgg = 0; pParse->useAgg = 0; } #endif /* ** Insert code into "v" that will push the record on the top of the ** stack into the sorter. */ static void pushOntoSorter(Parse *pParse, Vdbe *v, ExprList *pOrderBy){ int i; |
︙ | ︙ | |||
665 666 667 668 669 670 671 | ** ** If the declaration type is the exact datatype definition extracted from ** the original CREATE TABLE statement if the expression is a column. ** ** The declaration type for an expression is either TEXT, NUMERIC or ANY. ** The declaration type for a ROWID field is INTEGER. */ | | | < < | > > | | | > > > > > > > > | | 667 668 669 670 671 672 673 674 675 676 677 678 679 680 681 682 683 684 685 686 687 688 689 690 691 692 693 694 695 696 697 698 699 700 701 702 703 704 705 706 707 708 709 710 711 712 713 714 715 716 717 718 719 720 721 | ** ** If the declaration type is the exact datatype definition extracted from ** the original CREATE TABLE statement if the expression is a column. ** ** The declaration type for an expression is either TEXT, NUMERIC or ANY. ** The declaration type for a ROWID field is INTEGER. */ static const char *columnType(NameContext *pNC, Expr *pExpr){ char const *zType; int j; if( pExpr==0 || pNC->pSrcList==0 ) return 0; /* The TK_AS operator can only occur in ORDER BY, GROUP BY, HAVING, ** and LIMIT clauses. But pExpr originates in the result set of a ** SELECT. So pExpr can never contain an AS operator. */ assert( pExpr->op!=TK_AS ); switch( pExpr->op ){ case TK_COLUMN: { Table *pTab = 0; int iCol = pExpr->iColumn; while( pNC && !pTab ){ SrcList *pTabList = pNC->pSrcList; for(j=0;j<pTabList->nSrc && pTabList->a[j].iCursor!=pExpr->iTable;j++); if( j<pTabList->nSrc ){ pTab = pTabList->a[j].pTab; }else{ pNC = pNC->pNext; } } assert( pTab ); if( iCol<0 ) iCol = pTab->iPKey; assert( iCol==-1 || (iCol>=0 && iCol<pTab->nCol) ); if( iCol<0 ){ zType = "INTEGER"; }else{ zType = pTab->aCol[iCol].zType; } break; } #ifndef SQLITE_OMIT_SUBQUERY case TK_SELECT: { NameContext sNC; Select *pS = pExpr->pSelect; sNC.pSrcList = pExpr->pSelect->pSrc; sNC.pNext = pNC; zType = columnType(&sNC, pS->pEList->a[0].pExpr); break; } #endif default: zType = 0; } |
︙ | ︙ | |||
719 720 721 722 723 724 725 726 727 | static void generateColumnTypes( Parse *pParse, /* Parser context */ SrcList *pTabList, /* List of tables */ ExprList *pEList /* Expressions defining the result set */ ){ Vdbe *v = pParse->pVdbe; int i; for(i=0; i<pEList->nExpr; i++){ Expr *p = pEList->a[i].pExpr; | > > | | 729 730 731 732 733 734 735 736 737 738 739 740 741 742 743 744 745 746 747 | static void generateColumnTypes( Parse *pParse, /* Parser context */ SrcList *pTabList, /* List of tables */ ExprList *pEList /* Expressions defining the result set */ ){ Vdbe *v = pParse->pVdbe; int i; NameContext sNC; sNC.pSrcList = pTabList; for(i=0; i<pEList->nExpr; i++){ Expr *p = pEList->a[i].pExpr; const char *zType = columnType(&sNC, p); if( zType==0 ) continue; /* The vdbe must make it's own copy of the column-type, in case the ** schema is reset before this virtual machine is deleted. */ sqlite3VdbeSetColName(v, i+pEList->nExpr, zType, strlen(zType)); } } |
︙ | ︙ | |||
856 857 858 859 860 861 862 863 864 865 866 867 868 869 | pTab->aCol = aCol = sqliteMalloc( sizeof(pTab->aCol[0])*pTab->nCol ); for(i=0, pCol=aCol; i<pTab->nCol; i++, pCol++){ Expr *p, *pR; char *zType; char *zName; char *zBasename; int cnt; /* Get an appropriate name for the column */ p = pEList->a[i].pExpr; assert( p->pRight==0 || p->pRight->token.z==0 || p->pRight->token.z[0]!=0 ); if( (zName = pEList->a[i].zName)!=0 ){ /* If the column contains an "AS <name>" phrase, use <name> as the name */ | > | 868 869 870 871 872 873 874 875 876 877 878 879 880 881 882 | pTab->aCol = aCol = sqliteMalloc( sizeof(pTab->aCol[0])*pTab->nCol ); for(i=0, pCol=aCol; i<pTab->nCol; i++, pCol++){ Expr *p, *pR; char *zType; char *zName; char *zBasename; int cnt; NameContext sNC; /* Get an appropriate name for the column */ p = pEList->a[i].pExpr; assert( p->pRight==0 || p->pRight->token.z==0 || p->pRight->token.z[0]!=0 ); if( (zName = pEList->a[i].zName)!=0 ){ /* If the column contains an "AS <name>" phrase, use <name> as the name */ |
︙ | ︙ | |||
895 896 897 898 899 900 901 | sqliteFree(zBasename); } pCol->zName = zName; /* Get the typename, type affinity, and collating sequence for the ** column. */ | > | | 908 909 910 911 912 913 914 915 916 917 918 919 920 921 922 923 | sqliteFree(zBasename); } pCol->zName = zName; /* Get the typename, type affinity, and collating sequence for the ** column. */ sNC.pSrcList = pSelect->pSrc; zType = sqliteStrDup(columnType(&sNC, p)); pCol->zType = zType; pCol->affinity = SQLITE_AFF_NUMERIC; if( zType ){ pCol->affinity = sqlite3AffinityType(zType, strlen(zType)); } pCol->pColl = sqlite3ExprCollSeq(pParse, p); if( !pCol->pColl ){ |
︙ | ︙ | |||
971 972 973 974 975 976 977 978 979 980 981 982 983 984 | #ifndef SQLITE_OMIT_SUBQUERY /* A sub-query in the FROM clause of a SELECT */ assert( pFrom->pSelect!=0 ); if( pFrom->zAlias==0 ){ pFrom->zAlias = sqlite3MPrintf("sqlite_subquery_%p_", (void*)pFrom->pSelect); } pFrom->pTab = pTab = sqlite3ResultSetOfSelect(pParse, pFrom->zAlias, pFrom->pSelect); 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, | > | 985 986 987 988 989 990 991 992 993 994 995 996 997 998 999 | #ifndef SQLITE_OMIT_SUBQUERY /* A sub-query in the FROM clause of a SELECT */ assert( pFrom->pSelect!=0 ); if( pFrom->zAlias==0 ){ pFrom->zAlias = sqlite3MPrintf("sqlite_subquery_%p_", (void*)pFrom->pSelect); } sqlite3SelectResolve(pParse, pFrom->pSelect, 0); pFrom->pTab = pTab = sqlite3ResultSetOfSelect(pParse, pFrom->zAlias, pFrom->pSelect); 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, |
︙ | ︙ | |||
1488 1489 1490 1491 1492 1493 1494 | /* Generate code for the left and right SELECT statements. */ switch( p->op ){ case TK_ALL: { if( p->pOrderBy==0 ){ pPrior->nLimit = p->nLimit; pPrior->nOffset = p->nOffset; | | | | 1503 1504 1505 1506 1507 1508 1509 1510 1511 1512 1513 1514 1515 1516 1517 1518 1519 1520 1521 1522 1523 1524 1525 1526 | /* Generate code for the left and right SELECT statements. */ switch( p->op ){ case TK_ALL: { if( p->pOrderBy==0 ){ pPrior->nLimit = p->nLimit; pPrior->nOffset = p->nOffset; rc = sqlite3Select(pParse, pPrior, eDest, iParm, 0, 0, 0, aff); if( rc ){ goto multi_select_end; } p->pPrior = 0; p->iLimit = pPrior->iLimit; p->iOffset = pPrior->iOffset; p->nLimit = -1; p->nOffset = 0; rc = sqlite3Select(pParse, p, eDest, iParm, 0, 0, 0, aff); p->pPrior = pPrior; if( rc ){ goto multi_select_end; } break; } /* For UNION ALL ... ORDER BY fall through to the next case */ |
︙ | ︙ | |||
1546 1547 1548 1549 1550 1551 1552 | assert( nAddr<sizeof(aAddr)/sizeof(aAddr[0]) ); aAddr[nAddr++] = sqlite3VdbeAddOp(v, OP_SetNumColumns, unionTab, 0); assert( p->pEList ); } /* Code the SELECT statements to our left */ | > | | | 1561 1562 1563 1564 1565 1566 1567 1568 1569 1570 1571 1572 1573 1574 1575 1576 1577 1578 1579 1580 1581 1582 1583 1584 1585 1586 1587 1588 1589 1590 1591 1592 1593 1594 1595 | assert( nAddr<sizeof(aAddr)/sizeof(aAddr[0]) ); aAddr[nAddr++] = sqlite3VdbeAddOp(v, OP_SetNumColumns, unionTab, 0); assert( p->pEList ); } /* Code the SELECT statements to our left */ assert( !pPrior->pOrderBy ); rc = sqlite3Select(pParse, pPrior, priorOp, unionTab, 0, 0, 0, aff); if( rc ){ goto multi_select_end; } /* Code the current SELECT statement */ switch( p->op ){ case TK_EXCEPT: op = SRT_Except; break; case TK_UNION: op = SRT_Union; break; case TK_ALL: op = SRT_Table; break; } p->pPrior = 0; pOrderBy = p->pOrderBy; p->pOrderBy = 0; nLimit = p->nLimit; p->nLimit = -1; nOffset = p->nOffset; p->nOffset = 0; rc = sqlite3Select(pParse, p, op, unionTab, 0, 0, 0, aff); p->pPrior = pPrior; p->pOrderBy = pOrderBy; p->nLimit = nLimit; p->nOffset = nOffset; p->iLimit = -1; p->iOffset = -1; if( rc ){ |
︙ | ︙ | |||
1634 1635 1636 1637 1638 1639 1640 | sqlite3VdbeAddOp(v, OP_KeyAsData, tab1, 1); assert( nAddr<sizeof(aAddr)/sizeof(aAddr[0]) ); aAddr[nAddr++] = sqlite3VdbeAddOp(v, OP_SetNumColumns, tab1, 0); assert( p->pEList ); /* Code the SELECTs to our left into temporary table "tab1". */ | | | | 1650 1651 1652 1653 1654 1655 1656 1657 1658 1659 1660 1661 1662 1663 1664 1665 1666 1667 1668 1669 1670 1671 1672 1673 1674 1675 1676 1677 1678 1679 1680 1681 1682 1683 1684 | sqlite3VdbeAddOp(v, OP_KeyAsData, tab1, 1); assert( nAddr<sizeof(aAddr)/sizeof(aAddr[0]) ); aAddr[nAddr++] = sqlite3VdbeAddOp(v, OP_SetNumColumns, tab1, 0); assert( p->pEList ); /* Code the SELECTs to our left into temporary table "tab1". */ rc = sqlite3Select(pParse, pPrior, SRT_Union, tab1, 0, 0, 0, aff); if( rc ){ goto multi_select_end; } /* Code the current SELECT into temporary table "tab2" */ addr = sqlite3VdbeAddOp(v, OP_OpenTemp, tab2, 0); rc = multiSelectOpenTempAddr(p, addr); if( rc!=SQLITE_OK ){ goto multi_select_end; } sqlite3VdbeAddOp(v, OP_KeyAsData, tab2, 1); assert( nAddr<sizeof(aAddr)/sizeof(aAddr[0]) ); aAddr[nAddr++] = sqlite3VdbeAddOp(v, OP_SetNumColumns, tab2, 0); p->pPrior = 0; nLimit = p->nLimit; p->nLimit = -1; nOffset = p->nOffset; p->nOffset = 0; rc = sqlite3Select(pParse, p, SRT_Union, tab2, 0, 0, 0, aff); p->pPrior = pPrior; p->nLimit = nLimit; p->nOffset = nOffset; if( rc ){ goto multi_select_end; } |
︙ | ︙ | |||
1753 1754 1755 1756 1757 1758 1759 | if( p->pOrderBy ){ struct ExprList_item *pOrderByTerm = p->pOrderBy->a; for(i=0; i<p->pOrderBy->nExpr; i++, pOrderByTerm++){ Expr *pExpr = pOrderByTerm->pExpr; char *zName = pOrderByTerm->zName; assert( pExpr->op==TK_COLUMN && pExpr->iColumn<nCol ); | | | 1769 1770 1771 1772 1773 1774 1775 1776 1777 1778 1779 1780 1781 1782 1783 | if( p->pOrderBy ){ struct ExprList_item *pOrderByTerm = p->pOrderBy->a; for(i=0; i<p->pOrderBy->nExpr; i++, pOrderByTerm++){ Expr *pExpr = pOrderByTerm->pExpr; char *zName = pOrderByTerm->zName; assert( pExpr->op==TK_COLUMN && pExpr->iColumn<nCol ); /* assert( !pExpr->pColl ); */ if( zName ){ pExpr->pColl = sqlite3LocateCollSeq(pParse, zName, -1); }else{ pExpr->pColl = pKeyInfo->aColl[pExpr->iColumn]; } } generateSortTail(pParse, p, v, p->pEList->nExpr, eDest, iParm); |
︙ | ︙ | |||
1793 1794 1795 1796 1797 1798 1799 1800 1801 1802 1803 1804 1805 1806 | ** whose result set is defined by pEList appears as entry in the ** FROM clause of a SELECT such that the VDBE cursor assigned to that ** FORM clause entry is iTable. This routine make the necessary ** 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*); /* Forward Decl */ static void substExpr(Expr *pExpr, int iTable, ExprList *pEList){ if( pExpr==0 ) return; if( pExpr->op==TK_COLUMN && pExpr->iTable==iTable ){ if( pExpr->iColumn<0 ){ pExpr->op = TK_NULL; }else{ Expr *pNew; | > | 1809 1810 1811 1812 1813 1814 1815 1816 1817 1818 1819 1820 1821 1822 1823 | ** whose result set is defined by pEList appears as entry in the ** FROM clause of a SELECT such that the VDBE cursor assigned to that ** FORM clause entry is iTable. This routine make the necessary ** 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*); /* Forward Decl */ static void substSelect(Select *, 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 ){ if( pExpr->iColumn<0 ){ pExpr->op = TK_NULL; }else{ Expr *pNew; |
︙ | ︙ | |||
1820 1821 1822 1823 1824 1825 1826 1827 1828 1829 | pExpr->iAgg = pNew->iAgg; sqlite3TokenCopy(&pExpr->token, &pNew->token); sqlite3TokenCopy(&pExpr->span, &pNew->span); } }else{ substExpr(pExpr->pLeft, iTable, pEList); substExpr(pExpr->pRight, iTable, pEList); substExprList(pExpr->pList, iTable, pEList); } } | > < | > > > > > > > > | 1837 1838 1839 1840 1841 1842 1843 1844 1845 1846 1847 1848 1849 1850 1851 1852 1853 1854 1855 1856 1857 1858 1859 1860 1861 1862 1863 1864 1865 1866 1867 1868 | pExpr->iAgg = pNew->iAgg; sqlite3TokenCopy(&pExpr->token, &pNew->token); sqlite3TokenCopy(&pExpr->span, &pNew->span); } }else{ substExpr(pExpr->pLeft, iTable, pEList); substExpr(pExpr->pRight, iTable, pEList); substSelect(pExpr->pSelect, iTable, pEList); substExprList(pExpr->pList, iTable, pEList); } } static void 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); } } static void substSelect(Select *p, int iTable, ExprList *pEList){ if( !p ) return; substExprList(p->pEList, iTable, pEList); substExprList(p->pGroupBy, iTable, pEList); substExprList(p->pOrderBy, iTable, pEList); substExpr(p->pHaving, iTable, pEList); substExpr(p->pWhere, iTable, pEList); } #endif /* !defined(SQLITE_OMIT_VIEW) */ #ifndef SQLITE_OMIT_VIEW /* ** This routine attempts to flatten subqueries in order to speed ** execution. It returns 1 if it makes changes and 0 if no flattening |
︙ | ︙ | |||
2232 2233 2234 2235 2236 2237 2238 | ** the number of errors seen. ** ** An ORDER BY or GROUP BY is a list of expressions. If any expression ** is an integer constant, then that expression is replaced by the ** corresponding entry in the result set. */ static int processOrderGroupBy( | | < < < < > > > > | > | | | < < < < < < < < < > > | > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 2257 2258 2259 2260 2261 2262 2263 2264 2265 2266 2267 2268 2269 2270 2271 2272 2273 2274 2275 2276 2277 2278 2279 2280 2281 2282 2283 2284 2285 2286 2287 2288 2289 2290 2291 2292 2293 2294 2295 2296 2297 2298 2299 2300 2301 2302 2303 2304 2305 2306 2307 2308 2309 2310 2311 2312 2313 2314 2315 2316 2317 2318 2319 2320 2321 2322 2323 2324 2325 2326 2327 2328 2329 2330 2331 2332 2333 2334 2335 2336 2337 2338 2339 2340 2341 2342 2343 2344 2345 2346 2347 2348 2349 2350 2351 2352 2353 2354 2355 2356 2357 2358 2359 2360 2361 2362 2363 2364 2365 2366 2367 2368 2369 2370 2371 2372 2373 2374 2375 2376 2377 2378 2379 2380 2381 2382 2383 2384 2385 2386 2387 2388 2389 2390 2391 2392 2393 2394 2395 2396 2397 2398 2399 2400 2401 2402 2403 2404 2405 2406 2407 2408 2409 2410 2411 2412 2413 2414 2415 2416 2417 2418 2419 2420 2421 2422 2423 2424 2425 2426 2427 2428 2429 2430 2431 2432 2433 2434 2435 2436 2437 2438 2439 2440 2441 2442 2443 2444 2445 2446 2447 2448 | ** the number of errors seen. ** ** An ORDER BY or GROUP BY is a list of expressions. If any expression ** is an integer constant, then that expression is replaced by the ** corresponding entry in the result set. */ static int processOrderGroupBy( NameContext *pNC, /* Name context of the SELECT statement. */ ExprList *pOrderBy, /* The ORDER BY or GROUP BY clause to be processed */ const char *zType /* Either "ORDER" or "GROUP", as appropriate */ ){ int i; ExprList *pEList = pNC->pEList; /* The result set of the SELECT */ Parse *pParse = pNC->pParse; /* The result set of the SELECT */ assert( pEList ); if( pOrderBy==0 ) return 0; for(i=0; i<pOrderBy->nExpr; i++){ int iCol; Expr *pE = pOrderBy->a[i].pExpr; if( sqlite3ExprIsInteger(pE, &iCol) ){ if( iCol>0 && iCol<=pEList->nExpr ){ sqlite3ExprDelete(pE); pE = pOrderBy->a[i].pExpr = sqlite3ExprDup(pEList->a[iCol-1].pExpr); }else{ sqlite3ErrorMsg(pParse, "%s BY column number %d out of range - should be " "between 1 and %d", zType, iCol, pEList->nExpr); return 1; } } if( sqlite3ExprResolveNames(pNC, pE) ){ return 1; } if( sqlite3ExprIsConstant(pE) ){ sqlite3ErrorMsg(pParse, "%s BY terms must not be non-integer constants", zType); return 1; } } return 0; } /* ** This routine resolves any names used in the result set of the ** supplied SELECT statement. If the SELECT statement being resolved ** is a sub-select, then pOuterNC is a pointer to the NameContext ** of the parent SELECT. */ int sqlite3SelectResolve( Parse *pParse, /* The parser context */ Select *p, /* The SELECT statement being coded. */ NameContext *pOuterNC /* The outer name context. May be NULL. */ ){ ExprList *pEList; /* Result set. */ int i; /* For-loop variable used in multiple places */ NameContext sNC; /* Local name-context */ /* If this routine has run before, return immediately. */ if( p->isResolved ){ assert( !pOuterNC ); return SQLITE_OK; } p->isResolved = 1; /* If there have already been errors, do nothing. */ if( pParse->nErr>0 ){ return SQLITE_ERROR; } /* Prepare the select statement. This call will allocate all cursors ** required to handle the tables and subqueries in the FROM clause. */ if( prepSelectStmt(pParse, p) ){ return SQLITE_ERROR; } /* Set up the local name-context to pass to ExprResolveNames(). */ sNC.pNext = pOuterNC; sNC.pParse = pParse; sNC.pSrcList = p->pSrc; sNC.allowAgg = 1; sNC.hasAgg = 0; sNC.nErr = 0; sNC.nRef = 0; sNC.pEList = 0; /* NameContext.nDepth stores the depth of recursion for this query. For ** an outer query (e.g. SELECT * FROM sqlite_master) this is 1. For ** a subquery it is 2. For a subquery of a subquery, 3. And so on. ** Parse.nMaxDepth is the maximum depth for any subquery resolved so ** far. This is used to determine the number of aggregate contexts ** required at runtime. */ sNC.nDepth = (pOuterNC?pOuterNC->nDepth+1:1); if( sNC.nDepth>pParse->nMaxDepth ){ pParse->nMaxDepth = sNC.nDepth; } /* Resolve names in the result set. */ pEList = p->pEList; if( !pEList ) return SQLITE_ERROR; for(i=0; i<pEList->nExpr; i++){ Expr *pX = pEList->a[i].pExpr; if( sqlite3ExprResolveNames(&sNC, pX) ){ return SQLITE_ERROR; } } /* If there are no aggregate functions in the result-set, and no GROUP BY ** expression, do not allow aggregates in any of the other expressions. */ assert( !p->isAgg ); if( p->pGroupBy || sNC.hasAgg ){ p->isAgg = 1; }else{ sNC.allowAgg = 0; } /* If a HAVING clause is present, then there must be a GROUP BY clause. */ if( p->pHaving && !p->pGroupBy ){ sqlite3ErrorMsg(pParse, "a GROUP BY clause is required before HAVING"); return SQLITE_ERROR; } /* Add the expression list to the name-context before parsing the ** other expressions in the SELECT statement. This is so that ** expressions in the WHERE clause (etc.) can refer to expressions by ** aliases in the result set. ** ** Minor point: If this is the case, then the expression will be ** re-evaluated for each reference to it. */ sNC.pEList = p->pEList; if( sqlite3ExprResolveNames(&sNC, p->pWhere) || sqlite3ExprResolveNames(&sNC, p->pHaving) || processOrderGroupBy(&sNC, p->pOrderBy, "ORDER") || processOrderGroupBy(&sNC, p->pGroupBy, "GROUP") ){ return SQLITE_ERROR; } return SQLITE_OK; } /* ** An instance of the following struct is used by sqlite3Select() ** to save aggregate related information from the Parse object ** at the start of each call and to restore it at the end. See ** saveAggregateInfo() and restoreAggregateInfo(). */ struct AggregateInfo { u8 useAgg; int nAgg; AggExpr *aAgg; }; typedef struct AggregateInfo AggregateInfo; /* ** Copy aggregate related information from the Parse structure ** into the AggregateInfo structure. Zero the aggregate related ** values in the Parse struct. */ static void saveAggregateInfo(Parse *pParse, AggregateInfo *pInfo){ pInfo->aAgg = pParse->aAgg; pInfo->nAgg = pParse->nAgg; pInfo->useAgg = pParse->useAgg; pParse->aAgg = 0; pParse->nAgg = 0; pParse->useAgg = 0; } /* ** Copy aggregate related information from the AggregateInfo struct ** back into the Parse structure. The aggregate related information ** currently stored in the Parse structure is deleted. */ static void restoreAggregateInfo(Parse *pParse, AggregateInfo *pInfo){ sqliteFree(pParse->aAgg); pParse->aAgg = pInfo->aAgg; pParse->nAgg = pInfo->nAgg; pParse->useAgg = pInfo->useAgg; } /* ** Generate code for the given SELECT statement. ** ** The results are distributed in various ways depending on the ** value of eDest and iParm. ** ** eDest Value Result |
︙ | ︙ | |||
2328 2329 2330 2331 2332 2333 2334 | Parse *pParse, /* The parser context */ Select *p, /* The SELECT statement being coded. */ int eDest, /* How to dispose of the results */ int iParm, /* A parameter used by the eDest disposal method */ Select *pParent, /* Another SELECT for which this is a sub-query */ int parentTab, /* Index in pParent->pSrc of this query */ int *pParentAgg, /* True if pParent uses aggregate functions */ | | < | > > > > > > > > > > > < > > > < < < < < < < | 2495 2496 2497 2498 2499 2500 2501 2502 2503 2504 2505 2506 2507 2508 2509 2510 2511 2512 2513 2514 2515 2516 2517 2518 2519 2520 2521 2522 2523 2524 2525 2526 2527 2528 2529 2530 2531 2532 2533 2534 2535 2536 2537 2538 2539 2540 2541 2542 2543 2544 2545 2546 2547 2548 2549 2550 2551 2552 2553 2554 2555 2556 2557 2558 2559 2560 2561 2562 2563 2564 2565 2566 2567 2568 2569 | Parse *pParse, /* The parser context */ Select *p, /* The SELECT statement being coded. */ int eDest, /* How to dispose of the results */ int iParm, /* A parameter used by the eDest disposal method */ Select *pParent, /* Another SELECT for which this is a sub-query */ int parentTab, /* Index in pParent->pSrc of this query */ int *pParentAgg, /* True if pParent uses aggregate functions */ char *aff /* If eDest is SRT_Union, the affinity string */ ){ int i; WhereInfo *pWInfo; Vdbe *v; int isAgg; /* True for select lists like "count(*)" */ ExprList *pEList; /* List of columns to extract. */ SrcList *pTabList; /* List of tables to select from */ Expr *pWhere; /* The WHERE clause. May be NULL */ ExprList *pOrderBy; /* The ORDER BY clause. May be NULL */ ExprList *pGroupBy; /* The GROUP BY clause. May be NULL */ 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 rc = 1; /* Value to return from this function */ AggregateInfo sAggInfo; if( sqlite3_malloc_failed || pParse->nErr || p==0 ) return 1; if( sqlite3AuthCheck(pParse, SQLITE_SELECT, 0, 0, 0) ) return 1; #ifndef SQLITE_OMIT_COMPOUND_SELECT /* If there is are a sequence of queries, do the earlier ones first. */ if( p->pPrior ){ #ifndef SQLITE_OMIT_CURSOR if( p->pFetch ){ sqlite3ErrorMsg(pParse, "cursors cannot be used on compound queries"); goto select_end; } #endif return multiSelect(pParse, p, eDest, iParm, aff); } #endif saveAggregateInfo(pParse, &sAggInfo); pOrderBy = p->pOrderBy; if( eDest==SRT_Union || eDest==SRT_Except || eDest==SRT_Discard ){ p->pOrderBy = 0; } if( sqlite3SelectResolve(pParse, p, 0) ){ goto select_end; } p->pOrderBy = pOrderBy; /* Make local copies of the parameters for this query. */ pTabList = p->pSrc; pWhere = p->pWhere; pGroupBy = p->pGroupBy; pHaving = p->pHaving; isAgg = p->isAgg; isDistinct = p->isDistinct; pEList = p->pEList; if( pEList==0 ) goto select_end; /* ** Do not even attempt to generate any code if we have already seen ** errors before this routine starts. */ if( pParse->nErr>0 ) goto select_end; /* If writing to memory or generating a set ** only a single column may be output. */ assert( eDest!=SRT_Exists || pEList->nExpr==1 ); #ifndef SQLITE_OMIT_SUBQUERY if( (eDest==SRT_Mem || eDest==SRT_Set) && pEList->nExpr>1 ){ sqlite3ErrorMsg(pParse, "only a single result allowed for " |
︙ | ︙ | |||
2408 2409 2410 2411 2412 2413 2414 | case SRT_Discard: pOrderBy = 0; break; default: break; } | < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < | 2580 2581 2582 2583 2584 2585 2586 2587 2588 2589 2590 2591 2592 2593 | case SRT_Discard: pOrderBy = 0; break; default: break; } /* We cannot use a SQL cursor on a join or on a DISTINCT query */ #ifndef SQLITE_OMIT_CURSOR if( p->pFetch ){ if( p->isDistinct ){ sqlite3ErrorMsg(pParse, "cursors cannot be used on DISTINCT queries"); goto select_end; |
︙ | ︙ | |||
2489 2490 2491 2492 2493 2494 2495 | zSavedAuthContext = pParse->zAuthContext; pParse->zAuthContext = pTabList->a[i].zName; needRestoreContext = 1; }else{ needRestoreContext = 0; } sqlite3Select(pParse, pTabList->a[i].pSelect, SRT_TempTable, | | | 2628 2629 2630 2631 2632 2633 2634 2635 2636 2637 2638 2639 2640 2641 2642 | zSavedAuthContext = pParse->zAuthContext; pParse->zAuthContext = pTabList->a[i].zName; needRestoreContext = 1; }else{ needRestoreContext = 0; } sqlite3Select(pParse, pTabList->a[i].pSelect, SRT_TempTable, pTabList->a[i].iCursor, p, i, &isAgg, 0); if( needRestoreContext ){ pParse->zAuthContext = zSavedAuthContext; } pTabList = p->pSrc; pWhere = p->pWhere; if( eDest!=SRT_Union && eDest!=SRT_Except && eDest!=SRT_Discard ){ pOrderBy = p->pOrderBy; |
︙ | ︙ | |||
2519 2520 2521 2522 2523 2524 2525 | /* Check to see if this is a subquery that can be "flattened" into its parent. ** If flattening is a possiblity, do so and return immediately. */ #ifndef SQLITE_OMIT_VIEW if( pParent && pParentAgg && flattenSubquery(pParse, pParent, parentTab, *pParentAgg, isAgg) ){ if( isAgg ) *pParentAgg = 1; | | | 2658 2659 2660 2661 2662 2663 2664 2665 2666 2667 2668 2669 2670 2671 2672 | /* Check to see if this is a subquery that can be "flattened" into its parent. ** If flattening is a possiblity, do so and return immediately. */ #ifndef SQLITE_OMIT_VIEW if( pParent && pParentAgg && flattenSubquery(pParse, pParent, parentTab, *pParentAgg, isAgg) ){ if( isAgg ) *pParentAgg = 1; goto select_end; } #endif /* If there is an ORDER BY clause, resolve any collation sequences ** names that have been explicitly specified. */ if( pOrderBy ){ |
︙ | ︙ | |||
2551 2552 2553 2554 2555 2556 2557 | if( eDest==SRT_TempTable ){ sqlite3VdbeAddOp(v, OP_OpenTemp, iParm, 0); sqlite3VdbeAddOp(v, OP_SetNumColumns, iParm, pEList->nExpr); } /* Do an analysis of aggregate expressions. */ | < | 2690 2691 2692 2693 2694 2695 2696 2697 2698 2699 2700 2701 2702 2703 | if( eDest==SRT_TempTable ){ sqlite3VdbeAddOp(v, OP_OpenTemp, iParm, 0); sqlite3VdbeAddOp(v, OP_SetNumColumns, iParm, pEList->nExpr); } /* Do an analysis of aggregate expressions. */ if( isAgg || pGroupBy ){ assert( pParse->nAgg==0 ); isAgg = 1; for(i=0; i<pEList->nExpr; i++){ if( sqlite3ExprAnalyzeAggregates(pParse, pEList->a[i].pExpr) ){ goto select_end; } |
︙ | ︙ | |||
2742 2743 2744 2745 2746 2747 2748 | */ rc = 0; /* Control jumps to here if an error is encountered above, or upon ** successful coding of the SELECT. */ select_end: | | | 2880 2881 2882 2883 2884 2885 2886 2887 2888 2889 | */ rc = 0; /* Control jumps to here if an error is encountered above, or upon ** successful coding of the SELECT. */ select_end: restoreAggregateInfo(pParse, &sAggInfo); return rc; } |
Changes to src/sqliteInt.h.
1 2 3 4 5 6 7 8 9 10 11 12 13 | /* ** 2001 September 15 ** ** The author disclaims copyright to this source code. In place of ** a legal notice, here is a blessing: ** ** May you do good and not evil. ** May you find forgiveness for yourself and forgive others. ** May you share freely, never taking more than you give. ** ************************************************************************* ** Internal interface definitions for SQLite. ** | | | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 | /* ** 2001 September 15 ** ** The author disclaims copyright to this source code. In place of ** a legal notice, here is a blessing: ** ** May you do good and not evil. ** May you find forgiveness for yourself and forgive others. ** May you share freely, never taking more than you give. ** ************************************************************************* ** Internal interface definitions for SQLite. ** ** @(#) $Id: sqliteInt.h,v 1.364 2005/01/29 08:32:45 danielk1977 Exp $ */ #ifndef _SQLITEINT_H_ #define _SQLITEINT_H_ /* ** Cursor support is turned off unless the SQLITE_ENABLE_CURSOR option ** is defined. |
︙ | ︙ | |||
834 835 836 837 838 839 840 841 842 843 844 845 846 847 | ** The following are the meanings of bits in the Expr.flags field. */ #define EP_FromJoin 0x0001 /* Originated in ON or USING clause of a join */ #define EP_Agg 0x0002 /* Contains one or more aggregate functions */ #define EP_Resolved 0x0004 /* IDs have been resolved to COLUMNs */ #define EP_Error 0x0008 /* Expression contains one or more errors */ #define EP_Not 0x0010 /* Operator preceeded by NOT */ /* ** These macros can be used to test, set, or clear bits in the ** Expr.flags field. */ #define ExprHasProperty(E,P) (((E)->flags&(P))==(P)) #define ExprHasAnyProperty(E,P) (((E)->flags&(P))!=0) | > | 834 835 836 837 838 839 840 841 842 843 844 845 846 847 848 | ** The following are the meanings of bits in the Expr.flags field. */ #define EP_FromJoin 0x0001 /* Originated in ON or USING clause of a join */ #define EP_Agg 0x0002 /* Contains one or more aggregate functions */ #define EP_Resolved 0x0004 /* IDs have been resolved to COLUMNs */ #define EP_Error 0x0008 /* Expression contains one or more errors */ #define EP_Not 0x0010 /* Operator preceeded by NOT */ #define EP_VarSelect 0x0020 /* pSelect is correlated, not constant */ /* ** These macros can be used to test, set, or clear bits in the ** Expr.flags field. */ #define ExprHasProperty(E,P) (((E)->flags&(P))==(P)) #define ExprHasAnyProperty(E,P) (((E)->flags&(P))!=0) |
︙ | ︙ | |||
979 980 981 982 983 984 985 986 987 988 989 990 991 992 | */ struct Fetch { SqlCursor *pCursor; /* Cursor used by the fetch */ int isBackwards; /* Cursor moves backwards if true, forward if false */ int doRewind; /* True to rewind cursor before starting */ }; /* ** An instance of the following structure contains all information ** needed to generate code for a single SELECT statement. ** ** nLimit is set to -1 if there is no LIMIT clause. nOffset is set to 0. ** If there is a LIMIT clause, the parser sets nLimit to the value of the ** limit and nOffset to the value of the offset (or 0 if there is not | > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 980 981 982 983 984 985 986 987 988 989 990 991 992 993 994 995 996 997 998 999 1000 1001 1002 1003 1004 1005 1006 1007 1008 1009 1010 1011 1012 1013 1014 1015 1016 1017 1018 1019 1020 1021 1022 1023 1024 1025 1026 | */ struct Fetch { SqlCursor *pCursor; /* Cursor used by the fetch */ int isBackwards; /* Cursor moves backwards if true, forward if false */ int doRewind; /* True to rewind cursor before starting */ }; /* ** A NameContext defines a context in which to resolve table and column ** names. The context consists of a list of tables (the pSrcList) field and ** a list of named expression (pEList). The named expression list may ** be NULL. The pSrc corresponds to the FROM clause of a SELECT or ** to the table being operated on by INSERT, UPDATE, or DELETE. The ** pEList corresponds to the result set of a SELECT and is NULL for ** other statements. ** ** NameContexts can be nested. When resolving names, the inner-most ** context is searched first. If no match is found, the next outer ** context is checked. If there is still no match, the next context ** is checked. This process continues until either a match is found ** or all contexts are check. When a match is found, the nRef member of ** the context containing the match is incremented. ** ** Each subquery gets a new NameContext. The pNext field points to the ** NameContext in the parent query. Thus the process of scanning the ** NameContext list corresponds to searching through successively outer ** subqueries looking for a match. */ struct NameContext { Parse *pParse; /* The parser */ SrcList *pSrcList; /* One or more tables used to resolve names */ ExprList *pEList; /* Optional list of named expressions */ int nRef; /* Number of names resolved by this context */ int nErr; /* Number of errors encountered while resolving names */ u8 allowAgg; /* Aggregate functions allowed here */ u8 hasAgg; int nDepth; /* Depth of subquery recursion. 1 for no recursion */ NameContext *pNext; /* Next outer name context. NULL for outermost */ }; /* ** An instance of the following structure contains all information ** needed to generate code for a single SELECT statement. ** ** nLimit is set to -1 if there is no LIMIT clause. nOffset is set to 0. ** If there is a LIMIT clause, the parser sets nLimit to the value of the ** limit and nOffset to the value of the offset (or 0 if there is not |
︙ | ︙ | |||
1003 1004 1005 1006 1007 1008 1009 1010 1011 1012 1013 1014 1015 1016 | Expr *pHaving; /* The HAVING clause */ ExprList *pOrderBy; /* The ORDER BY clause */ Select *pPrior; /* Prior select in a compound select statement */ int nLimit, nOffset; /* LIMIT and OFFSET values. -1 means not used */ int iLimit, iOffset; /* Memory registers holding LIMIT & OFFSET counters */ IdList **ppOpenTemp; /* OP_OpenTemp addresses used by multi-selects */ Fetch *pFetch; /* If this stmt is part of a FETCH command */ }; /* ** The results of a select can be distributed in several ways. */ #define SRT_Callback 1 /* Invoke a callback with each row of result */ #define SRT_Mem 2 /* Store result in a memory cell */ | > > | 1037 1038 1039 1040 1041 1042 1043 1044 1045 1046 1047 1048 1049 1050 1051 1052 | Expr *pHaving; /* The HAVING clause */ ExprList *pOrderBy; /* The ORDER BY clause */ Select *pPrior; /* Prior select in a compound select statement */ int nLimit, nOffset; /* LIMIT and OFFSET values. -1 means not used */ int iLimit, iOffset; /* Memory registers holding LIMIT & OFFSET counters */ IdList **ppOpenTemp; /* OP_OpenTemp addresses used by multi-selects */ Fetch *pFetch; /* If this stmt is part of a FETCH command */ u8 isResolved; /* True once sqlite3SelectResolve() has run. */ u8 isAgg; /* True if this is an aggregate query */ }; /* ** The results of a select can be distributed in several ways. */ #define SRT_Callback 1 /* Invoke a callback with each row of result */ #define SRT_Mem 2 /* Store result in a memory cell */ |
︙ | ︙ | |||
1072 1073 1074 1075 1076 1077 1078 1079 1080 1081 1082 1083 1084 1085 1086 1087 | int nTab; /* Number of previously allocated VDBE cursors */ int nMem; /* Number of memory cells used so far */ int nSet; /* Number of sets used so far */ u32 cookieMask; /* Bitmask of schema verified databases */ int cookieValue[MAX_ATTACHED+2]; /* Values of cookies to verify */ int cookieGoto; /* Address of OP_Goto to cookie verifier subroutine */ u32 writeMask; /* Start a write transaction on these databases */ /* Above is constant between recursions. Below is reset before and after ** each recursion */ int nVar; /* Number of '?' variables seen in the SQL so far */ int nVarExpr; /* Number of used slots in apVarExpr[] */ int nVarExprAlloc; /* Number of allocated slots in apVarExpr[] */ Expr **apVarExpr; /* Pointers to :aaa and $aaaa wildcard expressions */ u8 explain; /* True if the EXPLAIN flag is found on the query */ | > > < < < < > > > | 1108 1109 1110 1111 1112 1113 1114 1115 1116 1117 1118 1119 1120 1121 1122 1123 1124 1125 1126 1127 1128 1129 1130 1131 1132 1133 1134 1135 1136 1137 1138 1139 1140 1141 1142 1143 1144 1145 1146 1147 1148 1149 | int nTab; /* Number of previously allocated VDBE cursors */ int nMem; /* Number of memory cells used so far */ int nSet; /* Number of sets used so far */ u32 cookieMask; /* Bitmask of schema verified databases */ int cookieValue[MAX_ATTACHED+2]; /* Values of cookies to verify */ int cookieGoto; /* Address of OP_Goto to cookie verifier subroutine */ u32 writeMask; /* Start a write transaction on these databases */ u8 useAgg; /* If true, extract field values from the aggregator ** while generating expressions. Normally false */ /* Above is constant between recursions. Below is reset before and after ** each recursion */ int nVar; /* Number of '?' variables seen in the SQL so far */ int nVarExpr; /* Number of used slots in apVarExpr[] */ int nVarExprAlloc; /* Number of allocated slots in apVarExpr[] */ Expr **apVarExpr; /* Pointers to :aaa and $aaaa wildcard expressions */ u8 explain; /* True if the EXPLAIN flag is found on the query */ #ifndef SQLITE_OMIT_CURSOR u8 fetchDir; /* The direction argument to the FETCH command */ int dirArg1; /* First argument to the direction */ int dirArg2; /* Second argument to the direction */ #endif Token sErrToken; /* The token at which the error occurred */ Token sNameToken; /* Token with unqualified schema object name */ Token sLastToken; /* The last token parsed */ const char *zSql; /* All SQL text */ const char *zTail; /* All SQL text past the last semicolon parsed */ Table *pNewTable; /* A table being constructed by CREATE TABLE */ Trigger *pNewTrigger; /* Trigger under construct by a CREATE TRIGGER */ TriggerStack *trigStack; /* Trigger actions being coded */ const char *zAuthContext; /* The 6th parameter to db->xAuth callbacks */ int nAgg; /* Number of aggregate expressions */ AggExpr *aAgg; /* An array of aggregate expressions */ int nMaxDepth; /* Maximum depth of subquery recursion */ }; /* ** An instance of the following structure can be declared on a stack and used ** to save the Parse.zAuthContext value so that it can be restored later. */ struct AuthContext { |
︙ | ︙ | |||
1271 1272 1273 1274 1275 1276 1277 | ** from sqlite3Init and OP_ParseSchema into the sqlite3InitCallback. */ typedef struct { sqlite3 *db; /* The database being initialized */ char **pzErrMsg; /* Error message stored here */ } InitData; | < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < | 1308 1309 1310 1311 1312 1313 1314 1315 1316 1317 1318 1319 1320 1321 | ** from sqlite3Init and OP_ParseSchema into the sqlite3InitCallback. */ typedef struct { sqlite3 *db; /* The database being initialized */ char **pzErrMsg; /* Error message stored here */ } InitData; /* ** Each SQL cursor (a cursor created by the DECLARE ... CURSOR syntax) ** is represented by an instance of the following structure. */ struct SqlCursor { char *zName; /* Name of this cursor */ int idx; /* Index of this cursor in db->apSqlCursor[] */ |
︙ | ︙ | |||
1409 1410 1411 1412 1413 1414 1415 | void sqlite3IdListDelete(IdList*); void sqlite3SrcListDelete(SrcList*); void sqlite3CreateIndex(Parse*,Token*,Token*,SrcList*,ExprList*,int,Token*, Token*); void sqlite3DropIndex(Parse*, SrcList*); void sqlite3AddKeyType(Vdbe*, ExprList*); void sqlite3AddIdxKeyType(Vdbe*, Index*); | | < | 1414 1415 1416 1417 1418 1419 1420 1421 1422 1423 1424 1425 1426 1427 1428 | void sqlite3IdListDelete(IdList*); void sqlite3SrcListDelete(SrcList*); void sqlite3CreateIndex(Parse*,Token*,Token*,SrcList*,ExprList*,int,Token*, Token*); void sqlite3DropIndex(Parse*, SrcList*); void sqlite3AddKeyType(Vdbe*, ExprList*); void sqlite3AddIdxKeyType(Vdbe*, Index*); int sqlite3Select(Parse*, Select*, int, int, Select*, int, int*, char *aff); Select *sqlite3SelectNew(ExprList*,SrcList*,Expr*,ExprList*,Expr*,ExprList*, int,int,int); void sqlite3SelectDelete(Select*); void sqlite3SelectUnbind(Select*); Table *sqlite3SrcListLookup(Parse*, SrcList*); int sqlite3IsReadOnly(Parse*, Table*, int); void sqlite3OpenTableForReading(Vdbe*, int iCur, Table*); |
︙ | ︙ | |||
1440 1441 1442 1443 1444 1445 1446 | void sqlite3UnlinkAndDeleteIndex(sqlite3*,int,const char*); void sqlite3Vacuum(Parse*, Token*); int sqlite3RunVacuum(char**, sqlite3*); char *sqlite3NameFromToken(Token*); int sqlite3ExprCheck(Parse*, Expr*, int, int*); int sqlite3ExprCompare(Expr*, Expr*); int sqliteFuncId(Token*); | | < | 1444 1445 1446 1447 1448 1449 1450 1451 1452 1453 1454 1455 1456 1457 1458 | void sqlite3UnlinkAndDeleteIndex(sqlite3*,int,const char*); void sqlite3Vacuum(Parse*, Token*); int sqlite3RunVacuum(char**, sqlite3*); char *sqlite3NameFromToken(Token*); int sqlite3ExprCheck(Parse*, Expr*, int, int*); int sqlite3ExprCompare(Expr*, Expr*); int sqliteFuncId(Token*); int sqlite3ExprResolveNames(NameContext *, Expr *); int sqlite3ExprAnalyzeAggregates(Parse*, Expr*); Vdbe *sqlite3GetVdbe(Parse*); void sqlite3Randomness(int, void*); void sqlite3RollbackAll(sqlite3*); void sqlite3CodeVerifySchema(Parse*, int); void sqlite3BeginTransaction(Parse*, int); void sqlite3CommitTransaction(Parse*); |
︙ | ︙ | |||
1569 1570 1571 1572 1573 1574 1575 1576 1577 1578 1579 1580 1581 1582 1583 1584 | extern const unsigned char sqlite3UpperToLower[]; void sqlite3RootPageMoved(Db*, int, int); void sqlite3Reindex(Parse*, Token*, Token*); void sqlite3AlterRenameTable(Parse*, SrcList*, Token*); int sqlite3GetToken(const unsigned char *, int *); void sqlite3NestedParse(Parse*, const char*, ...); void sqlite3ExpirePreparedStatements(sqlite3*); #ifndef SQLITE_OMIT_CURSOR void sqlite3CursorDelete(SqlCursor*); void sqlite3CursorCreate(Parse*, Token*, Select*); void sqlite3CursorClose(Parse*, Token*); void sqlite3Fetch(Parse*, Token*, IdList*); #endif /* SQLITE_OMIT_CURSOR */ #endif | > > | 1572 1573 1574 1575 1576 1577 1578 1579 1580 1581 1582 1583 1584 1585 1586 1587 1588 1589 | extern const unsigned char sqlite3UpperToLower[]; void sqlite3RootPageMoved(Db*, int, int); void sqlite3Reindex(Parse*, Token*, Token*); void sqlite3AlterRenameTable(Parse*, SrcList*, Token*); int sqlite3GetToken(const unsigned char *, int *); void sqlite3NestedParse(Parse*, const char*, ...); void sqlite3ExpirePreparedStatements(sqlite3*); void sqlite3CodeSubselect(Parse *, Expr *); int sqlite3SelectResolve(Parse *, Select *, NameContext *); #ifndef SQLITE_OMIT_CURSOR void sqlite3CursorDelete(SqlCursor*); void sqlite3CursorCreate(Parse*, Token*, Select*); void sqlite3CursorClose(Parse*, Token*); void sqlite3Fetch(Parse*, Token*, IdList*); #endif /* SQLITE_OMIT_CURSOR */ #endif |
Changes to src/trigger.c.
︙ | ︙ | |||
636 637 638 639 640 641 642 | orconf = (orconfin == OE_Default)?pTriggerStep->orconf:orconfin; pParse->trigStack->orconf = orconf; switch( pTriggerStep->op ){ case TK_SELECT: { Select * ss = sqlite3SelectDup(pTriggerStep->pSelect); assert(ss); assert(ss->pSrc); | > | | 636 637 638 639 640 641 642 643 644 645 646 647 648 649 650 651 | orconf = (orconfin == OE_Default)?pTriggerStep->orconf:orconfin; pParse->trigStack->orconf = orconf; switch( pTriggerStep->op ){ case TK_SELECT: { Select * ss = sqlite3SelectDup(pTriggerStep->pSelect); assert(ss); assert(ss->pSrc); sqlite3SelectResolve(pParse, ss, 0); sqlite3Select(pParse, ss, SRT_Discard, 0, 0, 0, 0, 0); sqlite3SelectDelete(ss); break; } case TK_UPDATE: { SrcList *pSrc; pSrc = targetSrcList(pParse, pTriggerStep); sqlite3VdbeAddOp(v, OP_ResetCount, 0, 0); |
︙ | ︙ | |||
740 741 742 743 744 745 746 | !checkColumnOverLap(pTrigger->pColumns, pChanges) ){ fire_this = 0; } } if( fire_this ){ int endTrigger; | < > > | | | 741 742 743 744 745 746 747 748 749 750 751 752 753 754 755 756 757 758 759 760 761 762 763 764 765 766 767 768 769 770 771 772 773 774 775 | !checkColumnOverLap(pTrigger->pColumns, pChanges) ){ fire_this = 0; } } if( fire_this ){ int endTrigger; Expr * whenExpr; AuthContext sContext; NameContext sNC; memset(&sNC, 0, sizeof(sNC)); sNC.pParse = pParse; /* Push an entry on to the trigger stack */ trigStackEntry.pTrigger = pTrigger; trigStackEntry.newIdx = newIdx; trigStackEntry.oldIdx = oldIdx; trigStackEntry.pTab = pTab; trigStackEntry.pNext = pParse->trigStack; trigStackEntry.ignoreJump = ignoreJump; pParse->trigStack = &trigStackEntry; sqlite3AuthContextPush(pParse, &sContext, pTrigger->name); /* code the WHEN clause */ endTrigger = sqlite3VdbeMakeLabel(pParse->pVdbe); whenExpr = sqlite3ExprDup(pTrigger->pWhen); if( sqlite3ExprResolveNames(&sNC, whenExpr) ){ pParse->trigStack = trigStackEntry.pNext; sqlite3ExprDelete(whenExpr); return 1; } sqlite3ExprIfFalse(pParse, whenExpr, endTrigger, 1); sqlite3ExprDelete(whenExpr); |
︙ | ︙ |
Changes to src/update.c.
︙ | ︙ | |||
8 9 10 11 12 13 14 | ** May you find forgiveness for yourself and forgive others. ** May you share freely, never taking more than you give. ** ************************************************************************* ** This file contains C code routines that are called by the parser ** to handle UPDATE statements. ** | | | 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 | ** May you find forgiveness for yourself and forgive others. ** May you share freely, never taking more than you give. ** ************************************************************************* ** This file contains C code routines that are called by the parser ** to handle UPDATE statements. ** ** $Id: update.c,v 1.104 2005/01/29 08:32:45 danielk1977 Exp $ */ #include "sqliteInt.h" /* ** Process an UPDATE statement. ** ** UPDATE OR IGNORE table_wxyz SET a=b, c=d WHERE e<5 AND f NOT NULL; |
︙ | ︙ | |||
45 46 47 48 49 50 51 52 53 54 55 56 57 58 | int *aXRef = 0; /* aXRef[i] is the index in pChanges->a[] of the ** an expression for the i-th column of the table. ** aXRef[i]==-1 if the i-th column is not changed. */ int chngRecno; /* True if the record number is being changed */ Expr *pRecnoExpr = 0; /* Expression defining the new record number */ int openAll = 0; /* True if all indices need to be opened */ AuthContext sContext; /* The authorization context */ #ifndef SQLITE_OMIT_TRIGGER int isView; /* Trying to update a view */ int triggers_exist = 0; /* True if any row triggers exist */ #endif int newIdx = -1; /* index of trigger "new" temp table */ | > | 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 | int *aXRef = 0; /* aXRef[i] is the index in pChanges->a[] of the ** an expression for the i-th column of the table. ** aXRef[i]==-1 if the i-th column is not changed. */ int chngRecno; /* True if the record number is being changed */ Expr *pRecnoExpr = 0; /* Expression defining the new record number */ int openAll = 0; /* True if all indices need to be opened */ AuthContext sContext; /* The authorization context */ NameContext sNC; /* The name-context to resolve expressions in */ #ifndef SQLITE_OMIT_TRIGGER int isView; /* Trying to update a view */ int triggers_exist = 0; /* True if any row triggers exist */ #endif int newIdx = -1; /* index of trigger "new" temp table */ |
︙ | ︙ | |||
108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 | ** need to occur right after the database cursor. So go ahead and ** allocate enough space, just in case. */ pTabList->a[0].iCursor = iCur = pParse->nTab++; for(pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext){ pParse->nTab++; } /* Resolve the column names in all the expressions of the ** of the UPDATE statement. Also find the column index ** for each column to be updated in the pChanges array. For each ** column to be updated, make sure we have authorization to change ** that column. */ chngRecno = 0; for(i=0; i<pChanges->nExpr; i++){ | > > > > > | < | 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 | ** need to occur right after the database cursor. So go ahead and ** allocate enough space, just in case. */ pTabList->a[0].iCursor = iCur = pParse->nTab++; for(pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext){ pParse->nTab++; } /* Initialize the name-context */ memset(&sNC, 0, sizeof(sNC)); sNC.pParse = pParse; sNC.pSrcList = pTabList; /* Resolve the column names in all the expressions of the ** of the UPDATE statement. Also find the column index ** for each column to be updated in the pChanges array. For each ** column to be updated, make sure we have authorization to change ** that column. */ chngRecno = 0; for(i=0; i<pChanges->nExpr; i++){ if( sqlite3ExprResolveNames(&sNC, pChanges->a[i].pExpr) ){ goto update_cleanup; } for(j=0; j<pTab->nCol; j++){ if( sqlite3StrICmp(pTab->aCol[j].zName, pChanges->a[i].zName)==0 ){ if( j==pTab->iPKey ){ chngRecno = 1; pRecnoExpr = pChanges->a[i].pExpr; |
︙ | ︙ | |||
194 195 196 197 198 199 200 | aIdxUsed[j] = 0; } } /* Resolve the column names in all the expressions in the ** WHERE clause. */ | | | 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 | aIdxUsed[j] = 0; } } /* Resolve the column names in all the expressions in the ** WHERE clause. */ if( sqlite3ExprResolveNames(&sNC, pWhere) ){ goto update_cleanup; } /* Start the view context */ if( isView ){ sqlite3AuthContextPush(pParse, &sContext, pTab->zName); |
︙ | ︙ | |||
217 218 219 220 221 222 223 | /* If we are trying to update a view, construct that view into ** a temporary table. */ if( isView ){ Select *pView; pView = sqlite3SelectDup(pTab->pSelect); | | | 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 | /* If we are trying to update a view, construct that view into ** a temporary table. */ if( isView ){ Select *pView; pView = sqlite3SelectDup(pTab->pSelect); sqlite3Select(pParse, pView, SRT_TempTable, iCur, 0, 0, 0, 0); sqlite3SelectDelete(pView); } /* Begin the database scan */ pWInfo = sqlite3WhereBegin(pParse, pTabList, pWhere, 0, 0); if( pWInfo==0 ) goto update_cleanup; |
︙ | ︙ |
Changes to src/vdbe.c.
︙ | ︙ | |||
39 40 41 42 43 44 45 | ** ** Various scripts scan this source file in order to generate HTML ** documentation, headers files, or other derived files. The formatting ** of the code in this file is, therefore, important. See other comments ** in this file for details. If in doubt, do not deviate from existing ** commenting and indentation practices when changing or adding code. ** | | | 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 | ** ** Various scripts scan this source file in order to generate HTML ** documentation, headers files, or other derived files. The formatting ** of the code in this file is, therefore, important. See other comments ** in this file for details. If in doubt, do not deviate from existing ** commenting and indentation practices when changing or adding code. ** ** $Id: vdbe.c,v 1.449 2005/01/29 08:32:45 danielk1977 Exp $ */ #include "sqliteInt.h" #include "os.h" #include <ctype.h> #include "vdbeInt.h" /* |
︙ | ︙ | |||
3952 3953 3954 3955 3956 3957 3958 3959 3960 3961 3962 3963 3964 3965 | case OP_ListReset: { if( p->pList ){ sqlite3VdbeKeylistFree(p->pList); p->pList = 0; } break; } #ifndef SQLITE_OMIT_TRIGGER /* Opcode: ContextPush * * * ** ** Save the current Vdbe context such that it can be restored by a ContextPop ** opcode. The context stores the last insert row id, the last statement change ** count, and the current statement change count. | > > > > > > > > > > > > > > > > > > > > > > > > > | 3952 3953 3954 3955 3956 3957 3958 3959 3960 3961 3962 3963 3964 3965 3966 3967 3968 3969 3970 3971 3972 3973 3974 3975 3976 3977 3978 3979 3980 3981 3982 3983 3984 3985 3986 3987 3988 3989 3990 | case OP_ListReset: { if( p->pList ){ sqlite3VdbeKeylistFree(p->pList); p->pList = 0; } break; } #ifndef SQLITE_OMIT_SUBQUERY /* Opcode: AggContextPush * * * ** ** Save the state of the current aggregator. It is restored an ** AggContextPop opcode. ** */ case OP_AggContextPush: { p->pAgg++; assert( p->pAgg<&p->apAgg[p->nAgg] ); break; } /* Opcode: AggContextPop * * * ** ** Restore the aggregator to the state it was in when AggContextPush ** was last called. Any data in the current aggregator is deleted. */ case OP_AggContextPop: { p->pAgg--; assert( p->pAgg>=p->apAgg ); break; } #endif #ifndef SQLITE_OMIT_TRIGGER /* Opcode: ContextPush * * * ** ** Save the current Vdbe context such that it can be restored by a ContextPop ** opcode. The context stores the last insert row id, the last statement change ** count, and the current statement change count. |
︙ | ︙ | |||
4181 4182 4183 4184 4185 4186 4187 | pc = pOp->p2 - 1; } break; } /* Opcode: AggReset P1 P2 P3 ** | | | | | | | | | | | | | 4206 4207 4208 4209 4210 4211 4212 4213 4214 4215 4216 4217 4218 4219 4220 4221 4222 4223 4224 4225 4226 4227 4228 4229 4230 4231 4232 4233 4234 4235 4236 4237 4238 4239 4240 4241 4242 4243 4244 4245 4246 4247 4248 4249 4250 4251 4252 4253 4254 4255 | pc = pOp->p2 - 1; } break; } /* Opcode: AggReset P1 P2 P3 ** ** Reset the current aggregator context so that it no longer contains any ** data. Future aggregator elements will contain P2 values each and be sorted ** using the KeyInfo structure pointed to by P3. ** ** If P1 is non-zero, then only a single aggregator row is available (i.e. ** there is no GROUP BY expression). In this case it is illegal to invoke ** OP_AggFocus. */ case OP_AggReset: { assert( !pOp->p3 || pOp->p3type==P3_KEYINFO ); if( pOp->p1 ){ rc = sqlite3VdbeAggReset(0, p->pAgg, (KeyInfo *)pOp->p3); p->pAgg->nMem = pOp->p2; /* Agg.nMem is used by AggInsert() */ rc = AggInsert(p->pAgg, 0, 0); }else{ rc = sqlite3VdbeAggReset(db, p->pAgg, (KeyInfo *)pOp->p3); p->pAgg->nMem = pOp->p2; } if( rc!=SQLITE_OK ){ goto abort_due_to_error; } p->pAgg->apFunc = sqliteMalloc( p->pAgg->nMem*sizeof(p->pAgg->apFunc[0]) ); if( p->pAgg->apFunc==0 ) goto no_mem; break; } /* Opcode: AggInit * P2 P3 ** ** Initialize the function parameters for an aggregate function. ** The aggregate will operate out of aggregate column P2. ** P3 is a pointer to the FuncDef structure for the function. */ case OP_AggInit: { int i = pOp->p2; assert( i>=0 && i<p->pAgg->nMem ); p->pAgg->apFunc[i] = (FuncDef*)pOp->p3; break; } /* Opcode: AggFunc * P2 P3 ** ** Execute the step function for an aggregate. The ** function has P2 arguments. P3 is a pointer to the FuncDef |
︙ | ︙ | |||
4251 4252 4253 4254 4255 4256 4257 | assert( apVal || n==0 ); for(i=0; i<n; i++, pRec++){ apVal[i] = pRec; storeTypeInfo(pRec, db->enc); } i = pTos->i; | | | | 4276 4277 4278 4279 4280 4281 4282 4283 4284 4285 4286 4287 4288 4289 4290 4291 4292 | assert( apVal || n==0 ); for(i=0; i<n; i++, pRec++){ apVal[i] = pRec; storeTypeInfo(pRec, db->enc); } i = pTos->i; assert( i>=0 && i<p->pAgg->nMem ); ctx.pFunc = (FuncDef*)pOp->p3; pMem = &p->pAgg->pCurrent->aMem[i]; ctx.s.z = pMem->zShort; /* Space used for small aggregate contexts */ ctx.pAgg = pMem->z; ctx.cnt = ++pMem->i; ctx.isError = 0; ctx.pColl = 0; if( ctx.pFunc->needCollSeq ){ assert( pOp>p->aOp ); |
︙ | ︙ | |||
4297 4298 4299 4300 4301 4302 4303 | char *zKey; int nKey; int res; assert( pTos>=p->aStack ); Stringify(pTos, db->enc); zKey = pTos->z; nKey = pTos->n; | | | | | | | | | | | | | | | | 4322 4323 4324 4325 4326 4327 4328 4329 4330 4331 4332 4333 4334 4335 4336 4337 4338 4339 4340 4341 4342 4343 4344 4345 4346 4347 4348 4349 4350 4351 4352 4353 4354 4355 4356 4357 4358 4359 4360 4361 4362 4363 4364 4365 4366 4367 4368 4369 4370 4371 4372 4373 4374 4375 4376 4377 4378 4379 4380 4381 4382 4383 4384 4385 4386 4387 4388 4389 4390 4391 4392 4393 4394 4395 4396 4397 4398 | char *zKey; int nKey; int res; assert( pTos>=p->aStack ); Stringify(pTos, db->enc); zKey = pTos->z; nKey = pTos->n; assert( p->pAgg->pBtree ); assert( p->pAgg->pCsr ); rc = sqlite3BtreeMoveto(p->pAgg->pCsr, zKey, nKey, &res); if( rc!=SQLITE_OK ){ goto abort_due_to_error; } if( res==0 ){ rc = sqlite3BtreeData(p->pAgg->pCsr, 0, sizeof(AggElem*), (char *)&p->pAgg->pCurrent); pc = pOp->p2 - 1; }else{ rc = AggInsert(p->pAgg, zKey, nKey); } if( rc!=SQLITE_OK ){ goto abort_due_to_error; } Release(pTos); pTos--; break; } /* Opcode: AggSet * P2 * ** ** Move the top of the stack into the P2-th field of the current ** aggregate. String values are duplicated into new memory. */ case OP_AggSet: { AggElem *pFocus; int i = pOp->p2; pFocus = p->pAgg->pCurrent; assert( pTos>=p->aStack ); if( pFocus==0 ) goto no_mem; assert( i>=0 && i<p->pAgg->nMem ); rc = sqlite3VdbeMemMove(&pFocus->aMem[i], pTos); pTos--; break; } /* Opcode: AggGet * P2 * ** ** Push a new entry onto the stack which is a copy of the P2-th field ** of the current aggregate. Strings are not duplicated so ** string values will be ephemeral. */ case OP_AggGet: { AggElem *pFocus; int i = pOp->p2; pFocus = p->pAgg->pCurrent; if( pFocus==0 ){ int res; if( sqlite3_malloc_failed ) goto no_mem; rc = sqlite3BtreeFirst(p->pAgg->pCsr, &res); if( rc!=SQLITE_OK ){ return rc; } if( res!=0 ){ rc = AggInsert(p->pAgg, "", 1); pFocus = p->pAgg->pCurrent; }else{ rc = sqlite3BtreeData(p->pAgg->pCsr, 0, 4, (char *)&pFocus); } } assert( i>=0 && i<p->pAgg->nMem ); pTos++; sqlite3VdbeMemShallowCopy(pTos, &pFocus->aMem[i], MEM_Ephem); if( pTos->flags&MEM_Str ){ sqlite3VdbeChangeEncoding(pTos, db->enc); } break; } |
︙ | ︙ | |||
4384 4385 4386 4387 4388 4389 4390 | ** zero or more AggNext operations. You must not execute an AggFocus ** in between an AggNext and an AggReset. */ case OP_AggNext: { int res; assert( rc==SQLITE_OK ); CHECK_FOR_INTERRUPT; | | | | | | | | | | | | | | 4409 4410 4411 4412 4413 4414 4415 4416 4417 4418 4419 4420 4421 4422 4423 4424 4425 4426 4427 4428 4429 4430 4431 4432 4433 4434 4435 4436 4437 4438 4439 4440 4441 4442 4443 4444 4445 4446 4447 4448 4449 4450 4451 4452 | ** zero or more AggNext operations. You must not execute an AggFocus ** in between an AggNext and an AggReset. */ case OP_AggNext: { int res; assert( rc==SQLITE_OK ); CHECK_FOR_INTERRUPT; if( p->pAgg->searching==0 ){ p->pAgg->searching = 1; if( p->pAgg->pCsr ){ rc = sqlite3BtreeFirst(p->pAgg->pCsr, &res); }else{ res = 0; } }else{ if( p->pAgg->pCsr ){ rc = sqlite3BtreeNext(p->pAgg->pCsr, &res); }else{ res = 1; } } if( rc!=SQLITE_OK ) goto abort_due_to_error; if( res!=0 ){ pc = pOp->p2 - 1; }else{ int i; sqlite3_context ctx; Mem *aMem; if( p->pAgg->pCsr ){ rc = sqlite3BtreeData(p->pAgg->pCsr, 0, sizeof(AggElem*), (char *)&p->pAgg->pCurrent); if( rc!=SQLITE_OK ) goto abort_due_to_error; } aMem = p->pAgg->pCurrent->aMem; for(i=0; i<p->pAgg->nMem; i++){ FuncDef *pFunc = p->pAgg->apFunc[i]; Mem *pMem = &aMem[i]; if( pFunc==0 || pFunc->xFinalize==0 ) continue; ctx.s.flags = MEM_Null; ctx.s.z = pMem->zShort; ctx.pAgg = (void*)pMem->z; ctx.cnt = pMem->i; ctx.pFunc = pFunc; |
︙ | ︙ | |||
4513 4514 4515 4516 4517 4518 4519 | if( !pOp->p1 ){ sqlite3ExpirePreparedStatements(db); }else{ p->expired = 1; } break; } | < | 4538 4539 4540 4541 4542 4543 4544 4545 4546 4547 4548 4549 4550 4551 | if( !pOp->p1 ){ sqlite3ExpirePreparedStatements(db); }else{ p->expired = 1; } break; } /* An other opcode is illegal... */ default: { sqlite3_snprintf(sizeof(zBuf),zBuf,"%d",pOp->opcode); sqlite3SetString(&p->zErrMsg, "unknown opcode ", zBuf, (char*)0); |
︙ | ︙ |
Changes to src/vdbe.h.
︙ | ︙ | |||
11 12 13 14 15 16 17 | ************************************************************************* ** Header file for the Virtual DataBase Engine (VDBE) ** ** This header defines the interface to the virtual database engine ** or VDBE. The VDBE implements an abstract machine that runs a ** simple program to access and modify the underlying database. ** | | | 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 | ************************************************************************* ** Header file for the Virtual DataBase Engine (VDBE) ** ** This header defines the interface to the virtual database engine ** or VDBE. The VDBE implements an abstract machine that runs a ** simple program to access and modify the underlying database. ** ** $Id: vdbe.h,v 1.92 2005/01/29 08:32:45 danielk1977 Exp $ */ #ifndef _SQLITE_VDBE_H_ #define _SQLITE_VDBE_H_ #include <stdio.h> /* ** A single VDBE is an opaque structure named "Vdbe". Only routines |
︙ | ︙ | |||
106 107 108 109 110 111 112 | void sqlite3VdbeChangeP2(Vdbe*, int addr, int P2); void sqlite3VdbeChangeP3(Vdbe*, int addr, const char *zP1, int N); void sqlite3VdbeDequoteP3(Vdbe*, int addr); int sqlite3VdbeFindOp(Vdbe*, int, int, int); VdbeOp *sqlite3VdbeGetOp(Vdbe*, int); int sqlite3VdbeMakeLabel(Vdbe*); void sqlite3VdbeDelete(Vdbe*); | | | 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 | void sqlite3VdbeChangeP2(Vdbe*, int addr, int P2); void sqlite3VdbeChangeP3(Vdbe*, int addr, const char *zP1, int N); void sqlite3VdbeDequoteP3(Vdbe*, int addr); int sqlite3VdbeFindOp(Vdbe*, int, int, int); VdbeOp *sqlite3VdbeGetOp(Vdbe*, int); int sqlite3VdbeMakeLabel(Vdbe*); void sqlite3VdbeDelete(Vdbe*); void sqlite3VdbeMakeReady(Vdbe*,int,int,int,int,int); int sqlite3VdbeFinalize(Vdbe*); void sqlite3VdbeResolveLabel(Vdbe*, int); int sqlite3VdbeCurrentAddr(Vdbe*); void sqlite3VdbeTrace(Vdbe*,FILE*); int sqlite3VdbeReset(Vdbe*); int sqliteVdbeSetVariables(Vdbe*,int,const char**); void sqlite3VdbeSetNumCols(Vdbe*,int); |
︙ | ︙ |
Changes to src/vdbeInt.h.
︙ | ︙ | |||
317 318 319 320 321 322 323 | int nVar; /* Number of entries in aVar[] */ Mem *aVar; /* Values for the OP_Variable opcode. */ char **azVar; /* Name of variables */ int okVar; /* True if azVar[] has been initialized */ int magic; /* Magic number for sanity checking */ int nMem; /* Number of memory locations currently allocated */ Mem *aMem; /* The memory locations */ | | > > | 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 | int nVar; /* Number of entries in aVar[] */ Mem *aVar; /* Values for the OP_Variable opcode. */ char **azVar; /* Name of variables */ int okVar; /* True if azVar[] has been initialized */ int magic; /* Magic number for sanity checking */ int nMem; /* Number of memory locations currently allocated */ Mem *aMem; /* The memory locations */ int nAgg; /* Number of elements in apAgg */ Agg *apAgg; /* Array of aggregate contexts */ Agg *pAgg; /* Current aggregate context */ int nCallback; /* Number of callbacks invoked so far */ Keylist *pList; /* A list of ROWIDs */ int contextStackTop; /* Index of top element in the context stack */ int contextStackDepth; /* The size of the "context" stack */ Context *contextStack; /* Stack used by opcodes ContextPush & ContextPop*/ int pc; /* The program counter */ int rc; /* Value to return */ |
︙ | ︙ |
Changes to src/vdbeaux.c.
︙ | ︙ | |||
582 583 584 585 586 587 588 589 590 591 592 593 594 595 | ** VDBE_MAGIC_RUN. */ void sqlite3VdbeMakeReady( Vdbe *p, /* The VDBE */ int nVar, /* Number of '?' see in the SQL statement */ int nMem, /* Number of memory cells to allocate */ int nCursor, /* Number of cursors to allocate */ int isExplain /* True if the EXPLAIN keywords is present */ ){ int n; assert( p!=0 ); assert( p->magic==VDBE_MAGIC_INIT ); | > | 582 583 584 585 586 587 588 589 590 591 592 593 594 595 596 | ** VDBE_MAGIC_RUN. */ void sqlite3VdbeMakeReady( Vdbe *p, /* The VDBE */ int nVar, /* Number of '?' see in the SQL statement */ int nMem, /* Number of memory cells to allocate */ int nCursor, /* Number of cursors to allocate */ int nAgg, /* Number of aggregate contexts required */ int isExplain /* True if the EXPLAIN keywords is present */ ){ int n; assert( p!=0 ); assert( p->magic==VDBE_MAGIC_INIT ); |
︙ | ︙ | |||
611 612 613 614 615 616 617 618 619 620 621 622 623 624 625 626 627 628 629 630 631 | p->aStack = sqliteMalloc( n*sizeof(p->aStack[0]) /* aStack */ + n*sizeof(Mem*) /* apArg */ + nVar*sizeof(Mem) /* aVar */ + nVar*sizeof(char*) /* azVar */ + nMem*sizeof(Mem) /* aMem */ + nCursor*sizeof(Cursor*) /* apCsr */ ); if( !sqlite3_malloc_failed ){ p->aMem = &p->aStack[n]; p->nMem = nMem; p->aVar = &p->aMem[nMem]; p->nVar = nVar; p->okVar = 0; p->apArg = (Mem**)&p->aVar[nVar]; p->azVar = (char**)&p->apArg[n]; p->apCsr = (Cursor**)&p->azVar[nVar]; p->nCursor = nCursor; for(n=0; n<nVar; n++){ p->aVar[n].flags = MEM_Null; } | > > > > > < < | | > > > | 612 613 614 615 616 617 618 619 620 621 622 623 624 625 626 627 628 629 630 631 632 633 634 635 636 637 638 639 640 641 642 643 644 645 646 647 648 649 650 | p->aStack = sqliteMalloc( n*sizeof(p->aStack[0]) /* aStack */ + n*sizeof(Mem*) /* apArg */ + nVar*sizeof(Mem) /* aVar */ + nVar*sizeof(char*) /* azVar */ + nMem*sizeof(Mem) /* aMem */ + nCursor*sizeof(Cursor*) /* apCsr */ + nAgg*sizeof(Agg) /* Aggregate contexts */ ); if( !sqlite3_malloc_failed ){ p->aMem = &p->aStack[n]; p->nMem = nMem; p->aVar = &p->aMem[nMem]; p->nVar = nVar; p->okVar = 0; p->apArg = (Mem**)&p->aVar[nVar]; p->azVar = (char**)&p->apArg[n]; p->apCsr = (Cursor**)&p->azVar[nVar]; if( nAgg>0 ){ p->nAgg = nAgg; p->apAgg = (Agg*)&p->apCsr[nCursor]; } p->nCursor = nCursor; for(n=0; n<nVar; n++){ p->aVar[n].flags = MEM_Null; } } } p->pAgg = p->apAgg; for(n=0; n<p->nMem; n++){ p->aMem[n].flags = MEM_Null; } #ifdef SQLITE_DEBUG if( (p->db->flags & SQLITE_VdbeListing)!=0 || sqlite3OsFileExists("vdbe_explain") ){ int i; printf("VDBE Program Listing:\n"); |
︙ | ︙ | |||
729 730 731 732 733 734 735 | ** If db is not NULL, then this is being called from with an OP_AggReset ** opcode. Open the temp-table, if it has not already been opened and ** delete the contents of the table used for aggregate information, ready ** for the next round of aggregate processing. */ int sqlite3VdbeAggReset(sqlite3 *db, Agg *pAgg, KeyInfo *pKeyInfo){ int rc = 0; | | > > | 736 737 738 739 740 741 742 743 744 745 746 747 748 749 750 751 752 753 | ** If db is not NULL, then this is being called from with an OP_AggReset ** opcode. Open the temp-table, if it has not already been opened and ** delete the contents of the table used for aggregate information, ready ** for the next round of aggregate processing. */ int sqlite3VdbeAggReset(sqlite3 *db, Agg *pAgg, KeyInfo *pKeyInfo){ int rc = 0; BtCursor *pCsr; if( !pAgg ) return SQLITE_OK; pCsr = pAgg->pCsr; assert( (pCsr && pAgg->nTab>0) || (!pCsr && pAgg->nTab==0) || sqlite3_malloc_failed ); /* If pCsr is not NULL, then the table used for aggregate information ** is open. Loop through it and free the AggElem* structure pointed at ** by each entry. If the finalizer has not been called for an AggElem, ** do that too. Finally, clear the btree table itself. |
︙ | ︙ | |||
882 883 884 885 886 887 888 | if( p->contextStack ){ for(i=0; i<p->contextStackTop; i++){ sqlite3VdbeKeylistFree(p->contextStack[i].pList); } sqliteFree(p->contextStack); } sqlite3VdbeSorterReset(p); | > | > | 891 892 893 894 895 896 897 898 899 900 901 902 903 904 905 906 907 | if( p->contextStack ){ for(i=0; i<p->contextStackTop; i++){ sqlite3VdbeKeylistFree(p->contextStack[i].pList); } sqliteFree(p->contextStack); } sqlite3VdbeSorterReset(p); for(i=0; i<p->nAgg; i++){ sqlite3VdbeAggReset(0, &p->apAgg[i], 0); } p->contextStack = 0; p->contextStackDepth = 0; p->contextStackTop = 0; sqliteFree(p->zErrMsg); p->zErrMsg = 0; } |
︙ | ︙ |
Changes to src/where.c.
︙ | ︙ | |||
12 13 14 15 16 17 18 | ** This module contains C code that generates VDBE code used to process ** the WHERE clause of SQL statements. This module is reponsible for ** generating the code that loops through a table looking for applicable ** rows. Indices are selected and used to speed the search when doing ** so is applicable. Because this module is responsible for selecting ** indices, you might also think of this module as the "query optimizer". ** | | | 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 | ** This module contains C code that generates VDBE code used to process ** the WHERE clause of SQL statements. This module is reponsible for ** generating the code that loops through a table looking for applicable ** rows. Indices are selected and used to speed the search when doing ** so is applicable. Because this module is responsible for selecting ** indices, you might also think of this module as the "query optimizer". ** ** $Id: where.c,v 1.132 2005/01/29 08:32:45 danielk1977 Exp $ */ #include "sqliteInt.h" /* ** The query generator uses an array of instances of this structure to ** help it analyze the subexpressions of the WHERE clause. Each WHERE ** clause subexpression is separated from the others by an AND operator. |
︙ | ︙ | |||
187 188 189 190 191 192 193 194 195 196 197 198 199 200 | ** In order for this routine to work, the calling function must have ** previously invoked sqlite3ExprResolveNames() on the expression. See ** the header comment on that routine for additional information. ** The sqlite3ExprResolveNames() routines looks for column names and ** sets their opcodes to TK_COLUMN and their Expr.iTable fields to ** the VDBE cursor number of the table. */ static Bitmask exprTableUsage(ExprMaskSet *pMaskSet, Expr *p){ Bitmask mask = 0; if( p==0 ) return 0; if( p->op==TK_COLUMN ){ mask = getMask(pMaskSet, p->iTable); return mask; } | > | | < > | > > > > | > > > | | > > | | | 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 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 | ** In order for this routine to work, the calling function must have ** previously invoked sqlite3ExprResolveNames() on the expression. See ** the header comment on that routine for additional information. ** The sqlite3ExprResolveNames() routines looks for column names and ** sets their opcodes to TK_COLUMN and their Expr.iTable fields to ** the VDBE cursor number of the table. */ static Bitmask exprListTableUsage(ExprMaskSet *, ExprList *); static Bitmask exprTableUsage(ExprMaskSet *pMaskSet, Expr *p){ Bitmask mask = 0; if( p==0 ) return 0; if( p->op==TK_COLUMN ){ mask = getMask(pMaskSet, p->iTable); return mask; } mask = exprTableUsage(pMaskSet, p->pRight); mask |= exprTableUsage(pMaskSet, p->pLeft); mask |= exprListTableUsage(pMaskSet, p->pList); if( p->pSelect ){ Select *pS = p->pSelect; mask |= exprListTableUsage(pMaskSet, pS->pEList); mask |= exprListTableUsage(pMaskSet, pS->pGroupBy); mask |= exprListTableUsage(pMaskSet, pS->pOrderBy); mask |= exprTableUsage(pMaskSet, pS->pWhere); mask |= exprTableUsage(pMaskSet, pS->pHaving); } return mask; } static Bitmask exprListTableUsage(ExprMaskSet *pMaskSet, ExprList *pList){ int i; Bitmask mask = 0; if( pList ){ for(i=0; i<pList->nExpr; i++){ mask |= exprTableUsage(pMaskSet, pList->a[i].pExpr); } } return mask; } /* ** Return TRUE if the given operator is one of the operators that is |
︙ | ︙ | |||
475 476 477 478 479 480 481 482 | int brk, /* Jump here to abandon the loop */ WhereLevel *pLevel /* When level of the FROM clause we are working on */ ){ Expr *pX = pTerm->p; if( pX->op!=TK_IN ){ assert( pX->op==TK_EQ ); sqlite3ExprCode(pParse, pX->pRight); }else{ | > | > > > > > | 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 | int brk, /* Jump here to abandon the loop */ WhereLevel *pLevel /* When level of the FROM clause we are working on */ ){ Expr *pX = pTerm->p; if( pX->op!=TK_IN ){ assert( pX->op==TK_EQ ); sqlite3ExprCode(pParse, pX->pRight); #ifndef SQLITE_OMIT_SUBQUERY }else{ int iTab; Vdbe *v = pParse->pVdbe; sqlite3CodeSubselect(pParse, pX); iTab = pX->iTable; sqlite3VdbeAddOp(v, OP_Rewind, iTab, brk); sqlite3VdbeAddOp(v, OP_KeyAsData, iTab, 1); VdbeComment((v, "# %.*s", pX->span.n, pX->span.z)); pLevel->inP2 = sqlite3VdbeAddOp(v, OP_Column, iTab, 0); pLevel->inOp = OP_Next; pLevel->inP1 = iTab; #endif } disableTerm(pLevel, &pTerm->p); } /* ** The number of bits in a Bitmask */ |
︙ | ︙ |
Changes to test/bind.test.
1 2 3 4 5 6 7 8 9 10 11 12 13 | # 2003 September 6 # # The author disclaims copyright to this source code. In place of # a legal notice, here is a blessing: # # May you do good and not evil. # May you find forgiveness for yourself and forgive others. # May you share freely, never taking more than you give. # #*********************************************************************** # This file implements regression tests for SQLite library. The # focus of this script testing the sqlite_bind API. # | | | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 | # 2003 September 6 # # The author disclaims copyright to this source code. In place of # a legal notice, here is a blessing: # # May you do good and not evil. # May you find forgiveness for yourself and forgive others. # May you share freely, never taking more than you give. # #*********************************************************************** # This file implements regression tests for SQLite library. The # focus of this script testing the sqlite_bind API. # # $Id: bind.test,v 1.28 2005/01/29 08:32:46 danielk1977 Exp $ # set testdir [file dirname $argv0] source $testdir/tester.tcl proc sqlite_step {stmt N VALS COLS} { upvar VALS vals |
︙ | ︙ | |||
474 475 476 477 478 479 480 | } 5 do_test bind-10.15 { sqlite3_bind_parameter_index $VM ?4 } 4 do_test bind-10.16 { sqlite3_bind_parameter_name $VM 1 } :abc | | | | | | 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 | } 5 do_test bind-10.15 { sqlite3_bind_parameter_index $VM ?4 } 4 do_test bind-10.16 { sqlite3_bind_parameter_name $VM 1 } :abc do_test bind-10.17 { sqlite3_bind_parameter_name $VM 2 } {} do_test bind-10.18 { sqlite3_bind_parameter_name $VM 3 } {} do_test bind-10.19 { sqlite3_bind_parameter_name $VM 4 } {?4} do_test bind-10.20 { sqlite3_bind_parameter_name $VM 5 } :pqr catch {sqlite3_finalize $VM} # Make sure we catch an unterminated "(" in a Tcl-style variable name # ifcapable tclvar { do_test bind-11.1 { catchsql {SELECT * FROM sqlite_master WHERE name=$abc(123 and sql NOT NULL;} } {1 {unrecognized token: "$abc(123"}} } finish_test |
Changes to test/collate3.test.
1 2 3 4 5 6 7 8 9 10 11 12 13 | # 2001 September 15 # # The author disclaims copyright to this source code. In place of # a legal notice, here is a blessing: # # May you do good and not evil. # May you find forgiveness for yourself and forgive others. # May you share freely, never taking more than you give. # #*********************************************************************** # This file implements regression tests for SQLite library. The # focus of this script is page cache subsystem. # | | | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 | # 2001 September 15 # # The author disclaims copyright to this source code. In place of # a legal notice, here is a blessing: # # May you do good and not evil. # May you find forgiveness for yourself and forgive others. # May you share freely, never taking more than you give. # #*********************************************************************** # This file implements regression tests for SQLite library. The # focus of this script is page cache subsystem. # # $Id: collate3.test,v 1.10 2005/01/29 08:32:46 danielk1977 Exp $ set testdir [file dirname $argv0] source $testdir/tester.tcl # # Tests are organised as follows: # |
︙ | ︙ | |||
127 128 129 130 131 132 133 | do_test collate3-2.8 { catchsql { SELECT DISTINCT c1 FROM collate3t1; } } {1 {no such collation sequence: string_compare}} ifcapable compound { | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 | do_test collate3-2.8 { catchsql { SELECT DISTINCT c1 FROM collate3t1; } } {1 {no such collation sequence: string_compare}} ifcapable compound { do_test collate3-2.9 { catchsql { SELECT c1 FROM collate3t1 UNION SELECT c1 FROM collate3t1; } } {1 {no such collation sequence: string_compare}} do_test collate3-2.10 { catchsql { SELECT c1 FROM collate3t1 EXCEPT SELECT c1 FROM collate3t1; } } {1 {no such collation sequence: string_compare}} do_test collate3-2.11 { catchsql { SELECT c1 FROM collate3t1 INTERSECT SELECT c1 FROM collate3t1; } } {1 {no such collation sequence: string_compare}} do_test collate3-2.12 { catchsql { SELECT c1 FROM collate3t1 UNION ALL SELECT c1 FROM collate3t1; } } {0 {}} do_test collate3-2.13 { catchsql { SELECT 10 UNION ALL SELECT 20 ORDER BY 1 COLLATE string_compare; } } {1 {no such collation sequence: string_compare}} do_test collate3-2.14 { catchsql { SELECT 10 INTERSECT SELECT 20 ORDER BY 1 COLLATE string_compare; } } {1 {no such collation sequence: string_compare}} do_test collate3-2.15 { catchsql { SELECT 10 EXCEPT SELECT 20 ORDER BY 1 COLLATE string_compare; } } {1 {no such collation sequence: string_compare}} do_test collate3-2.16 { catchsql { SELECT 10 UNION SELECT 20 ORDER BY 1 COLLATE string_compare; } } {1 {no such collation sequence: string_compare}} do_test collate3-2.17 { catchsql { SELECT c1 FROM collate3t1 UNION ALL SELECT c1 FROM collate3t1 ORDER BY 1; } } {1 {no such collation sequence: string_compare}} } ;# ifcapable compound # # Create an index that uses a collation sequence then close and # re-open the database without re-registering the collation # sequence. Then check that for the table with the index # * An INSERT fails, |
︙ | ︙ |
Changes to test/insert3.test.
1 2 3 4 5 6 7 8 9 10 11 12 13 | # 2005 January 13 # # The author disclaims copyright to this source code. In place of # a legal notice, here is a blessing: # # May you do good and not evil. # May you find forgiveness for yourself and forgive others. # May you share freely, never taking more than you give. # #*********************************************************************** # This file implements regression tests for SQLite library. The # focus of this file is testing corner cases of the INSERT statement. # | | | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 | # 2005 January 13 # # The author disclaims copyright to this source code. In place of # a legal notice, here is a blessing: # # May you do good and not evil. # May you find forgiveness for yourself and forgive others. # May you share freely, never taking more than you give. # #*********************************************************************** # This file implements regression tests for SQLite library. The # focus of this file is testing corner cases of the INSERT statement. # # $Id: insert3.test,v 1.3 2005/01/29 08:32:46 danielk1977 Exp $ set testdir [file dirname $argv0] source $testdir/tester.tcl # All the tests in this file require trigger support # ifcapable {trigger} { |
︙ | ︙ | |||
54 55 56 57 58 59 60 | } } {5 2 453 1 hello 2} do_test insert3-1.3 { execsql { SELECT * FROM log2 ORDER BY x; } } {hi 1} | > | | | | > | | | | | | | | > | 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 | } } {5 2 453 1 hello 2} do_test insert3-1.3 { execsql { SELECT * FROM log2 ORDER BY x; } } {hi 1} ifcapable compound { do_test insert3-1.4 { execsql { INSERT INTO t1 SELECT * FROM t1; SELECT 'a:', x, y FROM log UNION ALL SELECT 'b:', x, y FROM log2 ORDER BY x; } } {a: 5 4 b: 10 2 b: 20 1 a: 453 2 a: hello 4 b: hi 2 b: world 1} do_test insert3-1.5 { execsql { INSERT INTO t1(a) VALUES('xyz'); SELECT * FROM log ORDER BY x; } } {5 4 453 2 hello 4 xyz 1} } do_test insert3-2.1 { execsql { CREATE TABLE t2( a INTEGER PRIMARY KEY, b DEFAULT 'b', c DEFAULT 'c' |
︙ | ︙ |
Changes to test/misc4.test.
︙ | ︙ | |||
9 10 11 12 13 14 15 | # #*********************************************************************** # This file implements regression tests for SQLite library. # # This file implements tests for miscellanous features that were # left out of other test files. # | | | 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 | # #*********************************************************************** # This file implements regression tests for SQLite library. # # This file implements tests for miscellanous features that were # left out of other test files. # # $Id: misc4.test,v 1.14 2005/01/29 08:32:46 danielk1977 Exp $ set testdir [file dirname $argv0] source $testdir/tester.tcl # Prepare a statement that will create a temporary table. Then do # a rollback. Then try to execute the prepared statement. # |
︙ | ︙ | |||
115 116 117 118 119 120 121 | insert into b values ('+1',4); select a.*, x.* from a, (select key,sum(period) from b group by key) as x where a.key=x.key; } } {01 data01 01 3.0 +1 data+1 +1 7.0} | | > > > > > > > > > > > > > | 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 | insert into b values ('+1',4); select a.*, x.* from a, (select key,sum(period) from b group by key) as x where a.key=x.key; } } {01 data01 01 3.0 +1 data+1 +1 7.0} # This test case tests the same property as misc4-4.1, but it is # a bit smaller which makes it easier to work with while debugging. do_test misc4-4.2 { execsql { CREATE TABLE ab(a TEXT, b TEXT); INSERT INTO ab VALUES('01', '1'); } execsql { select * from ab, (select b from ab) as x where x.b = ab.a; } } {} } # Ticket #1036. When creating tables from a SELECT on a view, use the # short names of columns. # ifcapable view { do_test misc4-5.1 { execsql { |
︙ | ︙ |
Changes to test/select6.test.
︙ | ︙ | |||
8 9 10 11 12 13 14 | # May you share freely, never taking more than you give. # #*********************************************************************** # This file implements regression tests for SQLite library. The # focus of this file is testing SELECT statements that contain # subqueries in their FROM clause. # | | | 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 | # May you share freely, never taking more than you give. # #*********************************************************************** # This file implements regression tests for SQLite library. The # focus of this file is testing SELECT statements that contain # subqueries in their FROM clause. # # $Id: select6.test,v 1.17 2005/01/29 08:32:46 danielk1977 Exp $ set testdir [file dirname $argv0] source $testdir/tester.tcl # Omit this whole file if the library is build without subquery support. ifcapable !subquery { finish_test |
︙ | ︙ | |||
153 154 155 156 157 158 159 | SELECT a.q, a.p, b.r FROM (SELECT count(*) as p , b as q FROM t2 GROUP BY q) AS a, (SELECT max(a) as r, b as s FROM t2 GROUP BY s) as b WHERE a.q=b.s ORDER BY a.q } } {1 1 1 2 2 3 3 4 7 4 8 15 5 5 20} | | | | | 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 | SELECT a.q, a.p, b.r FROM (SELECT count(*) as p , b as q FROM t2 GROUP BY q) AS a, (SELECT max(a) as r, b as s FROM t2 GROUP BY s) as b WHERE a.q=b.s ORDER BY a.q } } {1 1 1 2 2 3 3 4 7 4 8 15 5 5 20} do_test select6-3.1 { execsql2 { SELECT * FROM (SELECT * FROM (SELECT * FROM t1 WHERE x=3)); } } {x 3 y 2} do_test select6-3.2 { execsql { SELECT * FROM (SELECT a.q, a.p, b.r FROM (SELECT count(*) as p , b as q FROM t2 GROUP BY q) AS a, (SELECT max(a) as r, b as s FROM t2 GROUP BY s) as b WHERE a.q=b.s ORDER BY a.q) ORDER BY "a.q" } } {1 1 1 2 2 3 3 4 7 4 8 15 5 5 20} do_test select6-3.3 { execsql { SELECT a,b,a+b FROM (SELECT avg(x) as 'a', avg(y) as 'b' FROM t1) } } {10.5 3.7 14.2} |
︙ | ︙ |
Changes to test/subquery.test.
1 2 3 4 5 6 7 8 9 10 11 12 13 | # 2005 January 19 # # The author disclaims copyright to this source code. In place of # a legal notice, here is a blessing: # # May you do good and not evil. # May you find forgiveness for yourself and forgive others. # May you share freely, never taking more than you give. # #************************************************************************* # This file implements regression tests for SQLite library. The # focus of this script is testing correlated subqueries # | | | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 | # 2005 January 19 # # The author disclaims copyright to this source code. In place of # a legal notice, here is a blessing: # # May you do good and not evil. # May you find forgiveness for yourself and forgive others. # May you share freely, never taking more than you give. # #************************************************************************* # This file implements regression tests for SQLite library. The # focus of this script is testing correlated subqueries # # $Id: subquery.test,v 1.3 2005/01/29 08:32:47 danielk1977 Exp $ # set testdir [file dirname $argv0] source $testdir/tester.tcl ifcapable !subquery { finish_test |
︙ | ︙ | |||
55 56 57 58 59 60 61 | } {3} do_test subquery-1.4 { execsql { SELECT b FROM t1 WHERE NOT EXISTS(SELECT * FROM t2 WHERE y=a) } } {13 31 57} | > > > > > | > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 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 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 | } {3} do_test subquery-1.4 { execsql { SELECT b FROM t1 WHERE NOT EXISTS(SELECT * FROM t2 WHERE y=a) } } {13 31 57} # Simple tests to make sure correlated subqueries in WHERE clauses # are used by the query optimizer correctly. do_test subquery-1.5 { execsql { SELECT a, x FROM t1, t2 WHERE t1.a = (SELECT x); } } {1 1 3 3 5 5 7 7} do_test subquery-1.6 { execsql { CREATE INDEX i1 ON t1(a); SELECT a, x FROM t1, t2 WHERE t1.a = (SELECT x); } } {1 1 3 3 5 5 7 7} do_test subquery-1.7 { execsql { SELECT a, x FROM t2, t1 WHERE t1.a = (SELECT x); } } {1 1 3 3 5 5 7 7} # Try an aggregate in both the subquery and the parent query. do_test subquery-1.6 { execsql { SELECT count(*) FROM t1 WHERE a > (SELECT count(*) FROM t2); } } {2} #------------------------------------------------------------------ # The following test cases - subquery-2.* - are not logically # organized. They're here largely because they were failing during # one stage of development of sub-queries. # do_test subquery-2.1 { execsql { SELECT (SELECT 10); } } {10} do_test subquery-2.2.1 { execsql { CREATE TABLE t3(a PRIMARY KEY, b); INSERT INTO t3 VALUES(1, 2); INSERT INTO t3 VALUES(3, 1); } } {} do_test subquery-2.2.2 { execsql { SELECT * FROM t3 WHERE a IN (SELECT b FROM t3); } } {1 2} do_test subquery-2.2.3 { execsql { DROP TABLE t3; } } {} do_test subquery-2.3.1 { execsql { CREATE TABLE t3(a TEXT); INSERT INTO t3 VALUES('10'); } } {} do_test subquery-2.3.2 { execsql { SELECT a IN (10.0, 20) FROM t3; } } {0} do_test subquery-2.3.3 { execsql { DROP TABLE t3; } } {} do_test subquery-2.4.1 { execsql { CREATE TABLE t3(a TEXT); INSERT INTO t3 VALUES('XX'); } } {} do_test subquery-2.4.2 { execsql { SELECT count(*) FROM t3 WHERE a IN (SELECT 'XX') } } {1} do_test subquery-2.4.3 { execsql { DROP TABLE t3; } } {} do_test subquery-2.5.1 { execsql { CREATE TABLE t3(a INTEGER); INSERT INTO t3 VALUES(10); CREATE TABLE t4(x TEXT); INSERT INTO t4 VALUES('10.0'); } } {} do_test subquery-2.5.2 { execsql { SELECT * FROM t4 WHERE x IN (SELECT a FROM t3); } } {10.0} do_test subquery-2.5.3 { execsql { CREATE INDEX t4i ON t4(x); SELECT * FROM t4 WHERE x IN (SELECT a FROM t3); } } {10.0} do_test subquery-2.5.4 { execsql { DROP TABLE t3; DROP TABLE t4; } } {} #------------------------------------------------------------------ # The following test cases - subquery-3.* - test tickets that # were raised during development of correlated subqueries. # # Ticket 1083 ifcapable view { do_test subquery-3.1 { catchsql { DROP TABLE t1; } catchsql { DROP TABLE t2; } execsql { CREATE TABLE t1(a,b); INSERT INTO t1 VALUES(1,2); CREATE VIEW v1 AS SELECT b FROM t1 WHERE a>0; CREATE TABLE t2(p,q); INSERT INTO t2 VALUES(2,9); SELECT * FROM v1 WHERE EXISTS(SELECT * FROM t2 WHERE p=v1.b); } } {2} } # Ticket 1084 do_test subquery-3.2 { catchsql { CREATE TABLE t1(a,b); INSERT INTO t1 VALUES(1,2); } execsql { SELECT (SELECT t1.a) FROM t1; } } {1} #------------------------------------------------------------------ # These tests - subquery-4.* - use the TCL statement cache to try # and expose bugs to do with re-using statements that have been # passed to sqlite3_reset(). # # One problem was that VDBE memory cells were not being initialised # to NULL on the second and subsequent executions. # do_test subquery-4.1.1 { execsql { SELECT (SELECT a FROM t1); } } {1} do_test subquery-4.2 { execsql { DELETE FROM t1; SELECT (SELECT a FROM t1); } } {{}} do_test subquery-4.2.1 { execsql { CREATE TABLE t3(a PRIMARY KEY); INSERT INTO t3 VALUES(10); } execsql {INSERT INTO t3 VALUES((SELECT max(a) FROM t3)+1)} } {} do_test subquery-4.2.2 { execsql {INSERT INTO t3 VALUES((SELECT max(a) FROM t3)+1)} } {} finish_test |
Changes to test/trigger2.test.
︙ | ︙ | |||
118 119 120 121 122 123 124 | SELECT * FROM clog ORDER BY idx; }] { lappend r [expr {int($v)}] } set r } [list 1 1 2 4 6 10 20 \ 2 1 2 13 24 10 20 \ | | | | 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 | SELECT * FROM clog ORDER BY idx; }] { lappend r [expr {int($v)}] } set r } [list 1 1 2 4 6 10 20 \ 2 1 2 13 24 10 20 \ 3 3 4 13 24 30 40 \ 4 3 4 40 60 30 40 \ 1 1 2 13 24 10 20 ] execsql { DELETE FROM rlog; DELETE FROM tbl; INSERT INTO tbl VALUES (100, 100); INSERT INTO tbl VALUES (300, 200); |
︙ | ︙ |
Changes to test/view.test.
1 2 3 4 5 6 7 8 9 10 11 12 13 | # 2002 February 26 # # The author disclaims copyright to this source code. In place of # a legal notice, here is a blessing: # # May you do good and not evil. # May you find forgiveness for yourself and forgive others. # May you share freely, never taking more than you give. # #*********************************************************************** # This file implements regression tests for SQLite library. The # focus of this file is testing VIEW statements. # | | | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 | # 2002 February 26 # # The author disclaims copyright to this source code. In place of # a legal notice, here is a blessing: # # May you do good and not evil. # May you find forgiveness for yourself and forgive others. # May you share freely, never taking more than you give. # #*********************************************************************** # This file implements regression tests for SQLite library. The # focus of this file is testing VIEW statements. # # $Id: view.test,v 1.23 2005/01/29 08:32:47 danielk1977 Exp $ set testdir [file dirname $argv0] source $testdir/tester.tcl # Omit this entire file if the library is not configured with views enabled. ifcapable !view { finish_test return |
︙ | ︙ | |||
150 151 152 153 154 155 156 | ifcapable compound { do_test view-3.4 { execsql2 { CREATE VIEW v3 AS SELECT a FROM t1 UNION SELECT b FROM t1 ORDER BY b; SELECT * FROM v3 LIMIT 4; } } {b 2 b 3 b 5 b 6} | | | 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 | ifcapable compound { do_test view-3.4 { execsql2 { CREATE VIEW v3 AS SELECT a FROM t1 UNION SELECT b FROM t1 ORDER BY b; SELECT * FROM v3 LIMIT 4; } } {b 2 b 3 b 5 b 6} do_test view-3.5 { execsql2 { CREATE VIEW v4 AS SELECT a, b FROM t1 UNION SELECT b AS 'x', a AS 'y' FROM t1 ORDER BY x, y; SELECT y FROM v4 ORDER BY y LIMIT 4; |
︙ | ︙ |