15821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/*
25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** 2006 January 09
35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)**
45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** The author disclaims copyright to this source code.  In place of
55821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** a legal notice, here is a blessing:
65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)**
75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)**    May you do good and not evil.
85821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)**    May you find forgiveness for yourself and forgive others.
95821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)**    May you share freely, never taking more than you give.
105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)**
115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)*************************************************************************
125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** Code for testing the client/server version of the SQLite library.
135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** Derived from test4.c.
145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)*/
155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "sqliteInt.h"
165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "tcl.h"
175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/*
195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** This test only works on UNIX with a SQLITE_THREADSAFE build that includes
205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** the SQLITE_SERVER option.
215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)*/
225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if defined(SQLITE_SERVER) && !defined(SQLITE_OMIT_SHARED_CACHE) && \
235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    SQLITE_OS_UNIX && SQLITE_THREADSAFE
245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <stdlib.h>
265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <string.h>
275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <pthread.h>
285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <sched.h>
295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <ctype.h>
305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/*
325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** Interfaces defined in server.c
335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)*/
345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int sqlite3_client_open(const char*, sqlite3**);
355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int sqlite3_client_prepare(sqlite3*,const char*,int,
365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                           sqlite3_stmt**,const char**);
375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int sqlite3_client_step(sqlite3_stmt*);
385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int sqlite3_client_reset(sqlite3_stmt*);
395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int sqlite3_client_finalize(sqlite3_stmt*);
405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int sqlite3_client_close(sqlite3*);
415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int sqlite3_server_start(void);
425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int sqlite3_server_stop(void);
435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/*
455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** Each thread is controlled by an instance of the following
465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** structure.
475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)*/
485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)typedef struct Thread Thread;
495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)struct Thread {
505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  /* The first group of fields are writable by the supervisor thread
515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ** and read-only to the client threads
525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  */
535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  char *zFilename;         /* Name of database file */
545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void (*xOp)(Thread*);    /* next operation to do */
555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  char *zArg;              /* argument usable by xOp */
565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  volatile int opnum;      /* Operation number */
575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  volatile int busy;       /* True if this thread is in use */
585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  /* The next group of fields are writable by the client threads
605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ** but read-only to the superviser thread.
615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  */
625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  volatile int completed;  /* Number of operations completed */
635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  sqlite3 *db;             /* Open database */
645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  sqlite3_stmt *pStmt;     /* Pending operation */
655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  char *zErr;              /* operation error */
665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  char *zStaticErr;        /* Static error message */
675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int rc;                  /* operation return code */
685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int argc;                /* number of columns in result */
695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const char *argv[100];   /* result columns */
705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const char *colv[100];   /* result column names */
715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/*
745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** There can be as many as 26 threads running at once.  Each is named
755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** by a capital letter: A, B, C, ..., Y, Z.
765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)*/
775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#define N_THREAD 26
785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static Thread threadset[N_THREAD];
795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/*
815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** The main loop for a thread.  Threads use busy waiting.
825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)*/
835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static void *client_main(void *pArg){
845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  Thread *p = (Thread*)pArg;
855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if( p->db ){
865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    sqlite3_client_close(p->db);
875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  sqlite3_client_open(p->zFilename, &p->db);
895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if( SQLITE_OK!=sqlite3_errcode(p->db) ){
905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    p->zErr = strdup(sqlite3_errmsg(p->db));
915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    sqlite3_client_close(p->db);
925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    p->db = 0;
935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  p->pStmt = 0;
955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  p->completed = 1;
965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  while( p->opnum<=p->completed ) sched_yield();
975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  while( p->xOp ){
985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if( p->zErr && p->zErr!=p->zStaticErr ){
995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      sqlite3_free(p->zErr);
1005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      p->zErr = 0;
1015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
1025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    (*p->xOp)(p);
1035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    p->completed++;
1045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    while( p->opnum<=p->completed ) sched_yield();
1055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if( p->pStmt ){
1075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    sqlite3_client_finalize(p->pStmt);
1085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    p->pStmt = 0;
1095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if( p->db ){
1115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    sqlite3_client_close(p->db);
1125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    p->db = 0;
1135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if( p->zErr && p->zErr!=p->zStaticErr ){
1155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    sqlite3_free(p->zErr);
1165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    p->zErr = 0;
1175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  p->completed++;
1195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#ifndef SQLITE_OMIT_DEPRECATED
1205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  sqlite3_thread_cleanup();
1215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif
1225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return 0;
1235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/*
1265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** Get a thread ID which is an upper case letter.  Return the index.
1275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** If the argument is not a valid thread ID put an error message in
1285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** the interpreter and return -1.
1295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)*/
1305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static int parse_client_id(Tcl_Interp *interp, const char *zArg){
1315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if( zArg==0 || zArg[0]==0 || zArg[1]!=0 || !isupper((unsigned char)zArg[0]) ){
1325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    Tcl_AppendResult(interp, "thread ID must be an upper case letter", 0);
1335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return -1;
1345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return zArg[0] - 'A';
1365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/*
1395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** Usage:    client_create NAME  FILENAME
1405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)**
1415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** NAME should be an upper case letter.  Start the thread running with
1425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** an open connection to the given database.
1435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)*/
1445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static int tcl_client_create(
1455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void *NotUsed,
1465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  Tcl_Interp *interp,    /* The TCL interpreter that invoked this command */
1475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int argc,              /* Number of arguments */
1485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const char **argv      /* Text of each argument */
1495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)){
1505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int i;
1515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  pthread_t x;
1525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int rc;
1535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if( argc!=3 ){
1555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
1565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)       " ID FILENAME", 0);
1575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return TCL_ERROR;
1585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  i = parse_client_id(interp, argv[1]);
1605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if( i<0 ) return TCL_ERROR;
1615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if( threadset[i].busy ){
1625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    Tcl_AppendResult(interp, "thread ", argv[1], " is already running", 0);
1635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return TCL_ERROR;
1645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  threadset[i].busy = 1;
1665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  sqlite3_free(threadset[i].zFilename);
1675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  threadset[i].zFilename = sqlite3_mprintf("%s", argv[2]);
1685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  threadset[i].opnum = 1;
1695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  threadset[i].completed = 0;
1705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  rc = pthread_create(&x, 0, client_main, &threadset[i]);
1715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if( rc ){
1725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    Tcl_AppendResult(interp, "failed to create the thread", 0);
1735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    sqlite3_free(threadset[i].zFilename);
1745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    threadset[i].busy = 0;
1755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return TCL_ERROR;
1765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  pthread_detach(x);
1785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  sqlite3_server_start();
1795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return TCL_OK;
1805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/*
1835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** Wait for a thread to reach its idle state.
1845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)*/
1855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static void client_wait(Thread *p){
1865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  while( p->opnum>p->completed ) sched_yield();
1875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/*
1905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** Usage:  client_wait ID
1915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)**
1925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** Wait on thread ID to reach its idle state.
1935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)*/
1945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static int tcl_client_wait(
1955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void *NotUsed,
1965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  Tcl_Interp *interp,    /* The TCL interpreter that invoked this command */
1975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int argc,              /* Number of arguments */
1985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const char **argv      /* Text of each argument */
1995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)){
2005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int i;
2015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if( argc!=2 ){
2035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
2045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)       " ID", 0);
2055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return TCL_ERROR;
2065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  i = parse_client_id(interp, argv[1]);
2085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if( i<0 ) return TCL_ERROR;
2095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if( !threadset[i].busy ){
2105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    Tcl_AppendResult(interp, "no such thread", 0);
2115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return TCL_ERROR;
2125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  client_wait(&threadset[i]);
2145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return TCL_OK;
2155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/*
2185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** Stop a thread.
2195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)*/
2205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static void stop_thread(Thread *p){
2215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  client_wait(p);
2225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  p->xOp = 0;
2235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  p->opnum++;
2245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  client_wait(p);
2255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  sqlite3_free(p->zArg);
2265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  p->zArg = 0;
2275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  sqlite3_free(p->zFilename);
2285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  p->zFilename = 0;
2295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  p->busy = 0;
2305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/*
2335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** Usage:  client_halt ID
2345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)**
2355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** Cause a client thread to shut itself down.  Wait for the shutdown to be
2365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** completed.  If ID is "*" then stop all client threads.
2375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)*/
2385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static int tcl_client_halt(
2395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void *NotUsed,
2405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  Tcl_Interp *interp,    /* The TCL interpreter that invoked this command */
2415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int argc,              /* Number of arguments */
2425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const char **argv      /* Text of each argument */
2435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)){
2445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int i;
2455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if( argc!=2 ){
2475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
2485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)       " ID", 0);
2495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return TCL_ERROR;
2505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if( argv[1][0]=='*' && argv[1][1]==0 ){
2525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    for(i=0; i<N_THREAD; i++){
2535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if( threadset[i].busy ){
2545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        stop_thread(&threadset[i]);
2555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
2565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
2575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }else{
2585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    i = parse_client_id(interp, argv[1]);
2595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if( i<0 ) return TCL_ERROR;
2605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if( !threadset[i].busy ){
2615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      Tcl_AppendResult(interp, "no such thread", 0);
2625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return TCL_ERROR;
2635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
2645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    stop_thread(&threadset[i]);
2655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  /* If no client threads are still running, also stop the server */
2685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for(i=0; i<N_THREAD && threadset[i].busy==0; i++){}
2695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if( i>=N_THREAD ){
2705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    sqlite3_server_stop();
2715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return TCL_OK;
2735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/*
2765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** Usage: client_argc  ID
2775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)**
2785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** Wait on the most recent client_step to complete, then return the
2795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** number of columns in the result set.
2805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)*/
2815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static int tcl_client_argc(
2825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void *NotUsed,
2835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  Tcl_Interp *interp,    /* The TCL interpreter that invoked this command */
2845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int argc,              /* Number of arguments */
2855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const char **argv      /* Text of each argument */
2865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)){
2875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int i;
2885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  char zBuf[100];
2895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if( argc!=2 ){
2915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
2925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)       " ID", 0);
2935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return TCL_ERROR;
2945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  i = parse_client_id(interp, argv[1]);
2965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if( i<0 ) return TCL_ERROR;
2975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if( !threadset[i].busy ){
2985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    Tcl_AppendResult(interp, "no such thread", 0);
2995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return TCL_ERROR;
3005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
3015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  client_wait(&threadset[i]);
3025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  sprintf(zBuf, "%d", threadset[i].argc);
3035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  Tcl_AppendResult(interp, zBuf, 0);
3045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return TCL_OK;
3055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/*
3085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** Usage: client_argv  ID   N
3095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)**
3105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** Wait on the most recent client_step to complete, then return the
3115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** value of the N-th columns in the result set.
3125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)*/
3135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static int tcl_client_argv(
3145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void *NotUsed,
3155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  Tcl_Interp *interp,    /* The TCL interpreter that invoked this command */
3165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int argc,              /* Number of arguments */
3175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const char **argv      /* Text of each argument */
3185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)){
3195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int i;
3205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int n;
3215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if( argc!=3 ){
3235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
3245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)       " ID N", 0);
3255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return TCL_ERROR;
3265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
3275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  i = parse_client_id(interp, argv[1]);
3285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if( i<0 ) return TCL_ERROR;
3295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if( !threadset[i].busy ){
3305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    Tcl_AppendResult(interp, "no such thread", 0);
3315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return TCL_ERROR;
3325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
3335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if( Tcl_GetInt(interp, argv[2], &n) ) return TCL_ERROR;
3345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  client_wait(&threadset[i]);
3355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if( n<0 || n>=threadset[i].argc ){
3365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    Tcl_AppendResult(interp, "column number out of range", 0);
3375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return TCL_ERROR;
3385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
3395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  Tcl_AppendResult(interp, threadset[i].argv[n], 0);
3405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return TCL_OK;
3415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/*
3445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** Usage: client_colname  ID   N
3455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)**
3465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** Wait on the most recent client_step to complete, then return the
3475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** name of the N-th columns in the result set.
3485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)*/
3495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static int tcl_client_colname(
3505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void *NotUsed,
3515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  Tcl_Interp *interp,    /* The TCL interpreter that invoked this command */
3525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int argc,              /* Number of arguments */
3535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const char **argv      /* Text of each argument */
3545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)){
3555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int i;
3565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int n;
3575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if( argc!=3 ){
3595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
3605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)       " ID N", 0);
3615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return TCL_ERROR;
3625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
3635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  i = parse_client_id(interp, argv[1]);
3645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if( i<0 ) return TCL_ERROR;
3655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if( !threadset[i].busy ){
3665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    Tcl_AppendResult(interp, "no such thread", 0);
3675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return TCL_ERROR;
3685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
3695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if( Tcl_GetInt(interp, argv[2], &n) ) return TCL_ERROR;
3705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  client_wait(&threadset[i]);
3715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if( n<0 || n>=threadset[i].argc ){
3725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    Tcl_AppendResult(interp, "column number out of range", 0);
3735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return TCL_ERROR;
3745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
3755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  Tcl_AppendResult(interp, threadset[i].colv[n], 0);
3765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return TCL_OK;
3775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/*
3805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** Usage: client_result  ID
3815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)**
3825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** Wait on the most recent operation to complete, then return the
3835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** result code from that operation.
3845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)*/
3855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static int tcl_client_result(
3865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void *NotUsed,
3875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  Tcl_Interp *interp,    /* The TCL interpreter that invoked this command */
3885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int argc,              /* Number of arguments */
3895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const char **argv      /* Text of each argument */
3905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)){
3915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int i;
3925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const char *zName;
3935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if( argc!=2 ){
3955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
3965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)       " ID", 0);
3975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return TCL_ERROR;
3985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
3995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  i = parse_client_id(interp, argv[1]);
4005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if( i<0 ) return TCL_ERROR;
4015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if( !threadset[i].busy ){
4025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    Tcl_AppendResult(interp, "no such thread", 0);
4035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return TCL_ERROR;
4045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
4055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  client_wait(&threadset[i]);
4065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  switch( threadset[i].rc ){
4075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case SQLITE_OK:         zName = "SQLITE_OK";          break;
4085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case SQLITE_ERROR:      zName = "SQLITE_ERROR";       break;
4095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case SQLITE_PERM:       zName = "SQLITE_PERM";        break;
4105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case SQLITE_ABORT:      zName = "SQLITE_ABORT";       break;
4115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case SQLITE_BUSY:       zName = "SQLITE_BUSY";        break;
4125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case SQLITE_LOCKED:     zName = "SQLITE_LOCKED";      break;
4135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case SQLITE_NOMEM:      zName = "SQLITE_NOMEM";       break;
4145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case SQLITE_READONLY:   zName = "SQLITE_READONLY";    break;
4155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case SQLITE_INTERRUPT:  zName = "SQLITE_INTERRUPT";   break;
4165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case SQLITE_IOERR:      zName = "SQLITE_IOERR";       break;
4175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case SQLITE_CORRUPT:    zName = "SQLITE_CORRUPT";     break;
4185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case SQLITE_FULL:       zName = "SQLITE_FULL";        break;
4195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case SQLITE_CANTOPEN:   zName = "SQLITE_CANTOPEN";    break;
4205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case SQLITE_PROTOCOL:   zName = "SQLITE_PROTOCOL";    break;
4215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case SQLITE_EMPTY:      zName = "SQLITE_EMPTY";       break;
4225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case SQLITE_SCHEMA:     zName = "SQLITE_SCHEMA";      break;
4235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case SQLITE_CONSTRAINT: zName = "SQLITE_CONSTRAINT";  break;
4245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case SQLITE_MISMATCH:   zName = "SQLITE_MISMATCH";    break;
4255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case SQLITE_MISUSE:     zName = "SQLITE_MISUSE";      break;
4265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case SQLITE_NOLFS:      zName = "SQLITE_NOLFS";       break;
4275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case SQLITE_AUTH:       zName = "SQLITE_AUTH";        break;
4285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case SQLITE_FORMAT:     zName = "SQLITE_FORMAT";      break;
4295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case SQLITE_RANGE:      zName = "SQLITE_RANGE";       break;
4305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case SQLITE_ROW:        zName = "SQLITE_ROW";         break;
4315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case SQLITE_DONE:       zName = "SQLITE_DONE";        break;
4325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    default:                zName = "SQLITE_Unknown";     break;
4335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
4345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  Tcl_AppendResult(interp, zName, 0);
4355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return TCL_OK;
4365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
4375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/*
4395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** Usage: client_error  ID
4405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)**
4415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** Wait on the most recent operation to complete, then return the
4425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** error string.
4435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)*/
4445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static int tcl_client_error(
4455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void *NotUsed,
4465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  Tcl_Interp *interp,    /* The TCL interpreter that invoked this command */
4475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int argc,              /* Number of arguments */
4485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const char **argv      /* Text of each argument */
4495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)){
4505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int i;
4515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if( argc!=2 ){
4535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
4545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)       " ID", 0);
4555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return TCL_ERROR;
4565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
4575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  i = parse_client_id(interp, argv[1]);
4585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if( i<0 ) return TCL_ERROR;
4595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if( !threadset[i].busy ){
4605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    Tcl_AppendResult(interp, "no such thread", 0);
4615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return TCL_ERROR;
4625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
4635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  client_wait(&threadset[i]);
4645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  Tcl_AppendResult(interp, threadset[i].zErr, 0);
4655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return TCL_OK;
4665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
4675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/*
4695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** This procedure runs in the thread to compile an SQL statement.
4705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)*/
4715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static void do_compile(Thread *p){
4725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if( p->db==0 ){
4735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    p->zErr = p->zStaticErr = "no database is open";
4745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    p->rc = SQLITE_ERROR;
4755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
4765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
4775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if( p->pStmt ){
4785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    sqlite3_client_finalize(p->pStmt);
4795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    p->pStmt = 0;
4805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
4815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  p->rc = sqlite3_client_prepare(p->db, p->zArg, -1, &p->pStmt, 0);
4825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
4835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/*
4855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** Usage: client_compile ID SQL
4865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)**
4875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** Compile a new virtual machine.
4885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)*/
4895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static int tcl_client_compile(
4905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void *NotUsed,
4915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  Tcl_Interp *interp,    /* The TCL interpreter that invoked this command */
4925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int argc,              /* Number of arguments */
4935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const char **argv      /* Text of each argument */
4945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)){
4955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int i;
4965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if( argc!=3 ){
4975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
4985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)       " ID SQL", 0);
4995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return TCL_ERROR;
5005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
5015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  i = parse_client_id(interp, argv[1]);
5025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if( i<0 ) return TCL_ERROR;
5035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if( !threadset[i].busy ){
5045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    Tcl_AppendResult(interp, "no such thread", 0);
5055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return TCL_ERROR;
5065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
5075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  client_wait(&threadset[i]);
5085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  threadset[i].xOp = do_compile;
5095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  sqlite3_free(threadset[i].zArg);
5105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  threadset[i].zArg = sqlite3_mprintf("%s", argv[2]);
5115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  threadset[i].opnum++;
5125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return TCL_OK;
5135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
5145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/*
5165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** This procedure runs in the thread to step the virtual machine.
5175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)*/
5185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static void do_step(Thread *p){
5195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int i;
5205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if( p->pStmt==0 ){
5215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    p->zErr = p->zStaticErr = "no virtual machine available";
5225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    p->rc = SQLITE_ERROR;
5235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
5245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
5255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  p->rc = sqlite3_client_step(p->pStmt);
5265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if( p->rc==SQLITE_ROW ){
5275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    p->argc = sqlite3_column_count(p->pStmt);
5285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    for(i=0; i<sqlite3_data_count(p->pStmt); i++){
5295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      p->argv[i] = (char*)sqlite3_column_text(p->pStmt, i);
5305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
5315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    for(i=0; i<p->argc; i++){
5325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      p->colv[i] = sqlite3_column_name(p->pStmt, i);
5335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
5345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
5355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
5365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/*
5385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** Usage: client_step ID
5395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)**
5405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** Advance the virtual machine by one step
5415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)*/
5425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static int tcl_client_step(
5435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void *NotUsed,
5445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  Tcl_Interp *interp,    /* The TCL interpreter that invoked this command */
5455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int argc,              /* Number of arguments */
5465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const char **argv      /* Text of each argument */
5475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)){
5485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int i;
5495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if( argc!=2 ){
5505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
5515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)       " IDL", 0);
5525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return TCL_ERROR;
5535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
5545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  i = parse_client_id(interp, argv[1]);
5555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if( i<0 ) return TCL_ERROR;
5565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if( !threadset[i].busy ){
5575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    Tcl_AppendResult(interp, "no such thread", 0);
5585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return TCL_ERROR;
5595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
5605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  client_wait(&threadset[i]);
5615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  threadset[i].xOp = do_step;
5625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  threadset[i].opnum++;
5635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return TCL_OK;
5645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
5655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/*
5675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** This procedure runs in the thread to finalize a virtual machine.
5685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)*/
5695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static void do_finalize(Thread *p){
5705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if( p->pStmt==0 ){
5715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    p->zErr = p->zStaticErr = "no virtual machine available";
5725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    p->rc = SQLITE_ERROR;
5735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
5745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
5755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  p->rc = sqlite3_client_finalize(p->pStmt);
5765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  p->pStmt = 0;
5775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
5785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/*
5805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** Usage: client_finalize ID
5815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)**
5825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** Finalize the virtual machine.
5835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)*/
5845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static int tcl_client_finalize(
5855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void *NotUsed,
5865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  Tcl_Interp *interp,    /* The TCL interpreter that invoked this command */
5875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int argc,              /* Number of arguments */
5885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const char **argv      /* Text of each argument */
5895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)){
5905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int i;
5915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if( argc!=2 ){
5925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
5935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)       " IDL", 0);
5945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return TCL_ERROR;
5955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
5965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  i = parse_client_id(interp, argv[1]);
5975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if( i<0 ) return TCL_ERROR;
5985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if( !threadset[i].busy ){
5995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    Tcl_AppendResult(interp, "no such thread", 0);
6005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return TCL_ERROR;
6015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
6025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  client_wait(&threadset[i]);
6035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  threadset[i].xOp = do_finalize;
6045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  sqlite3_free(threadset[i].zArg);
6055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  threadset[i].zArg = 0;
6065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  threadset[i].opnum++;
6075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return TCL_OK;
6085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
6095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/*
6115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** This procedure runs in the thread to reset a virtual machine.
6125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)*/
6135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static void do_reset(Thread *p){
6145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if( p->pStmt==0 ){
6155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    p->zErr = p->zStaticErr = "no virtual machine available";
6165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    p->rc = SQLITE_ERROR;
6175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
6185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
6195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  p->rc = sqlite3_client_reset(p->pStmt);
6205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  p->pStmt = 0;
6215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
6225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/*
6245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** Usage: client_reset ID
6255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)**
6265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** Finalize the virtual machine.
6275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)*/
6285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static int tcl_client_reset(
6295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void *NotUsed,
6305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  Tcl_Interp *interp,    /* The TCL interpreter that invoked this command */
6315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int argc,              /* Number of arguments */
6325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const char **argv      /* Text of each argument */
6335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)){
6345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int i;
6355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if( argc!=2 ){
6365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
6375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)       " IDL", 0);
6385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return TCL_ERROR;
6395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
6405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  i = parse_client_id(interp, argv[1]);
6415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if( i<0 ) return TCL_ERROR;
6425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if( !threadset[i].busy ){
6435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    Tcl_AppendResult(interp, "no such thread", 0);
6445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return TCL_ERROR;
6455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
6465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  client_wait(&threadset[i]);
6475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  threadset[i].xOp = do_reset;
6485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  sqlite3_free(threadset[i].zArg);
6495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  threadset[i].zArg = 0;
6505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  threadset[i].opnum++;
6515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return TCL_OK;
6525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
6535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/*
6555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** Usage: client_swap ID ID
6565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)**
6575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** Interchange the sqlite* pointer between two threads.
6585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)*/
6595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static int tcl_client_swap(
6605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void *NotUsed,
6615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  Tcl_Interp *interp,    /* The TCL interpreter that invoked this command */
6625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int argc,              /* Number of arguments */
6635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const char **argv      /* Text of each argument */
6645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)){
6655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int i, j;
6665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  sqlite3 *temp;
6675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if( argc!=3 ){
6685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
6695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)       " ID1 ID2", 0);
6705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return TCL_ERROR;
6715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
6725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  i = parse_client_id(interp, argv[1]);
6735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if( i<0 ) return TCL_ERROR;
6745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if( !threadset[i].busy ){
6755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    Tcl_AppendResult(interp, "no such thread", 0);
6765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return TCL_ERROR;
6775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
6785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  client_wait(&threadset[i]);
6795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  j = parse_client_id(interp, argv[2]);
6805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if( j<0 ) return TCL_ERROR;
6815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if( !threadset[j].busy ){
6825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    Tcl_AppendResult(interp, "no such thread", 0);
6835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return TCL_ERROR;
6845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
6855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  client_wait(&threadset[j]);
6865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  temp = threadset[i].db;
6875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  threadset[i].db = threadset[j].db;
6885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  threadset[j].db = temp;
6895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return TCL_OK;
6905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
6915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/*
6935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** Register commands with the TCL interpreter.
6945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)*/
6955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int Sqlitetest7_Init(Tcl_Interp *interp){
6965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  static struct {
6975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)     char *zName;
6985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)     Tcl_CmdProc *xProc;
6995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  } aCmd[] = {
7005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)     { "client_create",     (Tcl_CmdProc*)tcl_client_create     },
7015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)     { "client_wait",       (Tcl_CmdProc*)tcl_client_wait       },
7025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)     { "client_halt",       (Tcl_CmdProc*)tcl_client_halt       },
7035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)     { "client_argc",       (Tcl_CmdProc*)tcl_client_argc       },
7045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)     { "client_argv",       (Tcl_CmdProc*)tcl_client_argv       },
7055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)     { "client_colname",    (Tcl_CmdProc*)tcl_client_colname    },
7065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)     { "client_result",     (Tcl_CmdProc*)tcl_client_result     },
7075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)     { "client_error",      (Tcl_CmdProc*)tcl_client_error      },
7085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)     { "client_compile",    (Tcl_CmdProc*)tcl_client_compile    },
7095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)     { "client_step",       (Tcl_CmdProc*)tcl_client_step       },
7105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)     { "client_reset",      (Tcl_CmdProc*)tcl_client_reset      },
7115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)     { "client_finalize",   (Tcl_CmdProc*)tcl_client_finalize   },
7125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)     { "client_swap",       (Tcl_CmdProc*)tcl_client_swap       },
7135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  };
7145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int i;
7155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for(i=0; i<sizeof(aCmd)/sizeof(aCmd[0]); i++){
7175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    Tcl_CreateCommand(interp, aCmd[i].zName, aCmd[i].xProc, 0, 0);
7185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
7195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return TCL_OK;
7205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
7215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#else
7225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int Sqlitetest7_Init(Tcl_Interp *interp){ return TCL_OK; }
7235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif /* SQLITE_OS_UNIX */
724