/ Check-in [327e6909]
Login

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

Overview
Comment:Unload shared libraries when a database connection closes. (CVS 3208)
Downloads: Tarball | ZIP archive | SQL archive
Timelines: family | ancestors | descendants | both | trunk
Files: files | file ages | folders
SHA1:327e6909c9d35b651ab6f3a1a270022b354538c6
User & Date: drh 2006-06-08 15:48:01
Context
2006-06-08
16:10
In the shell, make sure the database is opened before trying to do an ".import". Bug reported on the mailing list. (CVS 3209) check-in: 39e34278 user: drh tags: trunk
15:48
Unload shared libraries when a database connection closes. (CVS 3208) check-in: 327e6909 user: drh tags: trunk
15:28
New shell command ".load" and the sqlite3_load_extension() API allow new SQL functions and collating sequences to be loaded at run-time from a DLL or shared library. (CVS 3207) check-in: 4ca932d3 user: drh tags: trunk
Changes
Hide Diffs Unified Diffs Ignore Whitespace Patch

Changes to src/loadext.c.

12
13
14
15
16
17
18

19
20
21
22
23
24
25
...
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
...
198
199
200
201
202
203
204

205










206
207
208
209
210
211
212
...
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266













267
** This file contains code used to dynamically load extensions into
** the SQLite library.
*/
#ifndef SQLITE_OMIT_LOAD_EXTENSION

#define SQLITE_CORE 1  /* Disable the API redefinition in sqlite3ext.h */
#include "sqlite3ext.h"

#include <string.h>
#include <ctype.h>

#ifndef SQLITE_ENABLE_COLUMN_METADATA
# define sqlite3_column_database_name   0
# define sqlite3_column_database_name16 0
# define sqlite3_column_table_name      0
................................................................................


 #if defined(_WIN32) || defined(WIN32) || defined(__MINGW32__) || defined(__BORLANDC__)
# include <windows.h>
# define SQLITE_LIBRARY_TYPE     HANDLE
# define SQLITE_OPEN_LIBRARY(A)  LoadLibrary(A)
# define SQLITE_FIND_SYMBOL(A,B) GetProcAddress(A,B)
# define SQLITE_LIBRARY_ERROR(A) FreeLibrary(A)
# define SQLITE_CLOSE_LIBRARY(A) 
#endif /* windows */

/*
** Non-windows implementation of shared-library loaders
*/
#if defined(HAVE_DLOPEN) && !defined(SQLITE_LIBRARY_TYPE)
# include <dlfcn.h>
# define SQLITE_LIBRARY_TYPE     void*
# define SQLITE_OPEN_LIBRARY(A)  dlopen(A, RTLD_NOW | RTLD_GLOBAL)
# define SQLITE_FIND_SYMBOL(A,B) dlsym(A,B)
# define SQLITE_LIBRARY_ERROR(A) dlclose(A)
# define SQLITE_CLOSE_LIBRARY(A)
#endif

