Many hyperlinks are disabled.
Use anonymous login
to enable hyperlinks.
Overview
Comment: | Add a new column in the SQLITE_MASTER table to record the root page number of primary key indices. (CVS 252) |
---|---|
Downloads: | Tarball | ZIP archive |
Timelines: | family | ancestors | descendants | both | trunk |
Files: | files | file ages | folders |
SHA1: |
602ea4f9f641070592c788ce22859b84 |
User & Date: | drh 2001-09-17 20:25:58.000 |
Context
2001-09-17
| ||
20:48 | Enchanced transaction tests (CVS 253) (check-in: b30f2b5e15 user: drh tags: trunk) | |
20:25 | Add a new column in the SQLITE_MASTER table to record the root page number of primary key indices. (CVS 252) (check-in: 602ea4f9f6 user: drh tags: trunk) | |
2001-09-16
| ||
13:36 | Version to 2.0.0 (CVS 251) (check-in: c67f6db681 user: drh tags: trunk) | |
Changes
Changes to Makefile.in.
︙ | ︙ | |||
70 71 72 73 74 75 76 77 78 79 80 81 82 83 | $(TOP)/src/btree.c \ $(TOP)/src/btree.h \ $(TOP)/src/build.c \ $(TOP)/src/delete.c \ $(TOP)/src/expr.c \ $(TOP)/src/insert.c \ $(TOP)/src/main.c \ $(TOP)/src/pager.c \ $(TOP)/src/pager.h \ $(TOP)/src/parse.y \ $(TOP)/src/printf.c \ $(TOP)/src/random.c \ $(TOP)/src/select.c \ $(TOP)/src/shell.c \ | > | 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 | $(TOP)/src/btree.c \ $(TOP)/src/btree.h \ $(TOP)/src/build.c \ $(TOP)/src/delete.c \ $(TOP)/src/expr.c \ $(TOP)/src/insert.c \ $(TOP)/src/main.c \ $(TOP)/src/os.c \ $(TOP)/src/pager.c \ $(TOP)/src/pager.h \ $(TOP)/src/parse.y \ $(TOP)/src/printf.c \ $(TOP)/src/random.c \ $(TOP)/src/select.c \ $(TOP)/src/shell.c \ |
︙ | ︙ |
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.37 2001/09/17 20:25:58 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 |
︙ | ︙ | |||
500 501 502 503 504 505 506 | pParse->pNewTable = 0; db->nTable++; db->flags |= SQLITE_InternChanges; } /* If the initFlag is 1 it means we are reading the SQL off the ** "sqlite_master" table on the disk. So do not write to the disk | | > > > > > > | | > | > < < < < < < < < < < < < | | | | < < | | > | > > > > > > > > > > > > > > | 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 | pParse->pNewTable = 0; db->nTable++; db->flags |= SQLITE_InternChanges; } /* If the initFlag is 1 it means we are reading the SQL off the ** "sqlite_master" table on the disk. So do not write to the disk ** again. Extract the root page number for the table from the ** pParse->newTnum field. (The page number should have been put ** there by the sqliteOpenCb routine.) If the table has a primary ** key, the root page of the index associated with the primary key ** should be in pParse->newKnum. */ if( pParse->initFlag ){ p->tnum = pParse->newTnum; if( p->pIndex ){ p->pIndex->tnum = pParse->newKnum; } } /* If not initializing, then create a record for the new table ** in the SQLITE_MASTER table of the database. */ if( !pParse->initFlag ){ int n, base; Vdbe *v; v = sqliteGetVdbe(pParse); if( v==0 ) return; n = (int)pEnd->z - (int)pParse->sFirstToken.z + 1; sqliteVdbeAddOp(v, OP_Open, 0, 2, MASTER_NAME, 0); sqliteVdbeAddOp(v, OP_NewRecno, 0, 0, 0, 0); sqliteVdbeAddOp(v, OP_String, 0, 0, "table", 0); sqliteVdbeAddOp(v, OP_String, 0, 0, p->zName, 0); sqliteVdbeAddOp(v, OP_String, 0, 0, p->zName, 0); sqliteVdbeAddOp(v, OP_CreateTable, 0, 0, 0, 0); sqliteVdbeTableRootAddr(v, &p->tnum); if( p->pIndex ){ /* If the table has a primary key, create an index in the database ** for that key and record the root page of the index in the "knum" ** column of of the SQLITE_MASTER table. */ Index *pIndex = p->pIndex; assert( pIndex->pNext==0 ); assert( pIndex->tnum==0 ); sqliteVdbeAddOp(v, OP_CreateIndex, 0, 0, 0, 0), sqliteVdbeIndexRootAddr(v, &pIndex->tnum); }else{ /* If the table does not have a primary key, the "knum" column is ** fill with a NULL value. */ sqliteVdbeAddOp(v, OP_Null, 0, 0, 0, 0); } base = sqliteVdbeAddOp(v, OP_String, 0, 0, 0, 0); sqliteVdbeChangeP3(v, base, pParse->sFirstToken.z, n); sqliteVdbeAddOp(v, OP_MakeRecord, 6, 0, 0, 0); sqliteVdbeAddOp(v, OP_Put, 0, 0, 0, 0); changeCookie(db); sqliteVdbeAddOp(v, OP_SetCookie, db->next_cookie, 0, 0, 0); sqliteVdbeAddOp(v, OP_Close, 0, 0, 0, 0); if( (db->flags & SQLITE_InTrans)==0 ){ sqliteVdbeAddOp(v, OP_Commit, 0, 0, 0, 0); } } } /* |
︙ | ︙ | |||
600 601 602 603 604 605 606 | if( v ){ static VdbeOp dropTable[] = { { OP_Open, 0, 2, MASTER_NAME}, { OP_Rewind, 0, 0, 0}, { OP_String, 0, 0, 0}, /* 2 */ { OP_Next, 0, ADDR(9), 0}, /* 3 */ { OP_Dup, 0, 0, 0}, | | | 609 610 611 612 613 614 615 616 617 618 619 620 621 622 623 | if( v ){ static VdbeOp dropTable[] = { { OP_Open, 0, 2, MASTER_NAME}, { OP_Rewind, 0, 0, 0}, { OP_String, 0, 0, 0}, /* 2 */ { OP_Next, 0, ADDR(9), 0}, /* 3 */ { OP_Dup, 0, 0, 0}, { OP_Column, 0, 2, 0}, { OP_Ne, 0, ADDR(3), 0}, { OP_Delete, 0, 0, 0}, { OP_Goto, 0, ADDR(3), 0}, { OP_Destroy, 0, 0, 0}, /* 9 */ { OP_SetCookie, 0, 0, 0}, /* 10 */ { OP_Close, 0, 0, 0}, }; |
︙ | ︙ | |||
668 669 670 671 672 673 674 675 676 677 678 679 680 681 682 683 684 685 686 687 688 | if( pParse->nErr || sqlite_malloc_failed ) goto exit_create_index; /* ** Find the table that is to be indexed. Return early if not found. */ if( pTable!=0 ){ pTab = sqliteTableFromToken(pParse, pTable); }else{ pTab = pParse->pNewTable; } if( pTab==0 || pParse->nErr ) goto exit_create_index; if( pTab->readOnly ){ sqliteSetString(&pParse->zErrMsg, "table ", pTab->zName, " may not have new indices added", 0); pParse->nErr++; goto exit_create_index; } /* ** Find the name of the index. Make sure there is not already another | > > | > > < < < < | | | | | | | | | | | | > > > > > | 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 722 723 724 725 726 727 728 729 | if( pParse->nErr || sqlite_malloc_failed ) goto exit_create_index; /* ** Find the table that is to be indexed. Return early if not found. */ if( pTable!=0 ){ assert( pName!=0 ); pTab = sqliteTableFromToken(pParse, pTable); }else{ assert( pName==0 ); pTab = pParse->pNewTable; } if( pTab==0 || pParse->nErr ) goto exit_create_index; if( pTab->readOnly ){ sqliteSetString(&pParse->zErrMsg, "table ", pTab->zName, " may not have new indices added", 0); pParse->nErr++; goto exit_create_index; } /* ** Find the name of the index. Make sure there is not already another ** index or table with the same name. If pName==0 it means that we are ** dealing with a primary key, which has no name, so this step can be ** skipped. */ if( pName ){ zName = sqliteTableNameFromToken(pName); if( zName==0 ) goto exit_create_index; if( sqliteFindIndex(db, zName) ){ sqliteSetString(&pParse->zErrMsg, "index ", zName, " already exists", 0); pParse->nErr++; goto exit_create_index; } if( sqliteFindTable(db, zName) ){ sqliteSetString(&pParse->zErrMsg, "there is already a table named ", zName, 0); pParse->nErr++; goto exit_create_index; } }else{ zName = 0; sqliteSetString(&zName, pTab->zName, " (primary key)", 0); if( zName==0 ) goto exit_create_index; } /* If pList==0, it means this routine was called to make a primary ** key out of the last column added to the table under construction. ** So create a fake list to simulate this. */ if( pList==0 ){ |
︙ | ︙ | |||
746 747 748 749 750 751 752 | sqliteFree(pIndex); goto exit_create_index; } pIndex->aiColumn[i] = j; } /* Link the new Index structure to its table and to the other | | > > | | | > | 760 761 762 763 764 765 766 767 768 769 770 771 772 773 774 775 776 777 778 779 780 781 782 | sqliteFree(pIndex); goto exit_create_index; } pIndex->aiColumn[i] = j; } /* Link the new Index structure to its table and to the other ** in-memory database structures. Note that primary key indices ** do not appear in the index hash table. */ if( pParse->explain==0 ){ if( pName!=0 ){ h = sqliteHashNoCase(pIndex->zName, 0) % N_HASH; pIndex->pHash = db->apIdxHash[h]; db->apIdxHash[h] = pIndex; } pIndex->pNext = pTab->pIndex; pTab->pIndex = pIndex; db->flags |= SQLITE_InternChanges; } /* If the initFlag is 1 it means we are reading the SQL off the ** "sqlite_master" table on the disk. So do not write to the disk |
︙ | ︙ | |||
788 789 790 791 792 793 794 795 796 | */ else if( pParse->initFlag==0 && pTable!=0 ){ static VdbeOp addTable[] = { { OP_Open, 2, 2, MASTER_NAME}, { OP_NewRecno, 2, 0, 0}, { OP_String, 0, 0, "index"}, { OP_String, 0, 0, 0}, /* 3 */ { OP_CreateIndex, 1, 0, 0}, { OP_Dup, 0, 0, 0}, | > | | | | | > < | | | | 805 806 807 808 809 810 811 812 813 814 815 816 817 818 819 820 821 822 823 824 825 826 827 828 829 830 831 832 833 834 835 836 837 838 839 840 841 842 843 844 845 846 847 848 849 850 851 | */ else if( pParse->initFlag==0 && pTable!=0 ){ static VdbeOp addTable[] = { { OP_Open, 2, 2, MASTER_NAME}, { OP_NewRecno, 2, 0, 0}, { OP_String, 0, 0, "index"}, { OP_String, 0, 0, 0}, /* 3 */ { OP_String, 0, 0, 0}, /* 4 */ { OP_CreateIndex, 1, 0, 0}, { OP_Dup, 0, 0, 0}, { OP_Open, 1, 0, 0}, /* 7 */ { OP_Null, 0, 0, 0}, { OP_String, 0, 0, 0}, /* 9 */ { OP_MakeRecord, 6, 0, 0}, { OP_Put, 2, 0, 0}, { OP_SetCookie, 0, 0, 0}, /* 12 */ { OP_Close, 2, 0, 0}, }; int n; Vdbe *v = pParse->pVdbe; int lbl1, lbl2; int i; v = sqliteGetVdbe(pParse); if( v==0 ) goto exit_create_index; if( pTable!=0 && (db->flags & SQLITE_InTrans)==0 ){ sqliteVdbeAddOp(v, OP_Transaction, 0, 0, 0, 0); sqliteVdbeAddOp(v, OP_VerifyCookie, db->schema_cookie, 0, 0, 0); } if( pStart && pEnd ){ int base; n = (int)pEnd->z - (int)pStart->z + 1; base = sqliteVdbeAddOpList(v, ArraySize(addTable), addTable); sqliteVdbeChangeP3(v, base+3, pIndex->zName, 0); sqliteVdbeChangeP3(v, base+4, pTab->zName, 0); sqliteVdbeIndexRootAddr(v, &pIndex->tnum); sqliteVdbeChangeP3(v, base+7, pIndex->zName, 0); sqliteVdbeChangeP3(v, base+9, pStart->z, n); changeCookie(db); sqliteVdbeChangeP1(v, base+12, db->next_cookie); } sqliteVdbeAddOp(v, OP_Open, 0, pTab->tnum, pTab->zName, 0); lbl1 = sqliteVdbeMakeLabel(v); lbl2 = sqliteVdbeMakeLabel(v); sqliteVdbeAddOp(v, OP_Rewind, 0, 0, 0, 0); sqliteVdbeAddOp(v, OP_Next, 0, lbl2, 0, lbl1); sqliteVdbeAddOp(v, OP_Recno, 0, 0, 0, 0); |
︙ | ︙ |
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 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 | ** ************************************************************************* ** 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.38 2001/09/17 20:25:58 drh Exp $ */ #include "sqliteInt.h" #if defined(HAVE_USLEEP) && HAVE_USLEEP #include <unistd.h> #endif /* ** This is the callback routine for the code that initializes the ** database. Each callback contains the following information: ** ** argv[0] = "meta" or "table" or "index" ** argv[1] = table or index name or meta statement type. ** argv[2] = root page number for table or index. NULL for meta. ** argv[3] = root page number of primary key for tables or NULL. ** argv[4] = SQL create statement for the table or index ** */ static int sqliteOpenCb(void *pDb, int argc, char **argv, char **azColName){ sqlite *db = (sqlite*)pDb; Parse sParse; int nErr = 0; /* TODO: Do some validity checks on all fields. In particular, ** make sure fields do not contain NULLs. */ assert( argc==5 ); switch( argv[0][0] ){ case 'm': { /* Meta information */ if( strcmp(argv[1],"file-format")==0 ){ db->file_format = atoi(argv[4]); }else if( strcmp(argv[1],"schema-cookie")==0 ){ db->schema_cookie = atoi(argv[4]); db->next_cookie = db->schema_cookie; } break; } case 'i': case 't': { /* CREATE TABLE and CREATE INDEX statements */ memset(&sParse, 0, sizeof(sParse)); sParse.db = db; sParse.initFlag = 1; sParse.newTnum = atoi(argv[2]); sParse.newKnum = argv[3] ? atoi(argv[3]) : 0; nErr = sqliteRunParser(&sParse, argv[4], 0); break; } default: { /* This can not happen! */ nErr = 1; assert( nErr==0 ); } |
︙ | ︙ | |||
84 85 86 87 88 89 90 91 | /* ** The master database table has a structure like this */ static char master_schema[] = "CREATE TABLE " MASTER_NAME " (\n" " type text,\n" " name text,\n" " tnum integer,\n" | > | > | | 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 | /* ** The master database table has a structure like this */ static char master_schema[] = "CREATE TABLE " MASTER_NAME " (\n" " type text,\n" " name text,\n" " tbl_name text,\n" " tnum integer,\n" " knum integer,\n" " sql text\n" ")" ; /* The following program is used to initialize the internal ** structure holding the tables and indexes of the database. ** The database contains a special table named "sqlite_master" ** defined as follows: ** ** CREATE TABLE sqlite_master ( ** type text, -- Either "table" or "index" or "meta" ** name text, -- Name of table or index ** tbl_name text, -- Associated table ** tnum integer, -- The integer page number of root page ** knum integer, -- Root page of primary key, or NULL ** sql text -- The CREATE statement for this object ** ); ** ** The sqlite_master table contains a single entry for each table ** and each index. The "type" column tells whether the entry is ** a table or index. The "name" column is the name of the object. ** The "tbl_name" is the name of the associated table. For tables, |
︙ | ︙ | |||
127 128 129 130 131 132 133 | ** SQL for each index. The callback will invoke the ** parser to build the internal representation of the ** database scheme. */ static VdbeOp initProg[] = { { OP_Open, 0, 2, 0}, { OP_Rewind, 0, 0, 0}, | | | > | | | | | | > | | | | | | > | | | | | > | | 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 | ** SQL for each index. The callback will invoke the ** parser to build the internal representation of the ** database scheme. */ static VdbeOp initProg[] = { { OP_Open, 0, 2, 0}, { OP_Rewind, 0, 0, 0}, { OP_Next, 0, 13, 0}, /* 2 */ { OP_Column, 0, 0, 0}, { OP_String, 0, 0, "meta"}, { OP_Ne, 0, 2, 0}, { OP_Column, 0, 0, 0}, { OP_Column, 0, 1, 0}, { OP_Column, 0, 3, 0}, { OP_Null, 0, 0, 0}, { OP_Column, 0, 5, 0}, { OP_Callback, 5, 0, 0}, { OP_Goto, 0, 2, 0}, { OP_Rewind, 0, 0, 0}, /* 13 */ { OP_Next, 0, 25, 0}, /* 14 */ { OP_Column, 0, 0, 0}, { OP_String, 0, 0, "table"}, { OP_Ne, 0, 14, 0}, { OP_Column, 0, 0, 0}, { OP_Column, 0, 1, 0}, { OP_Column, 0, 3, 0}, { OP_Column, 0, 4, 0}, { OP_Column, 0, 5, 0}, { OP_Callback, 5, 0, 0}, { OP_Goto, 0, 14, 0}, { OP_Rewind, 0, 0, 0}, /* 25 */ { OP_Next, 0, 37, 0}, /* 26 */ { OP_Column, 0, 0, 0}, { OP_String, 0, 0, "index"}, { OP_Ne, 0, 26, 0}, { OP_Column, 0, 0, 0}, { OP_Column, 0, 1, 0}, { OP_Column, 0, 3, 0}, { OP_Null, 0, 0, 0}, { OP_Column, 0, 5, 0}, { OP_Callback, 5, 0, 0}, { OP_Goto, 0, 26, 0}, { OP_String, 0, 0, "meta"}, /* 37 */ { OP_String, 0, 0, "schema-cookie"}, { OP_Null, 0, 0, 0}, { OP_Null, 0, 0, 0}, { OP_ReadCookie,0,0, 0}, { OP_Callback, 5, 0, 0}, { OP_Close, 0, 0, 0}, { OP_Halt, 0, 0, 0}, }; /* Create a virtual machine to run the initialization program. Run ** the program. The delete the virtual machine. */ |
︙ | ︙ | |||
186 187 188 189 190 191 192 | sqliteVdbeDelete(vdbe); if( rc==SQLITE_OK && db->file_format>1 && db->nTable>0 ){ sqliteSetString(pzErrMsg, "unsupported file format", 0); rc = SQLITE_ERROR; } if( rc==SQLITE_OK ){ Table *pTab; | | | | > | | 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 | sqliteVdbeDelete(vdbe); if( rc==SQLITE_OK && db->file_format>1 && db->nTable>0 ){ sqliteSetString(pzErrMsg, "unsupported file format", 0); rc = SQLITE_ERROR; } if( rc==SQLITE_OK ){ Table *pTab; char *azArg[6]; azArg[0] = "table"; azArg[1] = MASTER_NAME; azArg[2] = "2"; azArg[3] = 0; azArg[4] = master_schema; azArg[5] = 0; sqliteOpenCb(db, 5, azArg, 0); pTab = sqliteFindTable(db, MASTER_NAME); if( pTab ){ pTab->readOnly = 1; } db->flags |= SQLITE_Initialized; sqliteCommitInternalChanges(db); } |
︙ | ︙ |
Added src/os.c.
> > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 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 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 242 243 244 245 246 247 248 249 250 | /* ** 2001 September 16 ** ** 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 contains code that is specific to particular operating ** systems. The purpose of this file is to provide a uniform abstract ** on which the rest of SQLite can operate. */ #include "sqliteInt.h" #include "os.h" #if OS_UNIX # include <fcntl.h> # include <sys/stat.h> # include <unistd.h> # include <time.h> #endif #if OS_WIN # include <winbase.h> #endif /* ** Attempt to open a file for both reading and writing. If that ** fails, try opening it read-only. If the file does not exist, ** try to create it. ** ** On success, a handle for the open file is written to *pResult ** and *pReadonly is set to 0 if the file was opened for reading and ** writing or 1 if the file was opened read-only. The function returns ** SQLITE_OK. ** ** On failure, the function returns SQLITE_CANTOPEN and leaves ** *pResulst and *pReadonly unchanged. */ int sqliteOsOpenReadWrite(char *zFilename, OsFile *pResult, int *pReadonly){ #if OS_UNIX int fd = open(zFilename, O_RDWR|O_CREAT, 0644); if( fd<0 ){ fd = open(zFilename, O_RDONLY); if( fd<0 ){ return SQLITE_CANTOPEN; } *pReadonly = 1; }else{ *pReadonly = 0; } *pResult = fd; return SQLITE_OK; #endif #if OS_WIN HANDLE h = CreateFile(zFilename, GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_ALWAYS, FILE_ATTRIBUTE_NORMAL | FILE_FLAG_RANDOM_ACCESS, NULL ); if( h==INVALID_HANDLE_VALUE ){ HANDLE h = CreateFile(zFilename, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_ALWAYS, FILE_ATTRIBUTE_NORMAL | FILE_FLAG_RANDOM_ACCESS, NULL ); if( h==INVALID_HANDLE_VALUE ){ return SQLITE_CANTOPEN; } *pReadonly = 1; }else{ *pReadonly = 0; } *pResult = h; return SQLITE_OK; #endif /* ** Attempt to open a new file for exclusive access by this process. ** The file will be opened for both reading and writing. To avoid ** a potential security problem, we do not allow the file to have ** previously existed. Nor do we allow the file to be a symbolic ** link. ** ** On success, write the file handle into *pResult and return SQLITE_OK. ** ** On failure, return SQLITE_CANTOPEN. */ int sqliteOsOpenExclusive(char *zFilename, OsFile *pResult){ #if OS_UNIX struct stat buf; time_t now; int fd; if( access(zFilename, 0)==0 ){ return SQLITE_CANTOPEN; } #ifndef O_NOFOLLOW # define O_NOFOLLOW 0 #endif fd = open(zFilename, O_RDWR|O_CREAT|O_EXCL|O_NOFOLLOW, 0600); if( fd<0 ){ return SQLITE_CANTOPEN; } *pResult = fd; return SQLITE_OK; #endif #if OS_WIN HANDLE h = CreateFile(zFilename, GENERIC_READ | GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL | FILE_FLAG_RANDOM_ACCESS, NULL ); if( h==INVALID_HANDLE_VALUE ){ return SQLITE_CANTOPEN; } *pResult = h; return SQLITE_OK; #endif } /* ** Create a temporary file name in zBuf. zBuf must be big enough to ** hold at least SQLITE_TEMPNAME_SIZE characters. */ int sqliteOsTempFileName(char *zBuf){ #if OS_UNIX static const char *azDirs[] = { ".", "/var/tmp", "/usr/tmp", "/tmp", }; static char zChars[] = "abcdefghijklmnopqrstuvwxyz" "ABCDEFGHIJKLMNOPQRSTUVWXYZ" "0123456789"; int i, j; struct stat buf; char *zDir = "."; for(i=0; i<sizeof(azDirs)/sizeof(azDirs[0]); i++){ if( stat(azDirs[i], &buf) ) continue; if( !S_ISDIR(buf.st_mode) ) continue; if( access(azDirs[i], 07) ) continue; zDir = azDirs[i]; break; } do{ sprintf(zBuf, "%s/sqlite_", zDir); j = strlen(zBuf); for(i=0; i<15; i++){ int n = sqliteRandomByte() % sizeof(zChars); zBuf[j++] = zChars[n]; } zBuf[j] = 0; }while( access(zBuf,0)==0 ); #endif #if OS_WIN int i, j; HANDLE h; char zTempPath[SQLITE_TEMPNAME_SIZE]; GetTempPath(SQLITE_TEMPNAME_SIZE-30, zTempPath); for(;;){ sprintf(zBuf, "%s/sqlite_", zTempPath); j = strlen(zBuf); for(i=0; i<15; i++){ int n = sqliteRandomByte() % sizeof(zChars); zBuf[j++] = zChars[n]; } zBuf[j] = 0; h = CreateFile(zBuf, GENERIC_READ, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL | FILE_FLAG_RANDOM_ACCESS, NULL ); if( h!=INVALID_FILE_HANDLE ){ CloseHandle(h); continue; } break; } #endif return SQLITE_OK; } /* ** Close a file */ int sqliteOsClose(OsFile id){ #if OS_UNIX close(id); return SQLITE_OK; #endif #if OS_WIN CloseHandle(id); return SQLITE_OK; #endif } /* ** Read data from a file into a buffer */ /* ** Write data from a buffer into a file */ /* ** Move the read/write pointer in a file. */ /* ** Make sure all writes to a particular file are committed to disk. */ /* ** Truncate an open file to a specified size */ /* ** Determine the current size of a file in bytes */ /* ** Get a read or write lock on a file. */ /* ** Release the read or write lock from a file. */ /* ** Get information to seed the random number generator. */ /* ** Sleep for a little while. */ #endif /* OS_WIN */ |
Added src/os.h.
> > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 | /* ** 2001 September 16 ** ** 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 header file (together with is companion C source-code file ** "os.c") attempt to abstract the underlying operating system so that ** the SQLite library will work on both POSIX and windows systems. */ #ifndef _SQLITE_OS_H_ #define _SQLITE_OS_H_ /* ** A handle for an open file is stored in an OsFile object. */ #if OS_UNIX typedef int OsFile; # define SQLITE_TEMPNAME_SIZE 200 #endif #if OS_WIN typedef HANDLE OsFile; # define SQLITE_TEMPNAME_SIZE (MAX_PATH+1) #endif int sqliteOsOpenReadWrite(char*, OsFile*, int*); int sqliteOsOpenExclusive(char*, OsFile*); int sqliteOsTempFileName(char*); int sqliteOsClose(OsFile); int sqliteOsRead(OsFile, int amt, void*); int sqliteOsWrite(OsFile, int amt, void*); int sqliteOsSeek(OsFile, int offset); int sqliteOsSync(OsFile); int sqliteOsTruncate(OsFile, int size); int sqliteOsFileSize(OsFile, int *pSize); int sqliteOsLock(OsFile, int wrlock); int sqliteOsUnlock(OsFile); int sqliteOsRandomSeed(int amt, char*); int sqliteSleep(int ms); #endif /* _SQLITE_OS_H_ */ |
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.52 2001/09/17 20:25:58 drh Exp $ */ #include "sqlite.h" #include "vdbe.h" #include "parse.h" #include "btree.h" #include <stdio.h> #include <stdlib.h> |
︙ | ︙ | |||
362 363 364 365 366 367 368 369 370 371 372 373 374 375 | Token sLastToken; /* The last token parsed */ Table *pNewTable; /* A table being constructed by CREATE TABLE */ Vdbe *pVdbe; /* An engine for executing database bytecode */ int colNamesSet; /* TRUE after OP_ColumnCount has been issued to pVdbe */ int explain; /* True if the EXPLAIN flag is found on the query */ int initFlag; /* True if reparsing CREATE TABLEs */ int newTnum; /* Table number to use when reparsing CREATE TABLEs */ int nErr; /* Number of errors seen */ int nTab; /* Number of previously allocated cursors */ int nMem; /* Number of memory cells used so far */ int nSet; /* Number of sets used so far */ int nAgg; /* Number of aggregate expressions */ AggExpr *aAgg; /* An array of aggregate expressions */ int iAggCount; /* Index of the count(*) aggregate in aAgg[] */ | > | 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 | Token sLastToken; /* The last token parsed */ Table *pNewTable; /* A table being constructed by CREATE TABLE */ Vdbe *pVdbe; /* An engine for executing database bytecode */ int colNamesSet; /* TRUE after OP_ColumnCount has been issued to pVdbe */ int explain; /* True if the EXPLAIN flag is found on the query */ int initFlag; /* True if reparsing CREATE TABLEs */ int newTnum; /* Table number to use when reparsing CREATE TABLEs */ int newKnum; /* Primary key number when reparsing CREATE TABLEs */ int nErr; /* Number of errors seen */ int nTab; /* Number of previously allocated cursors */ int nMem; /* Number of memory cells used so far */ int nSet; /* Number of sets used so far */ int nAgg; /* Number of aggregate expressions */ AggExpr *aAgg; /* An array of aggregate expressions */ int iAggCount; /* Index of the count(*) aggregate in aAgg[] */ |
︙ | ︙ |
Changes to test/index.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 file is testing the CREATE INDEX statement. # | | | 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 file is testing the CREATE INDEX statement. # # $Id: index.test,v 1.13 2001/09/17 20:25:58 drh Exp $ set testdir [file dirname $argv0] source $testdir/tester.tcl # Create a basic index and verify it is added to sqlite_master # do_test index-1.1 { |
︙ | ︙ | |||
200 201 202 203 204 205 206 | execsql {SELECT count(*) FROM test1} } {19} do_test index-7.2 { execsql {SELECT f1 FROM test1 WHERE f2=65536} } {16} do_test index-7.3 { set code [execsql {EXPLAIN SELECT f1 FROM test1 WHERE f2=65536}] | | | 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 | execsql {SELECT count(*) FROM test1} } {19} do_test index-7.2 { execsql {SELECT f1 FROM test1 WHERE f2=65536} } {16} do_test index-7.3 { set code [execsql {EXPLAIN SELECT f1 FROM test1 WHERE f2=65536}] expr {[lsearch $code {test1 (primary key)}]>0} } {1} do_test index-7.4 { execsql {DROP table test1} execsql {SELECT name FROM sqlite_master WHERE type!='meta'} } {} # Make sure we cannot drop a non-existant index. |
︙ | ︙ |