Fix many problems with manifest types and column affinity. Most things are

working now. (CVS 1392)

FossilOrigin-Name: a62872aacd544a1465b06e007153168663f3c83a
This commit is contained in:
danielk1977 2004-05-18 09:58:06 +00:00
parent eb015e03e1
commit 84ac9d02dd
10 changed files with 354 additions and 190 deletions

View File

@ -1,5 +1,5 @@
C Bugfix\sfor\srow\sformat.\s(CVS\s1391)
D 2004-05-18T01:31:14
C Fix\smany\sproblems\swith\smanifest\stypes\sand\scolumn\saffinity.\sMost\sthings\sare\nworking\snow.\s(CVS\s1392)
D 2004-05-18T09:58:07
F Makefile.in ab7b0d5118e2da97bac66be8684a1034e3500f5a
F Makefile.linux-gcc b86a99c493a5bfb402d1d9178dcdc4bd4b32f906
F README f1de682fbbd94899d50aca13d387d1b3fd3be2dd
@ -26,16 +26,16 @@ F src/auth.c 5c2f0bea4729c98c2be3b69d6b466fc51448fe79
F src/btree.c bf8d9592b66fb9ba89a5be13fd99a7d8b8a67d7f
F src/btree.h 6f51ad0ffebfba71295fcacdbe86007512200050
F src/btree_rb.c 9d7973e266ee6f9c61ce592f68742ce9cd5b10e5
F src/build.c ddb0384afd2c82599b7d2bdefc4878850854931c
F src/build.c 84a9b37700a18db370b9dbb77f1636df5cdf0290
F src/copy.c 4d2038602fd0549d80c59bda27d96f13ea9b5e29
F src/date.c 0eb0a89960bb45c7f7e768748605a7a97b0c8064
F src/delete.c 8cb317fbba81b428301bccf04be1bea22203508b
F src/delete.c a069dcc2ec0cc3487c8ababebc59a429b4556144
F src/encode.c a876af473d1d636faa3dca51c7571f2e007eea37
F src/expr.c d39afb30c76c2f67fb5ffdfe530ed709c5009786
F src/func.c cfbb7096efb58e2857e3b312a8958a12774b625a
F src/hash.c 440c2f8cb373ee1b4e13a0988489c7cd95d55b6f
F src/hash.h 762d95f1e567664d1eafc1687de755626be962fb
F src/insert.c 72d9dd0b2543420a905ada68f098bc6754b8a1ea
F src/insert.c 60cc57b8468749d7e023798b9d7f91eeb4cd279a
F src/main.c 4b82d7e78f4c9799343b02740a5ba9768d5e464d
F src/md5.c 8e39fdae6d8776b87558e91dcc94740c9b635a9c
F src/os.c ddcda92f7fd71b4513c57c1ec797917f206d504e
@ -43,10 +43,10 @@ F src/os.h fbb2f6595fc34fa351830d88fe1c6b85118f0383
F src/pager.c 6ff6b906427d4824099140776cb8768f922f3dc5
F src/pager.h 78a00ac280899bcba1a89dc51585dcae6b7b3253
F src/parse.y d0258aa3cc8b0c5742b07b699d10fa98f3caea7d
F src/pragma.c 2c65f46a520cd3bab49623d68bec0a5afaae5b52
F src/pragma.c fcbd8bc7f2cc1429758a042920e13c8738a6050c
F src/printf.c ef750e8e2398ca7e8b58be991075f08c6a7f0e53
F src/random.c eff68e3f257e05e81eae6c4d50a51eb88beb4ff3
F src/select.c 62431fb1a1021301e35f12f64c325d5f20371393
F src/select.c f376f3beade0e1e4808b3a393c13f5b30baecf74
F src/shell.c 0c4662e13bfbfd3d13b066c5859cc97ad2f95d21
F src/sqlite.h.in 799c5e726296ec7bc20e6407cdf4df0e0bc00c0c
F src/sqliteInt.h ac5fe07df6cf0a4c935e5a88bc14bc620e4f1591
@ -59,14 +59,14 @@ F src/test4.c b3fab9aea7a8940a8a7386ce1c7e2157b09bd296
F src/test5.c eb39aac8fed61bd930b92613cd705c145244074a
F src/tokenize.c e7536dd31205d5afb76c1bdc832dea009c7a3847
F src/trigger.c 8df308e09113410bb895e88a2db65b55490268db
F src/update.c d14a0b0f3b35ea2469dda375e59a1064f02c7c0e
F src/update.c 0cc7291dd0e0f82cf93085e49c973e8ef9e51fd5
F src/utf.c fc799748d43fe1982d157b871e3e420a19c85d4f
F src/util.c f9511ffba78e6cf71a28774c2820d7750b5bacdf
F src/vacuum.c c134702e023db8778e6be59ac0ea7b02315b5476
F src/vdbe.c 8a6b971c130227fc90a6e899afe218277aa29fdd
F src/vdbe.c 5cc6e41f2c9f24bbbf591ca538c097c0f7b41a3d
F src/vdbe.h 94457ca73bae972dc61bca33a4dccc2e6e14e2f8
F src/vdbeInt.h 311c2a046ea419781d0ef331198b7b0a65eebc92
F src/vdbeaux.c 618861394df84d475e574e22b95e6ed1c9453b1d
F src/vdbeaux.c 760105ceedb7bcfcd3f4dbba7a5500321612669b
F src/where.c 5f480219a943b0fed1f6922d2fdbfba8616a9148
F test/all.test 569a92a8ee88f5300c057cc4a8f50fbbc69a3242
F test/attach.test cb9b884344e6cfa5e165965d5b1adea679a24c83
@ -192,7 +192,7 @@ F www/sqlite.tcl 3c83b08cf9f18aa2d69453ff441a36c40e431604
F www/tclsqlite.tcl b9271d44dcf147a93c98f8ecf28c927307abd6da
F www/vdbe.tcl 9b9095d4495f37697fd1935d10e14c6015e80aa1
F www/whentouse.tcl a8335bce47cc2fddb07f19052cb0cb4d9129a8e4
P 202a470f2c1804a96e69f16709d1a92e405971f0
R ffc409e8b16e570dc32c405b3b469d03
P c1745f47ae6597953426c852559c3ba559b5ecd4
R 02c7a45ac0cf509a83f0308e5e2e8fde
U danielk1977
Z 5eff88f75ed7e1dd3ba47379b0123d5b
Z 6d5d78b2c759d8987f601a926f92d5bb