/*
** Attempt to load an SQLite extension library contained in the file
** zFile.  The entry point is zProc.  zProc may be 0 in which case the
** name of the entry point is derived from the filename.
**
................................................................................
  const char *zProc,    /* Entry point.  Derived from zFile if 0 */
  char **pzErrMsg       /* Put error message here if not 0 */
){
#ifdef SQLITE_LIBRARY_TYPE
  SQLITE_LIBRARY_TYPE handle;
  int (*xInit)(sqlite3*,char**,const sqlite3_api_routines*);
  char *zErrmsg = 0;












  if( zProc==0 ){
    int i, j, n;
    char *z;
    char zBuf[200];
    n = strlen(zFile);
    for(i=n-1; i>0 && zFile[i-1]!='/'; i--){}
    for(j=i; zFile[j] && zFile[j]!='.'; j++){}
................................................................................
  xInit = (int(*)(sqlite3*,char**,const sqlite3_api_routines*))
                   SQLITE_FIND_SYMBOL(handle, zProc);
  if( xInit==0 ){
    if( pzErrMsg ){
       *pzErrMsg = sqlite3_mprintf("no entry point [%s] in shared library [%s]",
                                   zProc, zFile);
    }
    SQLITE_LIBRARY_ERROR(handle);
    return SQLITE_ERROR;
  }else if( xInit(db, &zErrmsg, &sqlite3_api) ){
    if( pzErrMsg ){
      *pzErrMsg = sqlite3_mprintf("error during initialization: %s", zErrmsg);
    }
    sqlite3_free(zErrmsg);
    SQLITE_LIBRARY_ERROR(handle);
    return SQLITE_ERROR;
  }
  SQLITE_CLOSE_LIBRARY(handle);
  return SQLITE_OK;
#else
  if( pzErrMsg ){
    *pzErrMsg = sqlite3_mprintf(
                     "shared library loading not enabled for this build");
  }
  return SQLITE_ERROR;
#endif
}













#endif /* SQLITE_OMIT_LOAD_EXTENSION */







>







 







<
|










<
|







 







>

>
>
>
>
>
>
>
>
>
>







 







|






|


|









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

12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
...
144
145
146
147
148
149
150

151
152
153
154
155
156
157
158
159
160
161

162
163
164
165
166
167
168
169
...
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
...
250
251
252
253
254
255
256
257
258
259
260
261
262
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
** This file contains code used to dynamically load extensions into
** the SQLite library.
*/
#ifndef SQLITE_OMIT_LOAD_EXTENSION

#define SQLITE_CORE 1  /* Disable the API redefinition in sqlite3ext.h */
#include "sqlite3ext.h"
#include "sqliteInt.h"
#include <string.h>
#include <ctype.h>

#ifndef SQLITE_ENABLE_COLUMN_METADATA
# define sqlite3_column_database_name   0
# define sqlite3_column_database_name16 0
# define sqlite3_column_table_name      0
................................................................................


 #if defined(_WIN32) || defined(WIN32) || defined(__MINGW32__) || defined(__BORLANDC__)
# include <windows.h>
# define SQLITE_LIBRARY_TYPE     HANDLE
# define SQLITE_OPEN_LIBRARY(A)  LoadLibrary(A)
# define SQLITE_FIND_SYMBOL(A,B) GetProcAddress(A,B)

# define SQLITE_CLOSE_LIBRARY(A) FreeLibrary(A)
#endif /* windows */

/*
** Non-windows implementation of shared-library loaders
*/
#if defined(HAVE_DLOPEN) && !defined(SQLITE_LIBRARY_TYPE)
# include <dlfcn.h>
# define SQLITE_LIBRARY_TYPE     void*
# define SQLITE_OPEN_LIBRARY(A)  dlopen(A, RTLD_NOW | RTLD_GLOBAL)
# define SQLITE_FIND_SYMBOL(A,B) dlsym(A,B)

# define SQLITE_CLOSE_LIBRARY(A) dlclose(A)
#endif

/*
** Attempt to load an SQLite extension library contained in the file
** zFile.  The entry point is zProc.  zProc may be 0 in which case the
** name of the entry point is derived from the filename.
**
................................................................................
  const char *zProc,    /* Entry point.  Derived from zFile if 0 */
  char **pzErrMsg       /* Put error message here if not 0 */
){
#ifdef SQLITE_LIBRARY_TYPE
  SQLITE_LIBRARY_TYPE handle;
  int (*xInit)(sqlite3*,char**,const sqlite3_api_routines*);
  char *zErrmsg = 0;
  SQLITE_LIBRARY_TYPE *aHandle;

  db->nExtension++;
  aHandle = sqliteMalloc(sizeof(handle)*db->nExtension);
  if( aHandle==0 ){
    return SQLITE_NOMEM;
  }
  if( db->nExtension>0 ){
    memcpy(aHandle, db->aExtension, sizeof(handle)*(db->nExtension-1));
  }
  sqliteFree(db->aExtension);
  db->aExtension = aHandle;
  if( zProc==0 ){
    int i, j, n;
    char *z;
    char zBuf[200];
    n = strlen(zFile);
    for(i=n-1; i>0 && zFile[i-1]!='/'; i--){}
    for(j=i; zFile[j] && zFile[j]!='.'; j++){}
................................................................................
  xInit = (int(*)(sqlite3*,char**,const sqlite3_api_routines*))
                   SQLITE_FIND_SYMBOL(handle, zProc);
  if( xInit==0 ){
    if( pzErrMsg ){
       *pzErrMsg = sqlite3_mprintf("no entry point [%s] in shared library [%s]",
                                   zProc, zFile);
    }
    SQLITE_CLOSE_LIBRARY(handle);
    return SQLITE_ERROR;
  }else if( xInit(db, &zErrmsg, &sqlite3_api) ){
    if( pzErrMsg ){
      *pzErrMsg = sqlite3_mprintf("error during initialization: %s", zErrmsg);
    }
    sqlite3_free(zErrmsg);
    SQLITE_CLOSE_LIBRARY(handle);
    return SQLITE_ERROR;
  }
  ((SQLITE_LIBRARY_TYPE*)db->aExtension)[db->nExtension-1] = handle;
  return SQLITE_OK;
#else
  if( pzErrMsg ){
    *pzErrMsg = sqlite3_mprintf(
                     "shared library loading not enabled for this build");
  }
  return SQLITE_ERROR;
#endif
}

/*
** Call this routine when the database connection is closing in order
** to clean up loaded extensions
*/
void sqlite3CloseExtensions(sqlite3 *db){
  int i;
  for(i=0; i<db->nExtension; i++){
    SQLITE_CLOSE_LIBRARY(((SQLITE_LIBRARY_TYPE*)db->aExtension)[i]);
  }
  sqliteFree(db->aExtension);
}

#endif /* SQLITE_OMIT_LOAD_EXTENSION */

Changes to src/main.c.

10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
...
161
162
163
164
165
166
167

168
169
170
171
172
173
174
**
*************************************************************************
** 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.340 2006/05/24 12:43:27 drh Exp $
*/
#include "sqliteInt.h"
#include "os.h"
#include <ctype.h>

/*
** The following constant value is used by the SQLITE_BIGENDIAN and
................................................................................
  sqlite3HashClear(&db->aCollSeq);

  sqlite3HashClear(&db->aFunc);
  sqlite3Error(db, SQLITE_OK, 0); /* Deallocates any cached error strings. */
  if( db->pErr ){
    sqlite3ValueFree(db->pErr);
  }


  db->magic = SQLITE_MAGIC_ERROR;

  /* The temp-database schema is allocated differently from the other schema
  ** objects (using sqliteMalloc() directly, instead of sqlite3BtreeSchema()).
  ** So it needs to be freed here. Todo: Why not roll the temp schema into
  ** the same sqliteMalloc() as the one that allocates the database 







|







 







>







10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
...
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
**
*************************************************************************
** 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.341 2006/06/08 15:48:01 drh Exp $
*/
#include "sqliteInt.h"
#include "os.h"
#include <ctype.h>

/*
** The following constant value is used by the SQLITE_BIGENDIAN and
................................................................................
  sqlite3HashClear(&db->aCollSeq);

  sqlite3HashClear(&db->aFunc);
  sqlite3Error(db, SQLITE_OK, 0); /* Deallocates any cached error strings. */
  if( db->pErr ){
    sqlite3ValueFree(db->pErr);
  }
  sqlite3CloseExtensions(db);

  db->magic = SQLITE_MAGIC_ERROR;

  /* The temp-database schema is allocated differently from the other schema
  ** objects (using sqliteMalloc() directly, instead of sqlite3BtreeSchema()).
  ** So it needs to be freed here. Todo: Why not roll the temp schema into
  ** the same sqliteMalloc() as the one that allocates the database 

Changes to src/sqliteInt.h.

7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
...
456
457
458
459
460
461
462


463
464
465
466
467
468
469
....
1736
1737
1738
1739
1740
1741
1742

1743
1744
1745
1746
1747
1748
1749
**    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.494 2006/05/25 12:17:31 drh Exp $
*/
#ifndef _SQLITEINT_H_
#define _SQLITEINT_H_

/*
** Extra interface definitions for those who need them
*/
................................................................................
  int nChange;                  /* Value returned by sqlite3_changes() */
  int nTotalChange;             /* Value returned by sqlite3_total_changes() */
  struct sqlite3InitInfo {      /* Information used during initialization */
    int iDb;                    /* When back is being initialized */
    int newTnum;                /* Rootpage of table being initialized */
    u8 busy;                    /* TRUE if currently initializing */
  } init;


  struct Vdbe *pVdbe;           /* List of active virtual machines */
  int activeVdbeCnt;            /* Number of vdbes currently executing */
  void (*xTrace)(void*,const char*);        /* Trace function */
  void *pTraceArg;                          /* Argument to the trace function */
  void (*xProfile)(void*,const char*,u64);  /* Profiling function */
  void *pProfileArg;                        /* Argument to profile function */
  void *pCommitArg;                 /* Argument to xCommitCallback() */   
................................................................................
  void (*)(sqlite3_context*,int,sqlite3_value **),
  void (*)(sqlite3_context*,int,sqlite3_value **), void (*)(sqlite3_context*));
