/ 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 Side-by-Side Diffs Ignore Whitespace Patch

Changes to src/loadext.c.

    12     12   ** This file contains code used to dynamically load extensions into
    13     13   ** the SQLite library.
    14     14   */
    15     15   #ifndef SQLITE_OMIT_LOAD_EXTENSION
    16     16   
    17     17   #define SQLITE_CORE 1  /* Disable the API redefinition in sqlite3ext.h */
    18     18   #include "sqlite3ext.h"
           19  +#include "sqliteInt.h"
    19     20   #include <string.h>
    20     21   #include <ctype.h>
    21     22   
    22     23   #ifndef SQLITE_ENABLE_COLUMN_METADATA
    23     24   # define sqlite3_column_database_name   0
    24     25   # define sqlite3_column_database_name16 0
    25     26   # define sqlite3_column_table_name      0
................................................................................
   143    144   
   144    145   
   145    146    #if defined(_WIN32) || defined(WIN32) || defined(__MINGW32__) || defined(__BORLANDC__)
   146    147   # include <windows.h>
   147    148   # define SQLITE_LIBRARY_TYPE     HANDLE
   148    149   # define SQLITE_OPEN_LIBRARY(A)  LoadLibrary(A)
   149    150   # define SQLITE_FIND_SYMBOL(A,B) GetProcAddress(A,B)
   150         -# define SQLITE_LIBRARY_ERROR(A) FreeLibrary(A)
   151         -# define SQLITE_CLOSE_LIBRARY(A) 
          151  +# define SQLITE_CLOSE_LIBRARY(A) FreeLibrary(A)
   152    152   #endif /* windows */
   153    153   
   154    154   /*
   155    155   ** Non-windows implementation of shared-library loaders
   156    156   */
   157    157   #if defined(HAVE_DLOPEN) && !defined(SQLITE_LIBRARY_TYPE)
   158    158   # include <dlfcn.h>
   159    159   # define SQLITE_LIBRARY_TYPE     void*
   160    160   # define SQLITE_OPEN_LIBRARY(A)  dlopen(A, RTLD_NOW | RTLD_GLOBAL)
   161    161   # define SQLITE_FIND_SYMBOL(A,B) dlsym(A,B)
   162         -# define SQLITE_LIBRARY_ERROR(A) dlclose(A)
   163         -# define SQLITE_CLOSE_LIBRARY(A)
          162  +# define SQLITE_CLOSE_LIBRARY(A) dlclose(A)
   164    163   #endif
   165    164   
   166    165   /*
   167    166   ** Attempt to load an SQLite extension library contained in the file
   168    167   ** zFile.  The entry point is zProc.  zProc may be 0 in which case the
   169    168   ** name of the entry point is derived from the filename.
   170    169   **
................................................................................
   198    197     const char *zProc,    /* Entry point.  Derived from zFile if 0 */
   199    198     char **pzErrMsg       /* Put error message here if not 0 */
   200    199   ){
   201    200   #ifdef SQLITE_LIBRARY_TYPE
   202    201     SQLITE_LIBRARY_TYPE handle;
   203    202     int (*xInit)(sqlite3*,char**,const sqlite3_api_routines*);
   204    203     char *zErrmsg = 0;
          204  +  SQLITE_LIBRARY_TYPE *aHandle;
   205    205   
          206  +  db->nExtension++;
          207  +  aHandle = sqliteMalloc(sizeof(handle)*db->nExtension);
          208  +  if( aHandle==0 ){
          209  +    return SQLITE_NOMEM;
          210  +  }
          211  +  if( db->nExtension>0 ){
          212  +    memcpy(aHandle, db->aExtension, sizeof(handle)*(db->nExtension-1));
          213  +  }
          214  +  sqliteFree(db->aExtension);
          215  +  db->aExtension = aHandle;
   206    216     if( zProc==0 ){
   207    217       int i, j, n;
   208    218       char *z;
   209    219       char zBuf[200];
   210    220       n = strlen(zFile);
   211    221       for(i=n-1; i>0 && zFile[i-1]!='/'; i--){}
   212    222       for(j=i; zFile[j] && zFile[j]!='.'; j++){}
................................................................................
   240    250     xInit = (int(*)(sqlite3*,char**,const sqlite3_api_routines*))
   241    251                      SQLITE_FIND_SYMBOL(handle, zProc);
   242    252     if( xInit==0 ){
   243    253       if( pzErrMsg ){
   244    254          *pzErrMsg = sqlite3_mprintf("no entry point [%s] in shared library [%s]",
   245    255                                      zProc, zFile);
   246    256       }
   247         -    SQLITE_LIBRARY_ERROR(handle);
          257  +    SQLITE_CLOSE_LIBRARY(handle);
   248    258       return SQLITE_ERROR;
   249    259     }else if( xInit(db, &zErrmsg, &sqlite3_api) ){
   250    260       if( pzErrMsg ){
   251    261         *pzErrMsg = sqlite3_mprintf("error during initialization: %s", zErrmsg);
   252    262       }
   253    263       sqlite3_free(zErrmsg);
   254         -    SQLITE_LIBRARY_ERROR(handle);
          264  +    SQLITE_CLOSE_LIBRARY(handle);
   255    265       return SQLITE_ERROR;
   256    266     }
   257         -  SQLITE_CLOSE_LIBRARY(handle);
          267  +  ((SQLITE_LIBRARY_TYPE*)db->aExtension)[db->nExtension-1] = handle;
   258    268     return SQLITE_OK;
   259    269   #else
   260    270     if( pzErrMsg ){
   261    271       *pzErrMsg = sqlite3_mprintf(
   262    272                        "shared library loading not enabled for this build");
   263    273     }
   264    274     return SQLITE_ERROR;
   265    275   #endif
   266    276   }
          277  +
          278  +/*
          279  +** Call this routine when the database connection is closing in order
          280  +** to clean up loaded extensions
          281  +*/
          282  +void sqlite3CloseExtensions(sqlite3 *db){
          283  +  int i;
          284  +  for(i=0; i<db->nExtension; i++){
          285  +    SQLITE_CLOSE_LIBRARY(((SQLITE_LIBRARY_TYPE*)db->aExtension)[i]);
          286  +  }
          287  +  sqliteFree(db->aExtension);
          288  +}
          289  +
   267    290   #endif /* SQLITE_OMIT_LOAD_EXTENSION */

Changes to src/main.c.

    10     10   **
    11     11   *************************************************************************
    12     12   ** Main file for the SQLite library.  The routines in this file
    13     13   ** implement the programmer interface to the library.  Routines in
    14     14   ** other files are for internal use by SQLite and should not be
    15     15   ** accessed by users of the library.
    16     16   **
    17         -** $Id: main.c,v 1.340 2006/05/24 12:43:27 drh Exp $
           17  +** $Id: main.c,v 1.341 2006/06/08 15:48:01 drh Exp $
    18     18   */
    19     19   #include "sqliteInt.h"
    20     20   #include "os.h"
    21     21   #include <ctype.h>
    22     22   
    23     23   /*
    24     24   ** The following constant value is used by the SQLITE_BIGENDIAN and
................................................................................
   161    161     sqlite3HashClear(&db->aCollSeq);
   162    162   
   163    163     sqlite3HashClear(&db->aFunc);
   164    164     sqlite3Error(db, SQLITE_OK, 0); /* Deallocates any cached error strings. */
   165    165     if( db->pErr ){
   166    166       sqlite3ValueFree(db->pErr);
   167    167     }
          168  +  sqlite3CloseExtensions(db);
   168    169   
   169    170     db->magic = SQLITE_MAGIC_ERROR;
   170    171   
   171    172     /* The temp-database schema is allocated differently from the other schema
   172    173     ** objects (using sqliteMalloc() directly, instead of sqlite3BtreeSchema()).
   173    174     ** So it needs to be freed here. Todo: Why not roll the temp schema into
   174    175     ** the same sqliteMalloc() as the one that allocates the database 

Changes to src/sqliteInt.h.

     7      7   **    May you do good and not evil.
     8      8   **    May you find forgiveness for yourself and forgive others.
     9      9   **    May you share freely, never taking more than you give.
    10     10   **
    11     11   *************************************************************************
    12     12   ** Internal interface definitions for SQLite.
    13     13   **
    14         -** @(#) $Id: sqliteInt.h,v 1.494 2006/05/25 12:17:31 drh Exp $
           14  +** @(#) $Id: sqliteInt.h,v 1.495 2006/06/08 15:48:01 drh Exp $
    15     15   */
    16     16   #ifndef _SQLITEINT_H_
    17     17   #define _SQLITEINT_H_
    18     18   
    19     19   /*
    20     20   ** Extra interface definitions for those who need them
    21     21   */
................................................................................
   456    456     int nChange;                  /* Value returned by sqlite3_changes() */
   457    457     int nTotalChange;             /* Value returned by sqlite3_total_changes() */
   458    458     struct sqlite3InitInfo {      /* Information used during initialization */
   459    459       int iDb;                    /* When back is being initialized */
   460    460       int newTnum;                /* Rootpage of table being initialized */
   461    461       u8 busy;                    /* TRUE if currently initializing */
   462    462     } init;
          463  +  int nExtension;               /* Number of loaded extensions */
          464  +  void *aExtension;             /* Array of shared libraray handles */
   463    465     struct Vdbe *pVdbe;           /* List of active virtual machines */
   464    466     int activeVdbeCnt;            /* Number of vdbes currently executing */
   465    467     void (*xTrace)(void*,const char*);        /* Trace function */
   466    468     void *pTraceArg;                          /* Argument to the trace function */
   467    469     void (*xProfile)(void*,const char*,u64);  /* Profiling function */
   468    470     void *pProfileArg;                        /* Argument to profile function */
   469    471     void *pCommitArg;                 /* Argument to xCommitCallback() */   
................................................................................
  1736   1738     void (*)(sqlite3_context*,int,sqlite3_value **),
  1737   1739     void (*)(sqlite3_context*,int,sqlite3_value **), void (*)(sqlite3_context*));
  1738   1740   int sqlite3ApiExit(sqlite3 *db, int);
  1739   1741   int sqlite3MallocFailed(void);
  1740   1742   void sqlite3FailedMalloc(void);
  1741   1743   void sqlite3AbortOtherActiveVdbes(sqlite3 *, Vdbe *);
  1742   1744   int sqlite3OpenTempDatabase(Parse *);
         1745  +void sqlite3CloseExtensions(sqlite3*);
  1743   1746   
  1744   1747   #ifndef SQLITE_OMIT_SHARED_CACHE
  1745   1748     void sqlite3TableLock(Parse *, int, int, u8, const char *);
  1746   1749   #else
  1747   1750     #define sqlite3TableLock(v,w,x,y,z)
  1748   1751   #endif
  1749   1752