Index: src/os_win.c
==================================================================
--- src/os_win.c
+++ src/os_win.c
@@ -3431,10 +3431,16 @@
}else{
a[1] = winIoerrRetryDelay;
}
OSTRACE(("FCNTL file=%p, rc=SQLITE_OK\n", pFile->h));
return SQLITE_OK;
+ }
+ case SQLITE_FCNTL_WIN32_GET_HANDLE: {
+ LPHANDLE phFile = (LPHANDLE)pArg;
+ *phFile = pFile->h;
+ OSTRACE(("FCNTL file=%p, rc=SQLITE_OK\n", pFile->h));
+ return SQLITE_OK;
}
#ifdef SQLITE_TEST
case SQLITE_FCNTL_WIN32_SET_HANDLE: {
LPHANDLE phFile = (LPHANDLE)pArg;
HANDLE hOldFile = pFile->h;
Index: src/sqlite.h.in
==================================================================
--- src/sqlite.h.in
+++ src/sqlite.h.in
@@ -963,10 +963,16 @@
**
[[SQLITE_FCNTL_HAS_MOVED]]
** The [SQLITE_FCNTL_HAS_MOVED] file control interprets its argument as a
** pointer to an integer and it writes a boolean into that integer depending
** on whether or not the file has been renamed, moved, or deleted since it
** was first opened.
+**
+** [[SQLITE_FCNTL_WIN32_GET_HANDLE]]
+** The [SQLITE_FCNTL_WIN32_GET_HANDLE] opcode can be used to obtain the
+** underlying native file handle associated with a file handle. This file
+** control interprets its argument as a pointer to a native file handle and
+** writes the resulting value there.
**
** [[SQLITE_FCNTL_WIN32_SET_HANDLE]]
** The [SQLITE_FCNTL_WIN32_SET_HANDLE] opcode is used for debugging. This
** opcode causes the xFileControl method to swap the file handle with the one
** pointed to by the pArg argument. This capability is used during testing
@@ -1014,10 +1020,11 @@
#define SQLITE_FCNTL_WAL_BLOCK 24
#define SQLITE_FCNTL_ZIPVFS 25
#define SQLITE_FCNTL_RBU 26
#define SQLITE_FCNTL_VFS_POINTER 27
#define SQLITE_FCNTL_JOURNAL_POINTER 28
+#define SQLITE_FCNTL_WIN32_GET_HANDLE 29
/* deprecated names */
#define SQLITE_GET_LOCKPROXYFILE SQLITE_FCNTL_GET_LOCKPROXYFILE
#define SQLITE_SET_LOCKPROXYFILE SQLITE_FCNTL_SET_LOCKPROXYFILE
#define SQLITE_LAST_ERRNO SQLITE_FCNTL_LAST_ERRNO
Index: src/test1.c
==================================================================
--- src/test1.c
+++ src/test1.c
@@ -5479,10 +5479,42 @@
rc = sqlite3_file_control(db, NULL, SQLITE_FCNTL_WIN32_AV_RETRY, (void*)a);
sqlite3_snprintf(sizeof(z), z, "%d %d %d", rc, a[0], a[1]);
Tcl_AppendResult(interp, z, (char*)0);
return TCL_OK;
}
+
+/*
+** tclcmd: file_control_win32_get_handle DB
+**
+** This TCL command runs the sqlite3_file_control interface with
+** the SQLITE_FCNTL_WIN32_GET_HANDLE opcode.
+*/
+static int file_control_win32_get_handle(
+ ClientData clientData, /* Pointer to sqlite3_enable_XXX function */
+ Tcl_Interp *interp, /* The TCL interpreter that invoked this command */
+ int objc, /* Number of arguments */
+ Tcl_Obj *CONST objv[] /* Command arguments */
+){
+ sqlite3 *db;
+ int rc;
+ HANDLE hFile = NULL;
+ char z[100];
+
+ if( objc!=2 ){
+ Tcl_AppendResult(interp, "wrong # args: should be \"",
+ Tcl_GetStringFromObj(objv[0], 0), " DB", 0);
+ return TCL_ERROR;
+ }
+ if( getDbPointer(interp, Tcl_GetString(objv[1]), &db) ){
+ return TCL_ERROR;
+ }
+ rc = sqlite3_file_control(db, NULL, SQLITE_FCNTL_WIN32_GET_HANDLE,
+ (void*)&hFile);
+ sqlite3_snprintf(sizeof(z), z, "%d %p", rc, (void*)hFile);
+ Tcl_AppendResult(interp, z, (char*)0);
+ return TCL_OK;
+}
/*
** tclcmd: file_control_win32_set_handle DB HANDLE
**
** This TCL command runs the sqlite3_file_control interface with
@@ -7212,10 +7244,11 @@
{ "file_control_lockproxy_test", file_control_lockproxy_test, 0 },
{ "file_control_chunksize_test", file_control_chunksize_test, 0 },
{ "file_control_sizehint_test", file_control_sizehint_test, 0 },
#if SQLITE_OS_WIN
{ "file_control_win32_av_retry", file_control_win32_av_retry, 0 },
+ { "file_control_win32_get_handle", file_control_win32_get_handle, 0 },
{ "file_control_win32_set_handle", file_control_win32_set_handle, 0 },
#endif
{ "file_control_persist_wal", file_control_persist_wal, 0 },
{ "file_control_powersafe_overwrite",file_control_powersafe_overwrite,0},
{ "file_control_vfsname", file_control_vfsname, 0 },
Index: test/filectrl.test
==================================================================
--- test/filectrl.test
+++ test/filectrl.test
@@ -41,6 +41,32 @@
set fn [file_control_tempfilename db]
set fn
} {/etilqs_/}
db close
forcedelete .test_control_lockproxy.db-conch test.proxy
+forcedelete test.db test2.db
+
+if {$tcl_platform(platform)=="windows"} {
+ do_test filectrl-2.1 {
+ sqlite3 db test2.db
+ set size [file size test2.db]
+ set handle [file_control_win32_get_handle db]
+ db close
+ forcedelete test2.db
+ list $size $handle [expr {$handle != 0}]
+ } {/^0 \{0 \d+\} 1$/}
+
+ do_test filectrl-2.2 {
+ sqlite3 db test2.db
+ execsql {
+ CREATE TABLE t1(x);
+ INSERT INTO t1 (x) VALUES(RANDOMBLOB(1048576));
+ }
+ set size [file size test2.db]
+ set handle [file_control_win32_get_handle db]
+ db close
+ forcedelete test2.db
+ list $size $handle [expr {$handle != 0}]
+ } {/^1\d+ \{0 \d+\} 1$/}
+}
+
finish_test