SQLite

Check-in [72bf73b2c1]
Login

Many hyperlinks are disabled.
Use anonymous login to enable hyperlinks.

Overview
Comment:Disallow temporary indices on persistent tables. (CVS 1122)
Downloads: Tarball | ZIP archive
Timelines: family | ancestors | descendants | both | trunk
Files: files | file ages | folders
SHA1: 72bf73b2c1e3594aa85920e47fc345bba56c80d0
User & Date: drh 2003-11-27 00:48:58.000
Context
2003-12-04
13:44
Update change log and version in preparation for the 2.8.7 release. (CVS 1123) (check-in: 9e79ab6ce0 user: drh tags: trunk)
2003-11-27
00:48
Disallow temporary indices on persistent tables. (CVS 1122) (check-in: 72bf73b2c1 user: drh tags: trunk)
2003-11-25
23:48
Fix typos in file format documentation. Ticket #505. (CVS 1121) (check-in: 4eef93814f user: drh tags: trunk)
Changes
Side-by-Side Diff Ignore Whitespace Patch
Changes to src/build.c.
19
20
21
22
23
24
25
26

27
28
29
30
31
32
33
19
20
21
22
23
24
25

26
27
28
29
30
31
32
33







-
+







**     DROP INDEX
**     creating ID lists
**     BEGIN TRANSACTION
**     COMMIT
**     ROLLBACK
**     PRAGMA
**
** $Id: build.c,v 1.160 2003/09/06 22:18:08 drh Exp $
** $Id: build.c,v 1.161 2003/11/27 00:48:58 drh Exp $
*/
#include "sqliteInt.h"
#include <ctype.h>

