/ Check-in [800c11f4]
Login

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

Overview
Comment:Add hooks on each attached database connection for storing auxiliary information. Add the USING clause to ATTACH. (CVS 1232)
Downloads: Tarball | ZIP archive | SQL archive
Timelines: family | ancestors | descendants | both | trunk
Files: files | file ages | folders
SHA1:800c11f4bce014a07110eb539992a609e6418406
User & Date: drh 2004-02-12 18:46:39
Context
2004-02-12
19:01
Add the SQLITE_NOTADB return code for cases when you try to open a file that does not even remotely resemble an SQLite database file. (CVS 1233) check-in: 0c77cee7 user: drh tags: trunk
18:46
Add hooks on each attached database connection for storing auxiliary information. Add the USING clause to ATTACH. (CVS 1232) check-in: 800c11f4 user: drh tags: trunk
17:28
All REPLACE INTO syntax inside of triggers. Ticket #610. (CVS 1231) check-in: a6b862a9 user: drh tags: trunk
Changes
Hide Diffs Unified Diffs Ignore Whitespace Patch

Changes to src/attach.c.

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
..
87
88
89
90
91
92
93
















94
95
96
97
98
99
100
**    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 used to implement the ATTACH and DETACH commands.
**
** $Id: attach.c,v 1.9 2004/01/20 11:54:03 drh Exp $
*/
#include "sqliteInt.h"

