diff options
author | drh <> | 2024-07-30 16:51:51 +0000 |
---|---|---|
committer | drh <> | 2024-07-30 16:51:51 +0000 |
commit | 1631c64f780b54a0363495b58c52b8c942516671 (patch) | |
tree | 87be6add6e6b51c2e476693758c93be8ba5f3c2c /src/tclsqlite.c | |
parent | 064b681e9bb2a0230c312c5a48f0797f821b3074 (diff) | |
download | sqlite-1631c64f780b54a0363495b58c52b8c942516671.tar.gz sqlite-1631c64f780b54a0363495b58c52b8c942516671.zip |
Fix the incrblob channel so that partial close works with Tcl9.
FossilOrigin-Name: d54ec2de78c2aed12be643e59a30b6827fe4728a0ab6504dd64ee9116e5f885a
Diffstat (limited to 'src/tclsqlite.c')
-rw-r--r-- | src/tclsqlite.c | 30 |
1 files changed, 26 insertions, 4 deletions
diff --git a/src/tclsqlite.c b/src/tclsqlite.c index ae3b61c6c..189446bca 100644 --- a/src/tclsqlite.c +++ b/src/tclsqlite.c @@ -203,6 +203,7 @@ struct IncrblobChannel { sqlite3_blob *pBlob; /* sqlite3 blob handle */ SqliteDb *pDb; /* Associated database connection */ int iSeek; /* Current seek offset */ + int isClosed; /* TCL_CLOSE_READ or TCL_CLOSE_WRITE */ Tcl_Channel channel; /* Channel identifier */ IncrblobChannel *pNext; /* Linked list of all open incrblob channels */ IncrblobChannel *pPrev; /* Linked list of all open incrblob channels */ @@ -242,14 +243,27 @@ static void closeIncrblobChannels(SqliteDb *pDb){ /* ** Close an incremental blob channel. */ -static int SQLITE_TCLAPI incrblobClose( +static int SQLITE_TCLAPI incrblobClose2( ClientData instanceData, - Tcl_Interp *interp + Tcl_Interp *interp, + int flags ){ IncrblobChannel *p = (IncrblobChannel *)instanceData; - int rc = sqlite3_blob_close(p->pBlob); + int rc; sqlite3 *db = p->pDb->db; + if( flags ){ + p->isClosed |= flags; + if( (p->isClosed & (TCL_CLOSE_READ|TCL_CLOSE_WRITE)) + != (TCL_CLOSE_READ|TCL_CLOSE_WRITE) ){ + /* Not yet fully closed. Just return. */ + return TCL_OK; + } + } + + /* If we reach this point, then we really do need to close the channel */ + rc = sqlite3_blob_close(p->pBlob); + /* Remove the channel from the SqliteDb.pIncrblob list. */ if( p->pNext ){ p->pNext->pPrev = p->pPrev; @@ -270,6 +284,13 @@ static int SQLITE_TCLAPI incrblobClose( } return TCL_OK; } +static int SQLITE_TCLAPI incrblobClose( + ClientData instanceData, + Tcl_Interp *interp +){ + return incrblobClose2(instanceData, interp, 0); +} + /* ** Read data from an incremental blob channel. @@ -390,7 +411,7 @@ static Tcl_ChannelType IncrblobChannelType = { 0, /* getOptionProc */ incrblobWatch, /* watchProc (this is a no-op) */ incrblobHandle, /* getHandleProc (always returns error) */ - 0, /* close2Proc */ + incrblobClose2, /* close2Proc */ 0, /* blockModeProc */ 0, /* flushProc */ 0, /* handlerProc */ @@ -428,6 +449,7 @@ static int createIncrblobChannel( p = (IncrblobChannel *)Tcl_Alloc(sizeof(IncrblobChannel)); p->iSeek = 0; p->pBlob = pBlob; + if( (flags & TCL_WRITABLE)==0 ) p->isClosed |= TCL_CLOSE_WRITE; sqlite3_snprintf(sizeof(zChannel), zChannel, "incrblob_%d", ++count); p->channel = Tcl_CreateChannel(&IncrblobChannelType, zChannel, p, flags); |