SQLite

Check-in [8a593e9c2d]
Login

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

Overview
Comment:Regression tests now work - except for some changes in error message text. The library is now safe to use for experimental work. (CVS 885)
Downloads: Tarball | ZIP archive
Timelines: family | ancestors | descendants | both | trunk
Files: files | file ages | folders
SHA1: 8a593e9c2d57e758739a7ef54fa40ca6a0071a9a
User & Date: drh 2003-03-27 13:50:00.000
Context
2003-03-30
00:19
Fix a memory leak in triggers and update tests to show the latest error message text. (CVS 886) (check-in: b90d9de32d user: drh tags: trunk)
2003-03-27
13:50
Regression tests now work - except for some changes in error message text. The library is now safe to use for experimental work. (CVS 885) (check-in: 8a593e9c2d user: drh tags: trunk)
13:01
Fix a segfault in the trigger code. (CVS 884) (check-in: 7672914b19 user: drh tags: trunk)
Changes
Unified Diff Ignore Whitespace Patch
Changes to src/build.c.
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.134 2003/03/27 12:51:24 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







|







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.135 2003/03/27 13:50:00 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
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
** a particular database table given the name
** of that table.  Return NULL if not found.
*/
Table *sqliteFindTable(sqlite *db, const char *zName, const char *zDatabase){
  Table *p = 0;
  int i;
  for(i=0; i<db->nDb; i++){

    if( zDatabase!=0 && sqliteStrICmp(zDatabase, db->aDb[i].zName) ) continue;
    p = sqliteHashFind(&db->aDb[i].tblHash, zName, strlen(zName)+1);
    if( p ) break;
  }
  return p;
}

/*
** Locate the in-memory structure that describes 
** a particular index given the name of that index.
** Return NULL if not found.
*/
Index *sqliteFindIndex(sqlite *db, const char *zName, const char *zDb){
  Index *p = 0;
  int i;
  for(i=0; i<db->nDb; i++){

    if( zDb && sqliteStrICmp(zDb, db->aDb[i].zName) ) continue;
    p = sqliteHashFind(&db->aDb[i].idxHash, zName, strlen(zName)+1);
    if( p ) break;
  }
  return p;
}

/*
** Remove the given index from the index hash table, and free







>
|
|














>
|
|







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
** a particular database table given the name
** of that table.  Return NULL if not found.
*/
Table *sqliteFindTable(sqlite *db, const char *zName, const char *zDatabase){
  Table *p = 0;
  int i;
  for(i=0; i<db->nDb; i++){
    int j = (i<2) ? i^1 : i;   /* Search TEMP before MAIN */
    if( zDatabase!=0 && sqliteStrICmp(zDatabase, db->aDb[j].zName) ) continue;
    p = sqliteHashFind(&db->aDb[j].tblHash, zName, strlen(zName)+1);
    if( p ) break;
  }
  return p;
}

/*
** Locate the in-memory structure that describes 
** a particular index given the name of that index.
** Return NULL if not found.
*/
Index *sqliteFindIndex(sqlite *db, const char *zName, const char *zDb){
  Index *p = 0;
  int i;
  for(i=0; i<db->nDb; i++){
    int j = (i<2) ? i^1 : i;  /* Search TEMP before MAIN */
    if( zDb && sqliteStrICmp(zDb, db->aDb[j].zName) ) continue;
    p = sqliteHashFind(&db->aDb[j].idxHash, zName, strlen(zName)+1);
    if( p ) break;
  }
  return p;
}

