Many hyperlinks are disabled.
Use anonymous login
to enable hyperlinks.
Overview
Comment: | More bugs fixed for views. (CVS 416) |
---|---|
Downloads: | Tarball | ZIP archive |
Timelines: | family | ancestors | descendants | both | trunk |
Files: | files | file ages | folders |
SHA1: |
813077623087ffc6cd506f57cf6d1e3d |
User & Date: | drh 2002-03-03 23:06:01.000 |
Context
2002-03-04
| ||
02:26 | Updates to the documentation. Changed version number to 2.4.0-beta1 (CVS 417) (check-in: 36a8fe0ad0 user: drh tags: trunk) | |
2002-03-03
| ||
23:06 | More bugs fixed for views. (CVS 416) (check-in: 8130776230 user: drh tags: trunk) | |
18:59 | VIEWs are bound to tables when they are used, not when they are first entered. This works around the problem of what to do if a table is deleted that a view refers to. (CVS 415) (check-in: 6121e5ab93 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.58 2002/03/03 23:06:01 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. |
︙ | ︙ | |||
2984 2985 2986 2987 2988 2989 2990 2991 2992 2993 2994 2995 2996 2997 | */ checkList(&sCheck, 1, pBt->page1->freeList, pBt->page1->nFree, "Main freelist: "); /* Check all the tables. */ for(i=0; i<nRoot; i++){ checkTreePage(&sCheck, aRoot[i], 0, "List of tree roots: ", 0,0,0,0); } /* Make sure every page in the file is referenced */ for(i=1; i<=sCheck.nPage; i++){ if( sCheck.anRef[i]==0 ){ | > | 2984 2985 2986 2987 2988 2989 2990 2991 2992 2993 2994 2995 2996 2997 2998 | */ checkList(&sCheck, 1, pBt->page1->freeList, pBt->page1->nFree, "Main freelist: "); /* Check all the tables. */ for(i=0; i<nRoot; i++){ if( aRoot[i]==0 ) continue; checkTreePage(&sCheck, aRoot[i], 0, "List of tree roots: ", 0,0,0,0); } /* Make sure every page in the file is referenced */ for(i=1; i<=sCheck.nPage; i++){ if( sCheck.anRef[i]==0 ){ |
︙ | ︙ |
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.83 2002/03/03 23:06:01 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 |
︙ | ︙ | |||
749 750 751 752 753 754 755 | ** in the SQLITE_MASTER table of the database. The record number ** for the new table entry should already be on the stack. ** ** If this is a TEMPORARY table, then just create the table. Do not ** make an entry in SQLITE_MASTER. */ if( !pParse->initFlag ){ | | > > | | > > > > > | > > > | 749 750 751 752 753 754 755 756 757 758 759 760 761 762 763 764 765 766 767 768 769 770 771 772 773 774 775 776 777 778 779 780 781 782 783 784 | ** in the SQLITE_MASTER table of the database. The record number ** for the new table entry should already be on the stack. ** ** If this is a TEMPORARY table, then just create the table. Do not ** make an entry in SQLITE_MASTER. */ if( !pParse->initFlag ){ int n; Vdbe *v; v = sqliteGetVdbe(pParse); if( v==0 ) return; if( p->pSelect==0 ){ /* A regular table */ sqliteVdbeAddOp(v, OP_CreateTable, 0, p->isTemp); sqliteVdbeChangeP3(v, -1, (char *)&p->tnum, P3_POINTER); }else{ /* A view */ sqliteVdbeAddOp(v, OP_Integer, 0, 0); } p->tnum = 0; if( !p->isTemp ){ sqliteVdbeAddOp(v, OP_Pull, 1, 0); sqliteVdbeAddOp(v, OP_String, 0, 0); if( p->pSelect==0 ){ sqliteVdbeChangeP3(v, -1, "table", P3_STATIC); }else{ sqliteVdbeChangeP3(v, -1, "view", P3_STATIC); } sqliteVdbeAddOp(v, OP_String, 0, 0); sqliteVdbeChangeP3(v, -1, p->zName, P3_STATIC); sqliteVdbeAddOp(v, OP_String, 0, 0); sqliteVdbeChangeP3(v, -1, p->zName, P3_STATIC); sqliteVdbeAddOp(v, OP_Dup, 4, 0); sqliteVdbeAddOp(v, OP_String, 0, 0); if( pSelect ){ |
︙ | ︙ | |||
804 805 806 807 808 809 810 | Parse *pParse, /* The parsing context */ Token *pBegin, /* The CREATE token that begins the statement */ Token *pName, /* The token that holds the name of the view */ Select *pSelect /* A SELECT statement that will become the new view */ ){ Token sEnd; Table *p; | | > > > > | | 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 852 853 | Parse *pParse, /* The parsing context */ Token *pBegin, /* The CREATE token that begins the statement */ Token *pName, /* The token that holds the name of the view */ Select *pSelect /* A SELECT statement that will become the new view */ ){ Token sEnd; Table *p; const char *z; int n, offset; sqliteStartTable(pParse, pBegin, pName, 0); p = pParse->pNewTable; if( p==0 ){ sqliteSelectDelete(pSelect); return; } p->pSelect = pSelect; if( !pParse->initFlag ){ if( sqliteViewGetColumnNames(pParse, p) ){ return; } } sEnd = pParse->sLastToken; if( sEnd.z[0]!=0 && sEnd.z[0]!=';' ){ sEnd.z += sEnd.n; } sEnd.n = 0; n = ((int)sEnd.z) - (int)pBegin->z; z = pBegin->z; while( n>0 && (z[n-1]==';' || isspace(z[n-1])) ){ n--; } sEnd.z = &z[n-1]; sEnd.n = 1; z = p->pSelect->zSelect = sqliteStrNDup(z, n); if( z ){ offset = ((int)z) - (int)pBegin->z; sqliteSelectMoveStrings(p->pSelect, offset); sqliteEndTable(pParse, &sEnd, 0); } return; } |
︙ | ︙ | |||
962 963 964 965 966 967 968 | return pTab; } /* ** This routine is called to do the work of a DROP TABLE statement. ** pName is the name of the table to be dropped. */ | | > > > > > > > > > > > > | 976 977 978 979 980 981 982 983 984 985 986 987 988 989 990 991 992 993 994 995 996 997 998 999 1000 1001 1002 1003 1004 1005 1006 1007 1008 1009 1010 1011 1012 1013 1014 1015 | return pTab; } /* ** This routine is called to do the work of a DROP TABLE statement. ** pName is the name of the table to be dropped. */ void sqliteDropTable(Parse *pParse, Token *pName, int isView){ Table *pTable; Vdbe *v; int base; sqlite *db = pParse->db; if( pParse->nErr || sqlite_malloc_failed ) return; pTable = sqliteTableFromToken(pParse, pName); if( pTable==0 ) return; if( pTable->readOnly ){ sqliteSetString(&pParse->zErrMsg, "table ", pTable->zName, " may not be dropped", 0); pParse->nErr++; return; } if( isView && pTable->pSelect==0 ){ sqliteSetString(&pParse->zErrMsg, "use DROP TABLE to delete table ", pTable->zName, 0); pParse->nErr++; return; } if( !isView && pTable->pSelect ){ sqliteSetString(&pParse->zErrMsg, "use DROP VIEW to delete view ", pTable->zName, 0); pParse->nErr++; return; } /* Generate code to remove the table from the master table ** on disk. */ v = sqliteGetVdbe(pParse); if( v ){ |
︙ | ︙ | |||
1004 1005 1006 1007 1008 1009 1010 | sqliteBeginWriteOperation(pParse); if( !pTable->isTemp ){ base = sqliteVdbeAddOpList(v, ArraySize(dropTable), dropTable); sqliteVdbeChangeP3(v, base+2, pTable->zName, 0); changeCookie(db); sqliteVdbeChangeP1(v, base+9, db->next_cookie); } | > | | | > | 1030 1031 1032 1033 1034 1035 1036 1037 1038 1039 1040 1041 1042 1043 1044 1045 1046 1047 1048 | sqliteBeginWriteOperation(pParse); if( !pTable->isTemp ){ base = sqliteVdbeAddOpList(v, ArraySize(dropTable), dropTable); sqliteVdbeChangeP3(v, base+2, pTable->zName, 0); changeCookie(db); sqliteVdbeChangeP1(v, base+9, db->next_cookie); } if( !isView ){ sqliteVdbeAddOp(v, OP_Destroy, pTable->tnum, pTable->isTemp); for(pIdx=pTable->pIndex; pIdx; pIdx=pIdx->pNext){ sqliteVdbeAddOp(v, OP_Destroy, pIdx->tnum, pTable->isTemp); } } sqliteEndWriteOperation(pParse); } /* Move the table (and all its indices) to the pending DROP queue. ** Or, if the table was never committed, just delete it. If the table ** has been committed and is placed on the pending DROP queue, then the |
︙ | ︙ | |||
1867 1868 1869 1870 1871 1872 1873 | { OP_Open, 0, 2, 0}, { OP_Rewind, 0, 6, 0}, { OP_Column, 0, 3, 0}, { OP_SetInsert, 0, 0, 0}, { OP_Next, 0, 3, 0}, { OP_IntegrityCk, 0, 0, 0}, { OP_ColumnCount, 1, 0, 0}, | | | 1895 1896 1897 1898 1899 1900 1901 1902 1903 1904 1905 1906 1907 1908 1909 1910 1911 1912 1913 | { OP_Open, 0, 2, 0}, { OP_Rewind, 0, 6, 0}, { OP_Column, 0, 3, 0}, { OP_SetInsert, 0, 0, 0}, { OP_Next, 0, 3, 0}, { OP_IntegrityCk, 0, 0, 0}, { OP_ColumnCount, 1, 0, 0}, { OP_ColumnName, 0, 0, "integrity_check"}, { OP_Callback, 1, 0, 0}, }; Vdbe *v = sqliteGetVdbe(pParse); if( v==0 ) return; sqliteVdbeAddOpList(v, ArraySize(checkDb), checkDb); }else {} sqliteFree(zLeft); sqliteFree(zRight); } |
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.55 2002/03/03 23:06:01 drh Exp $ */ %token_prefix TK_ %token_type {Token} %default_type {Token} %extra_argument {Parse *pParse} %syntax_error { sqliteSetString(&pParse->zErrMsg,"syntax error",0); |
︙ | ︙ | |||
184 185 186 187 188 189 190 | resolvetype(A) ::= ABORT. { A = OE_Abort; } resolvetype(A) ::= FAIL. { A = OE_Fail; } resolvetype(A) ::= IGNORE. { A = OE_Ignore; } resolvetype(A) ::= REPLACE. { A = OE_Replace; } ////////////////////////// The DROP TABLE ///////////////////////////////////// // | | | | 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 | resolvetype(A) ::= ABORT. { A = OE_Abort; } resolvetype(A) ::= FAIL. { A = OE_Fail; } resolvetype(A) ::= IGNORE. { A = OE_Ignore; } resolvetype(A) ::= REPLACE. { A = OE_Replace; } ////////////////////////// The DROP TABLE ///////////////////////////////////// // cmd ::= DROP TABLE ids(X). {sqliteDropTable(pParse,&X,0);} ///////////////////// The CREATE VIEW statement ///////////////////////////// // cmd ::= CREATE(X) VIEW ids(Y) AS select(S). { sqliteCreateView(pParse, &X, &Y, S); } cmd ::= DROP VIEW ids(X). { sqliteDropTable(pParse, &X, 1); } //////////////////////// The SELECT statement ///////////////////////////////// // cmd ::= select(X). { sqliteSelect(pParse, X, SRT_Callback, 0, 0, 0, 0); sqliteSelectDelete(X); |
︙ | ︙ |
Changes to src/shell.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 code to implement the "sqlite" command line ** utility for accessing SQLite databases. ** | | | 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 code to implement the "sqlite" command line ** utility for accessing SQLite databases. ** ** $Id: shell.c,v 1.47 2002/03/03 23:06:01 drh Exp $ */ #include <stdlib.h> #include <string.h> #include <stdio.h> #include "sqlite.h" #include <ctype.h> #if !defined(_WIN32) && !defined(WIN32) |
︙ | ︙ | |||
717 718 719 720 721 722 723 | if( c=='t' && n>1 && strncmp(azArg[0], "tables", n)==0 ){ char **azResult; int nRow, rc; char *zErrMsg; if( nArg==1 ){ rc = sqlite_get_table(db, "SELECT name FROM sqlite_master " | | | | 717 718 719 720 721 722 723 724 725 726 727 728 729 730 731 732 733 734 735 736 737 738 | if( c=='t' && n>1 && strncmp(azArg[0], "tables", n)==0 ){ char **azResult; int nRow, rc; char *zErrMsg; if( nArg==1 ){ rc = sqlite_get_table(db, "SELECT name FROM sqlite_master " "WHERE type IN ('table','view') " "ORDER BY name", &azResult, &nRow, 0, &zErrMsg ); }else{ rc = sqlite_get_table_printf(db, "SELECT name FROM sqlite_master " "WHERE type IN ('table','view') AND name LIKE '%%%q%%' " "ORDER BY name", &azResult, &nRow, 0, &zErrMsg, azArg[1] ); } if( zErrMsg ){ fprintf(stderr,"Error: %s\n", zErrMsg); free(zErrMsg); |
︙ | ︙ |
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.101 2002/03/03 23:06:02 drh Exp $ */ #include "sqlite.h" #include "hash.h" #include "vdbe.h" #include "parse.h" #include "btree.h" #include <stdio.h> |
︙ | ︙ | |||
582 583 584 585 586 587 588 | void sqliteAddPrimaryKey(Parse*, IdList*, int); void sqliteAddColumnType(Parse*,Token*,Token*); void sqliteAddDefaultValue(Parse*,Token*,int); void sqliteEndTable(Parse*,Token*,Select*); void sqliteCreateView(Parse*,Token*,Token*,Select*); int sqliteViewGetColumnNames(Parse*,Table*); void sqliteViewResetAll(sqlite*); | | | 582 583 584 585 586 587 588 589 590 591 592 593 594 595 596 | void sqliteAddPrimaryKey(Parse*, IdList*, int); void sqliteAddColumnType(Parse*,Token*,Token*); void sqliteAddDefaultValue(Parse*,Token*,int); void sqliteEndTable(Parse*,Token*,Select*); void sqliteCreateView(Parse*,Token*,Token*,Select*); int sqliteViewGetColumnNames(Parse*,Table*); void sqliteViewResetAll(sqlite*); void sqliteDropTable(Parse*, Token*, int); void sqliteDeleteTable(sqlite*, Table*); void sqliteInsert(Parse*, Token*, ExprList*, Select*, IdList*, int); IdList *sqliteIdListAppend(IdList*, Token*); void sqliteIdListAddAlias(IdList*, Token*); void sqliteIdListDelete(IdList*); void sqliteCreateIndex(Parse*, Token*, Token*, IdList*, int, Token*, Token*); void sqliteDropIndex(Parse*, Token*); |
︙ | ︙ |
Changes to test/view.test.
1 2 3 4 5 6 7 8 9 10 11 12 13 | # 2002 February 26 # # The author disclaims copyright to this source code. In place of # a legal notice, here is a blessing: # # May you do good and not evil. # May you find forgiveness for yourself and forgive others. # May you share freely, never taking more than you give. # #*********************************************************************** # This file implements regression tests for SQLite library. The # focus of this file is testing VIEW statements. # | | | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 | # 2002 February 26 # # The author disclaims copyright to this source code. In place of # a legal notice, here is a blessing: # # May you do good and not evil. # May you find forgiveness for yourself and forgive others. # May you share freely, never taking more than you give. # #*********************************************************************** # This file implements regression tests for SQLite library. The # focus of this file is testing VIEW statements. # # $Id: view.test,v 1.3 2002/03/03 23:06:02 drh Exp $ set testdir [file dirname $argv0] source $testdir/tester.tcl do_test view-1.0 { execsql { CREATE TABLE t1(a,b,c); INSERT INTO t1 VALUES(1,2,3); |
︙ | ︙ | |||
81 82 83 84 85 86 87 88 | do_test view-1.8 { db close sqlite db test.db execsql { SELECT * FROM v1 ORDER BY a; } } {2 3 5 6 8 9} | > > > > > > | > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 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 | do_test view-1.8 { db close sqlite db test.db execsql { SELECT * FROM v1 ORDER BY a; } } {2 3 5 6 8 9} do_test view-2.1 { execsql { CREATE VIEW v2 AS SELECT * FROM t1 WHERE a>5 }; # No semicolon execsql2 { SELECT * FROM v2; } } {x 7 a 8 b 9 c 10} do_test view-2.2 { catchsql { INSERT INTO v2 VALUES(1,2,3,4); } } {1 {view v2 may not be modified}} do_test view-2.3 { catchsql { UPDATE v2 SET a=10 WHERE a=5; } } {1 {view v2 may not be modified}} do_test view-2.4 { catchsql { DELETE FROM v2; } } {1 {view v2 may not be modified}} do_test view-2.5 { execsql { INSERT INTO t1 VALUES(11,12,13,14); SELECT * FROM v2 ORDER BY x; } } {7 8 9 10 11 12 13 14} do_test view-2.6 { execsql { SELECT x FROM v2 WHERE a>10 } } {11} finish_test |