More changes to do with the new sqlite3_step() API. (CVS 1458)
FossilOrigin-Name: e83138250ce0a8caacbd1822eec2e06796d2f5f2
This commit is contained in:
parent
8c6fa9b03b
commit
17240fd90f
20
manifest
20
manifest
@ -1,5 +1,5 @@
|
||||
C Minor\scode\sfixes\sin\sbtree.c\sand\spragma.c\sto\shelp\swith\swatcom\sC.\s(CVS\s1457)
|
||||
D 2004-05-26T00:01:54
|
||||
C More\schanges\sto\sdo\swith\sthe\snew\ssqlite3_step()\sAPI.\s(CVS\s1458)
|
||||
D 2004-05-26T00:07:25
|
||||
F Makefile.in ab7b0d5118e2da97bac66be8684a1034e3500f5a
|
||||
F Makefile.linux-gcc b86a99c493a5bfb402d1d9178dcdc4bd4b32f906
|
||||
F README f1de682fbbd94899d50aca13d387d1b3fd3be2dd
|
||||
@ -55,11 +55,11 @@ F src/printf.c ef750e8e2398ca7e8b58be991075f08c6a7f0e53
|
||||
F src/random.c eff68e3f257e05e81eae6c4d50a51eb88beb4ff3
|
||||
F src/select.c 867cab23c0577d4ac0510c925a85b8e032cfe139
|
||||
F src/shell.c ed4d237b3e52a0a42512bfcc53530e46de20c28f
|
||||
F src/sqlite.h.in 87fff6c325bb946205247854320011f17a137f79
|
||||
F src/sqlite.h.in 532e8b3b4a266ab5d7245a8ca3173fdd10f4a89f
|
||||
F src/sqliteInt.h 6559811caeae0d1855e0b973e363a8c5141e566b
|
||||
F src/table.c af14284fa36c8d41f6829e3f2819dce07d3e2de2
|
||||
F src/tclsqlite.c 0b62e8df6da5abdddf49f3d9274a8103ee61fb63
|
||||
F src/test1.c 81525798a9d159eab12ce9b7de5e54d9307dda4b
|
||||
F src/test1.c 616c288a49b48facb54b9a925aeede1ba4093d8c
|
||||
F src/test2.c 6195a1ca2c8d0d2d93644e86da3289b403486872
|
||||
F src/test3.c 5e4a6d596f982f6f47a5f9f75ede9b4a3b739968
|
||||
F src/test4.c b9947c319a5c023c10c1e953e6610abd571c2283
|
||||
@ -70,7 +70,7 @@ F src/update.c 2b5ec85fa19020686ed2fc4a3fc43cbcefbfdfa7
|
||||
F src/utf.c 1d38da85bffb928fb0d9f301e7db913a6df486ce
|
||||
F src/util.c 4c0adcbc9ce6678dd046931253e45d623c6d279f
|
||||
F src/vacuum.c 8734f89742f246abd91dbd3e087fc153bddbfbad
|
||||
F src/vdbe.c fe75ac32889c717df2e96ae38edb7ab7fc42c48a
|
||||
F src/vdbe.c 7f41e2f73dcca885618b9baec0ffea9f8b0714aa
|
||||
F src/vdbe.h ebd59ee7a988d39c58b27149593f09a432ad1410
|
||||
F src/vdbeInt.h e500998a0ab3b10850c771c60d6b132037ff56e7
|
||||
F src/vdbeaux.c b2527b7ce884c2c1dc102d48a07c6327f8eac3c2
|
||||
@ -81,7 +81,7 @@ F test/attach2.test 5472d442bb2ef1ee587e0ae7472bb68b52509a38
|
||||
F test/auth.test 5c4d95cdaf539c0c236e20ce1f71a93e7dde9185
|
||||
F test/bigfile.test ea904b853ce2d703b16c5ce90e2b54951bc1ae81
|
||||
F test/bigrow.test 8ab252dba108f12ad64e337b0f2ff31a807ac578
|
||||
F test/bind.test 947eea896241b90bae0928e3a655bb5d7f0680bb
|
||||
F test/bind.test b2e77ea6e9317b48210d47fa03ea1f7169bcf764
|
||||
F test/btree.test 08e4093c78d2bc1d54e27266f8d17fed14751125
|
||||
F test/btree2.test aa4a6d05b1ea90b1acaf83ba89039dd302a88635
|
||||
F test/btree4.test 3797b4305694c7af6828675b0f4b1424b8ca30e4
|
||||
@ -203,7 +203,7 @@ F www/sqlite.tcl 3c83b08cf9f18aa2d69453ff441a36c40e431604
|
||||
F www/tclsqlite.tcl b9271d44dcf147a93c98f8ecf28c927307abd6da
|
||||
F www/vdbe.tcl 9b9095d4495f37697fd1935d10e14c6015e80aa1
|
||||
F www/whentouse.tcl a8335bce47cc2fddb07f19052cb0cb4d9129a8e4
|
||||
P ae18fcb7ad91096f8029605b54d71ec225f31f32
|
||||
R 47dad5a8dd6b54a73599bfb643e19e5f
|
||||
U drh
|
||||
Z 5fd7d5705c8bcbb7d653c6f399f44fb3
|
||||
P 143c502a59e727975f61c8d13b6c5a90dad038f3
|
||||
R aab0f00d021548c4204f1bc870566ab7
|
||||
U danielk1977
|
||||
Z 3b5c9e0de208be70045790485a870245
|
||||
|
@ -1 +1 @@
|
||||
143c502a59e727975f61c8d13b6c5a90dad038f3
|
||||
e83138250ce0a8caacbd1822eec2e06796d2f5f2
|
@ -12,7 +12,7 @@
|
||||
** This header file defines the interface that the SQLite library
|
||||
** presents to client programs.
|
||||
**
|
||||
** @(#) $Id: sqlite.h.in,v 1.77 2004/05/25 23:35:19 danielk1977 Exp $
|
||||
** @(#) $Id: sqlite.h.in,v 1.78 2004/05/26 00:07:25 danielk1977 Exp $
|
||||
*/
|
||||
#ifndef _SQLITE_H_
|
||||
#define _SQLITE_H_
|
||||
@ -585,54 +585,6 @@ int sqlite3_compile(
|
||||
char **pzErrmsg /* OUT: Error message. */
|
||||
);
|
||||
|
||||
/*
|
||||
** After an SQL statement has been compiled, it is handed to this routine
|
||||
** to be executed. This routine executes the statement as far as it can
|
||||
** go then returns. The return value will be one of SQLITE_DONE,
|
||||
** SQLITE_ERROR, SQLITE_BUSY, SQLITE_ROW, or SQLITE_MISUSE.
|
||||
**
|
||||
** SQLITE_DONE means that the execute of the SQL statement is complete
|
||||
** an no errors have occurred. sqlite3_step() should not be called again
|
||||
** for the same virtual machine. *pN is set to the number of columns in
|
||||
** the result set and *pazColName is set to an array of strings that
|
||||
** describe the column names and datatypes. The name of the i-th column
|
||||
** is (*pazColName)[i] and the datatype of the i-th column is
|
||||
** (*pazColName)[i+*pN]. *pazValue is set to NULL.
|
||||
**
|
||||
** SQLITE_ERROR means that the virtual machine encountered a run-time
|
||||
** error. sqlite3_step() should not be called again for the same
|
||||
** virtual machine. *pN is set to 0 and *pazColName and *pazValue are set
|
||||
** to NULL. Use sqlite3_finalize() to obtain the specific error code
|
||||
** and the error message text for the error.
|
||||
**
|
||||
** SQLITE_BUSY means that an attempt to open the database failed because
|
||||
** another thread or process is holding a lock. The calling routine
|
||||
** can try again to open the database by calling sqlite3_step() again.
|
||||
** The return code will only be SQLITE_BUSY if no busy handler is registered
|
||||
** using the sqlite3_busy_handler() or sqlite3_busy_timeout() routines. If
|
||||
** a busy handler callback has been registered but returns 0, then this
|
||||
** routine will return SQLITE_ERROR and sqltie_finalize() will return
|
||||
** SQLITE_BUSY when it is called.
|
||||
**
|
||||
** SQLITE_ROW means that a single row of the result is now available.
|
||||
** The data is contained in *pazValue. The value of the i-th column is
|
||||
** (*azValue)[i]. *pN and *pazColName are set as described in SQLITE_DONE.
|
||||
** Invoke sqlite3_step() again to advance to the next row.
|
||||
**
|
||||
** SQLITE_MISUSE is returned if sqlite3_step() is called incorrectly.
|
||||
** For example, if you call sqlite3_step() after the virtual machine
|
||||
** has halted (after a prior call to sqlite3_step() has returned SQLITE_DONE)
|
||||
** or if you call sqlite3_step() with an incorrectly initialized virtual
|
||||
** machine or a virtual machine that has been deleted or that is associated
|
||||
** with an sqlite structure that has been closed.
|
||||
*/
|
||||
int sqlite3_step(
|
||||
sqlite_vm *pVm, /* The virtual machine to execute */
|
||||
int *pN, /* OUT: Number of columns in result */
|
||||
const char ***pazValue, /* OUT: Column data */
|
||||
const char ***pazColName /* OUT: Column names and datatypes */
|
||||
);
|
||||
|
||||
/*
|
||||
** This routine is called to delete a virtual machine after it has finished
|
||||
** executing. The return value is the result code. SQLITE_OK is returned
|
||||
@ -1123,7 +1075,7 @@ const void *sqlite3_column_decltype16(sqlite3_stmt*,int);
|
||||
** SQLITE_DONE. Or it could be the case the the same database connection
|
||||
** is being used simulataneously by two or more threads.
|
||||
*/
|
||||
int sqlite3_step_new(sqlite3_stmt*);
|
||||
int sqlite3_step(sqlite3_stmt*);
|
||||
|
||||
|
||||
/*
|
||||
|
124
src/test1.c
124
src/test1.c
@ -13,7 +13,7 @@
|
||||
** is not included in the SQLite library. It is used for automated
|
||||
** testing of the SQLite library.
|
||||
**
|
||||
** $Id: test1.c,v 1.52 2004/05/25 23:35:19 danielk1977 Exp $
|
||||
** $Id: test1.c,v 1.53 2004/05/26 00:07:26 danielk1977 Exp $
|
||||
*/
|
||||
#include "sqliteInt.h"
|
||||
#include "tcl.h"
|
||||
@ -758,68 +758,6 @@ static int sqlite_datatypes(
|
||||
return TCL_OK;
|
||||
}
|
||||
|
||||
/*
|
||||
** Usage: sqlite3_step VM ?NVAR? ?VALUEVAR? ?COLNAMEVAR?
|
||||
**
|
||||
** Step a virtual machine. Return a the result code as a string.
|
||||
** Column results are written into three variables.
|
||||
*/
|
||||
#if 0
|
||||
static int test_step(
|
||||
void *NotUsed,
|
||||
Tcl_Interp *interp, /* The TCL interpreter that invoked this command */
|
||||
int argc, /* Number of arguments */
|
||||
char **argv /* Text of each argument */
|
||||
){
|
||||
sqlite_vm *vm;
|
||||
int rc, i;
|
||||
const char **azValue = 0;
|
||||
const char **azColName = 0;
|
||||
int N = 0;
|
||||
char *zRc;
|
||||
char zBuf[50];
|
||||
if( argc<2 || argc>5 ){
|
||||
Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
|
||||
" VM NVAR VALUEVAR COLNAMEVAR", 0);
|
||||
return TCL_ERROR;
|
||||
}
|
||||
if( getVmPointer(interp, argv[1], &vm) ) return TCL_ERROR;
|
||||
rc = sqlite3_step(vm, argc>=3?&N:0, argc>=4?&azValue:0, argc==5?&azColName:0);
|
||||
if( argc>=3 ){
|
||||
sprintf(zBuf, "%d", N);
|
||||
Tcl_SetVar(interp, argv[2], zBuf, 0);
|
||||
}
|
||||
if( argc>=4 ){
|
||||
Tcl_SetVar(interp, argv[3], "", 0);
|
||||
if( azValue ){
|
||||
for(i=0; i<N; i++){
|
||||
Tcl_SetVar(interp, argv[3], azValue[i] ? azValue[i] : "",
|
||||
TCL_APPEND_VALUE | TCL_LIST_ELEMENT);
|
||||
}
|
||||
}
|
||||
}
|
||||
if( argc==5 ){
|
||||
Tcl_SetVar(interp, argv[4], "", 0);
|
||||
if( azColName ){
|
||||
for(i=0; i<N*2; i++){
|
||||
Tcl_SetVar(interp, argv[4], azColName[i] ? azColName[i] : "",
|
||||
TCL_APPEND_VALUE | TCL_LIST_ELEMENT);
|
||||
}
|
||||
}
|
||||
}
|
||||
switch( rc ){
|
||||
case SQLITE_DONE: zRc = "SQLITE_DONE"; break;
|
||||
case SQLITE_BUSY: zRc = "SQLITE_BUSY"; break;
|
||||
case SQLITE_ROW: zRc = "SQLITE_ROW"; break;
|
||||
case SQLITE_ERROR: zRc = "SQLITE_ERROR"; break;
|
||||
case SQLITE_MISUSE: zRc = "SQLITE_MISUSE"; break;
|
||||
default: zRc = "unknown"; break;
|
||||
}
|
||||
Tcl_AppendResult(interp, zRc, 0);
|
||||
return TCL_OK;
|
||||
}
|
||||
#endif
|
||||
|
||||
/*
|
||||
** Usage: sqlite3_finalize STMT
|
||||
**
|
||||
@ -1416,7 +1354,7 @@ static int test_open16(
|
||||
**
|
||||
** Advance the statement to the next row.
|
||||
*/
|
||||
static int test_step_new(
|
||||
static int test_step(
|
||||
void * clientData,
|
||||
Tcl_Interp *interp,
|
||||
int objc,
|
||||
@ -1432,9 +1370,10 @@ static int test_step_new(
|
||||
}
|
||||
|
||||
if( getStmtPointer(interp, Tcl_GetString(objv[1]), &pStmt) ) return TCL_ERROR;
|
||||
rc = sqlite3_step_new(pStmt);
|
||||
rc = sqlite3_step(pStmt);
|
||||
|
||||
if( rc!=SQLITE_DONE && rc!=SQLITE_ROW ) return TCL_ERROR;
|
||||
Tcl_SetResult(interp, errorName(rc), 0);
|
||||
return TCL_OK;
|
||||
}
|
||||
|
||||
@ -1505,6 +1444,56 @@ static int test_column_data16(
|
||||
return TCL_OK;
|
||||
}
|
||||
|
||||
/*
|
||||
** Usage: sqlite3_column_count STMT
|
||||
**
|
||||
** Return the number of columns returned by the sql statement STMT.
|
||||
*/
|
||||
static int test_column_count(
|
||||
void * clientData,
|
||||
Tcl_Interp *interp,
|
||||
int objc,
|
||||
Tcl_Obj *CONST objv[]
|
||||
){
|
||||
sqlite3_stmt *pStmt;
|
||||
|
||||
if( objc!=2 ){
|
||||
Tcl_AppendResult(interp, "wrong # args: should be \"",
|
||||
Tcl_GetString(objv[0]), " STMT column", 0);
|
||||
return TCL_ERROR;
|
||||
}
|
||||
|
||||
if( getStmtPointer(interp, Tcl_GetString(objv[1]), &pStmt) ) return TCL_ERROR;
|
||||
|
||||
Tcl_SetObjResult(interp, Tcl_NewIntObj(sqlite3_column_count(pStmt)));
|
||||
return TCL_OK;
|
||||
}
|
||||
|
||||
/*
|
||||
** Usage: sqlite3_data_count STMT
|
||||
**
|
||||
** Return the number of columns returned by the sql statement STMT.
|
||||
*/
|
||||
static int test_data_count(
|
||||
void * clientData,
|
||||
Tcl_Interp *interp,
|
||||
int objc,
|
||||
Tcl_Obj *CONST objv[]
|
||||
){
|
||||
sqlite3_stmt *pStmt;
|
||||
|
||||
if( objc!=2 ){
|
||||
Tcl_AppendResult(interp, "wrong # args: should be \"",
|
||||
Tcl_GetString(objv[0]), " STMT column", 0);
|
||||
return TCL_ERROR;
|
||||
}
|
||||
|
||||
if( getStmtPointer(interp, Tcl_GetString(objv[1]), &pStmt) ) return TCL_ERROR;
|
||||
|
||||
Tcl_SetObjResult(interp, Tcl_NewIntObj(sqlite3_data_count(pStmt)));
|
||||
return TCL_OK;
|
||||
}
|
||||
|
||||
/*
|
||||
** This is a collating function named "REVERSE" which sorts text
|
||||
** in reverse order.
|
||||
@ -1577,7 +1566,6 @@ int Sqlitetest1_Init(Tcl_Interp *interp){
|
||||
{ "sqlite_malloc_fail", (Tcl_CmdProc*)sqlite_malloc_fail },
|
||||
{ "sqlite_malloc_stat", (Tcl_CmdProc*)sqlite_malloc_stat },
|
||||
#endif
|
||||
/*{ "sqlite_step", (Tcl_CmdProc*)test_step * },*/
|
||||
{ "sqlite_bind", (Tcl_CmdProc*)test_bind },
|
||||
{ "breakpoint", (Tcl_CmdProc*)test_breakpoint },
|
||||
};
|
||||
@ -1601,9 +1589,11 @@ int Sqlitetest1_Init(Tcl_Interp *interp){
|
||||
{ "sqlite3_open16", (Tcl_ObjCmdProc*)test_open16 },
|
||||
{ "sqlite3_finalize", (Tcl_ObjCmdProc*)test_finalize },
|
||||
{ "sqlite3_reset", (Tcl_ObjCmdProc*)test_reset },
|
||||
{ "sqlite3_step", (Tcl_ObjCmdProc*)test_step_new },
|
||||
{ "sqlite3_step", (Tcl_ObjCmdProc*)test_step},
|
||||
{ "sqlite3_column_data", (Tcl_ObjCmdProc*)test_column_data },
|
||||
{ "sqlite3_column_data16", (Tcl_ObjCmdProc*)test_column_data16 },
|
||||
{ "sqlite3_column_count", (Tcl_ObjCmdProc*)test_column_count },
|
||||
{ "sqlite3_data_count", (Tcl_ObjCmdProc*)test_data_count },
|
||||
{ "add_reverse_collating_func", (Tcl_ObjCmdProc*)reverse_collfunc },
|
||||
};
|
||||
int i;
|
||||
|
83
src/vdbe.c
83
src/vdbe.c
@ -43,7 +43,7 @@
|
||||
** in this file for details. If in doubt, do not deviate from existing
|
||||
** commenting and indentation practices when changing or adding code.
|
||||
**
|
||||
** $Id: vdbe.c,v 1.329 2004/05/25 23:35:19 danielk1977 Exp $
|
||||
** $Id: vdbe.c,v 1.330 2004/05/26 00:07:26 danielk1977 Exp $
|
||||
*/
|
||||
#include "sqliteInt.h"
|
||||
#include "os.h"
|
||||
@ -492,90 +492,11 @@ static void hardRealify(Mem *pStack, u8 enc){
|
||||
pStack->flags = MEM_Real;
|
||||
}
|
||||
|
||||
/*
|
||||
** Advance the virtual machine to the next output row.
|
||||
**
|
||||
** The return vale will be either SQLITE_BUSY, SQLITE_DONE,
|
||||
** SQLITE_ROW, SQLITE_ERROR, or SQLITE_MISUSE.
|
||||
**
|
||||
** SQLITE_BUSY means that the virtual machine attempted to open
|
||||
** a locked database and there is no busy callback registered.
|
||||
** Call sqlite3_step() again to retry the open. *pN is set to 0
|
||||
** and *pazColName and *pazValue are both set to NULL.
|
||||
**
|
||||
** SQLITE_DONE means that the virtual machine has finished
|
||||
** executing. sqlite3_step() should not be called again on this
|
||||
** virtual machine. *pN and *pazColName are set appropriately
|
||||
** but *pazValue is set to NULL.
|
||||
**
|
||||
** SQLITE_ROW means that the virtual machine has generated another
|
||||
** row of the result set. *pN is set to the number of columns in
|
||||
** the row. *pazColName is set to the names of the columns followed
|
||||
** by the column datatypes. *pazValue is set to the values of each
|
||||
** column in the row. The value of the i-th column is (*pazValue)[i].
|
||||
** The name of the i-th column is (*pazColName)[i] and the datatype
|
||||
** of the i-th column is (*pazColName)[i+*pN].
|
||||
**
|
||||
** SQLITE_ERROR means that a run-time error (such as a constraint
|
||||
** violation) has occurred. The details of the error will be returned
|
||||
** by the next call to sqlite3_finalize(). sqlite3_step() should not
|
||||
** be called again on the VM.
|
||||
**
|
||||
** SQLITE_MISUSE means that the this routine was called inappropriately.
|
||||
** Perhaps it was called on a virtual machine that had already been
|
||||
** finalized or on one that had previously returned SQLITE_ERROR or
|
||||
** SQLITE_DONE. Or it could be the case the the same database connection
|
||||
** is being used simulataneously by two or more threads.
|
||||
*/
|
||||
#if 0
|
||||
int sqlite3_step(
|
||||
sqlite_vm *pVm, /* The virtual machine to execute */
|
||||
int *pN, /* OUT: Number of columns in result */
|
||||
const char ***pazValue, /* OUT: Column data */
|
||||
const char ***pazColName /* OUT: Column names and datatypes */
|
||||
){
|
||||
sqlite3_stmt *pStmt = (sqlite3_stmt*)pVm;
|
||||
int rc;
|
||||
|
||||
rc = sqlite3_step_new(pStmt);
|
||||
|
||||
if( pazValue ) *pazValue = 0;
|
||||
if( pazColName ) *pazColName = 0;
|
||||
if( pN ) *pN = 0;
|
||||
|
||||
if( rc==SQLITE_DONE || rc==SQLITE_ROW ){
|
||||
int i;
|
||||
int cols = sqlite3_column_count(pStmt) * (pazColName?1:0);
|
||||
int vals = sqlite3_data_count(pStmt) * (pazValue?1:0);
|
||||
|
||||
/* Temporary memory leak */
|
||||
if( cols ) *pazColName = sqliteMalloc(sizeof(char *)*cols * 2);
|
||||
if( pN ) *pN = cols;
|
||||
|
||||
for(i=0; i<cols; i++){
|
||||
(*pazColName)[i] = sqlite3_column_name(pStmt, i);
|
||||
}
|
||||
for(i=cols; i<(2*cols); i++){
|
||||
(*pazColName)[i] = sqlite3_column_decltype(pStmt, i-cols);
|
||||
}
|
||||
|
||||
if( rc==SQLITE_ROW ){
|
||||
if( vals ) *pazValue = sqliteMalloc(sizeof(char *)*vals);
|
||||
for(i=0; i<vals; i++){
|
||||
(*pazValue)[i] = sqlite3_column_data(pStmt, i);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return rc;
|
||||
}
|
||||
#endif
|
||||
|
||||
/*
|
||||
** Execute the statement pStmt, either until a row of data is ready, the
|
||||
** statement is completely executed or an error occurs.
|
||||
*/
|
||||
int sqlite3_step_new(sqlite3_stmt *pStmt){
|
||||
int sqlite3_step(sqlite3_stmt *pStmt){
|
||||
Vdbe *p = (Vdbe*)pStmt;
|
||||
sqlite *db;
|
||||
int rc;
|
||||
|
@ -11,12 +11,29 @@
|
||||
# This file implements regression tests for SQLite library. The
|
||||
# focus of this script testing the sqlite_bind API.
|
||||
#
|
||||
# $Id: bind.test,v 1.7 2004/05/24 12:55:55 danielk1977 Exp $
|
||||
# $Id: bind.test,v 1.8 2004/05/26 00:07:25 danielk1977 Exp $
|
||||
#
|
||||
|
||||
set testdir [file dirname $argv0]
|
||||
source $testdir/tester.tcl
|
||||
|
||||
proc sqlite_step {stmt N VALS COLS} {
|
||||
upvar VALS vals
|
||||
upvar COLS cols
|
||||
set vals [list]
|
||||
set cols [list]
|
||||
|
||||
set rc [sqlite3_step $stmt]
|
||||
for {set i 0} {$i < [sqlite3_column_count $stmt]} {incr i} {
|
||||
lappend cols [sqlite3_column_name $stmt $i]
|
||||
}
|
||||
for {set i 0} {$i < [sqlite3_data_count $stmt]} {incr i} {
|
||||
lappend vals [sqlite3_column_data $stmt $i]
|
||||
}
|
||||
|
||||
return $rc
|
||||
}
|
||||
|
||||
do_test bind-1.1 {
|
||||
db close
|
||||
set DB [sqlite db test.db]
|
||||
|
Loading…
Reference in New Issue
Block a user