/*
** Remove the given index from the index hash table, and free
1440
1441
1442
1443
1444
1445
1446
1447
1448
1449
1450
1451
1452
1453
1454
1455

  /*
  ** Find the table that is to be indexed.  Return early if not found.
  */
  if( pTable!=0 ){
    assert( pName!=0 );
    assert( pTable->nSrc==1 );
    pTab =  sqliteTableNameToTable(pParse, 
                 pTable->a[0].zName, pTable->a[0].zDatabase);
  }else{
    assert( pName==0 );
    pTab =  pParse->pNewTable;
  }
  if( pTab==0 || pParse->nErr ) goto exit_create_index;
  if( !isTemp && (pTab->readOnly || pTab->iDb>=2) ){
    sqliteSetString(&pParse->zErrMsg, "table ", pTab->zName, 







|
<







1442
1443
1444
1445
1446
1447
1448
1449

1450
1451
1452
1453
1454
1455
1456

  /*
  ** Find the table that is to be indexed.  Return early if not found.
  */
  if( pTable!=0 ){
    assert( pName!=0 );
    assert( pTable->nSrc==1 );
    pTab =  sqliteSrcListLookup(pParse, pTable);

  }else{
    assert( pName==0 );
    pTab =  pParse->pNewTable;
  }
  if( pTab==0 || pParse->nErr ) goto exit_create_index;
  if( !isTemp && (pTab->readOnly || pTab->iDb>=2) ){
    sqliteSetString(&pParse->zErrMsg, "table ", pTab->zName, 
1981
1982
1983
1984
1985
1986
1987
1988
1989
1990
1991
1992
1993
1994
1995
1996
1997
  Index *pIdx;
  char *zFile = 0;
  sqlite *db = pParse->db;


  if( sqlite_malloc_failed  ) goto copy_cleanup;
  assert( pTableName->nSrc==1 );
  pTab = sqliteTableNameToTable(pParse, pTableName->a[0].zName,
                                pTableName->a[0].zDatabase);
  if( pTab==0 ) goto copy_cleanup;
  zFile = sqliteStrNDup(pFilename->z, pFilename->n);
  sqliteDequote(zFile);
  if( sqliteAuthCheck(pParse, SQLITE_INSERT, pTab->zName, zFile)
      || sqliteAuthCheck(pParse, SQLITE_COPY, pTab->zName, zFile) ){
    goto copy_cleanup;
  }
  v = sqliteGetVdbe(pParse);







|
<
|







1982
1983
1984
1985
1986
1987
1988
1989

1990
1991
1992
1993
1994
1995
1996
1997
  Index *pIdx;
  char *zFile = 0;
  sqlite *db = pParse->db;


  if( sqlite_malloc_failed  ) goto copy_cleanup;
  assert( pTableName->nSrc==1 );
  pTab = sqliteSrcListLookup(pParse, pTableName);

  if( pTab==0 || sqliteIsReadOnly(pParse, pTab) ) goto copy_cleanup;
  zFile = sqliteStrNDup(pFilename->z, pFilename->n);
  sqliteDequote(zFile);
  if( sqliteAuthCheck(pParse, SQLITE_INSERT, pTab->zName, zFile)
      || sqliteAuthCheck(pParse, SQLITE_COPY, pTab->zName, zFile) ){
    goto copy_cleanup;
  }
  v = sqliteGetVdbe(pParse);
Changes to src/delete.c.
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
**    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 DELETE FROM statements.
**
** $Id: delete.c,v 1.48 2003/03/27 12:51:24 drh Exp $
*/
#include "sqliteInt.h"


/*
** Given a table name, find the corresponding table and make sure the

** table is writeable.  Generate an error and return NULL if not.  If
** everything checks out, return a pointer to the Table structure.
*/
Table *sqliteTableNameToTable(Parse *pParse, const char *zTab, const char *zDb){
  Table *pTab;




  pTab = sqliteFindTable(pParse->db, zTab, zDb);
  if( pTab==0 ){
    if( zDb==0 || zDb[0]==0 ){
      sqliteSetString(&pParse->zErrMsg, "no such table: ", zTab, 0);
    }else{
      sqliteSetString(&pParse->zErrMsg, "no such table: ", zDb, ".", zTab, 0);
    }
    pParse->nErr++;




    return 0;
  }







  if( pTab->readOnly || pTab->pSelect ){
    sqliteSetString(&pParse->zErrMsg, 
      pTab->pSelect ? "view " : "table ",
      zTab,
      " may not be modified", 0);
    pParse->nErr++;
    return 0;      
  }
  return pTab;
}

/*
** Process a DELETE FROM statement.
*/
void sqliteDeleteFrom(
  Parse *pParse,         /* The parser context */
  SrcList *pTabList,     /* The table from which we should delete things */







|



<

<
>
|
|

|
|
>
>
>
>
|
|
|
|
|
|
|
|
>
>
>
>
|
|
>
>
>
>
>
>
>


|
<


|

|








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
**    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 DELETE FROM statements.
**
** $Id: delete.c,v 1.49 2003/03/27 13:50:00 drh Exp $
*/
#include "sqliteInt.h"


/*

** Look up every table that is named in pSrc.  If any table is not found,
** add an error message to pParse->zErrMsg and return NULL.  If all tables
** are found, return a pointer to the last table.
*/
Table *sqliteSrcListLookup(Parse *pParse, SrcList *pSrc){
  Table *pTab = 0;
  int i;
  for(i=0; i<pSrc->nSrc; i++){
    const char *zTab = pSrc->a[i].zName;
    const char *zDb = pSrc->a[i].zDatabase;
    pTab = sqliteFindTable(pParse->db, zTab, zDb);
    if( pTab==0 ){
      if( zDb==0 || zDb[0]==0 ){
        sqliteSetString(&pParse->zErrMsg, "no such table: ", zTab, 0);
      }else{
        sqliteSetString(&pParse->zErrMsg, "no such table: ", zDb, ".", zTab, 0);
      }
      pParse->nErr++;
      break;
    }
    pSrc->a[i].pTab = pTab;
  }
  return pTab;
}

/*
** Check to make sure the given table is writable.  If it is not
** writable, generate an error message and return 1.  If it is
** writable return 0;
*/
int sqliteIsReadOnly(Parse *pParse, Table *pTab){
  if( pTab->readOnly || pTab->pSelect ){
    sqliteSetString(&pParse->zErrMsg, 
      pTab->pSelect ? "view " : "table ", pTab->zName,

      " may not be modified", 0);
    pParse->nErr++;
    return 1;
  }
  return 0;
}

/*
** Process a DELETE FROM statement.
*/
void sqliteDeleteFrom(
  Parse *pParse,         /* The parser context */
  SrcList *pTabList,     /* The table from which we should delete things */
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
  }

  /* Locate the table which we want to delete.  This table has to be
  ** put in an SrcList structure because some of the subroutines we
  ** will be calling are designed to work with multiple tables and expect
  ** an SrcList* parameter instead of just a Table* parameter.
  */
  pTab = pTabList->a[0].pTab = sqliteTableNameToTable(pParse, zTab, zDb);
  if( pTab==0 ){
    goto delete_from_cleanup;
  }
  assert( pTab->pSelect==0 );  /* This table is not a view */
  if( sqliteAuthCheck(pParse, SQLITE_DELETE, pTab->zName, 0) ){
    goto delete_from_cleanup;
  }








|
|







110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
  }

  /* Locate the table which we want to delete.  This table has to be
  ** put in an SrcList structure because some of the subroutines we
  ** will be calling are designed to work with multiple tables and expect
  ** an SrcList* parameter instead of just a Table* parameter.
  */
  pTab = sqliteSrcListLookup(pParse, pTabList);
  if( pTab==0 || sqliteIsReadOnly(pParse, pTab) ){
    goto delete_from_cleanup;
  }
  assert( pTab->pSelect==0 );  /* This table is not a view */
  if( sqliteAuthCheck(pParse, SQLITE_DELETE, pTab->zName, 0) ){
    goto delete_from_cleanup;
  }

Changes to src/insert.c.
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.75 2003/03/27 12:51:25 drh Exp $
*/
#include "sqliteInt.h"

/*
** This routine is call to handle SQL of the following forms:
**
**    insert into TABLE (IDLIST) values(EXPRLIST)







|







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.76 2003/03/27 13:50:00 drh Exp $
*/
#include "sqliteInt.h"

/*
** This routine is call to handle SQL of the following forms:
**
**    insert into TABLE (IDLIST) values(EXPRLIST)
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
  ExprList *pList,      /* List of values to be inserted */
  Select *pSelect,      /* A SELECT statement to use as the data source */
  IdList *pColumn,      /* Column names corresponding to IDLIST. */
  int onError           /* How to handle constraint errors */
){
  Table *pTab;          /* The table to insert into */
  char *zTab;           /* Name of the table into which we are inserting */
  char *zDb;            /* Name of the database holding zTab */
  int i, j, idx;        /* Loop counters */
  Vdbe *v;              /* Generate code into this virtual machine */
  Index *pIdx;          /* For looping over indices of the table */
  int nColumn;          /* Number of columns in the data */
  int base;             /* First available cursor */
  int iCont, iBreak;    /* Beginning and end of the loop over srcTab */
  sqlite *db;           /* The main database structure */







<







89
90
91
92
93
94
95

96
97
98
99
100
101
102
  ExprList *pList,      /* List of values to be inserted */
  Select *pSelect,      /* A SELECT statement to use as the data source */
  IdList *pColumn,      /* Column names corresponding to IDLIST. */
  int onError           /* How to handle constraint errors */
){
  Table *pTab;          /* The table to insert into */
  char *zTab;           /* Name of the table into which we are inserting */

  int i, j, idx;        /* Loop counters */
  Vdbe *v;              /* Generate code into this virtual machine */
  Index *pIdx;          /* For looping over indices of the table */
  int nColumn;          /* Number of columns in the data */
  int base;             /* First available cursor */
  int iCont, iBreak;    /* Beginning and end of the loop over srcTab */
  sqlite *db;           /* The main database structure */
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
  db = pParse->db;

  /* Locate the table into which we will be inserting new information.
  */
  assert( pTabList->nSrc==1 );
  zTab = pTabList->a[0].zName;
  if( zTab==0 ) goto insert_cleanup;
  zDb = pTabList->a[0].zDatabase;
  pTab = sqliteTableNameToTable(pParse, zTab, zDb);
  if( pTab==0 ){
    goto insert_cleanup;
  }
  if( sqliteAuthCheck(pParse, SQLITE_INSERT, pTab->zName, 0) ){
    goto insert_cleanup;
  }








<
|







116
117
118
119
120
121
122

123
124
125
126
127
128
129
130
  db = pParse->db;

  /* Locate the table into which we will be inserting new information.
  */
  assert( pTabList->nSrc==1 );
  zTab = pTabList->a[0].zName;
  if( zTab==0 ) goto insert_cleanup;

  pTab = sqliteSrcListLookup(pParse, pTabList);
  if( pTab==0 ){
    goto insert_cleanup;
  }
  if( sqliteAuthCheck(pParse, SQLITE_INSERT, pTab->zName, 0) ){
    goto insert_cleanup;
  }

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
/*
** 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.165 2003/03/27 12:51:25 drh Exp $
*/
#include "config.h"
#include "sqlite.h"
#include "hash.h"
#include "vdbe.h"
#include "parse.h"
#include "btree.h"













|







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.166 2003/03/27 13:50:00 drh Exp $
*/
#include "config.h"
#include "sqlite.h"
#include "hash.h"
#include "vdbe.h"
#include "parse.h"
#include "btree.h"
249
250
251
252
253
254
255







256
257
258
259
260
261
262
#endif
#ifndef SQLITE_OMIT_AUTHORIZATION
  int (*xAuth)(void*,int,const char*,const char*); /* Access Auth function */
  void *pAuthArg;               /* 1st argument to the access auth function */
#endif
};








/*
** Possible values for the sqlite.flags.
*/
#define SQLITE_VdbeTrace      0x00000001  /* True to trace VDBE execution */
#define SQLITE_Initialized    0x00000002  /* True after initialization */
#define SQLITE_Interrupt      0x00000004  /* Cancel current operation */
#define SQLITE_InTrans        0x00000008  /* True if in a transaction */







>
>
>
>
>
>
>







249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
#endif
#ifndef SQLITE_OMIT_AUTHORIZATION
  int (*xAuth)(void*,int,const char*,const char*); /* Access Auth function */
  void *pAuthArg;               /* 1st argument to the access auth function */
#endif
};

/*
** The following are the indices of in sqlite.aDb[] of the main database
** file and the file used to store TEMP tables.
*/
#define DB_TMP     0
#define DB_MAIN    1

/*
** Possible values for the sqlite.flags.
*/
#define SQLITE_VdbeTrace      0x00000001  /* True to trace VDBE execution */
#define SQLITE_Initialized    0x00000002  /* True after initialization */
#define SQLITE_Interrupt      0x00000004  /* Cancel current operation */
#define SQLITE_InTrans        0x00000008  /* True if in a transaction */
997
998
999
1000
1001
1002
1003
1004

1005
1006
1007
1008
1009
1010
1011
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*);
void sqliteSelectUnbind(Select*);
Table *sqliteTableNameToTable(Parse*, const char*, const char*);

void sqliteDeleteFrom(Parse*, SrcList*, Expr*);
void sqliteUpdate(Parse*, SrcList*, ExprList*, Expr*, int);
WhereInfo *sqliteWhereBegin(Parse*, int, SrcList*, Expr*, int, ExprList**);
void sqliteWhereEnd(WhereInfo*);
void sqliteExprCode(Parse*, Expr*);
void sqliteExprIfTrue(Parse*, Expr*, int, int);
void sqliteExprIfFalse(Parse*, Expr*, int, int);







|
>







1004
1005
1006
1007
1008
1009
1010
1011
1012
1013
1014
1015
1016
1017
1018
1019
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*);
void sqliteSelectUnbind(Select*);
Table *sqliteSrcListLookup(Parse*, SrcList*);
int sqliteIsReadOnly(Parse*, Table*);
void sqliteDeleteFrom(Parse*, SrcList*, Expr*);
void sqliteUpdate(Parse*, SrcList*, ExprList*, Expr*, int);
WhereInfo *sqliteWhereBegin(Parse*, int, SrcList*, Expr*, int, ExprList**);
void sqliteWhereEnd(WhereInfo*);
void sqliteExprCode(Parse*, Expr*);
void sqliteExprIfTrue(Parse*, Expr*, int, int);
void sqliteExprIfFalse(Parse*, Expr*, int, int);
Changes to src/trigger.c.
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
  ** 2. the table (or view) does exist.
  ** 3. that we are not trying to create a trigger on the sqlite_master table
  ** 4. That we are not trying to create an INSTEAD OF trigger on a table.
  ** 5. That we are not trying to create a BEFORE or AFTER trigger on a view.
  */
  if( sqlite_malloc_failed ) goto trigger_cleanup;
  assert( pTableName->nSrc==1 );
  tab = sqliteTableNameToTable(pParse, pTableName->a[0].zName,
                                pTableName->a[0].zDatabase);
  if( !tab ){
    goto trigger_cleanup;
  }
  if( tab->iDb>=2 ){
    sqliteSetString(&pParse->zErrMsg, "triggers may not be added to "
       "auxiliary database \"", db->aDb[tab->iDb].zName, "\"", 0);
    pParse->nErr++;







|
<







57
58
59
60
61
62
63
64

65
66
67
68
69
70
71
  ** 2. the table (or view) does exist.
  ** 3. that we are not trying to create a trigger on the sqlite_master table
  ** 4. That we are not trying to create an INSTEAD OF trigger on a table.
  ** 5. That we are not trying to create a BEFORE or AFTER trigger on a view.
  */
  if( sqlite_malloc_failed ) goto trigger_cleanup;
  assert( pTableName->nSrc==1 );
  tab = sqliteSrcListLookup(pParse, pTableName);

  if( !tab ){
    goto trigger_cleanup;
  }
  if( tab->iDb>=2 ){
    sqliteSetString(&pParse->zErrMsg, "triggers may not be added to "
       "auxiliary database \"", db->aDb[tab->iDb].zName, "\"", 0);
    pParse->nErr++;
352
353
354
355
356
357
358

359
360
361
362
363
364
365
366
367

  if( sqlite_malloc_failed ) goto drop_trigger_cleanup;
  assert( pName->nSrc==1 );
  zDb = pName->a[0].zDatabase;
  zName = pName->a[0].zName;
  nName = strlen(zName);
  for(i=0; i<db->nDb; i++){

    if( zDb && sqliteStrICmp(db->aDb[i].zName, zDb) ) continue;
    pTrigger = sqliteHashFind(&(db->aDb[i].trigHash), zName, nName+1);
    if( pTrigger ) break;
  }
  if( !pTrigger ){
    sqliteSetString(&pParse->zErrMsg, "no such trigger: ", zName, 0);
    goto drop_trigger_cleanup;
  }
  assert( pTrigger->iDb>=0 && pTrigger->iDb<db->nDb );







>
|
|







351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367

  if( sqlite_malloc_failed ) goto drop_trigger_cleanup;
  assert( pName->nSrc==1 );
  zDb = pName->a[0].zDatabase;
  zName = pName->a[0].zName;
  nName = strlen(zName);
  for(i=0; i<db->nDb; i++){
    int j = (i<2) ? i^1 : i;  /* Search TEMP before MAIN */
    if( zDb && sqliteStrICmp(db->aDb[j].zName, zDb) ) continue;
    pTrigger = sqliteHashFind(&(db->aDb[j].trigHash), zName, nName+1);
    if( pTrigger ) break;
  }
  if( !pTrigger ){
    sqliteSetString(&pParse->zErrMsg, "no such trigger: ", zName, 0);
    goto drop_trigger_cleanup;
  }
  assert( pTrigger->iDb>=0 && pTrigger->iDb<db->nDb );
Changes to src/update.c.
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.56 2003/03/27 12:51:25 drh Exp $
*/
#include "sqliteInt.h"

/*
** Process an UPDATE statement.
*/
void sqliteUpdate(







|







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.57 2003/03/27 13:50:00 drh Exp $
*/
#include "sqliteInt.h"

/*
** Process an UPDATE statement.
*/
void sqliteUpdate(
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
  }

  /* Locate the table which we want to update.  This table has to be
  ** put in an SrcList structure because some of the subroutines we
  ** will be calling are designed to work with multiple tables and expect
  ** an SrcList* parameter instead of just a Table* parameter.
  */
  pTab = pTabList->a[0].pTab = sqliteTableNameToTable(pParse, zTab, zDb);
  if( pTab==0 ) goto update_cleanup;
  assert( pTab->pSelect==0 );  /* This table is not a VIEW */
  aXRef = sqliteMalloc( sizeof(int) * pTab->nCol );
  if( aXRef==0 ) goto update_cleanup;
  for(i=0; i<pTab->nCol; i++) aXRef[i] = -1;

  /* If there are FOR EACH ROW triggers, allocate temp tables */
  if( row_triggers_exist ){







|
|







80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
  }

  /* Locate the table which we want to update.  This table has to be
  ** put in an SrcList structure because some of the subroutines we
  ** will be calling are designed to work with multiple tables and expect
  ** an SrcList* parameter instead of just a Table* parameter.
  */
  pTab = sqliteSrcListLookup(pParse, pTabList);
  if( pTab==0 || sqliteIsReadOnly(pParse, pTab) ) goto update_cleanup;
  assert( pTab->pSelect==0 );  /* This table is not a VIEW */
  aXRef = sqliteMalloc( sizeof(int) * pTab->nCol );
  if( aXRef==0 ) goto update_cleanup;
  for(i=0; i<pTab->nCol; i++) aXRef[i] = -1;

  /* If there are FOR EACH ROW triggers, allocate temp tables */
  if( row_triggers_exist ){