mirror of
https://github.com/sqlite/sqlite.git
synced 2025-08-08 14:02:16 +03:00
Use the pointer-map pages to make the incremental blob API more efficient. (CVS 3896)
FossilOrigin-Name: 93a3bf71d576096f4b5a3db256ca6f9b5521d137
This commit is contained in:
@@ -12,7 +12,7 @@
|
||||
** A TCL Interface to SQLite. Append this file to sqlite3.c and
|
||||
** compile the whole thing to build a TCL-enabled version of SQLite.
|
||||
**
|
||||
** $Id: tclsqlite.c,v 1.180 2007/05/01 17:49:49 danielk1977 Exp $
|
||||
** $Id: tclsqlite.c,v 1.181 2007/05/02 13:16:31 danielk1977 Exp $
|
||||
*/
|
||||
#include "tcl.h"
|
||||
#include <errno.h>
|
||||
@@ -89,6 +89,8 @@ struct SqlPreparedStmt {
|
||||
char zSql[1]; /* Text of the SQL statement */
|
||||
};
|
||||
|
||||
typedef struct IncrblobChannel IncrblobChannel;
|
||||
|
||||
/*
|
||||
** There is one instance of this structure for each SQLite database
|
||||
** that has been opened by the SQLite TCL interface.
|
||||
@@ -114,20 +116,56 @@ struct SqliteDb {
|
||||
SqlPreparedStmt *stmtLast; /* Last statement in the list */
|
||||
int maxStmt; /* The next maximum number of stmtList */
|
||||
int nStmt; /* Number of statements in stmtList */
|
||||
IncrblobChannel *pIncrblob;/* Linked list of open incrblob channels */
|
||||
};
|
||||
|
||||
typedef struct IncrblobChannel IncrblobChannel;
|
||||
struct IncrblobChannel {
|
||||
sqlite3_blob *pBlob;
|
||||
int iSeek; /* Current seek offset */
|
||||
SqliteDb *pDb; /* Associated database connection */
|
||||
sqlite3_blob *pBlob; /* sqlite3 blob handle */
|
||||
int iSeek; /* Current seek offset */
|
||||
|
||||
Tcl_Channel channel; /* Channel identifier */
|
||||
IncrblobChannel *pNext; /* Linked list of all open incrblob channels */
|
||||
IncrblobChannel *pPrev; /* Linked list of all open incrblob channels */
|
||||
};
|
||||
|
||||
/*
|
||||
** Close all incrblob channels opened using database connection pDb.
|
||||
** This is called when shutting down the database connection.
|
||||
*/
|
||||
static void closeIncrblobChannels(SqliteDb *pDb){
|
||||
IncrblobChannel *p;
|
||||
IncrblobChannel *pNext;
|
||||
|
||||
for(p=pDb->pIncrblob; p; p=pNext){
|
||||
pNext = p->pNext;
|
||||
|
||||
/* Note: Calling unregister here call Tcl_Close on the incrblob channel,
|
||||
** which deletes the IncrblobChannel structure at *p. So do not
|
||||
** call Tcl_Free() here.
|
||||
*/
|
||||
Tcl_UnregisterChannel(pDb->interp, p->channel);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
** Close an incremental blob channel.
|
||||
*/
|
||||
static int incrblobClose(ClientData instanceData, Tcl_Interp *interp){
|
||||
IncrblobChannel *p = (IncrblobChannel *)instanceData;
|
||||
sqlite3_blob_close(p->pBlob);
|
||||
|
||||
/* Remove the channel from the SqliteDb.pIncrblob list. */
|
||||
if( p->pNext ){
|
||||
p->pNext->pPrev = p->pPrev;
|
||||
}
|
||||
if( p->pPrev ){
|
||||
p->pPrev->pNext = p->pNext;
|
||||
}
|
||||
if( p->pDb->pIncrblob==p ){
|
||||
p->pDb->pIncrblob = p->pNext;
|
||||
}
|
||||
|
||||
Tcl_Free((char *)p);
|
||||
return TCL_OK;
|
||||
}
|
||||
@@ -164,6 +202,9 @@ static int incrblobInput(
|
||||
return nRead;
|
||||
}
|
||||
|
||||
/*
|
||||
** Write data to an incremental blob channel.
|
||||
*/
|
||||
static int incrblobOutput(
|
||||
ClientData instanceData,
|
||||
CONST char *buf,
|
||||
@@ -263,7 +304,6 @@ static int createIncrblobChannel(
|
||||
IncrblobChannel *p;
|
||||
sqlite3_blob *pBlob;
|
||||
int rc;
|
||||
Tcl_Channel channel;
|
||||
int flags = TCL_READABLE|TCL_WRITABLE;
|
||||
|
||||
/* This variable is used to name the channels: "incrblob_[incr count]" */
|
||||
@@ -281,10 +321,19 @@ static int createIncrblobChannel(
|
||||
p->pBlob = pBlob;
|
||||
|
||||
sprintf(zChannel, "incrblob_%d", ++count);
|
||||
channel = Tcl_CreateChannel(&IncrblobChannelType, zChannel, p, flags);
|
||||
Tcl_RegisterChannel(interp, channel);
|
||||
p->channel = Tcl_CreateChannel(&IncrblobChannelType, zChannel, p, flags);
|
||||
Tcl_RegisterChannel(interp, p->channel);
|
||||
|
||||
Tcl_SetResult(interp, (char *)Tcl_GetChannelName(channel), TCL_VOLATILE);
|
||||
/* Link the new channel into the SqliteDb.pIncrblob list. */
|
||||
p->pNext = pDb->pIncrblob;
|
||||
p->pPrev = 0;
|
||||
if( p->pNext ){
|
||||
p->pNext->pPrev = p;
|
||||
}
|
||||
pDb->pIncrblob = p;
|
||||
p->pDb = pDb;
|
||||
|
||||
Tcl_SetResult(interp, (char *)Tcl_GetChannelName(p->channel), TCL_VOLATILE);
|
||||
return TCL_OK;
|
||||
}
|
||||
|
||||
@@ -363,6 +412,7 @@ static void flushStmtCache( SqliteDb *pDb ){
|
||||
static void DbDeleteCmd(void *db){
|
||||
SqliteDb *pDb = (SqliteDb*)db;
|
||||
flushStmtCache(pDb);
|
||||
closeIncrblobChannels(pDb);
|
||||
sqlite3_close(pDb->db);
|
||||
while( pDb->pFunc ){
|
||||
SqlFunc *pFunc = pDb->pFunc;
|
||||
|
Reference in New Issue
Block a user