Many hyperlinks are disabled.
Use anonymous login
to enable hyperlinks.
Overview
Comment: | Added basic support for enforcement of UNIQUE on indices and primary keys. Support for addition constraints is to follow. (CVS 267) |
---|---|
Downloads: | Tarball | ZIP archive |
Timelines: | family | ancestors | descendants | both | trunk |
Files: | files | file ages | folders |
SHA1: |
34c42967f3d52dfb65d9f31db4f6995d |
User & Date: | drh 2001-09-27 03:22:33.000 |
Context
2001-09-27
| ||
15:11 | Fixed the support of UNIQUE and PRIMARY KEY. (CVS 268) (check-in: 116fdad068 user: drh tags: trunk) | |
03:22 | Added basic support for enforcement of UNIQUE on indices and primary keys. Support for addition constraints is to follow. (CVS 267) (check-in: 34c42967f3 user: drh tags: trunk) | |
2001-09-25
| ||
02:04 | Fix an RCSID problem. (CVS 266) (check-in: 0e9cfcd53e user: drh tags: trunk) | |
Changes
Changes to src/btree.c.
1 2 3 4 5 6 7 8 9 10 11 | /* ** 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. ** ************************************************************************* | | | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 | /* ** 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. ** ************************************************************************* ** $Id: btree.c,v 1.31 2001/09/27 03:22:33 drh Exp $ ** ** This file implements a external (disk-based) database using BTrees. ** For a detailed discussion of BTrees, refer to ** ** Donald E. Knuth, THE ART OF COMPUTER PROGRAMMING, Volume 3: ** "Sorting And Searching", pages 473-480. Addison-Wesley ** Publishing Company, Reading, Massachusetts. |
︙ | ︙ | |||
1066 1067 1068 1069 1070 1071 1072 | } } getPayload(pCur, offset + pCell->h.nKey, amt, zBuf); return amt; } /* | > | | > | > > > | < < > | > > | > > > | | | | | < > | | | | > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | > | 1066 1067 1068 1069 1070 1071 1072 1073 1074 1075 1076 1077 1078 1079 1080 1081 1082 1083 1084 1085 1086 1087 1088 1089 1090 1091 1092 1093 1094 1095 1096 1097 1098 1099 1100 1101 1102 1103 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 1136 1137 1138 1139 1140 1141 1142 1143 1144 1145 1146 1147 1148 1149 1150 1151 1152 1153 1154 1155 1156 1157 1158 1159 1160 1161 1162 1163 1164 1165 1166 1167 1168 1169 1170 1171 1172 1173 1174 1175 1176 1177 1178 1179 1180 1181 1182 1183 1184 1185 1186 1187 | } } getPayload(pCur, offset + pCell->h.nKey, amt, zBuf); return amt; } /* ** Compare the first nKey bytes of the key of the entry that pCur ** points to against the first nKey bytes of pKey. Set *pRes to ** show the comparison results: ** ** *pRes<0 This means pCur<pKey ** ** *pRes==0 This means pCur==pKey for all nKey bytes ** ** *pRes>0 This means pCur>pKey ** ** If pCur contains N bytes where N<nKey and the N bytes of pCur ** match the first N bytes of pKey, then *pRes<0 is returned. ** If pCur differs from pKey in the first N bytes, then *pRes<0 ** or *pRes>0 depending on the difference. ** ** If pCur contains M bytes where M>nKey then only the first nKey ** bytes of pCur are used in the comparison. The result is the same ** as it would be if pCur were truncated to nKey bytes. */ int sqliteBtreeKeyCompare( BtCursor *pCur, const void *pKey, int nKey, int *pResult ){ Pgno nextPage; int n, c, rc; Cell *pCell; const char *zKey = (const char*)pKey; assert( pCur->pPage ); assert( pCur->idx>=0 && pCur->idx<pCur->pPage->nCell ); pCell = pCur->pPage->apCell[pCur->idx]; if( nKey > pCell->h.nKey ){ nKey = pCell->h.nKey; } n = nKey; if( n>MX_LOCAL_PAYLOAD ){ n = MX_LOCAL_PAYLOAD; } c = memcmp(pCell->aPayload, zKey, n); if( c!=0 ){ *pResult = c; return SQLITE_OK; } zKey += n; nKey -= n; nextPage = pCell->ovfl; while( nKey>0 ){ OverflowPage *pOvfl; if( nextPage==0 ){ return SQLITE_CORRUPT; } rc = sqlitepager_get(pCur->pBt->pPager, nextPage, (void**)&pOvfl); if( rc ){ return rc; } nextPage = pOvfl->iNext; n = nKey; if( n>OVERFLOW_SIZE ){ n = OVERFLOW_SIZE; } c = memcmp(pOvfl->aPayload, zKey, n); sqlitepager_unref(pOvfl); if( c!=0 ){ *pResult = c; return SQLITE_OK; } nKey -= n; zKey += n; } *pResult = c; return SQLITE_OK; } /* ** Compare the key for the entry that pCur points to against the ** given key (pKey,nKeyOrig). Put the comparison result in *pResult. ** The result is negative if pCur<pKey, zero if they are equal and ** positive if pCur>pKey. ** ** Shorter strings are considered less than longer strings if they ** are otherwise equal. All bytes of both pCur and pKey are considered ** in this comparison. This is different from sqliteBtreeKeyCompare() ** which only considers the first nKeyOrig bytes of pCur. ** ** SQLITE_OK is returned on success. If part of the cursor key ** is on overflow pages and we are unable to access those overflow ** pages, then some other value might be returned to indicate the ** reason for the error. */ static int compareKey( BtCursor *pCur, /* Points to the entry against which we are comparing */ const char *pKey, /* The comparison key */ int nKeyOrig, /* Number of bytes in the comparison key */ int *pResult /* Write the comparison results here */ ){ int rc, c; rc = sqliteBtreeKeyCompare(pCur, pKey, nKeyOrig, &c); if( rc!=SQLITE_OK ) return rc; if( c==0 ){ Cell *pCell; assert( pCur->pPage ); assert( pCur->pPage->nCell>pCur->idx && pCur->idx>=0 ); pCell = pCur->pPage->apCell[pCur->idx]; c = pCell->h.nKey - nKeyOrig; } *pResult = c; return SQLITE_OK; } /* ** Move the cursor down to a new child page. */ |
︙ | ︙ |
Changes to src/btree.h.
︙ | ︙ | |||
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 header file defines the interface that the sqlite B-Tree file ** subsystem. ** | | | 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 header file defines the interface that the sqlite B-Tree file ** subsystem. ** ** @(#) $Id: btree.h,v 1.16 2001/09/27 03:22:33 drh Exp $ */ #ifndef _BTREE_H_ #define _BTREE_H_ typedef struct Btree Btree; typedef struct BtCursor BtCursor; |
︙ | ︙ | |||
37 38 39 40 41 42 43 44 45 46 47 48 49 50 | int sqliteBtreeDelete(BtCursor*); int sqliteBtreeInsert(BtCursor*, const void *pKey, int nKey, const void *pData, int nData); int sqliteBtreeFirst(BtCursor*, int *pRes); int sqliteBtreeNext(BtCursor*, int *pRes); int sqliteBtreeKeySize(BtCursor*, int *pSize); int sqliteBtreeKey(BtCursor*, int offset, int amt, char *zBuf); int sqliteBtreeDataSize(BtCursor*, int *pSize); int sqliteBtreeData(BtCursor*, int offset, int amt, char *zBuf); int sqliteBtreeCloseCursor(BtCursor*); #define SQLITE_N_BTREE_META 4 int sqliteBtreeGetMeta(Btree*, int*); int sqliteBtreeUpdateMeta(Btree*, int*); | > | 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 | int sqliteBtreeDelete(BtCursor*); int sqliteBtreeInsert(BtCursor*, const void *pKey, int nKey, const void *pData, int nData); int sqliteBtreeFirst(BtCursor*, int *pRes); int sqliteBtreeNext(BtCursor*, int *pRes); int sqliteBtreeKeySize(BtCursor*, int *pSize); int sqliteBtreeKey(BtCursor*, int offset, int amt, char *zBuf); int sqliteBtreeKeyCompare(BtCursor*, const void *pKey, int nKey, int *pRes); int sqliteBtreeDataSize(BtCursor*, int *pSize); int sqliteBtreeData(BtCursor*, int offset, int amt, char *zBuf); int sqliteBtreeCloseCursor(BtCursor*); #define SQLITE_N_BTREE_META 4 int sqliteBtreeGetMeta(Btree*, int*); int sqliteBtreeUpdateMeta(Btree*, int*); |
︙ | ︙ |
Changes to src/build.c.
︙ | ︙ | |||
21 22 23 24 25 26 27 | ** COPY ** VACUUM ** BEGIN TRANSACTION ** COMMIT ** ROLLBACK ** PRAGMA ** | | | 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 | ** COPY ** VACUUM ** BEGIN TRANSACTION ** COMMIT ** ROLLBACK ** PRAGMA ** ** $Id: build.c,v 1.42 2001/09/27 03:22:33 drh Exp $ */ #include "sqliteInt.h" #include <ctype.h> /* ** This routine is called after a single SQL statement has been ** parsed and we want to execute the VDBE code to implement |
︙ | ︙ | |||
641 642 643 644 645 646 647 648 649 650 651 652 653 654 | ** most recently added column of the table is labeled as the primary key. */ void sqliteCreateIndex( Parse *pParse, /* All information about this parse */ Token *pName, /* Name of the index. May be NULL */ Token *pTable, /* Name of the table to index. Use pParse->pNewTable if 0 */ IdList *pList, /* A list of columns to be indexed */ Token *pStart, /* The CREATE token that begins a CREATE TABLE statement */ Token *pEnd /* The ")" that closes the CREATE INDEX statement */ ){ Table *pTab; /* Table to be indexed */ Index *pIndex; /* The index to be created */ char *zName = 0; int i, j; | > | 641 642 643 644 645 646 647 648 649 650 651 652 653 654 655 | ** most recently added column of the table is labeled as the primary key. */ void sqliteCreateIndex( Parse *pParse, /* All information about this parse */ Token *pName, /* Name of the index. May be NULL */ Token *pTable, /* Name of the table to index. Use pParse->pNewTable if 0 */ IdList *pList, /* A list of columns to be indexed */ int isUnique, /* True if all entries in this index must be unique */ Token *pStart, /* The CREATE token that begins a CREATE TABLE statement */ Token *pEnd /* The ")" that closes the CREATE INDEX statement */ ){ Table *pTab; /* Table to be indexed */ Index *pIndex; /* The index to be created */ char *zName = 0; int i, j; |
︙ | ︙ | |||
720 721 722 723 724 725 726 727 728 729 730 731 732 733 | sizeof(int)*pList->nId ); if( pIndex==0 ) goto exit_create_index; pIndex->aiColumn = (int*)&pIndex[1]; pIndex->zName = (char*)&pIndex->aiColumn[pList->nId]; strcpy(pIndex->zName, zName); pIndex->pTable = pTab; pIndex->nColumn = pList->nId; /* Scan the names of the columns of the table to be indexed and ** load the column indices into the Index structure. Report an error ** if any column is not found. */ for(i=0; i<pList->nId; i++){ for(j=0; j<pTab->nCol; j++){ | > | 721 722 723 724 725 726 727 728 729 730 731 732 733 734 735 | sizeof(int)*pList->nId ); if( pIndex==0 ) goto exit_create_index; pIndex->aiColumn = (int*)&pIndex[1]; pIndex->zName = (char*)&pIndex->aiColumn[pList->nId]; strcpy(pIndex->zName, zName); pIndex->pTable = pTab; pIndex->nColumn = pList->nId; pIndex->isUnique = isUnique; /* Scan the names of the columns of the table to be indexed and ** load the column indices into the Index structure. Report an error ** if any column is not found. */ for(i=0; i<pList->nId; i++){ for(j=0; j<pTab->nCol; j++){ |
︙ | ︙ | |||
829 830 831 832 833 834 835 | sqliteVdbeAddOp(v, OP_Rewind, 0, 0, 0, 0); sqliteVdbeAddOp(v, OP_Next, 0, lbl2, 0, lbl1); sqliteVdbeAddOp(v, OP_Recno, 0, 0, 0, 0); for(i=0; i<pIndex->nColumn; i++){ sqliteVdbeAddOp(v, OP_Column, 0, pIndex->aiColumn[i], 0, 0); } sqliteVdbeAddOp(v, OP_MakeIdxKey, pIndex->nColumn, 0, 0, 0); | | | 831 832 833 834 835 836 837 838 839 840 841 842 843 844 845 | sqliteVdbeAddOp(v, OP_Rewind, 0, 0, 0, 0); sqliteVdbeAddOp(v, OP_Next, 0, lbl2, 0, lbl1); sqliteVdbeAddOp(v, OP_Recno, 0, 0, 0, 0); for(i=0; i<pIndex->nColumn; i++){ sqliteVdbeAddOp(v, OP_Column, 0, pIndex->aiColumn[i], 0, 0); } sqliteVdbeAddOp(v, OP_MakeIdxKey, pIndex->nColumn, 0, 0, 0); sqliteVdbeAddOp(v, OP_PutIdx, 1, pIndex->isUnique, 0, 0); sqliteVdbeAddOp(v, OP_Goto, 0, lbl1, 0, 0); sqliteVdbeAddOp(v, OP_Noop, 0, 0, 0, lbl2); sqliteVdbeAddOp(v, OP_Close, 1, 0, 0, 0); sqliteVdbeAddOp(v, OP_Close, 0, 0, 0, 0); if( pTable!=0 && (db->flags & SQLITE_InTrans)==0 ){ sqliteVdbeAddOp(v, OP_Commit, 0, 0, 0, 0); } |
︙ | ︙ | |||
1102 1103 1104 1105 1106 1107 1108 | if( pIdx->pNext ){ sqliteVdbeAddOp(v, OP_Dup, 0, 0, 0, 0); } for(j=0; j<pIdx->nColumn; j++){ sqliteVdbeAddOp(v, OP_FileColumn, pIdx->aiColumn[j], 0, 0, 0); } sqliteVdbeAddOp(v, OP_MakeIdxKey, pIdx->nColumn, 0, 0, 0); | | | 1104 1105 1106 1107 1108 1109 1110 1111 1112 1113 1114 1115 1116 1117 1118 | if( pIdx->pNext ){ sqliteVdbeAddOp(v, OP_Dup, 0, 0, 0, 0); } for(j=0; j<pIdx->nColumn; j++){ sqliteVdbeAddOp(v, OP_FileColumn, pIdx->aiColumn[j], 0, 0, 0); } sqliteVdbeAddOp(v, OP_MakeIdxKey, pIdx->nColumn, 0, 0, 0); sqliteVdbeAddOp(v, OP_PutIdx, i, pIdx->isUnique, 0, 0); } sqliteVdbeAddOp(v, OP_Goto, 0, addr, 0, 0); sqliteVdbeAddOp(v, OP_Noop, 0, 0, 0, end); if( (db->flags & SQLITE_InTrans)==0 ){ sqliteVdbeAddOp(v, OP_Commit, 0, 0, 0, 0); } } |
︙ | ︙ |
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.20 2001/09/27 03:22:33 drh Exp $ */ #include "sqliteInt.h" /* ** This routine is call to handle SQL of the following forms: ** ** insert into TABLE (IDLIST) values(EXPRLIST) |
︙ | ︙ | |||
227 228 229 230 231 232 233 | }else if( srcTab>=0 ){ sqliteVdbeAddOp(v, OP_Column, srcTab, idx, 0, 0); }else{ sqliteExprCode(pParse, pList->a[j].pExpr); } } sqliteVdbeAddOp(v, OP_MakeIdxKey, pIdx->nColumn, 0, 0, 0); | | | 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 | }else if( srcTab>=0 ){ sqliteVdbeAddOp(v, OP_Column, srcTab, idx, 0, 0); }else{ sqliteExprCode(pParse, pList->a[j].pExpr); } } sqliteVdbeAddOp(v, OP_MakeIdxKey, pIdx->nColumn, 0, 0, 0); sqliteVdbeAddOp(v, OP_PutIdx, idx+base, pIdx->isUnique, 0, 0); } /* The bottom of the loop, if the data source is a SELECT statement */ if( srcTab>=0 ){ sqliteVdbeAddOp(v, OP_Goto, 0, iCont, 0, 0); sqliteVdbeAddOp(v, OP_Noop, 0, 0, 0, iBreak); |
︙ | ︙ |
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.31 2001/09/27 03:22:33 drh Exp $ */ %token_prefix TK_ %token_type {Token} %default_type {Token} %extra_argument {Parse *pParse} %syntax_error { sqliteSetString(&pParse->zErrMsg,"syntax error",0); |
︙ | ︙ | |||
120 121 122 123 124 125 126 | carg ::= DEFAULT PLUS FLOAT(X). {sqliteAddDefaultValue(pParse,&X,0);} carg ::= DEFAULT MINUS FLOAT(X). {sqliteAddDefaultValue(pParse,&X,1);} carg ::= DEFAULT NULL. // In addition to the type name, we also care about the primary key. // ccons ::= NOT NULL. | | | | 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 | carg ::= DEFAULT PLUS FLOAT(X). {sqliteAddDefaultValue(pParse,&X,0);} carg ::= DEFAULT MINUS FLOAT(X). {sqliteAddDefaultValue(pParse,&X,1);} carg ::= DEFAULT NULL. // In addition to the type name, we also care about the primary key. // ccons ::= NOT NULL. ccons ::= PRIMARY KEY sortorder. {sqliteCreateIndex(pParse,0,0,0,1,0,0);} ccons ::= UNIQUE. ccons ::= CHECK LP expr RP. // For the time being, the only constraint we care about is the primary // key. // conslist_opt ::= . conslist_opt ::= COMMA conslist. conslist ::= conslist COMMA tcons. conslist ::= conslist tcons. conslist ::= tcons. tcons ::= CONSTRAINT ids. tcons ::= PRIMARY KEY LP idxlist(X) RP. {sqliteCreateIndex(pParse,0,0,X,1,0,0);} tcons ::= UNIQUE LP idlist RP. tcons ::= CHECK expr. idlist ::= idlist COMMA ids. idlist ::= ids. // The next command format is dropping tables. // |
︙ | ︙ | |||
441 442 443 444 445 446 447 | exprlist(A) ::= exprlist(X) COMMA expritem(Y). {A = sqliteExprListAppend(X,Y,0);} exprlist(A) ::= expritem(X). {A = sqliteExprListAppend(0,X,0);} expritem(A) ::= expr(X). {A = X;} expritem(A) ::= . {A = 0;} | | | > | | > | 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 | exprlist(A) ::= exprlist(X) COMMA expritem(Y). {A = sqliteExprListAppend(X,Y,0);} exprlist(A) ::= expritem(X). {A = sqliteExprListAppend(0,X,0);} expritem(A) ::= expr(X). {A = X;} expritem(A) ::= . {A = 0;} cmd ::= CREATE(S) uniqueflag(U) INDEX ids(X) ON ids(Y) LP idxlist(Z) RP(E). {sqliteCreateIndex(pParse, &X, &Y, Z, U, &S, &E);} %type uniqueflag {int} uniqueflag(A) ::= UNIQUE. { A = 1; } uniqueflag(A) ::= . { A = 0; } %type idxlist {IdList*} %destructor idxlist {sqliteIdListDelete($$);} %type idxitem {Token} idxlist(A) ::= idxlist(X) COMMA idxitem(Y). {A = sqliteIdListAppend(X,&Y);} |
︙ | ︙ |
Changes to src/sqlite.h.in.
︙ | ︙ | |||
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 header file defines the interface that the SQLite library ** presents to client programs. ** | | | 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 header file defines the interface that the SQLite library ** presents to client programs. ** ** @(#) $Id: sqlite.h.in,v 1.20 2001/09/27 03:22:33 drh Exp $ */ #ifndef _SQLITE_H_ #define _SQLITE_H_ #include <stdarg.h> /* Needed for the definition of va_list */ /* ** The version of the SQLite library. |
︙ | ︙ | |||
129 130 131 132 133 134 135 | void *, /* 1st argument to callback function */ char **errmsg /* Error msg written here */ ); /* ** Return values for sqlite_exec() */ | | | | | | | | | | | | | | | | | | | | > > > > > > > | 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 | void *, /* 1st argument to callback function */ char **errmsg /* Error msg written here */ ); /* ** Return values for sqlite_exec() */ #define SQLITE_OK 0 /* Successful result */ #define SQLITE_ERROR 1 /* SQL error or missing database */ #define SQLITE_INTERNAL 2 /* An internal logic error in SQLite */ #define SQLITE_PERM 3 /* Access permission denied */ #define SQLITE_ABORT 4 /* Callback routine requested an abort */ #define SQLITE_BUSY 5 /* The database file is locked */ #define SQLITE_LOCKED 6 /* A table in the database is locked */ #define SQLITE_NOMEM 7 /* A malloc() failed */ #define SQLITE_READONLY 8 /* Attempt to write a readonly database */ #define SQLITE_INTERRUPT 9 /* Operation terminated by sqlite_interrupt() */ #define SQLITE_IOERR 10 /* Some kind of disk I/O error occurred */ #define SQLITE_CORRUPT 11 /* The database disk image is malformed */ #define SQLITE_NOTFOUND 12 /* (Internal Only) Table or record not found */ #define SQLITE_FULL 13 /* Insertion failed because database is full */ #define SQLITE_CANTOPEN 14 /* Unable to open the database file */ #define SQLITE_PROTOCOL 15 /* Database lock protocol error */ #define SQLITE_EMPTY 16 /* (Internal Only) Database table is empty */ #define SQLITE_SCHEMA 17 /* The database schema changed */ #define SQLITE_TOOBIG 18 /* Too much data for one row of a table */ #define SQLITE_CONSTRAINT 19 /* Abort due to contraint violation */ /* If the parameter to this routine is one of the return value constants ** defined above, then this routine returns a constant text string which ** descripts (in English) the meaning of the return value. */ const char *sqliteErrStr(int); /* This function causes any pending database operation to abort and ** return at its earliest opportunity. This routine is typically ** called in response to a user action such as pressing "Cancel" ** or Ctrl-C where the user wants a long query operation to halt ** immediately. */ |
︙ | ︙ |
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.55 2001/09/27 03:22:33 drh Exp $ */ #include "sqlite.h" #include "hash.h" #include "vdbe.h" #include "parse.h" #include "btree.h" #include <stdio.h> |
︙ | ︙ | |||
186 187 188 189 190 191 192 | */ struct Table { char *zName; /* Name of the table */ int nCol; /* Number of columns in this table */ Column *aCol; /* Information about each column */ Index *pIndex; /* List of SQL indexes on this table. */ int tnum; /* Page containing root for this table */ | | | | | 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 | */ struct Table { char *zName; /* Name of the table */ int nCol; /* Number of columns in this table */ Column *aCol; /* Information about each column */ 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 */ }; /* ** Each SQL index is represented in memory by an ** instance of the following structure. ** ** The columns of the table that are to be indexed are described |
︙ | ︙ | |||
216 217 218 219 220 221 222 | */ struct Index { char *zName; /* Name of this index */ int nColumn; /* Number of columns in the table used by this index */ int *aiColumn; /* Which columns are used by this index. 1st is 0 */ Table *pTable; /* The SQL table being indexed */ int tnum; /* Page containing root of this index in database file */ | | | | | 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 | */ struct Index { char *zName; /* Name of this index */ int nColumn; /* Number of columns in the table used by this index */ int *aiColumn; /* Which columns are used by this index. 1st is 0 */ Table *pTable; /* The SQL table being indexed */ int tnum; /* Page containing root of this index in database file */ u8 isUnique; /* True if keys must all be unique */ u8 isCommit; /* True if creation of this index has been committed */ u8 isDelete; /* True if deletion of this index has not been comitted */ Index *pNext; /* The next index associated with the same table */ }; /* ** Each token coming out of the lexer is an instance of ** this structure. */ |
︙ | ︙ | |||
427 428 429 430 431 432 433 | void sqliteEndTable(Parse*,Token*); void sqliteDropTable(Parse*, Token*); void sqliteDeleteTable(sqlite*, Table*); void sqliteInsert(Parse*, Token*, ExprList*, Select*, IdList*); IdList *sqliteIdListAppend(IdList*, Token*); void sqliteIdListAddAlias(IdList*, Token*); void sqliteIdListDelete(IdList*); | | | 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 | void sqliteEndTable(Parse*,Token*); void sqliteDropTable(Parse*, Token*); void sqliteDeleteTable(sqlite*, Table*); void sqliteInsert(Parse*, Token*, ExprList*, Select*, IdList*); IdList *sqliteIdListAppend(IdList*, Token*); void sqliteIdListAddAlias(IdList*, Token*); void sqliteIdListDelete(IdList*); void sqliteCreateIndex(Parse*, Token*, Token*, IdList*, int, Token*, Token*); void sqliteDropIndex(Parse*, Token*); int sqliteSelect(Parse*, Select*, int, int); Select *sqliteSelectNew(ExprList*,IdList*,Expr*,ExprList*,Expr*,ExprList*,int); void sqliteSelectDelete(Select*); void sqliteDeleteFrom(Parse*, Token*, Expr*); void sqliteUpdate(Parse*, Token*, ExprList*, Expr*); WhereInfo *sqliteWhereBegin(Parse*, IdList*, Expr*, int); |
︙ | ︙ | |||
459 460 461 462 463 464 465 | Vdbe *sqliteGetVdbe(Parse*); int sqliteRandomByte(sqlite*); int sqliteRandomInteger(sqlite*); void sqliteBeginTransaction(Parse*); void sqliteCommitTransaction(Parse*); void sqliteRollbackTransaction(Parse*); char *sqlite_mprintf(const char *, ...); | < | 459 460 461 462 463 464 465 | Vdbe *sqliteGetVdbe(Parse*); int sqliteRandomByte(sqlite*); int sqliteRandomInteger(sqlite*); void sqliteBeginTransaction(Parse*); void sqliteCommitTransaction(Parse*); void sqliteRollbackTransaction(Parse*); char *sqlite_mprintf(const char *, ...); |
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.16 2001/09/27 03:22:34 drh Exp $ */ #include "sqliteInt.h" /* ** Process an UPDATE statement. */ void sqliteUpdate( |
︙ | ︙ | |||
202 203 204 205 206 207 208 | for(i=0; i<nIdx; i++){ sqliteVdbeAddOp(v, OP_Dup, pTab->nCol, 0, 0, 0); /* The KEY */ pIdx = apIdx[i]; for(j=0; j<pIdx->nColumn; j++){ sqliteVdbeAddOp(v, OP_Dup, j+pTab->nCol-pIdx->aiColumn[j], 0, 0, 0); } sqliteVdbeAddOp(v, OP_MakeIdxKey, pIdx->nColumn, 0, 0, 0); | | | 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 | for(i=0; i<nIdx; i++){ sqliteVdbeAddOp(v, OP_Dup, pTab->nCol, 0, 0, 0); /* The KEY */ pIdx = apIdx[i]; for(j=0; j<pIdx->nColumn; j++){ sqliteVdbeAddOp(v, OP_Dup, j+pTab->nCol-pIdx->aiColumn[j], 0, 0, 0); } sqliteVdbeAddOp(v, OP_MakeIdxKey, pIdx->nColumn, 0, 0, 0); sqliteVdbeAddOp(v, OP_PutIdx, base+i+1, pIdx->isUnique, 0, 0); } /* Write the new data back into the database. */ sqliteVdbeAddOp(v, OP_MakeRecord, pTab->nCol, 0, 0, 0); sqliteVdbeAddOp(v, OP_Put, base, 0, 0, 0); |
︙ | ︙ |
Changes to src/util.c.
︙ | ︙ | |||
10 11 12 13 14 15 16 | ** ************************************************************************* ** Utility functions used throughout sqlite. ** ** This file contains functions for allocating memory, comparing ** strings, and stuff like that. ** | | | 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 | ** ************************************************************************* ** Utility functions used throughout sqlite. ** ** This file contains functions for allocating memory, comparing ** strings, and stuff like that. ** ** $Id: util.c,v 1.29 2001/09/27 03:22:34 drh Exp $ */ #include "sqliteInt.h" #include <stdarg.h> #include <ctype.h> /* ** If malloc() ever fails, this global variable gets set to 1. |
︙ | ︙ | |||
983 984 985 986 987 988 989 990 991 992 993 | case SQLITE_NOTFOUND: z = "table or record not found"; break; case SQLITE_FULL: z = "database is full"; break; case SQLITE_CANTOPEN: z = "unable to open database file"; break; case SQLITE_PROTOCOL: z = "database locking protocol failure"; break; case SQLITE_EMPTY: z = "table contains no data"; break; case SQLITE_SCHEMA: z = "database schema has changed"; break; case SQLITE_TOOBIG: z = "too much data for one table row"; break; default: z = "unknown error"; break; } return z; } | > | 983 984 985 986 987 988 989 990 991 992 993 994 | case SQLITE_NOTFOUND: z = "table or record not found"; break; case SQLITE_FULL: z = "database is full"; break; case SQLITE_CANTOPEN: z = "unable to open database file"; break; case SQLITE_PROTOCOL: z = "database locking protocol failure"; break; case SQLITE_EMPTY: z = "table contains no data"; break; case SQLITE_SCHEMA: z = "database schema has changed"; break; case SQLITE_TOOBIG: z = "too much data for one table row"; break; case SQLITE_CONSTRAINT: z = "constraint failed"; break; default: z = "unknown error"; break; } return z; } |
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.78 2001/09/27 03:22:34 drh Exp $ */ #include "sqliteInt.h" #include <ctype.h> #include <unistd.h> /* ** SQL is translated into a sequence of instructions to be |
︙ | ︙ | |||
63 64 65 66 67 68 69 | int lastRecno; /* Last recno from a Next or NextIdx operation */ Bool recnoIsValid; /* True if lastRecno is valid */ Bool keyAsData; /* The OP_Column command works on key instead of data */ Bool atFirst; /* True if pointing to first entry */ Btree *pBt; /* Separate file holding temporary table */ char *zKey; /* Key used in BeginIdx and NextIdx operators */ int nKey; /* Number of bytes in zKey[] */ | < | 63 64 65 66 67 68 69 70 71 72 73 74 75 76 | int lastRecno; /* Last recno from a Next or NextIdx operation */ Bool recnoIsValid; /* True if lastRecno is valid */ Bool keyAsData; /* The OP_Column command works on key instead of data */ Bool atFirst; /* True if pointing to first entry */ Btree *pBt; /* Separate file holding temporary table */ char *zKey; /* Key used in BeginIdx and NextIdx operators */ int nKey; /* Number of bytes in zKey[] */ }; typedef struct Cursor Cursor; /* ** A sorter builds a list of elements to be sorted. Each element of ** the list is an instance of the following structure. */ |
︙ | ︙ | |||
2615 2616 2617 2618 2619 2620 2621 | int res, rx; Cursor *pCrsr; VERIFY( if( tos<0 ) goto not_enough_stack; ) if( i>=0 && i<p->nCursor && (pCrsr = &p->aCsr[i])->pCursor!=0 ){ if( Stringify(p, tos) ) goto no_mem; if( pCrsr->zKey ) sqliteFree(pCrsr->zKey); pCrsr->nKey = aStack[tos].n; | | < | 2614 2615 2616 2617 2618 2619 2620 2621 2622 2623 2624 2625 2626 2627 2628 2629 | int res, rx; Cursor *pCrsr; VERIFY( if( tos<0 ) goto not_enough_stack; ) if( i>=0 && i<p->nCursor && (pCrsr = &p->aCsr[i])->pCursor!=0 ){ if( Stringify(p, tos) ) goto no_mem; if( pCrsr->zKey ) sqliteFree(pCrsr->zKey); pCrsr->nKey = aStack[tos].n; pCrsr->zKey = sqliteMalloc( pCrsr->nKey ); if( pCrsr->zKey==0 ) goto no_mem; memcpy(pCrsr->zKey, zStack[tos], aStack[tos].n); pCrsr->zKey[aStack[tos].n] = 0; rx = sqliteBtreeMoveto(pCrsr->pCursor, zStack[tos], aStack[tos].n, &res); pCrsr->atFirst = rx==SQLITE_OK && res>0; pCrsr->recnoIsValid = 0; } POPSTACK; |
︙ | ︙ | |||
2658 2659 2660 2661 2662 2663 2664 | res = 0; }else{ rx = sqliteBtreeNext(pCur, &res); if( rx!=SQLITE_OK ) goto abort_due_to_error; } sqliteBtreeKeySize(pCur, &size); if( res>0 || size!=pCrsr->nKey+sizeof(u32) || | | | | > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | | 2656 2657 2658 2659 2660 2661 2662 2663 2664 2665 2666 2667 2668 2669 2670 2671 2672 2673 2674 2675 2676 2677 2678 2679 2680 2681 2682 2683 2684 2685 2686 2687 2688 2689 2690 2691 2692 2693 2694 2695 2696 2697 2698 2699 2700 2701 2702 2703 2704 2705 2706 2707 2708 2709 2710 2711 2712 2713 2714 2715 2716 2717 2718 2719 2720 2721 2722 2723 2724 2725 2726 2727 2728 2729 2730 2731 2732 | res = 0; }else{ rx = sqliteBtreeNext(pCur, &res); if( rx!=SQLITE_OK ) goto abort_due_to_error; } sqliteBtreeKeySize(pCur, &size); if( res>0 || size!=pCrsr->nKey+sizeof(u32) || sqliteBtreeKeyCompare(pCur, pCrsr->zKey, pCrsr->nKey, &res)!=SQLITE_OK || res!=0 ){ pc = pOp->p2 - 1; POPSTACK; }else{ int recno; sqliteBtreeKey(pCur, pCrsr->nKey, sizeof(u32), (char*)&recno); recno = bigEndian(recno); p->aCsr[i].lastRecno = aStack[tos].i = recno; p->aCsr[i].recnoIsValid = 1; aStack[tos].flags = STK_Int; } } break; } /* Opcode: PutIdx P1 P2 P3 ** ** The top of the stack hold an SQL index key made using the ** MakeIdxKey instruction. This opcode writes that key into the ** index P1. Data for the entry is nil. ** ** If P2==1, then the key must be unique. If the key is not unique, ** the program aborts with a SQLITE_CONSTRAINT error and the database ** is rolled back. If P3 is not null, then it because part of the ** error message returned with the SQLITE_CONSTRAINT. */ case OP_PutIdx: { int i = pOp->p1; int tos = p->tos; BtCursor *pCrsr; VERIFY( if( tos<0 ) goto not_enough_stack; ) if( VERIFY( i>=0 && i<p->nCursor && ) (pCrsr = p->aCsr[i].pCursor)!=0 ){ int nKey = aStack[tos].n; const char *zKey = zStack[tos]; if( pOp->p2 ){ int res, n; assert( aStack[tos].n >= 4 ); rc = sqliteBtreeMoveto(pCrsr, zKey, nKey-4, &res); if( rc!=SQLITE_OK ) goto abort_due_to_error; while( res!=0 ){ int c; sqliteBtreeKeySize(pCrsr, &n); if( n==nKey && sqliteBtreeKeyCompare(pCrsr, zKey, nKey-4, &c)==SQLITE_OK && c==0 ){ rc = SQLITE_CONSTRAINT; if( pOp->p3 && pOp->p3[0] ){ sqliteSetString(pzErrMsg, "duplicate index entry: ", pOp->p3,0); } goto abort_due_to_error; } if( res<0 ){ sqliteBtreeNext(pCrsr, &res); res = +1; }else{ break; } } } rc = sqliteBtreeInsert(pCrsr, zKey, nKey, "", 0); } POPSTACK; break; } /* Opcode: DeleteIdx P1 * * ** |
︙ | ︙ |
Changes to www/changes.tcl.
︙ | ︙ | |||
14 15 16 17 18 19 20 21 22 23 24 25 26 27 | proc chng {date desc} { puts "<DT><B>$date</B></DT>" puts "<DD><P><UL>$desc</UL></P></DD>" } chng {2001 Sep 22 (2.0-beta-1)} { <li>Fixes to the rollback and locking behavior</li> } chng {2001 Sep 20 (2.0-alpha-2)} { <li>Initial release of version 2.0. The idea of renaming the library to "SQLus" was abandoned in favor of keeping the "SQLite" name and bumping the major version number.</li> | > > | 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 | proc chng {date desc} { puts "<DT><B>$date</B></DT>" puts "<DD><P><UL>$desc</UL></P></DD>" } chng {2001 Sep 22 (2.0-beta-1)} { <li>SQLite now honors the UNIQUE keyword in CREATE UNIQUE INDEX. Primary keys are required to unique indices.</li> <li>Fixes to the rollback and locking behavior</li> } chng {2001 Sep 20 (2.0-alpha-2)} { <li>Initial release of version 2.0. The idea of renaming the library to "SQLus" was abandoned in favor of keeping the "SQLite" name and bumping the major version number.</li> |
︙ | ︙ |