View File

@ -1 +1 @@
c1745f47ae6597953426c852559c3ba559b5ecd4
a62872aacd544a1465b06e007153168663f3c83a

View File

@ -23,7 +23,7 @@
** ROLLBACK
** PRAGMA
**
** $Id: build.c,v 1.186 2004/05/18 01:23:38 danielk1977 Exp $
** $Id: build.c,v 1.187 2004/05/18 09:58:07 danielk1977 Exp $
*/
#include "sqliteInt.h"
#include <ctype.h>
@ -790,7 +790,7 @@ char sqlite3AffinityType(const char *zType, int nType){
for(n=0; n<(nType-2); n++){
for(i=0; i<sizeof(substrings)/sizeof(substrings[0]); i++){
if( 0==sqlite3StrNICmp(zType, substrings[i].zSub, substrings[i].nSub) ){
if( 0==sqlite3StrNICmp(&zType[n], substrings[i].zSub, substrings[i].nSub) ){
return substrings[i].affinity;
}
}
@ -992,7 +992,7 @@ void sqlite3EndTable(Parse *pParse, Token *pEnd, Select *pSelect){
n = Addr(pEnd->z) - Addr(pParse->sFirstToken.z) + 1;
sqlite3VdbeChangeP3(v, -1, pParse->sFirstToken.z, n);
}
sqlite3VdbeAddOp(v, OP_MakeRecord, 5, 0);
sqlite3VdbeOp3(v, OP_MakeRecord, 5, 0, "tttit", P3_STATIC);
sqlite3VdbeAddOp(v, OP_PutIntKey, 0, 0);
if( !p->iDb ){
sqlite3ChangeCookie(db, v);
@ -1002,7 +1002,7 @@ void sqlite3EndTable(Parse *pParse, Token *pEnd, Select *pSelect){
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);
sqlite3Select(pParse, pSelect, SRT_Table, 1, 0, 0, 0, 0);
}
sqlite3EndWriteOperation(pParse);
}
@ -1720,7 +1720,7 @@ void sqlite3CreateIndex(
n = Addr(pEnd->z) - Addr(pStart->z) + 1;
sqlite3VdbeChangeP3(v, addr, pStart->z, n);
}
sqlite3VdbeAddOp(v, OP_MakeRecord, 5, 0);
sqlite3VdbeOp3(v, OP_MakeRecord, 5, 0, "tttit", P3_STATIC);
sqlite3VdbeAddOp(v, OP_PutIntKey, 0, 0);
if( pTable ){
sqlite3VdbeAddOp(v, OP_Integer, pTab->iDb, 0);

View File

@ -12,7 +12,7 @@
** This file contains C code routines that are called by the parser
** to handle DELETE FROM statements.
**
** $Id: delete.c,v 1.66 2004/05/18 01:23:38 danielk1977 Exp $
** $Id: delete.c,v 1.67 2004/05/18 09:58:07 danielk1977 Exp $
*/
#include "sqliteInt.h"
@ -149,7 +149,7 @@ void sqlite3DeleteFrom(
*/
if( isView ){
Select *pView = sqlite3SelectDup(pTab->pSelect);
sqlite3Select(pParse, pView, SRT_TempTable, iCur, 0, 0, 0);
sqlite3Select(pParse, pView, SRT_TempTable, iCur, 0, 0, 0, 0);
sqlite3SelectDelete(pView);
}
@ -213,6 +213,7 @@ void sqlite3DeleteFrom(
*/
if( row_triggers_exist ){
sqlite3VdbeAddOp(v, OP_OpenPseudo, oldIdx, 0);
sqlite3VdbeAddOp(v, OP_SetNumColumns, oldIdx, pTab->nCol);
}
/* Delete every item whose key was written to the list during the

View File

@ -12,7 +12,7 @@
** This file contains C code routines that are called by the parser
** to handle INSERT statements in SQLite.
**
** $Id: insert.c,v 1.101 2004/05/18 01:23:38 danielk1977 Exp $
** $Id: insert.c,v 1.102 2004/05/18 09:58:07 danielk1977 Exp $
*/
#include "sqliteInt.h"
@ -260,7 +260,7 @@ void sqlite3Insert(
iInitCode = sqlite3VdbeAddOp(v, OP_Goto, 0, 0);
iSelectLoop = sqlite3VdbeCurrentAddr(v);
iInsertBlock = sqlite3VdbeMakeLabel(v);
rc = sqlite3Select(pParse, pSelect, SRT_Subroutine, iInsertBlock, 0,0,0);
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);
@ -278,7 +278,7 @@ void sqlite3Insert(
if( row_triggers_exist ){
useTempTable = 1;
}else{
int addr = sqlite3VdbeFindOp(v, OP_OpenRead, pTab->tnum);
int addr = sqlite3VdbeFindOp(v, 0, OP_OpenRead, pTab->tnum);
useTempTable = 0;
if( addr>0 ){
VdbeOp *pOp = sqlite3VdbeGetOp(v, addr-2);
@ -398,6 +398,7 @@ void sqlite3Insert(
*/
if( row_triggers_exist ){
sqlite3VdbeAddOp(v, OP_OpenPseudo, newIdx, 0);
sqlite3VdbeAddOp(v, OP_SetNumColumns, newIdx, pTab->nCol);
}
/* Initialize the count of rows to be inserted

View File

@ -11,7 +11,7 @@
*************************************************************************
** This file contains code used to implement the PRAGMA command.
**
** $Id: pragma.c,v 1.24 2004/05/18 01:23:38 danielk1977 Exp $
** $Id: pragma.c,v 1.25 2004/05/18 09:58:08 danielk1977 Exp $
*/
#include "sqliteInt.h"
#include <ctype.h>
@ -622,11 +622,11 @@ void sqlite3Pragma(Parse *pParse, Token *pLeft, Token *pRight, int minusFlag){
*/
addr = sqlite3VdbeAddOpList(v, ArraySize(checkDb), checkDb);
sqlite3VdbeChangeP1(v, addr+1, i);
sqlite3VdbeChangeP2(v, addr+3, addr+7);
sqlite3VdbeChangeP2(v, addr+6, addr+4);
sqlite3VdbeChangeP2(v, addr+7, i);
sqlite3VdbeChangeP2(v, addr+10, addr+ArraySize(checkDb));
sqlite3VdbeChangeP3(v, addr+13, db->aDb[i].zName, P3_STATIC);
sqlite3VdbeChangeP2(v, addr+4, addr+8);
sqlite3VdbeChangeP2(v, addr+7, addr+5);
sqlite3VdbeChangeP2(v, addr+8, i);
sqlite3VdbeChangeP2(v, addr+11, addr+ArraySize(checkDb));
sqlite3VdbeChangeP3(v, addr+14, db->aDb[i].zName, P3_STATIC);
/* Make sure all the indices are constructed correctly.
*/

View File

@ -12,7 +12,7 @@
** This file contains C code routines that are called by the parser
** to handle SELECT statements in SQLite.
**
** $Id: select.c,v 1.166 2004/05/18 01:23:38 danielk1977 Exp $
** $Id: select.c,v 1.167 2004/05/18 09:58:08 danielk1977 Exp $
*/
#include "sqliteInt.h"
@ -382,7 +382,8 @@ static int selectInnerLoop(
int eDest, /* How to dispose of the results */
int iParm, /* An argument to the disposal method */
int iContinue, /* Jump here to continue with next row */
int iBreak /* Jump here to break out of the inner loop */
int iBreak, /* Jump here to break out of the inner loop */
char *aff /* affinity string if eDest is SRT_Union */
){
Vdbe *v = pParse->pVdbe;
int i;
@ -440,6 +441,7 @@ static int selectInnerLoop(
*/
case SRT_Union: {
sqlite3VdbeAddOp(v, OP_MakeRecord, nColumn, NULL_ALWAYS_DISTINCT);
sqlite3VdbeChangeP3(v, -1, aff, P3_STATIC);
sqlite3VdbeAddOp(v, OP_String, 0, 0);
sqlite3VdbeAddOp(v, OP_PutStrKey, iParm, 0);
break;
@ -467,6 +469,7 @@ static int selectInnerLoop(
case SRT_Except: {
int addr;
addr = sqlite3VdbeAddOp(v, OP_MakeRecord, nColumn, NULL_ALWAYS_DISTINCT);
sqlite3VdbeChangeP3(v, -1, aff, P3_STATIC);
sqlite3VdbeAddOp(v, OP_NotFound, iParm, addr+3);
sqlite3VdbeAddOp(v, OP_Delete, iParm, 0);
break;
@ -491,7 +494,7 @@ static int selectInnerLoop(
char aff = (iParm>>16)&0xFF;
aff = sqlite3CompareAffinity(pEList->a[0].pExpr, aff);
affStr = sqlite3AffinityString(aff);
sqlite3VdbeOp3(v, OP_MakeKey, 1, 1, affStr, P3_STATIC);
sqlite3VdbeOp3(v, OP_MakeKey, 1, 0, affStr, P3_STATIC);
sqlite3VdbeAddOp(v, OP_String, 0, 0);
sqlite3VdbeAddOp(v, OP_PutStrKey, (iParm&0x0000FFFF), 0);
}
@ -612,11 +615,13 @@ static void generateSortTail(
}
case SRT_Subroutine: {
int i;
sqlite3VdbeAddOp(v, OP_Integer, p->pEList->nExpr, 0);
sqlite3VdbeAddOp(v, OP_Pull, 1, 0);
for(i=0; i<nColumn; i++){
sqlite3VdbeAddOp(v, OP_Column, -1-i, i);
}
sqlite3VdbeAddOp(v, OP_Gosub, 0, iParm);
sqlite3VdbeAddOp(v, OP_Pop, 1, 0);
sqlite3VdbeAddOp(v, OP_Pop, 2, 0);
break;
}
default: {
@ -1208,6 +1213,19 @@ static void multiSelectSortOrder(Select *p, ExprList *pOrderBy){
}
}
static void multiSelectAffinity(Select *p, char *zAff){
int i;
if( !p ) return;
multiSelectAffinity(p->pPrior, zAff);
for(i=0; i<p->pEList->nExpr; i++){
if( zAff[i]=='\0' ){
zAff[i] = sqlite3ExprAffinity(p->pEList->a[i].pExpr);
}
}
}
/*
** Compute the iLimit and iOffset fields of the SELECT based on the
** nLimit and nOffset fields. nLimit and nOffset hold the integers
@ -1284,31 +1302,62 @@ static void computeLimitRegisters(Parse *pParse, Select *p){
** Notice that because of the way SQLite parses compound SELECTs, the
** individual selects always group from left to right.
*/
static int multiSelect(Parse *pParse, Select *p, int eDest, int iParm){
int rc; /* Success code from a subroutine */
static int multiSelect(
Parse *pParse,
Select *p,
int eDest,
int iParm,
char *aff /* If eDest is SRT_Union, the affinity string */
){
int rc = SQLITE_OK; /* Success code from a subroutine */
Select *pPrior; /* Another SELECT immediately to our left */
Vdbe *v; /* Generate code to this VDBE */
char *affStr = 0;
if( !aff ){
int len;
rc = fillInColumnList(pParse, p);
if( rc!=SQLITE_OK ){
goto multi_select_end;
}
len = p->pEList->nExpr+1;
affStr = (char *)sqliteMalloc(p->pEList->nExpr+1);
if( !affStr ){
rc = SQLITE_NOMEM;
goto multi_select_end;
}
memset(affStr, (int)SQLITE_AFF_NUMERIC, len-1);
aff = affStr;
}
/* Make sure there is no ORDER BY or LIMIT clause on prior SELECTs. Only
** the last SELECT in the series may have an ORDER BY or LIMIT.
*/
if( p==0 || p->pPrior==0 ) return 1;
if( p==0 || p->pPrior==0 ){
rc = 1;
goto multi_select_end;
}
pPrior = p->pPrior;
if( pPrior->pOrderBy ){
sqlite3ErrorMsg(pParse,"ORDER BY clause should come after %s not before",
selectOpName(p->op));
return 1;
rc = 1;
goto multi_select_end;
}
if( pPrior->nLimit>=0 || pPrior->nOffset>0 ){
sqlite3ErrorMsg(pParse,"LIMIT clause should come after %s not before",
selectOpName(p->op));
return 1;
rc = 1;
goto multi_select_end;
}
/* Make sure we have a valid query engine. If not, create a new one.
*/
v = sqlite3GetVdbe(pParse);
if( v==0 ) return 1;
if( v==0 ){
rc = 1;
goto multi_select_end;
}
/* Create the destination temporary table if necessary
*/
@ -1326,16 +1375,20 @@ static int multiSelect(Parse *pParse, Select *p, int eDest, int iParm){
if( p->pOrderBy==0 ){
pPrior->nLimit = p->nLimit;
pPrior->nOffset = p->nOffset;
rc = sqlite3Select(pParse, pPrior, eDest, iParm, 0, 0, 0);
if( rc ) return rc;
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);
rc = sqlite3Select(pParse, p, eDest, iParm, 0, 0, 0, aff);
p->pPrior = pPrior;
if( rc ) return rc;
if( rc ){
goto multi_select_end;
}
break;
}
/* For UNION ALL ... ORDER BY fall through to the next case */
@ -1361,7 +1414,8 @@ static int multiSelect(Parse *pParse, Select *p, int eDest, int iParm){
unionTab = pParse->nTab++;
if( p->pOrderBy
&& matchOrderbyToColumn(pParse, p, p->pOrderBy, unionTab, 1) ){
return 1;
rc = 1;
goto multi_select_end;
}
if( p->op!=TK_ALL ){
sqlite3VdbeAddOp(v, OP_OpenTemp, unionTab, 1);
@ -1369,12 +1423,18 @@ static int multiSelect(Parse *pParse, Select *p, int eDest, int iParm){
}else{
sqlite3VdbeAddOp(v, OP_OpenTemp, unionTab, 0);
}
assert( p->pEList );
}
/* Code the SELECT statements to our left
*/
rc = sqlite3Select(pParse, pPrior, priorOp, unionTab, 0, 0, 0);
if( rc ) return rc;
rc = sqlite3Select(pParse, pPrior, priorOp, unionTab, 0, 0, 0, aff);
if( rc ){
goto multi_select_end;
}
if( p->op==TK_ALL ){
sqlite3VdbeAddOp(v, OP_SetNumColumns, unionTab, pPrior->pEList->nExpr);
}
/* Code the current SELECT statement
*/
@ -1390,12 +1450,15 @@ static int multiSelect(Parse *pParse, Select *p, int eDest, int iParm){
p->nLimit = -1;
nOffset = p->nOffset;
p->nOffset = 0;
rc = sqlite3Select(pParse, p, op, unionTab, 0, 0, 0);
rc = sqlite3Select(pParse, p, op, unionTab, 0, 0, 0, aff);
p->pPrior = pPrior;
p->pOrderBy = pOrderBy;
p->nLimit = nLimit;
p->nOffset = nOffset;
if( rc ) return rc;
if( rc ){
goto multi_select_end;
}
/* Convert the data in the temporary table into whatever form
** it is that we currently need.
@ -1415,8 +1478,11 @@ static int multiSelect(Parse *pParse, Select *p, int eDest, int iParm){
multiSelectSortOrder(p, p->pOrderBy);
rc = selectInnerLoop(pParse, p, p->pEList, unionTab, p->pEList->nExpr,
p->pOrderBy, -1, eDest, iParm,
iCont, iBreak);
if( rc ) return 1;
iCont, iBreak, 0);
if( rc ){
rc = 1;
goto multi_select_end;
}
sqlite3VdbeResolveLabel(v, iCont);
sqlite3VdbeAddOp(v, OP_Next, unionTab, iStart);
sqlite3VdbeResolveLabel(v, iBreak);
@ -1439,15 +1505,19 @@ static int multiSelect(Parse *pParse, Select *p, int eDest, int iParm){
tab1 = pParse->nTab++;
tab2 = pParse->nTab++;
if( p->pOrderBy && matchOrderbyToColumn(pParse,p,p->pOrderBy,tab1,1) ){
return 1;
rc = 1;
goto multi_select_end;
}
sqlite3VdbeAddOp(v, OP_OpenTemp, tab1, 1);
sqlite3VdbeAddOp(v, OP_KeyAsData, tab1, 1);
assert( p->pEList );
/* Code the SELECTs to our left into temporary table "tab1".
*/
rc = sqlite3Select(pParse, pPrior, SRT_Union, tab1, 0, 0, 0);
if( rc ) return rc;
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"
*/
@ -1458,11 +1528,13 @@ static int multiSelect(Parse *pParse, Select *p, int eDest, int iParm){
p->nLimit = -1;
nOffset = p->nOffset;
p->nOffset = 0;
rc = sqlite3Select(pParse, p, SRT_Union, tab2, 0, 0, 0);
rc = sqlite3Select(pParse, p, SRT_Union, tab2, 0, 0, 0, aff);
p->pPrior = pPrior;
p->nLimit = nLimit;
p->nOffset = nOffset;
if( rc ) return rc;
if( rc ){
goto multi_select_end;
}
/* Generate code to take the intersection of the two temporary
** tables.
@ -1481,8 +1553,11 @@ static int multiSelect(Parse *pParse, Select *p, int eDest, int iParm){
multiSelectSortOrder(p, p->pOrderBy);
rc = selectInnerLoop(pParse, p, p->pEList, tab1, p->pEList->nExpr,
p->pOrderBy, -1, eDest, iParm,
iCont, iBreak);
if( rc ) return 1;
iCont, iBreak, 0);
if( rc ){
rc = 1;
goto multi_select_end;
}
sqlite3VdbeResolveLabel(v, iCont);
sqlite3VdbeAddOp(v, OP_Next, tab1, iStart);
sqlite3VdbeResolveLabel(v, iBreak);
@ -1498,9 +1573,20 @@ static int multiSelect(Parse *pParse, Select *p, int eDest, int iParm){
if( p->pEList->nExpr!=pPrior->pEList->nExpr ){
sqlite3ErrorMsg(pParse, "SELECTs to the left and right of %s"
" do not have the same number of result columns", selectOpName(p->op));
return 1;
rc = 1;
goto multi_select_end;
}
return 0;
multi_select_end:
if( affStr ){
if( rc!=SQLITE_OK ){
sqliteFree(affStr);
}else{
multiSelectAffinity(p, affStr);
sqlite3VdbeOp3(v, OP_Noop, 0, 0, affStr, P3_DYNAMIC);
}
}
return rc;
}
/*
@ -1937,7 +2023,7 @@ static int simpleMinMaxQuery(Parse *pParse, Select *p, int eDest, int iParm){
memset(&eListItem, 0, sizeof(eListItem));
eList.a = &eListItem;
eList.a[0].pExpr = pExpr;
selectInnerLoop(pParse, p, &eList, 0, 0, 0, -1, eDest, iParm, cont, cont);
selectInnerLoop(pParse, p, &eList, 0, 0, 0, -1, eDest, iParm, cont, cont, 0);
sqlite3VdbeResolveLabel(v, cont);
sqlite3VdbeAddOp(v, OP_Close, base, 0);
@ -2003,7 +2089,8 @@ int sqlite3Select(
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 */
int *pParentAgg, /* True if pParent uses aggregate functions */
char *aff /* If eDest is SRT_Union, the affinity string */
){
int i;
WhereInfo *pWInfo;
@ -2025,7 +2112,7 @@ int sqlite3Select(
/* If there is are a sequence of queries, do the earlier ones first.
*/
if( p->pPrior ){
return multiSelect(pParse, p, eDest, iParm);
return multiSelect(pParse, p, eDest, iParm, aff);
}
/* Make local copies of the parameters for this query.
@ -2181,6 +2268,21 @@ int sqlite3Select(
generateColumnNames(pParse, pTabList, pEList);
}
/* If the destination is SRT_Union, then set the number of columns in
** the records that will be inserted into the temporary table. The caller
** couldn't do this, in case the select statement is of the form
** "SELECT * FROM ....".
**
** We need to do this before we start inserting records into the
** temporary table (which has had OP_KeyAsData executed on it), because
** it is required by the key comparison function. So do it now, even
** though this means that OP_SetNumColumns may be executed on the same
** cursor more than once.
*/
if( eDest==SRT_Union ){
sqlite3VdbeAddOp(v, OP_SetNumColumns, iParm, pEList->nExpr);
}
/* Generate code for all sub-queries in the FROM clause
*/
for(i=0; i<pTabList->nSrc; i++){
@ -2196,7 +2298,7 @@ int sqlite3Select(
needRestoreContext = 0;
}
sqlite3Select(pParse, pTabList->a[i].pSelect, SRT_TempTable,
pTabList->a[i].iCursor, p, i, &isAgg);
pTabList->a[i].iCursor, p, i, &isAgg, 0);
if( needRestoreContext ){
pParse->zAuthContext = zSavedAuthContext;
}
@ -2324,7 +2426,7 @@ int sqlite3Select(
*/
if( !isAgg ){
if( selectInnerLoop(pParse, p, pEList, 0, 0, pOrderBy, distinct, eDest,
iParm, pWInfo->iContinue, pWInfo->iBreak) ){
iParm, pWInfo->iContinue, pWInfo->iBreak, aff) ){
goto select_end;
}
}
@ -2383,7 +2485,7 @@ int sqlite3Select(
sqlite3ExprIfFalse(pParse, pHaving, startagg, 1);
}
if( selectInnerLoop(pParse, p, pEList, 0, 0, pOrderBy, distinct, eDest,
iParm, startagg, endagg) ){
iParm, startagg, endagg, aff) ){
goto select_end;
}
sqlite3VdbeAddOp(v, OP_Goto, 0, startagg);

View File

@ -12,7 +12,7 @@
** This file contains C code routines that are called by the parser
** to handle UPDATE statements.
**
** $Id: update.c,v 1.75 2004/05/18 01:23:38 danielk1977 Exp $
** $Id: update.c,v 1.76 2004/05/18 09:58:08 danielk1977 Exp $
*/
#include "sqliteInt.h"
@ -216,7 +216,7 @@ void sqlite3Update(
if( isView ){
Select *pView;
pView = sqlite3SelectDup(pTab->pSelect);
sqlite3Select(pParse, pView, SRT_TempTable, iCur, 0, 0, 0);
sqlite3Select(pParse, pView, SRT_TempTable, iCur, 0, 0, 0, 0);
sqlite3SelectDelete(pView);
}
@ -243,7 +243,9 @@ void sqlite3Update(
/* Create pseudo-tables for NEW and OLD
*/
sqlite3VdbeAddOp(v, OP_OpenPseudo, oldIdx, 0);
sqlite3VdbeAddOp(v, OP_SetNumColumns, oldIdx, pTab->nCol);
sqlite3VdbeAddOp(v, OP_OpenPseudo, newIdx, 0);
sqlite3VdbeAddOp(v, OP_SetNumColumns, newIdx, pTab->nCol);
/* The top of the update loop for when there are triggers.
*/

View File

@ -43,7 +43,7 @@
** 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.297 2004/05/18 01:23:38 danielk1977 Exp $
** $Id: vdbe.c,v 1.298 2004/05/18 09:58:08 danielk1977 Exp $
*/
#include "sqliteInt.h"
#include "os.h"
@ -485,6 +485,57 @@ static void applyAffinity(Mem *pRec, char affinity){
}
}
static int getBtreeMem(
BtCursor *pCur, /* Cursor pointing at record to retrieve. */
int offset, /* Offset from the start of data to return bytes from. */
int amt, /* Number of bytes to return. */
int key, /* If true, retrieve from the btree key, not data. */
Mem *pMem /* OUT: Return data in this Mem structure. */
){
char *zData;
if( key ){
zData = (char *)sqlite3BtreeKeyFetch(pCur, offset+amt);
}else{
zData = (char *)sqlite3BtreeDataFetch(pCur, offset+amt);
}
if( zData ){
pMem->z = &zData[offset];
pMem->n = amt;
pMem->flags = MEM_Blob|MEM_Ephem;
}else{
int rc;
if( amt>NBFS ){
zData = (char *)sqliteMallocRaw(amt);
if( !zData ){
return SQLITE_NOMEM;
}
pMem->flags = MEM_Blob|MEM_Dyn;
}else{
zData = &(pMem->zShort[0]);
pMem->flags = MEM_Blob|MEM_Short;
}
pMem->z = zData;
if( key ){
rc = sqlite3BtreeKey(pCur, offset, amt, zData);
}else{
rc = sqlite3BtreeData(pCur, offset, amt, zData);
}
if( rc!=SQLITE_OK ){
if( amt>NBFS ){
sqliteFree(zData);
}
return rc;
}
}
return SQLITE_OK;
}
#ifdef VDBE_PROFILE
/*
** The following routine only works on pentium-class processors.
@ -2019,7 +2070,8 @@ case OP_SetNumColumns: {
** a table. For P1==-1, the top of the stack is used. For P1==-2, the
** next on the stack is used. And so forth. The value pushed is always
** just a pointer into the record which is stored further down on the
** stack. The column value is not copied.
** stack. The column value is not copied. The number of columns in the
** record is stored on the stack just above the record itself.
*/
case OP_Column: {
int payloadSize; /* Number of bytes in the record */
@ -2029,30 +2081,61 @@ case OP_Column: {
char *zRec; /* Pointer to record-data from stack or pseudo-table. */
BtCursor *pCrsr;
char *zData;
int freeZdata = 0; /* zData requires sqliteFree() */
u64 nField; /* number of fields in the record */
int len; /* The length of the serialized data for the column */
int offset = 0;
int nn;
char *zData;
Mem zMem;
zMem.flags = 0;
assert( i<p->nCursor );
pTos++;
/* If the record is coming from the stack, not from a cursor, then there
** is nowhere to cache the record header infomation. This simplifies
** things greatly, so deal with this case seperately.
*/
if( i<0 ){
char *zRec; /* Pointer to record data from the stack. */
int off = 0; /* Offset in zRec to start of the columns data. */
int off2 = 0; /* Offset in zRec to the next serial type to read */
u64 colType; /* The serial type of the value being read. */
assert( &pTos[i-1]>=p->aStack );
assert( pTos[i].flags & MEM_Str );
assert( pTos[i-1].flags & MEM_Int );
if( pTos[i].n==0 ){
pTos->flags = MEM_Null;
break;
}
zRec = pTos[i].z;
nField = pTos[i-1].i;
for( nn=0; nn<nField; nn++ ){
u64 v;
off2 += sqlite3GetVarint(&zRec[off2], &v);
if( nn==p2 ){
colType = v;
}else if( nn<p2 ){
off += sqlite3VdbeSerialTypeLen(v);
}
}
off += off2;
sqlite3VdbeSerialGet(&zRec[off], colType, pTos);
break;
}
/* This block sets the variable payloadSize, and if the data is coming
** from the stack or from a pseudo-table zRec. If the data is coming
** from a real cursor, then zRec is left as NULL.
*/
if( i<0 ){
assert( &pTos[i]>=p->aStack );
assert( pTos[i].flags & MEM_Str );
zRec = pTos[i].z;
payloadSize = pTos[i].n;
pC->cacheValid = 0;
assert(!"broken for now");
}else if( (pC = p->apCsr[i])->pCursor!=0 ){
if( (pC = p->apCsr[i])->pCursor!=0 ){
sqlite3VdbeCursorMoveto(pC);
zRec = 0;
pCrsr = pC->pCursor;
@ -2093,31 +2176,8 @@ case OP_Column: {
/* Read and parse the table header. Store the results of the parse
** into the record header cache fields of the cursor.
*/
if( !pC->cacheValid ){
if( !pC || !pC->cacheValid ){
pC->payloadSize = payloadSize;
#if 0
if( zRec ){
zData = zRec;
}else{
/* We can assume that 10 bytes (maximum length of a varint) fits
** on the main page in all cases.
*/
int n = 10;
if( payloadSize<10 ) n = payloadSize;
if( pC->keyAsData ){
zData = (char *)sqlite3BtreeKeyFetch(pCrsr, n);
}else{
zData = (char *)sqlite3BtreeDataFetch(pCrsr, n);
}
assert( zData );
}
{
u64 x;
offset = sqlite3GetVarint(zData, &x);
assert( x==nField );
}
#endif
if( !pC->aType ){
pC->aType = sqliteMallocRaw( nField*sizeof(pC->aType[0]) );
if( pC->aType==0 ){
@ -2125,52 +2185,28 @@ case OP_Column: {
}
}
if( !zRec ){
/* If the record is stored in a table, see if enough of it is on
** the main page to use sqlite3BtreeDataFetch() to get the data
** containing the nField serial types (varints). This will almost
** always work, but if it doesn't sqliteMalloc() space and use
** sqlite3BtreeData().
**
** Estimate the maximum space required by the nField varints by
if( zRec ){
zData = zRec;
}else{
/* Estimate the maximum space required by the nField varints by
** assuming the maximum space for each is the length required to store:
**
** (<record length> * 2) + 13
**
** This is the serial-type for a text object as long as the record
** itself. In all cases the length required to store this is three
** bytes or less.
** itself. In almost all cases the length required to store this is
** three bytes or less.
*/
int max_space = sqlite3VarintLen((((u64)payloadSize)<<1)+13)*nField;
max_space += offset;
if( max_space>payloadSize ){
max_space = payloadSize;
}
if( pC->keyAsData ){
zData = (char *)sqlite3BtreeKeyFetch(pCrsr, max_space);
}else{
zData = (char *)sqlite3BtreeDataFetch(pCrsr, max_space);
}
if( !zData ){
/* This code will run very infrequently (e.g. tables with several
** hundred columns).
*/
zData = (char *)sqliteMallocRaw(max_space);
if( !zData ){
goto no_mem;
}
if( pC->keyAsData ){
rc = sqlite3BtreeKey(pCrsr, 0, max_space, zData);
}else{
rc = sqlite3BtreeData(pCrsr, 0, max_space, zData);
}
if( rc!=SQLITE_OK ){
sqliteFree(zData);
goto abort_due_to_error;
}
freeZdata = 1;
rc = getBtreeMem(pCrsr, 0, max_space, pC->keyAsData, &zMem);
if( rc!=SQLITE_OK ){
goto abort_due_to_error;
}
zData = zMem.z;
}
/* Read all the serial types for the record. At the end of this block
@ -2179,12 +2215,11 @@ case OP_Column: {
for(nn=0; nn<nField; nn++){
offset += sqlite3GetVarint(&zData[offset], &pC->aType[nn]);
}
if( freeZdata ){
freeZdata = 0;
sqliteFree(zData);
}
pC->nHeader = offset;
pC->cacheValid = 1;
Release(&zMem);
zMem.flags = 0;
}
/* Compute the offset from the beginning of the record to the beginning
@ -2194,44 +2229,17 @@ case OP_Column: {
for(nn=0; nn<p2; nn++){
offset += sqlite3VdbeSerialTypeLen(pC->aType[nn]);
}
len = sqlite3VdbeSerialTypeLen(pC->aType[p2]);
if( !zRec ){
/* If the record is stored in a table, see if enough of it
** is on the main page to read our column using
** sqlite3BtreeDataFetch(). If not sqliteMalloc() space and read data
** with sqlite3BtreeData().
*/
if( pC->keyAsData ){
zData = (char *)sqlite3BtreeKeyFetch(pCrsr, offset+len);
}else{
zData = (char *)sqlite3BtreeDataFetch(pCrsr, offset+len);
}
if( !zData ){
zData = (char *)sqliteMallocRaw(len);
if( !zData ){
goto no_mem;
}
if( pC->keyAsData ){
rc = sqlite3BtreeKey(pCrsr, offset, len, zData);
}else{
rc = sqlite3BtreeData(pCrsr, offset, len, zData);
}
if( rc!=SQLITE_OK ){
sqliteFree( zData );
goto abort_due_to_error;
}
freeZdata = 1;
offset = 0;
}
if( zRec ){
zData = &zRec[offset];
}else{
len = sqlite3VdbeSerialTypeLen(pC->aType[p2]);
getBtreeMem(pCrsr, offset, len, pC->keyAsData, &zMem);
zData = zMem.z;
}
sqlite3VdbeSerialGet(zData, pC->aType[p2], pTos);
/* Deserialize the value directly into the top of the stack */
sqlite3VdbeSerialGet(&zData[offset], pC->aType[p2], pTos);
if( freeZdata ){
sqliteFree(zData);
}
Release(&zMem);
break;
}
@ -2293,7 +2301,6 @@ case OP_MakeRecord: {
/* Loop through the elements that will make up the record to figure
** out how much space is required for the new record.
*/
// nBytes = sqlite3VarintLen(nField);
for(pRec=pData0; pRec<=pTos; pRec++){
u64 serial_type;
if( zAffinity ){
@ -2317,7 +2324,6 @@ case OP_MakeRecord: {
/* Write the record */
zCsr = zNewRecord;
// zCsr += sqlite3PutVarint(zCsr, nField); /* number of fields */
for(pRec=pData0; pRec<=pTos; pRec++){
u64 serial_type = sqlite3VdbeSerialType(pRec);
zCsr += sqlite3PutVarint(zCsr, serial_type); /* serial type */
@ -2348,9 +2354,9 @@ case OP_MakeRecord: {
/* Opcode: MakeKey P1 P2 P3
**
** Convert the top P1 entries of the stack into a single entry suitable
** for use as the key in an index. If P2 is not zero, then the original
** entries are popped off the stack. If P2 is zero, the original entries
** remain on the stack.
** for use as the key in an index. If P2 is zero, then the original
** entries are popped off the stack. If P2 is not zero, the original
** entries remain on the stack.
**
** P3 is interpreted in the same way as for MakeIdxKey.
*/
@ -3449,11 +3455,16 @@ case OP_SetCounts: {
** off (if P2==0). In key-as-data mode, the OP_Column opcode pulls
** data off of the key rather than the data. This is used for
** processing compound selects.
**
** This opcode also instructs the cursor that the keys used will be
** serialized in the record format usually used for table data, not
** the usual index key format.
*/
case OP_KeyAsData: {
int i = pOp->p1;
assert( i>=0 && i<p->nCursor );
p->apCsr[i]->keyAsData = pOp->p2;
sqlite3BtreeSetCompare(p->apCsr[i]->pCursor, sqlite3VdbeRowCompare, p->apCsr[i]);
break;
}

View File

@ -366,13 +366,14 @@ void sqlite3VdbeCompressSpace(Vdbe *p, int addr){
}
/*
** Search for the current program for the given opcode and P2
** value. Return the address plus 1 if found and 0 if not found.
** Search the current program starting at instruction addr for the given
** opcode and P2 value. Return the address plus 1 if found and 0 if not
** found.
*/
int sqlite3VdbeFindOp(Vdbe *p, int op, int p2){
int sqlite3VdbeFindOp(Vdbe *p, int addr, int op, int p2){
int i;
assert( p->magic==VDBE_MAGIC_INIT );
for(i=0; i<p->nOp; i++){
for(i=addr; i<p->nOp; i++){
if( p->aOp[i].opcode==op && p->aOp[i].p2==p2 ) return i+1;
}
return 0;
@ -1478,7 +1479,7 @@ int sqlite3VdbeKeyCompare(
** or positive integer if {nKey1, pKey1} is less than, equal to or
** greater than {nKey2, pKey2}.
**
** This function is pretty inefficient and will probably be replace
** This function is pretty inefficient and will probably be replaced
** by something else in the near future. It is currently required
** by compound SELECT operators.
*/
@ -1487,12 +1488,58 @@ int sqlite3VdbeRowCompare(
int nKey1, const void *pKey1,
int nKey2, const void *pKey2
){
Cursor *pC = (Cursor *)userData;
int offset1 = 0;
int offset2 = 0;
int toffset1 = 0;
int toffset2 = 0;
int i;
const unsigned char *aKey1 = (const unsigned char *)pKey1;
const unsigned char *aKey2 = (const unsigned char *)pKey2;
assert( userData==0 );
assert( pC );
assert( pC->nField>0 );
for( i=0; i<pC->nField; i++ ){
u64 dummy;
offset1 += sqlite3GetVarint(&aKey1[offset1], &dummy);
offset2 += sqlite3GetVarint(&aKey1[offset1], &dummy);
}
for( i=0; i<pC->nField; i++ ){
Mem mem1;
Mem mem2;
u64 serial_type1;
u64 serial_type2;
int rc;
/* Read the serial types for the next element in each key. */
toffset1 += sqlite3GetVarint(&aKey1[toffset1], &serial_type1);
toffset2 += sqlite3GetVarint(&aKey2[toffset2], &serial_type2);
assert( serial_type1 && serial_type2 );
/* Assert that there is enough space left in each key for the blob of
** data to go with the serial type just read. This assert may fail if
** the file is corrupted. Then read the value from each key into mem1
** and mem2 respectively.
*/
offset1 += sqlite3VdbeSerialGet(&aKey1[offset1], serial_type1, &mem1);
offset2 += sqlite3VdbeSerialGet(&aKey2[offset2], serial_type2, &mem2);
rc = sqlite3MemCompare(&mem1, &mem2);
if( mem1.flags&MEM_Dyn ){
sqliteFree(mem1.z);
}
if( mem2.flags&MEM_Dyn ){
sqliteFree(mem2.z);
}
if( rc!=0 ){
return rc;
}
}
return 0;
}