Many hyperlinks are disabled.
Use anonymous login
to enable hyperlinks.
Overview
Comment: | Comment changes. Change the use of BTree so that either the key is an integer or the data is empty. (CVS 337) |
---|---|
Downloads: | Tarball | ZIP archive |
Timelines: | family | ancestors | descendants | both | trunk |
Files: | files | file ages | folders |
SHA1: |
18e606f7486eb3a4ab128504d88a44f5 |
User & Date: | drh 2001-12-31 02:48:51.000 |
Context
2002-01-04
| ||
03:09 | An attempt to delete a single row using a WHERE clause that specifies the rowid would result in an error if the rowid did not exist. This problem has been resolved. (CVS 338) (check-in: 011be9a9d2 user: drh tags: trunk) | |
2001-12-31
| ||
02:48 | Comment changes. Change the use of BTree so that either the key is an integer or the data is empty. (CVS 337) (check-in: 18e606f748 user: drh tags: trunk) | |
2001-12-22
| ||
22:00 | Version 2.2.0 (CVS 453) (check-in: 6bb62d8fab user: drh tags: trunk) | |
Changes
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.30 2001/12/31 02:48:51 drh Exp $ */ #include "sqliteInt.h" /* ** This routine is call to handle SQL of the following forms: ** ** insert into TABLE (IDLIST) values(EXPRLIST) |
︙ | ︙ | |||
128 129 130 131 132 133 134 135 136 137 138 139 140 141 | pParse->nErr++; goto insert_cleanup; } /* If the INSERT statement included an IDLIST term, then make sure ** all elements of the IDLIST really are columns of the table and ** remember the column indices. */ if( pColumn ){ for(i=0; i<pColumn->nId; i++){ pColumn->a[i].idx = -1; } for(i=0; i<pColumn->nId; i++){ for(j=0; j<pTab->nCol; j++){ | > > > > > > > | 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 | pParse->nErr++; goto insert_cleanup; } /* If the INSERT statement included an IDLIST term, then make sure ** all elements of the IDLIST really are columns of the table and ** remember the column indices. ** ** If the table has an INTEGER PRIMARY KEY column and that column ** is named in the IDLIST, then record in the keyColumn variable ** the index into IDLIST of the primary key column. keyColumn is ** the index of the primary key as it appears in IDLIST, not as ** is appears in the original table. (The index of the primary ** key in the original table is pTab->iPKey.) */ if( pColumn ){ for(i=0; i<pColumn->nId; i++){ pColumn->a[i].idx = -1; } for(i=0; i<pColumn->nId; i++){ for(j=0; j<pTab->nCol; j++){ |
︙ | ︙ | |||
153 154 155 156 157 158 159 | pParse->nErr++; goto insert_cleanup; } } } /* If there is not IDLIST term but the table has an integer primary | | > | 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 | pParse->nErr++; goto insert_cleanup; } } } /* If there is not IDLIST term but the table has an integer primary ** key, the set the keyColumn variable to the primary key column index ** in the original table definition. */ if( pColumn==0 ){ keyColumn = pTab->iPKey; } /* Open cursors into the table that is received the new data and ** all indices of that table. |
︙ | ︙ | |||
201 202 203 204 205 206 207 | sqliteExprCode(pParse, pList->a[keyColumn].pExpr); } sqliteVdbeAddOp(v, OP_MustBeInt, 0, 0); }else{ sqliteVdbeAddOp(v, OP_NewRecno, base, 0); } | | | | 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 | sqliteExprCode(pParse, pList->a[keyColumn].pExpr); } sqliteVdbeAddOp(v, OP_MustBeInt, 0, 0); }else{ sqliteVdbeAddOp(v, OP_NewRecno, base, 0); } /* If there are indices, we'll need the new record number again, so make ** a copy. */ if( pTab->pIndex ){ sqliteVdbeAddOp(v, OP_Dup, 0, 0); } /* Push onto the stack data for all columns of the new entry, beginning ** with the first column. */ for(i=0; i<pTab->nCol; i++){ if( i==pTab->iPKey ){ /* The value of the INTEGER PRIMARY KEY column is always a NULL. ** Whenever this column is used, the record number will be substituted ** in its place, so there is no point in it taking up space in ** the data record. */ sqliteVdbeAddOp(v, OP_String, 0, 0); continue; } if( pColumn==0 ){ j = i; }else{ |
︙ | ︙ |
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.52 2001/12/31 02:48:51 drh Exp $ */ #include "sqliteInt.h" /* ** Allocate a new Select structure and return a pointer to that ** structure. */ |
︙ | ︙ | |||
126 127 128 129 130 131 132 | int lbl = sqliteVdbeMakeLabel(v); sqliteVdbeAddOp(v, OP_MakeKey, pEList->nExpr, 1); sqliteVdbeAddOp(v, OP_Distinct, distinct, lbl); sqliteVdbeAddOp(v, OP_Pop, pEList->nExpr+1, 0); sqliteVdbeAddOp(v, OP_Goto, 0, iContinue); sqliteVdbeResolveLabel(v, lbl); sqliteVdbeAddOp(v, OP_String, 0, 0); | < | 126 127 128 129 130 131 132 133 134 135 136 137 138 139 | int lbl = sqliteVdbeMakeLabel(v); sqliteVdbeAddOp(v, OP_MakeKey, pEList->nExpr, 1); sqliteVdbeAddOp(v, OP_Distinct, distinct, lbl); sqliteVdbeAddOp(v, OP_Pop, pEList->nExpr+1, 0); sqliteVdbeAddOp(v, OP_Goto, 0, iContinue); sqliteVdbeResolveLabel(v, lbl); sqliteVdbeAddOp(v, OP_String, 0, 0); sqliteVdbeAddOp(v, OP_Put, distinct, 0); } /* If there is an ORDER BY clause, then store the results ** in a sorter. */ if( pOrderBy ){ |
︙ | ︙ | |||
155 156 157 158 159 160 161 | /* In this mode, write each query result to the key of the temporary ** table iParm. */ if( eDest==SRT_Union ){ sqliteVdbeAddOp(v, OP_MakeRecord, nColumn, 0); sqliteVdbeAddOp(v, OP_String, iParm, 0); | < | 154 155 156 157 158 159 160 161 162 163 164 165 166 167 | /* In this mode, write each query result to the key of the temporary ** table iParm. */ if( eDest==SRT_Union ){ sqliteVdbeAddOp(v, OP_MakeRecord, nColumn, 0); sqliteVdbeAddOp(v, OP_String, iParm, 0); sqliteVdbeAddOp(v, OP_Put, iParm, 0); }else /* Store the result as data using a unique key. */ if( eDest==SRT_Table ){ sqliteVdbeAddOp(v, OP_MakeRecord, nColumn, 0); |
︙ | ︙ | |||
185 186 187 188 189 190 191 | /* If we are creating a set for an "expr IN (SELECT ...)" construct, ** then there should be a single item on the stack. Write this ** item into the set table with bogus data. */ if( eDest==SRT_Set ){ assert( nColumn==1 ); sqliteVdbeAddOp(v, OP_String, 0, 0); | < | 183 184 185 186 187 188 189 190 191 192 193 194 195 196 | /* If we are creating a set for an "expr IN (SELECT ...)" construct, ** then there should be a single item on the stack. Write this ** item into the set table with bogus data. */ if( eDest==SRT_Set ){ assert( nColumn==1 ); sqliteVdbeAddOp(v, OP_String, 0, 0); sqliteVdbeAddOp(v, OP_Put, iParm, 0); }else /* If this is a scalar select that is part of an expression, then ** store the results in the appropriate memory cell and break out ** of the scan loop. |
︙ | ︙ | |||
905 906 907 908 909 910 911 | /* Reset the aggregator */ if( isAgg ){ sqliteVdbeAddOp(v, OP_AggReset, 0, pParse->nAgg); if( pGroupBy==0 ){ sqliteVdbeAddOp(v, OP_String, 0, 0); | < | 902 903 904 905 906 907 908 909 910 911 912 913 914 915 | /* Reset the aggregator */ if( isAgg ){ sqliteVdbeAddOp(v, OP_AggReset, 0, pParse->nAgg); if( pGroupBy==0 ){ sqliteVdbeAddOp(v, OP_String, 0, 0); sqliteVdbeAddOp(v, OP_AggFocus, 0, 0); for(i=0; i<pParse->nAgg; i++){ Expr *pE; if( !pParse->aAgg[i].isAgg ) continue; pE = pParse->aAgg[i].pExpr; assert( pE==0 || pE->op==TK_AGG_FUNCTION ); assert( pE==0 || (pE->pList!=0 && pE->pList->nExpr==1) ); |
︙ | ︙ |
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.74 2001/12/31 02:48:51 drh Exp $ */ #include "sqlite.h" #include "hash.h" #include "vdbe.h" #include "parse.h" #include "btree.h" #include <stdio.h> |
︙ | ︙ | |||
226 227 228 229 230 231 232 | ** Each SQL table is represented in memory by ** an instance of the following structure. */ struct Table { char *zName; /* Name of the table */ int nCol; /* Number of columns in this table */ Column *aCol; /* Information about each column */ | | | 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 | ** Each SQL table is represented in memory by ** an instance of the following structure. */ struct Table { char *zName; /* Name of the table */ int nCol; /* Number of columns in this table */ Column *aCol; /* Information about each column */ int iPKey; /* If not less then 0, use aCol[iPKey] as the primary key */ Index *pIndex; /* List of SQL indexes on this table. */ int tnum; /* Page containing root for this table */ u8 readOnly; /* True if this table should not be written by the user */ u8 isCommit; /* True if creation of this table has been committed */ u8 isDelete; /* True if this table is being deleted */ u8 isTemp; /* True if stored in db->pBeTemp instead of db->pBe */ u8 hasPrimKey; /* True if there exists a primary key */ |
︙ | ︙ |
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.25 2001/12/31 02:48:51 drh Exp $ */ #include "sqliteInt.h" /* ** Process an UPDATE statement. */ void sqliteUpdate( |
︙ | ︙ | |||
45 46 47 48 49 50 51 | if( pParse->nErr || sqlite_malloc_failed ) goto update_cleanup; db = pParse->db; /* Locate the table which we want to update. This table has to be ** put in an IdList structure because some of the subroutines we ** will be calling are designed to work with multiple tables and expect | | | 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 | if( pParse->nErr || sqlite_malloc_failed ) goto update_cleanup; db = pParse->db; /* Locate the table which we want to update. This table has to be ** put in an IdList structure because some of the subroutines we ** will be calling are designed to work with multiple tables and expect ** an IdList* parameter instead of just a Table* parameter. */ pTabList = sqliteIdListAppend(0, pTableName); if( pTabList==0 ) goto update_cleanup; for(i=0; i<pTabList->nId; i++){ pTabList->a[i].pTab = sqliteFindTable(db, pTabList->a[i].zName); if( pTabList->a[i].pTab==0 ){ sqliteSetString(&pParse->zErrMsg, "no such table: ", |
︙ | ︙ | |||
115 116 117 118 119 120 121 | pParse->nErr++; goto update_cleanup; } } /* Allocate memory for the array apIdx[] and fill it with pointers to every ** index that needs to be updated. Indices only need updating if their | | > | 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 | pParse->nErr++; goto update_cleanup; } } /* Allocate memory for the array apIdx[] and fill it with pointers to every ** index that needs to be updated. Indices only need updating if their ** key includes one of the columns named in pChanges or if the record ** number of the original table entry is changing. */ for(nIdx=0, pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext){ if( chngRecno ){ i = 0; }else { for(i=0; i<pIdx->nColumn; i++){ if( aXRef[pIdx->aiColumn[i]]>=0 ) break; |
︙ | ︙ | |||
199 200 201 202 203 204 205 | /* Delete the old indices for the current record. */ for(i=0; i<nIdx; i++){ sqliteVdbeAddOp(v, OP_Dup, 0, 0); pIdx = apIdx[i]; for(j=0; j<pIdx->nColumn; j++){ | > > > > | > | 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 | /* Delete the old indices for the current record. */ for(i=0; i<nIdx; i++){ sqliteVdbeAddOp(v, OP_Dup, 0, 0); pIdx = apIdx[i]; for(j=0; j<pIdx->nColumn; j++){ int x = pIdx->aiColumn[j]; if( x==pTab->iPKey ){ sqliteVdbeAddOp(v, OP_Dup, j, 0); }else{ sqliteVdbeAddOp(v, OP_Column, base, x); } } sqliteVdbeAddOp(v, OP_MakeIdxKey, pIdx->nColumn, 0); sqliteVdbeAddOp(v, OP_IdxDelete, base+i+1, 0); } /* If changing the record number, remove the old record number ** from the top of the stack and replace it with the new one. |
︙ | ︙ | |||
229 230 231 232 233 234 235 | if( j<0 ){ sqliteVdbeAddOp(v, OP_Column, base, i); }else{ sqliteExprCode(pParse, pChanges->a[j].pExpr); } } | | | 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 | if( j<0 ){ sqliteVdbeAddOp(v, OP_Column, base, i); }else{ sqliteExprCode(pParse, pChanges->a[j].pExpr); } } /* If changing the record number, delete the old record. */ if( chngRecno ){ sqliteVdbeAddOp(v, OP_Delete, 0, 0); } /* Insert new index entries that correspond to the new data */ |
︙ | ︙ |
Changes to src/vdbe.c.
︙ | ︙ | |||
26 27 28 29 30 31 32 | ** type to the other occurs as necessary. ** ** Most of the code in this file is taken up by the sqliteVdbeExec() ** function which does the work of interpreting a VDBE program. ** But other routines are also provided to help in building up ** a program instruction by instruction. ** | | | 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 | ** type to the other occurs as necessary. ** ** Most of the code in this file is taken up by the sqliteVdbeExec() ** function which does the work of interpreting a VDBE program. ** But other routines are also provided to help in building up ** a program instruction by instruction. ** ** $Id: vdbe.c,v 1.103 2001/12/31 02:48:51 drh Exp $ */ #include "sqliteInt.h" #include <ctype.h> /* ** The following global variable is incremented every time a cursor ** moves, either by the OP_MoveTo or the OP_Next opcode. The test |
︙ | ︙ | |||
52 53 54 55 56 57 58 | /* ** Boolean values */ typedef unsigned char Bool; /* | | | | | | | 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 | /* ** Boolean values */ typedef unsigned char Bool; /* ** A cursor is a pointer into a single BTree within a database file. ** The cursor can seek to a BTree entry with a particular key, or ** loop over all entries of the Btree. You can also insert new BTree ** entries or retrieve the key or data from the entry that the cursor ** is currently pointing to. ** ** Every cursor that the virtual machine has open is represented by an ** instance of the following structure. */ struct Cursor { BtCursor *pCursor; /* The cursor structure of the backend */ int lastRecno; /* Last recno from a Next or NextIdx operation */ |
︙ | ︙ | |||
94 95 96 97 98 99 100 | #define NSORT 30 /* ** Number of bytes of string storage space available to each stack ** layer without having to malloc. NBFS is short for Number of Bytes ** For Strings. */ | | | 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 | #define NSORT 30 /* ** Number of bytes of string storage space available to each stack ** layer without having to malloc. NBFS is short for Number of Bytes ** For Strings. */ #define NBFS 32 /* ** A single level of the stack is an instance of the following ** structure. Except, string values are stored on a separate ** list of of pointers to character. The reason for storing ** strings separately is so that they can be easily passed ** to the callback function. |
︙ | ︙ | |||
166 167 168 169 170 171 172 | typedef struct Set Set; struct Set { Hash hash; /* A set is just a hash table */ }; /* ** A Keylist is a bunch of keys into a table. The keylist can | | | | 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 | typedef struct Set Set; struct Set { Hash hash; /* A set is just a hash table */ }; /* ** A Keylist is a bunch of keys into a table. The keylist can ** grow without bound. The keylist stores the ROWIDs of database ** records that need to be deleted or updated. */ typedef struct Keylist Keylist; struct Keylist { int nKey; /* Number of slots in aKey[] */ int nUsed; /* Next unwritten slot in aKey[] */ int nRead; /* Next unread slot in aKey[] */ Keylist *pNext; /* Next block of keys */ |
︙ | ︙ | |||
390 391 392 393 394 395 396 | ** ** If n>=0 then the P3 operand is dynamic, meaning that a copy of ** the string is made into memory obtained from sqliteMalloc(). ** A value of n==0 means copy bytes of zP3 up to and including the ** first null byte. If n>0 then copy n+1 bytes of zP3. ** ** If n==P3_STATIC it means that zP3 is a pointer to a constant static | | | 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 | ** ** If n>=0 then the P3 operand is dynamic, meaning that a copy of ** the string is made into memory obtained from sqliteMalloc(). ** A value of n==0 means copy bytes of zP3 up to and including the ** first null byte. If n>0 then copy n+1 bytes of zP3. ** ** If n==P3_STATIC it means that zP3 is a pointer to a constant static ** string and we can just copy the pointer. n==P3_POINTER means zP3 is ** a pointer to some object other than a string. ** ** If addr<0 then change P3 on the most recently inserted instruction. */ void sqliteVdbeChangeP3(Vdbe *p, int addr, const char *zP3, int n){ Op *pOp; if( p==0 || p->aOp==0 ) return; |
︙ | ︙ | |||
1173 1174 1175 1176 1177 1178 1179 1180 1181 1182 1183 1184 1185 1186 | case OP_String: { int i = ++p->tos; char *z; VERIFY( if( NeedStack(p, p->tos) ) goto no_mem; ) z = pOp->p3; if( z==0 ){ zStack[i] = 0; aStack[i].flags = STK_Null; }else{ zStack[i] = z; aStack[i].n = strlen(z) + 1; aStack[i].flags = STK_Str | STK_Static; } break; | > | 1173 1174 1175 1176 1177 1178 1179 1180 1181 1182 1183 1184 1185 1186 1187 | case OP_String: { int i = ++p->tos; char *z; VERIFY( if( NeedStack(p, p->tos) ) goto no_mem; ) z = pOp->p3; if( z==0 ){ zStack[i] = 0; aStack[i].n = 0; aStack[i].flags = STK_Null; }else{ zStack[i] = z; aStack[i].n = strlen(z) + 1; aStack[i].flags = STK_Str | STK_Static; } break; |
︙ | ︙ |