/*
** This routine is called when a new SQL statement is beginning to
** be parsed.  Check to see if the schema for the database needs
730
731
732
733
734
735
736
737

738
739
740
741
742
743
744
730
731
732
733
734
735
736

737
738
739
740
741
742
743
744







-
+







    zType = pTab->aCol[iCol].zType;
  }
  if( pParse->db->file_format>=1 && 
           zType && sqliteStrICmp(zType, "INTEGER")==0 ){
    pTab->iPKey = iCol;
    pTab->keyConf = onError;
  }else{
    sqliteCreateIndex(pParse, 0, 0, pList, onError, 0, 0, 0);
    sqliteCreateIndex(pParse, 0, 0, pList, onError, 0, 0);
    pList = 0;
  }

primary_key_exit:
  sqliteIdListDelete(pList);
  return;
}
1533
1534
1535
1536
1537
1538
1539
1540
1541
1542
1543
1544
1545
1546
1547
1548
1549

1550
1551
1552
1553

1554
1555
1556
1557
1558
1559
1560
1533
1534
1535
1536
1537
1538
1539

1540
1541
1542
1543
1544
1545
1546
1547
1548
1549
1550
1551
1552

1553
1554
1555
1556
1557
1558
1559
1560







-









+



-
+







*/
void sqliteCreateIndex(
  Parse *pParse,   /* All information about this parse */
  Token *pName,    /* Name of the index.  May be NULL */
  SrcList *pTable, /* Name of the table to index.  Use pParse->pNewTable if 0 */
  IdList *pList,   /* A list of columns to be indexed */
  int onError,     /* OE_Abort, OE_Ignore, OE_Replace, or OE_None */
  int isTemp,      /* True if this is a temporary index */
  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;
  Token nullId;    /* Fake token for an empty ID list */
  DbFixer sFix;    /* For assigning database names to pTable */
  int isTemp;      /* True for a temporary index */
  sqlite *db = pParse->db;

  if( pParse->nErr || sqlite_malloc_failed ) goto exit_create_index;
  if( !isTemp && pParse->initFlag 
  if( pParse->initFlag 
     && sqliteFixInit(&sFix, pParse, pParse->iDb, "index", pName)
     && sqliteFixSrcList(&sFix, pTable)
  ){
    goto exit_create_index;
  }

  /*
1571
1572
1573
1574
1575
1576
1577
1578

1579
1580

1581
1582
1583
1584
1585
1586
1587
1588
1589
1590

1591
1592
1593
1594
1595
1596
1597
1598
1571
1572
1573
1574
1575
1576
1577

1578
1579

1580
1581
1582
1583
1584
1585
1586
1587
1588


1589

1590
1591
1592
1593
1594
1595
1596







-
+

-
+








-
-
+
-







  if( pTab==0 || pParse->nErr ) goto exit_create_index;
  if( pTab->readOnly ){
    sqliteSetString(&pParse->zErrMsg, "table ", pTab->zName,
      " may not be indexed", 0);
    pParse->nErr++;
    goto exit_create_index;
  }
  if( !isTemp && pTab->iDb>=2 && pParse->initFlag==0 ){
  if( pTab->iDb>=2 && pParse->initFlag==0 ){
    sqliteSetString(&pParse->zErrMsg, "table ", pTab->zName, 
      " may not have non-temporary indices added", 0);
      " may not have indices added", 0);
    pParse->nErr++;
    goto exit_create_index;
  }
  if( pTab->pSelect ){
    sqliteSetString(&pParse->zErrMsg, "views may not be indexed", 0);
    pParse->nErr++;
    goto exit_create_index;
  }
  if( pTab->iDb==1 ){
    isTemp = 1;
  isTemp = pTab->iDb==1;
  }

  /*
  ** Find the name of the index.  Make sure there is not already another
  ** index or table with the same name.  
  **
  ** Exception:  If we are reading the names of permanent indices from the
  ** sqlite_master table (because some other process changed the schema) and
1635
1636
1637
1638
1639
1640
1641
1642
1643

1644
1645
1646
1647
1648
1649
1650
1633
1634
1635
1636
1637
1638
1639


1640
1641
1642
1643
1644
1645
1646
1647







-
-
+








  /* Check for authorization to create an index.
  */
#ifndef SQLITE_OMIT_AUTHORIZATION
  {
    const char *zDb = db->aDb[pTab->iDb].zName;

    assert( isTemp==0 || isTemp==1 );
    assert( pTab->iDb==pParse->iDb || isTemp==1 );
    assert( pTab->iDb==pParse->iDb || isTemp );
    if( sqliteAuthCheck(pParse, SQLITE_INSERT, SCHEMA_TABLE(isTemp), 0, zDb) ){
      goto exit_create_index;
    }
    i = SQLITE_CREATE_INDEX;
    if( isTemp ) i = SQLITE_CREATE_TEMP_INDEX;
    if( sqliteAuthCheck(pParse, i, zName, pTab->zName, zDb) ){
      goto exit_create_index;
Changes to src/parse.y.
10
11
12
13
14
15
16
17

18
19
20
21
22
23
24
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.103 2003/09/30 01:54:14 drh Exp $
** @(#) $Id: parse.y,v 1.104 2003/11/27 00:48:58 drh Exp $
*/
%token_prefix TK_
%token_type {Token}
%default_type {Token}
%extra_argument {Parse *pParse}
%syntax_error {
  if( pParse->zErrMsg==0 ){
173
174
175
176
177
178
179
180

181
182
183
184
185
186
187
173
174
175
176
177
178
179

180
181
182
183
184
185
186
187







-
+








// In addition to the type name, we also care about the primary key and
// UNIQUE constraints.
//
ccons ::= NULL onconf.
ccons ::= NOT NULL onconf(R).               {sqliteAddNotNull(pParse, R);}
ccons ::= PRIMARY KEY sortorder onconf(R).  {sqliteAddPrimaryKey(pParse,0,R);}
ccons ::= UNIQUE onconf(R).           {sqliteCreateIndex(pParse,0,0,0,R,0,0,0);}
ccons ::= UNIQUE onconf(R).           {sqliteCreateIndex(pParse,0,0,0,R,0,0);}
ccons ::= CHECK LP expr RP onconf.
ccons ::= REFERENCES nm(T) idxlist_opt(TA) refargs(R).
                                {sqliteCreateForeignKey(pParse,0,&T,TA,R);}
ccons ::= defer_subclause(D).   {sqliteDeferForeignKey(pParse,D);}
ccons ::= COLLATE id(C).  {
   sqliteAddCollateType(pParse, sqliteCollateType(C.z, C.n));
}
220
221
222
223
224
225
226
227

228
229
230
231
232
233
234
220
221
222
223
224
225
226

227
228
229
230
231
232
233
234







-
+







conslist ::= conslist COMMA tcons.
conslist ::= conslist tcons.
conslist ::= tcons.
tcons ::= CONSTRAINT nm.
tcons ::= PRIMARY KEY LP idxlist(X) RP onconf(R).
                                             {sqliteAddPrimaryKey(pParse,X,R);}
tcons ::= UNIQUE LP idxlist(X) RP onconf(R).
                                     {sqliteCreateIndex(pParse,0,0,X,R,0,0,0);}
                                       {sqliteCreateIndex(pParse,0,0,X,R,0,0);}
tcons ::= CHECK expr onconf.
tcons ::= FOREIGN KEY LP idxlist(FA) RP
          REFERENCES nm(T) idxlist_opt(TA) refargs(R) defer_subclause_opt(D). {
    sqliteCreateForeignKey(pParse, FA, &T, TA, R);
    sqliteDeferForeignKey(pParse, D);
}
%type defer_subclause_opt {int}
697
698
699
700
701
702
703
704

705
706
707
708
709

710
711
712
713
714
715
716
697
698
699
700
701
702
703

704
705
706
707
708

709
710
711
712
713
714
715
716







-
+




-
+







   {A = sqliteExprListAppend(X,Y,0);}
exprlist(A) ::= expritem(X).            {A = sqliteExprListAppend(0,X,0);}
expritem(A) ::= expr(X).                {A = X;}
expritem(A) ::= .                       {A = 0;}

///////////////////////////// The CREATE INDEX command ///////////////////////
//
cmd ::= CREATE(S) temp(T) uniqueflag(U) INDEX nm(X)
cmd ::= CREATE(S) uniqueflag(U) INDEX nm(X)
        ON nm(Y) dbnm(D) LP idxlist(Z) RP(E) onconf(R). {
  SrcList *pSrc = sqliteSrcListAppend(0, &Y, &D);
  if( U!=OE_None ) U = R;
  if( U==OE_Default) U = OE_Abort;
  sqliteCreateIndex(pParse, &X, pSrc, Z, U, T, &S, &E);
  sqliteCreateIndex(pParse, &X, pSrc, Z, U, &S, &E);
}

%type uniqueflag {int}
uniqueflag(A) ::= UNIQUE.  { A = OE_Abort; }
uniqueflag(A) ::= .        { A = OE_None; }

%type idxlist {IdList*}
Changes to src/sqliteInt.h.
1
2
3
4
5
6
7
8
9
10
11
12
13
14

15
16
17
18
19
20
21
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.202 2003/11/11 23:30:36 drh Exp $
** @(#) $Id: sqliteInt.h,v 1.203 2003/11/27 00:48:58 drh Exp $
*/
#include "config.h"
#include "sqlite.h"
#include "hash.h"
#include "vdbe.h"
#include "parse.h"
#include "btree.h"
1097
1098
1099
1100
1101
1102
1103
1104

1105
1106
1107
1108
1109
1110
1111
1097
1098
1099
1100
1101
1102
1103

1104
1105
1106
1107
1108
1109
1110
1111







-
+







IdList *sqliteIdListAppend(IdList*, Token*);
int sqliteIdListIndex(IdList*,const char*);
SrcList *sqliteSrcListAppend(SrcList*, Token*, Token*);
void sqliteSrcListAddAlias(SrcList*, Token*);
void sqliteSrcListAssignCursors(Parse*, SrcList*);
void sqliteIdListDelete(IdList*);
void sqliteSrcListDelete(SrcList*);
void sqliteCreateIndex(Parse*,Token*,SrcList*,IdList*,int,int,Token*,Token*);
void sqliteCreateIndex(Parse*,Token*,SrcList*,IdList*,int,Token*,Token*);
void sqliteDropIndex(Parse*, SrcList*);
void sqliteAddKeyType(Vdbe*, ExprList*);
void sqliteAddIdxKeyType(Vdbe*, Index*);
int sqliteSelect(Parse*, Select*, int, int, Select*, int, int*);
Select *sqliteSelectNew(ExprList*,SrcList*,Expr*,ExprList*,Expr*,ExprList*,
                        int,int,int);
void sqliteSelectDelete(Select*);
Changes to test/auth.test.
8
9
10
11
12
13
14
15

16
17
18
19
20
21
22
8
9
10
11
12
13
14

15
16
17
18
19
20
21
22







-
+







#    May you share freely, never taking more than you give.
#
#***********************************************************************
# This file implements regression tests for SQLite library.  The
# focus of this script is testing the ATTACH and DETACH commands
# and related functionality.
#
# $Id: auth.test,v 1.10 2003/06/06 19:00:42 drh Exp $
# $Id: auth.test,v 1.11 2003/11/27 00:49:23 drh Exp $
#

set testdir [file dirname $argv0]
source $testdir/tester.tcl

# disable this test if the SQLITE_OMIT_AUTHORIZATION macro is
# defined during compilation.
263
264
265
266
267
268
269
270

271
272
273
274
275
276
277
278





279
280
281
282
283
284
285
263
264
265
266
267
268
269

270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290







-
+








+
+
+
+
+







  }
  catchsql {INSERT INTO t2 VALUES(1,2,3)}
} {0 {}}
do_test auth-1.34 {
  execsql {SELECT * FROM t2}
} {1 2 3}

do_test auth-1.35 {
do_test auth-1.35.1 {
  proc auth {code arg1 arg2 arg3 arg4} {
    if {$code=="SQLITE_READ" && $arg1=="t2" && $arg2=="b"} {
      return SQLITE_DENY
    }
    return SQLITE_OK
  }
  catchsql {SELECT * FROM t2}
} {1 {access to t2.b is prohibited}}
do_test auth-1.35.2 {
  execsql {ATTACH DATABASE 'test.db' AS two}
  catchsql {SELECT * FROM two.t2}
} {1 {access to two.t2.b is prohibited}}
execsql {DETACH DATABASE two}
do_test auth-1.36 {
  proc auth {code arg1 arg2 arg3 arg4} {
    if {$code=="SQLITE_READ" && $arg1=="t2" && $arg2=="b"} {
      return SQLITE_IGNORE
    }
    return SQLITE_OK
  }
Changes to test/trigger2.test.
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
56
57
58
59
60
61
62

63
64
65
66
67
68
69







-







	{CREATE TEMP TABLE tbl (a, b);} 
	{CREATE TABLE tbl (a, b);} 
	{CREATE TABLE tbl (a INTEGER PRIMARY KEY, b);} 
	{CREATE TEMPORARY TABLE tbl (a INTEGER PRIMARY KEY, b);} 
        {CREATE TABLE tbl (a, b PRIMARY KEY);} 
	{CREATE TABLE tbl (a, b); CREATE INDEX tbl_idx ON tbl(b);} 
	{CREATE TEMP TABLE tbl (a, b); CREATE INDEX tbl_idx ON tbl(b);} 
	{CREATE TABLE tbl (a, b); CREATE TEMP INDEX tbl_idx ON tbl(b);} 
} {
  incr ii
  catchsql { DROP INDEX tbl_idx; }
  catchsql {
    DROP TABLE rlog;
    DROP TABLE clog;
    DROP TABLE tbl;