int sqlite3ApiExit(sqlite3 *db, int);
int sqlite3MallocFailed(void);
void sqlite3FailedMalloc(void);
void sqlite3AbortOtherActiveVdbes(sqlite3 *, Vdbe *);
int sqlite3OpenTempDatabase(Parse *);


#ifndef SQLITE_OMIT_SHARED_CACHE
  void sqlite3TableLock(Parse *, int, int, u8, const char *);
#else
  #define sqlite3TableLock(v,w,x,y,z)
#endif








|







 







>
>







 







>







7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
...
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
....
1738
1739
1740
1741
1742
1743
1744
1745
1746
1747
1748
1749
1750
1751
1752
**    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.495 2006/06/08 15:48:01 drh Exp $
*/
#ifndef _SQLITEINT_H_
#define _SQLITEINT_H_

/*
** Extra interface definitions for those who need them
*/
................................................................................
  int nChange;                  /* Value returned by sqlite3_changes() */
  int nTotalChange;             /* Value returned by sqlite3_total_changes() */
  struct sqlite3InitInfo {      /* Information used during initialization */
    int iDb;                    /* When back is being initialized */
    int newTnum;                /* Rootpage of table being initialized */
    u8 busy;                    /* TRUE if currently initializing */
  } init;
  int nExtension;               /* Number of loaded extensions */
  void *aExtension;             /* Array of shared libraray handles */
  struct Vdbe *pVdbe;           /* List of active virtual machines */
  int activeVdbeCnt;            /* Number of vdbes currently executing */
  void (*xTrace)(void*,const char*);        /* Trace function */
  void *pTraceArg;                          /* Argument to the trace function */
  void (*xProfile)(void*,const char*,u64);  /* Profiling function */
  void *pProfileArg;                        /* Argument to profile function */
  void *pCommitArg;                 /* Argument to xCommitCallback() */   
................................................................................
  void (*)(sqlite3_context*,int,sqlite3_value **),
  void (*)(sqlite3_context*,int,sqlite3_value **), void (*)(sqlite3_context*));
int sqlite3ApiExit(sqlite3 *db, int);
int sqlite3MallocFailed(void);
void sqlite3FailedMalloc(void);
void sqlite3AbortOtherActiveVdbes(sqlite3 *, Vdbe *);
int sqlite3OpenTempDatabase(Parse *);
void sqlite3CloseExtensions(sqlite3*);

#ifndef SQLITE_OMIT_SHARED_CACHE
  void sqlite3TableLock(Parse *, int, int, u8, const char *);
#else
  #define sqlite3TableLock(v,w,x,y,z)
#endif