/*
** This routine is called by the parser to process an ATTACH statement:
**
**     ATTACH DATABASE filename AS dbname
**
** The pFilename and pDbname arguments are the tokens that define the
** filename and dbname in the ATTACH statement.
*/
void sqliteAttach(Parse *pParse, Token *pFilename, Token *pDbname){
  Db *aNew;
  int rc, i;
  char *zFile, *zName;
  sqlite *db;
  Vdbe *v;

  v = sqliteGetVdbe(pParse);
................................................................................
  sqliteHashInit(&aNew->trigHash, SQLITE_HASH_STRING, 0);
  sqliteHashInit(&aNew->aFKey, SQLITE_HASH_STRING, 1);
  aNew->zName = zName;
  rc = sqliteBtreeFactory(db, zFile, 0, MAX_PAGES, &aNew->pBt);
  if( rc ){
    sqliteErrorMsg(pParse, "unable to open database: %s", zFile);
  }
















  sqliteFree(zFile);
  db->flags &= ~SQLITE_Initialized;
  if( pParse->nErr ) return;
  if( rc==SQLITE_OK ){
    rc = sqliteInit(pParse->db, &pParse->zErrMsg);
  }
  if( rc ){







|











|







 







>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>







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
..
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
**    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 used to implement the ATTACH and DETACH commands.
**
** $Id: attach.c,v 1.10 2004/02/12 18:46:39 drh Exp $
*/
#include "sqliteInt.h"

/*
** This routine is called by the parser to process an ATTACH statement:
**
**     ATTACH DATABASE filename AS dbname
**
** The pFilename and pDbname arguments are the tokens that define the
** filename and dbname in the ATTACH statement.
*/
void sqliteAttach(Parse *pParse, Token *pFilename, Token *pDbname, Token *pKey){
  Db *aNew;
  int rc, i;
  char *zFile, *zName;
  sqlite *db;
  Vdbe *v;

  v = sqliteGetVdbe(pParse);
................................................................................
  sqliteHashInit(&aNew->trigHash, SQLITE_HASH_STRING, 0);
  sqliteHashInit(&aNew->aFKey, SQLITE_HASH_STRING, 1);
  aNew->zName = zName;
  rc = sqliteBtreeFactory(db, zFile, 0, MAX_PAGES, &aNew->pBt);
  if( rc ){
    sqliteErrorMsg(pParse, "unable to open database: %s", zFile);
  }
#if SQLITE_HAS_CODEC
  {
    extern int sqliteCodecAttach(sqlite*, int, void*, int);
    char *zKey = 0;
    int nKey;
    if( pKey && pKey->z && pKey->n ){
      sqliteSetNString(&zKey, pKey->z, pKey->n, 0);
      sqliteDequote(zKey);
      nKey = strlen(zKey);
    }else{
      zKey = 0;
      nKey = 0;
    }
    sqliteCodecAttach(db, db->nDb-1, zKey, nKey);
  }
#endif
  sqliteFree(zFile);
  db->flags &= ~SQLITE_Initialized;
  if( pParse->nErr ) return;
  if( rc==SQLITE_OK ){
    rc = sqliteInit(pParse->db, &pParse->zErrMsg);
  }
  if( rc ){

Changes to src/build.c.

19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
...
276
277
278
279
280
281
282







283
284

285
286
287
288
289
290
291
292
293
**     DROP INDEX
**     creating ID lists
**     BEGIN TRANSACTION
**     COMMIT
**     ROLLBACK
**     PRAGMA
**
** $Id: build.c,v 1.165 2004/02/11 09:46:31 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
................................................................................

  /* If one or more of the auxiliary database files has been closed,
  ** then remove then from the auxiliary database list.  We take the
  ** opportunity to do this here since we have just deleted all of the
  ** schema hash tables and therefore do not have to make any changes
  ** to any of those tables.
  */







  for(i=j=2; i<db->nDb; i++){
    if( db->aDb[i].pBt==0 ){

      sqliteFree(db->aDb[i].zName);
      db->aDb[i].zName = 0;
      continue;
    }
    if( j<i ){
      db->aDb[j] = db->aDb[i];
    }
    j++;
  }







|







 







>
>
>
>
>
>
>

|
>
|
|







19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
...
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
**     DROP INDEX
**     creating ID lists
**     BEGIN TRANSACTION
**     COMMIT
**     ROLLBACK
**     PRAGMA
**
** $Id: build.c,v 1.166 2004/02/12 18:46:39 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
................................................................................

  /* If one or more of the auxiliary database files has been closed,
  ** then remove then from the auxiliary database list.  We take the
  ** opportunity to do this here since we have just deleted all of the
  ** schema hash tables and therefore do not have to make any changes
  ** to any of those tables.
  */
  for(i=0; i<db->nDb; i++){
    struct Db *pDb = &db->aDb[i];
    if( pDb->pBt==0 ){
      if( pDb->pAux && pDb->xFreeAux ) pDb->xFreeAux(pDb->pAux);
      pDb->pAux = 0;
    }
  }
  for(i=j=2; i<db->nDb; i++){
    struct Db *pDb = &db->aDb[i];
    if( pDb->pBt==0 ){
      sqliteFree(pDb->zName);
      pDb->zName = 0;
      continue;
    }
    if( j<i ){
      db->aDb[j] = db->aDb[i];
    }
    j++;
  }

Changes to src/main.c.

10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
...
548
549
550
551
552
553
554
555

556
557
558
559
560
561
562
563
564
565
566
567
568
**
*************************************************************************
** 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.148 2004/02/12 15:31:21 drh Exp $
*/
#include "sqliteInt.h"
#include "os.h"
#include <ctype.h>

/*
** A pointer to this structure is used to communicate information
................................................................................
  db->want_to_close = 1;
  if( sqliteSafetyCheck(db) || sqliteSafetyOn(db) ){
    /* printf("DID NOT CLOSE\n"); fflush(stdout); */
    return;
  }
  db->magic = SQLITE_MAGIC_CLOSED;
  for(j=0; j<db->nDb; j++){
    if( db->aDb[j].pBt ){

      sqliteBtreeClose(db->aDb[j].pBt);
      db->aDb[j].pBt = 0;
    }
    if( j>=2 ){
      sqliteFree(db->aDb[j].zName);
      db->aDb[j].zName = 0;
    }
  }
  sqliteResetInternalSchema(db, 0);
  assert( db->nDb<=2 );
  assert( db->aDb==db->aDbStatic );
  for(i=sqliteHashFirst(&db->aFunc); i; i=sqliteHashNext(i)){
    FuncDef *pFunc, *pNext;







|







 







|
>
|
|
<
<
<
<







10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
...
548
549
550
551
552
553
554
555
556
557
558




559
560
561
562
563
564
565
**
*************************************************************************
** 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.149 2004/02/12 18:46:39 drh Exp $
*/
#include "sqliteInt.h"
#include "os.h"
#include <ctype.h>

/*
** A pointer to this structure is used to communicate information
................................................................................
  db->want_to_close = 1;
  if( sqliteSafetyCheck(db) || sqliteSafetyOn(db) ){
    /* printf("DID NOT CLOSE\n"); fflush(stdout); */
    return;
  }
  db->magic = SQLITE_MAGIC_CLOSED;
  for(j=0; j<db->nDb; j++){
    struct Db *pDb = &db->aDb[j];
    if( pDb->pBt ){
      sqliteBtreeClose(pDb->pBt);
      pDb->pBt = 0;




    }
  }
  sqliteResetInternalSchema(db, 0);
  assert( db->nDb<=2 );
  assert( db->aDb==db->aDbStatic );
  for(i=sqliteHashFirst(&db->aFunc); i; i=sqliteHashNext(i)){
    FuncDef *pFunc, *pNext;

Changes to src/parse.y.

10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
...
876
877
878
879
880
881
882
883
884
885



886
887
888
889
890
891
892
893
**
*************************************************************************
** 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.108 2004/02/12 17:28:13 drh Exp $
*/
%token_prefix TK_
%token_type {Token}
%default_type {Token}
%extra_argument {Parse *pParse}
%syntax_error {
  if( pParse->zErrMsg==0 ){
................................................................................

////////////////////////  DROP TRIGGER statement //////////////////////////////
cmd ::= DROP TRIGGER nm(X) dbnm(D). {
  sqliteDropTrigger(pParse,sqliteSrcListAppend(0,&X,&D));
}

//////////////////////// ATTACH DATABASE file AS name /////////////////////////
cmd ::= ATTACH database_kw_opt ids(F) AS nm(D). {
  sqliteAttach(pParse, &F, &D);
}




database_kw_opt ::= DATABASE.
database_kw_opt ::= .

//////////////////////// DETACH DATABASE name /////////////////////////////////
cmd ::= DETACH database_kw_opt nm(D). {
  sqliteDetach(pParse, &D);
}







|







 







|
|

>
>
>








10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
...
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
**
*************************************************************************
** 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.109 2004/02/12 18:46:39 drh Exp $
*/
%token_prefix TK_
%token_type {Token}
%default_type {Token}
%extra_argument {Parse *pParse}
%syntax_error {
  if( pParse->zErrMsg==0 ){
................................................................................

////////////////////////  DROP TRIGGER statement //////////////////////////////
cmd ::= DROP TRIGGER nm(X) dbnm(D). {
  sqliteDropTrigger(pParse,sqliteSrcListAppend(0,&X,&D));
}

//////////////////////// ATTACH DATABASE file AS name /////////////////////////
cmd ::= ATTACH database_kw_opt ids(F) AS nm(D) key_opt(K). {
  sqliteAttach(pParse, &F, &D, &K);
}
%type key_opt {Token}
key_opt(A) ::= USING ids(X).  { A = X; }
key_opt(A) ::= .              { A.z = 0; A.n = 0; }

database_kw_opt ::= DATABASE.
database_kw_opt ::= .

//////////////////////// DETACH DATABASE name /////////////////////////////////
cmd ::= DETACH database_kw_opt nm(D). {
  sqliteDetach(pParse, &D);
}

Changes to src/sqliteInt.h.

7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
...
250
251
252
253
254
255
256


257
258
259
260
261
262
263
....
1203
1204
1205
1206
1207
1208
1209
1210
1211
1212
1213
1214
1215
1216
1217
1218
1219
1220
1221
1222
**    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.210 2004/02/11 09:46:33 drh Exp $
*/
#include "config.h"
#include "sqlite.h"
#include "hash.h"
#include "vdbe.h"
#include "parse.h"
#include "btree.h"
................................................................................
  int schema_cookie;   /* Database schema version number for this file */
  Hash tblHash;        /* All tables indexed by name */
  Hash idxHash;        /* All (named) indices indexed by name */
  Hash trigHash;       /* All triggers indexed by name */
  Hash aFKey;          /* Foreign keys indexed by to-table */
  u8 inTrans;          /* 0: not writable.  1: Transaction.  2: Checkpoint */
  u16 flags;           /* Flags associated with this database */


};

/*
** These macros can be used to test, set, or clear bits in the 
** Db.flags field.
*/
#define DbHasProperty(D,I,P)     (((D)->aDb[I].flags&(P))==(P))
................................................................................
  void sqliteAuthContextPop(AuthContext*);
#else
# define sqliteAuthRead(a,b,c)
# define sqliteAuthCheck(a,b,c,d,e)    SQLITE_OK
# define sqliteAuthContextPush(a,b,c)
# define sqliteAuthContextPop(a)  ((void)(a))
#endif
void sqliteAttach(Parse*, Token*, Token*);
void sqliteDetach(Parse*, Token*);
int sqliteBtreeFactory(const sqlite *db, const char *zFilename,
                       int mode, int nPg, Btree **ppBtree);
int sqliteFixInit(DbFixer*, Parse*, int, const char*, const Token*);
int sqliteFixSrcList(DbFixer*, SrcList*);
int sqliteFixSelect(DbFixer*, Select*);
int sqliteFixExpr(DbFixer*, Expr*);
int sqliteFixExprList(DbFixer*, ExprList*);
int sqliteFixTriggerStep(DbFixer*, TriggerStep*);
double sqliteAtoF(const char *z);
int sqlite_snprintf(int,char*,const char*,...);
int sqliteFitsIn32Bits(const char *);







|







 







>
>







 







|












7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
...
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
....
1205
1206
1207
1208
1209
1210
1211
1212
1213
1214
1215
1216
1217
1218
1219
1220
1221
1222
1223
1224
**    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.211 2004/02/12 18:46:39 drh Exp $
*/
#include "config.h"
#include "sqlite.h"
#include "hash.h"
#include "vdbe.h"
#include "parse.h"
#include "btree.h"
................................................................................
  int schema_cookie;   /* Database schema version number for this file */
  Hash tblHash;        /* All tables indexed by name */
  Hash idxHash;        /* All (named) indices indexed by name */
  Hash trigHash;       /* All triggers indexed by name */
  Hash aFKey;          /* Foreign keys indexed by to-table */
  u8 inTrans;          /* 0: not writable.  1: Transaction.  2: Checkpoint */
  u16 flags;           /* Flags associated with this database */
  void *pAux;          /* Auxiliary data.  Usually NULL */
  void (*xFreeAux)(void*);  /* Routine to free pAux */
};

/*
** These macros can be used to test, set, or clear bits in the 
** Db.flags field.
*/
#define DbHasProperty(D,I,P)     (((D)->aDb[I].flags&(P))==(P))
................................................................................
  void sqliteAuthContextPop(AuthContext*);
#else
# define sqliteAuthRead(a,b,c)
# define sqliteAuthCheck(a,b,c,d,e)    SQLITE_OK
# define sqliteAuthContextPush(a,b,c)
# define sqliteAuthContextPop(a)  ((void)(a))
#endif
void sqliteAttach(Parse*, Token*, Token*, Token*);
void sqliteDetach(Parse*, Token*);
int sqliteBtreeFactory(const sqlite *db, const char *zFilename,
                       int mode, int nPg, Btree **ppBtree);
int sqliteFixInit(DbFixer*, Parse*, int, const char*, const Token*);
int sqliteFixSrcList(DbFixer*, SrcList*);
int sqliteFixSelect(DbFixer*, Select*);
int sqliteFixExpr(DbFixer*, Expr*);
int sqliteFixExprList(DbFixer*, ExprList*);
int sqliteFixTriggerStep(DbFixer*, TriggerStep*);
double sqliteAtoF(const char *z);
int sqlite_snprintf(int,char*,const char*,...);
int sqliteFitsIn32Bits(const char *);

Changes to test/memleak.test.

6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
..
36
37
38
39
40
41
42








43
44
45
46
47
48
49
#    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 runs all tests.
#
# $Id: memleak.test,v 1.2 2003/02/26 13:52:52 drh Exp $

set testdir [file dirname $argv0]
source $testdir/tester.tcl
rename finish_test really_finish_test
proc finish_test {} {
  catch {db close}
  memleak_check
................................................................................
  all.test
  quick.test
  malloc.test
  misuse.test
  memleak.test
  btree2.test
  trans.test








}
if {[llength $argv]>0} {
  set FILELIST $argv
  set argv {}
} else {
  set FILELIST [lsort -dictionary [glob $testdir/*.test]]
}







|







 







>
>
>
>
>
>
>
>







6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
..
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
#    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 runs all tests.
#
# $Id: memleak.test,v 1.3 2004/02/12 18:46:39 drh Exp $

set testdir [file dirname $argv0]
source $testdir/tester.tcl
rename finish_test really_finish_test
proc finish_test {} {
  catch {db close}
  memleak_check
................................................................................
  all.test
  quick.test
  malloc.test
  misuse.test
  memleak.test
  btree2.test
  trans.test
}
if {[sqlite -has-codec]} {
  lappend EXCLUDE \
    attach.test \
    attach2.test \
    auth.test \
    format3.test \
    version.test
}
if {[llength $argv]>0} {
  set FILELIST $argv
  set argv {}
} else {
  set FILELIST [lsort -dictionary [glob $testdir/*.test]]
}