From 4ff6dfa7de8464d6ea10f513bc0ef8e50bfec308 Mon Sep 17 00:00:00 2001 From: drh Date: Sun, 3 Mar 2002 23:06:00 +0000 Subject: [PATCH] More bugs fixed for views. (CVS 416) FossilOrigin-Name: 813077623087ffc6cd506f57cf6d1e3d9239f806 --- manifest | 22 ++++++++++----------- manifest.uuid | 2 +- src/btree.c | 3 ++- src/build.c | 52 +++++++++++++++++++++++++++++++++++++------------ src/parse.y | 6 +++--- src/shell.c | 6 +++--- src/sqliteInt.h | 4 ++-- test/view.test | 38 +++++++++++++++++++++++++++++++++++- 8 files changed, 99 insertions(+), 34 deletions(-) diff --git a/manifest b/manifest index fb765b9332..be9374a0b2 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C VIEWs\sare\sbound\sto\stables\swhen\sthey\sare\sused,\snot\swhen\sthey\sare\sfirst\nentered.\s\sThis\sworks\saround\sthe\sproblem\sof\swhat\sto\sdo\sif\sa\stable\sis\sdeleted\nthat\sa\sview\srefers\sto.\s(CVS\s415) -D 2002-03-03T18:59:40 +C More\sbugs\sfixed\sfor\sviews.\s(CVS\s416) +D 2002-03-03T23:06:01 F Makefile.in 50f1b3351df109b5774771350d8c1b8d3640130d F Makefile.template 89e373b2dad0321df00400fa968dc14b61a03296 F README a4c0ba11354ef6ba0776b400d057c59da47a4cc0 @@ -19,9 +19,9 @@ F ltmain.sh e9ed72eb1d690f447c13945eaf69e28af531eda1 F publish.sh 5b59f4aff037aafa0e4a3b6fa599495dbd73f360 F sqlite.1 2e2bb0529ef468ade9e4322bd609d0695fb9ded9 F src/TODO af7f3cab0228e34149cf98e073aa83d45878e7e6 -F src/btree.c e732bb03715f326a25e0b6fea2e778e063ec3893 +F src/btree.c d25ea795a0f7017bc2099c437e6cc01d4c31b22d F src/btree.h 8abeabfe6e0b1a990b64fa457592a6482f6674f3 -F src/build.c 7c65eeab9644c6699cc20a4e93fadd24513e5d72 +F src/build.c 5b91d41cbeed1da348a43a8af3eb5a7ce5812673 F src/delete.c 577da499162291c1855f0b304b211bffcf9da945 F src/expr.c e12ca550536c0bae7a3acef49dfa3068fe5f0900 F src/func.c 5b4d9707b0c8f463824c1f04547b524cba24bf7b @@ -34,14 +34,14 @@ F src/os.c f6bc9b7ab530346bb7fef2ed39f2f1f214bc14ea F src/os.h a17596ecc7f38a228b83ecdb661fb03ce44726d6 F src/pager.c 0aa358a378c416ee0b0be5bf03fa7c35f7992c9b F src/pager.h feb18aab2f6dea439393f23a382699b9b1053c32 -F src/parse.y d62960cdee2d2e7821f277d2fe63d823c86602ba +F src/parse.y 25b794bfbed2a68d13d7d40a986a0ebe2beb3e24 F src/printf.c 300a90554345751f26e1fc0c0333b90a66110a1d F src/random.c 19e8e00fe0df32a742f115773f57651be327cabe F src/select.c 49c78aa0c96dda036846937b516658536db98b56 -F src/shell.c 9f8249ca5b8f8aad40becd778c151b58c0d6109e +F src/shell.c b3454229599246b944cdb5b95753af3fca5d8bb0 F src/shell.tcl 27ecbd63dd88396ad16d81ab44f73e6c0ea9d20e F src/sqlite.h.in a9b5772604265f98f3120573ef29e37b9d917216 -F src/sqliteInt.h 9018cf8cd1e469d7b3fc0c6a7afaeaf765043172 +F src/sqliteInt.h dde4e52e234e54e8ac9d3a1964e93c5fa6c2de15 F src/table.c 203a09d5d0009eeeb1f670370d52b4ce163a3b52 F src/tclsqlite.c b9cf346e95291cb4c4f1bf5ac1d77db6b8ad023d F src/test1.c 33efd350dca27c52c58c553c04fd3a6a51f13c1f @@ -99,7 +99,7 @@ F test/trans.test 9e49495c06b1c41f889bf4f0fb195a015b126de0 F test/unique.test 07776624b82221a80c8b4138ce0dd8b0853bb3ea F test/update.test 3cf1ca0565f678063c2dfa9a7948d2d66ae1a778 F test/vacuum.test 059871b312eb910bbe49dafde1d01490cc2c6bbe -F test/view.test 56802271e3098cc719b0b2ef7fe41c5275080287 +F test/view.test 4a8a9cf59b54409228c7b9b918ed8bf9bade1220 F test/where.test 032d581c3de4893eba33b569e581c46b941bb02a F tool/lemon.c a26214e008a7351c0c9fc57c5aab44b403c36c42 F tool/lempar.c 2ff255186fffb38a43a9f7b010e87eee6308edcc @@ -127,7 +127,7 @@ F www/speed.tcl 83457b2bf6bb430900bd48ca3dd98264d9a916a5 F www/sqlite.tcl 8b5884354cb615049aed83039f8dfe1552a44279 F www/tclsqlite.tcl 829b393d1ab187fd7a5e978631b3429318885c49 F www/vdbe.tcl 2013852c27a02a091d39a766bc87cff329f21218 -P dfe431c9b70bc3a1bf5148826edce0846737e66b -R d212405b74c1101eea18c187f0e9c551 +P 6121e5ab9328c90c64d40ade3de73ad11d4aaf4e +R 83a8a52daf3c29d4bf2f935e98a598c9 U drh -Z 14456ce632fb768365261ac0c9859518 +Z 8a99e2c5584a6641ebfdb027f72777c2 diff --git a/manifest.uuid b/manifest.uuid index 9874b7d631..ac548d2fbd 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -6121e5ab9328c90c64d40ade3de73ad11d4aaf4e \ No newline at end of file +813077623087ffc6cd506f57cf6d1e3d9239f806 \ No newline at end of file diff --git a/src/btree.c b/src/btree.c index 0e8a2695a0..de288f9b45 100644 --- a/src/btree.c +++ b/src/btree.c @@ -9,7 +9,7 @@ ** May you share freely, never taking more than you give. ** ************************************************************************* -** $Id: btree.c,v 1.57 2002/03/02 20:41:58 drh Exp $ +** $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 @@ -2988,6 +2988,7 @@ char *sqliteBtreeIntegrityCheck(Btree *pBt, int *aRoot, int nRoot){ /* Check all the tables. */ for(i=0; i @@ -753,18 +753,28 @@ void sqliteEndTable(Parse *pParse, Token *pEnd, Select *pSelect){ ** make an entry in SQLITE_MASTER. */ if( !pParse->initFlag ){ - int n, addr; + int n; Vdbe *v; v = sqliteGetVdbe(pParse); if( v==0 ) return; - addr = sqliteVdbeAddOp(v, OP_CreateTable, 0, p->isTemp); - sqliteVdbeChangeP3(v, addr, (char *)&p->tnum, P3_POINTER); + 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); - sqliteVdbeChangeP3(v, -1, "table", P3_STATIC); + 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); @@ -808,7 +818,7 @@ void sqliteCreateView( ){ Token sEnd; Table *p; - char *z; + const char *z; int n, offset; sqliteStartTable(pParse, pBegin, pName, 0); @@ -829,7 +839,11 @@ void sqliteCreateView( } sEnd.n = 0; n = ((int)sEnd.z) - (int)pBegin->z; - z = p->pSelect->zSelect = sqliteStrNDup(pBegin->z, n+1); + 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); @@ -966,7 +980,7 @@ Table *sqliteTableFromToken(Parse *pParse, Token *pTok){ ** 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){ +void sqliteDropTable(Parse *pParse, Token *pName, int isView){ Table *pTable; Vdbe *v; int base; @@ -981,6 +995,18 @@ void sqliteDropTable(Parse *pParse, Token *pName){ 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. @@ -1008,9 +1034,11 @@ void sqliteDropTable(Parse *pParse, Token *pName){ changeCookie(db); sqliteVdbeChangeP1(v, base+9, db->next_cookie); } - sqliteVdbeAddOp(v, OP_Destroy, pTable->tnum, pTable->isTemp); - for(pIdx=pTable->pIndex; pIdx; pIdx=pIdx->pNext){ - sqliteVdbeAddOp(v, OP_Destroy, pIdx->tnum, pTable->isTemp); + 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); } @@ -1871,7 +1899,7 @@ void sqlitePragma(Parse *pParse, Token *pLeft, Token *pRight, int minusFlag){ { OP_Next, 0, 3, 0}, { OP_IntegrityCk, 0, 0, 0}, { OP_ColumnCount, 1, 0, 0}, - { OP_ColumnName, 0, 0, "sanity_check"}, + { OP_ColumnName, 0, 0, "integrity_check"}, { OP_Callback, 1, 0, 0}, }; Vdbe *v = sqliteGetVdbe(pParse); diff --git a/src/parse.y b/src/parse.y index 6e3f45c442..7a2f13b106 100644 --- a/src/parse.y +++ b/src/parse.y @@ -14,7 +14,7 @@ ** the parser. Lemon will also generate a header file containing ** numeric codes for all of the tokens. ** -** @(#) $Id: parse.y,v 1.54 2002/03/02 17:04:08 drh Exp $ +** @(#) $Id: parse.y,v 1.55 2002/03/03 23:06:01 drh Exp $ */ %token_prefix TK_ %token_type {Token} @@ -188,7 +188,7 @@ resolvetype(A) ::= REPLACE. { A = OE_Replace; } ////////////////////////// The DROP TABLE ///////////////////////////////////// // -cmd ::= DROP TABLE ids(X). {sqliteDropTable(pParse,&X);} +cmd ::= DROP TABLE ids(X). {sqliteDropTable(pParse,&X,0);} ///////////////////// The CREATE VIEW statement ///////////////////////////// // @@ -196,7 +196,7 @@ cmd ::= CREATE(X) VIEW ids(Y) AS select(S). { sqliteCreateView(pParse, &X, &Y, S); } cmd ::= DROP VIEW ids(X). { - sqliteDropTable(pParse, &X); + sqliteDropTable(pParse, &X, 1); } //////////////////////// The SELECT statement ///////////////////////////////// diff --git a/src/shell.c b/src/shell.c index 959412ace6..b2368d009a 100644 --- a/src/shell.c +++ b/src/shell.c @@ -12,7 +12,7 @@ ** This file contains code to implement the "sqlite" command line ** utility for accessing SQLite databases. ** -** $Id: shell.c,v 1.46 2002/02/26 23:24:27 drh Exp $ +** $Id: shell.c,v 1.47 2002/03/03 23:06:01 drh Exp $ */ #include #include @@ -721,14 +721,14 @@ static void do_meta_command(char *zLine, sqlite *db, struct callback_data *p){ if( nArg==1 ){ rc = sqlite_get_table(db, "SELECT name FROM sqlite_master " - "WHERE type='table' " + "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='table' AND name LIKE '%%%q%%' " + "WHERE type IN ('table','view') AND name LIKE '%%%q%%' " "ORDER BY name", &azResult, &nRow, 0, &zErrMsg, azArg[1] ); diff --git a/src/sqliteInt.h b/src/sqliteInt.h index cdc7a0ce08..4dd693c325 100644 --- a/src/sqliteInt.h +++ b/src/sqliteInt.h @@ -11,7 +11,7 @@ ************************************************************************* ** Internal interface definitions for SQLite. ** -** @(#) $Id: sqliteInt.h,v 1.100 2002/03/03 18:59:41 drh Exp $ +** @(#) $Id: sqliteInt.h,v 1.101 2002/03/03 23:06:02 drh Exp $ */ #include "sqlite.h" #include "hash.h" @@ -586,7 +586,7 @@ void sqliteEndTable(Parse*,Token*,Select*); void sqliteCreateView(Parse*,Token*,Token*,Select*); int sqliteViewGetColumnNames(Parse*,Table*); void sqliteViewResetAll(sqlite*); -void sqliteDropTable(Parse*, Token*); +void sqliteDropTable(Parse*, Token*, int); void sqliteDeleteTable(sqlite*, Table*); void sqliteInsert(Parse*, Token*, ExprList*, Select*, IdList*, int); IdList *sqliteIdListAppend(IdList*, Token*); diff --git a/test/view.test b/test/view.test index 2421aaebf6..859d9e95b1 100644 --- a/test/view.test +++ b/test/view.test @@ -11,7 +11,7 @@ # This file implements regression tests for SQLite library. The # focus of this file is testing VIEW statements. # -# $Id: view.test,v 1.2 2002/03/03 18:59:41 drh Exp $ +# $Id: view.test,v 1.3 2002/03/03 23:06:02 drh Exp $ set testdir [file dirname $argv0] source $testdir/tester.tcl @@ -86,5 +86,41 @@ do_test view-1.8 { } } {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