Blame src/test3.c

Packit 87b942
/*
Packit 87b942
** 2001 September 15
Packit 87b942
**
Packit 87b942
** The author disclaims copyright to this source code.  In place of
Packit 87b942
** a legal notice, here is a blessing:
Packit 87b942
**
Packit 87b942
**    May you do good and not evil.
Packit 87b942
**    May you find forgiveness for yourself and forgive others.
Packit 87b942
**    May you share freely, never taking more than you give.
Packit 87b942
**
Packit 87b942
*************************************************************************
Packit 87b942
** Code for testing the btree.c module in SQLite.  This code
Packit 87b942
** is not included in the SQLite library.  It is used for automated
Packit 87b942
** testing of the SQLite library.
Packit 87b942
*/
Packit 87b942
#include "sqliteInt.h"
Packit 87b942
#include "btreeInt.h"
Packit 87b942
#if defined(INCLUDE_SQLITE_TCL_H)
Packit 87b942
#  include "sqlite_tcl.h"
Packit 87b942
#else
Packit 87b942
#  include "tcl.h"
Packit 87b942
#endif
Packit 87b942
#include <stdlib.h>
Packit 87b942
#include <string.h>
Packit 87b942
Packit 87b942
extern const char *sqlite3ErrName(int);
Packit 87b942
Packit 87b942
/*
Packit 87b942
** A bogus sqlite3 connection structure for use in the btree
Packit 87b942
** tests.
Packit 87b942
*/
Packit 87b942
static sqlite3 sDb;
Packit 87b942
static int nRefSqlite3 = 0;
Packit 87b942
Packit 87b942
/*
Packit 87b942
** Usage:   btree_open FILENAME NCACHE
Packit 87b942
**
Packit 87b942
** Open a new database
Packit 87b942
*/
Packit 87b942
static int SQLITE_TCLAPI btree_open(
Packit 87b942
  void *NotUsed,
Packit 87b942
  Tcl_Interp *interp,    /* The TCL interpreter that invoked this command */
Packit 87b942
  int argc,              /* Number of arguments */
Packit 87b942
  const char **argv      /* Text of each argument */
Packit 87b942
){
Packit 87b942
  Btree *pBt;
Packit 87b942
  int rc, nCache;
Packit 87b942
  char zBuf[100];
Packit 87b942
  int n;
Packit 87b942
  char *zFilename;
Packit 87b942
  if( argc!=3 ){
Packit 87b942
    Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
Packit 87b942
       " FILENAME NCACHE FLAGS\"", 0);
Packit 87b942
    return TCL_ERROR;
Packit 87b942
  }
Packit 87b942
  if( Tcl_GetInt(interp, argv[2], &nCache) ) return TCL_ERROR;
Packit 87b942
  nRefSqlite3++;
Packit 87b942
  if( nRefSqlite3==1 ){
Packit 87b942
    sDb.pVfs = sqlite3_vfs_find(0);
Packit 87b942
    sDb.mutex = sqlite3MutexAlloc(SQLITE_MUTEX_RECURSIVE);
Packit 87b942
    sqlite3_mutex_enter(sDb.mutex);
Packit 87b942
  }
Packit 87b942
  n = (int)strlen(argv[1]);
Packit 87b942
  zFilename = sqlite3_malloc( n+2 );
Packit 87b942
  if( zFilename==0 ) return TCL_ERROR;
Packit 87b942
  memcpy(zFilename, argv[1], n+1);
Packit 87b942
  zFilename[n+1] = 0;
Packit 87b942
  rc = sqlite3BtreeOpen(sDb.pVfs, zFilename, &sDb, &pBt, 0, 
Packit 87b942
     SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE | SQLITE_OPEN_MAIN_DB);
Packit 87b942
  sqlite3_free(zFilename);
Packit 87b942
  if( rc!=SQLITE_OK ){
Packit 87b942
    Tcl_AppendResult(interp, sqlite3ErrName(rc), 0);
Packit 87b942
    return TCL_ERROR;
Packit 87b942
  }
Packit 87b942
  sqlite3BtreeSetCacheSize(pBt, nCache);
Packit 87b942
  sqlite3_snprintf(sizeof(zBuf), zBuf,"%p", pBt);
Packit 87b942
  Tcl_AppendResult(interp, zBuf, 0);
Packit 87b942
  return TCL_OK;
Packit 87b942
}
Packit 87b942
Packit 87b942
/*
Packit 87b942
** Usage:   btree_close ID
Packit 87b942
**
Packit 87b942
** Close the given database.
Packit 87b942
*/
Packit 87b942
static int SQLITE_TCLAPI btree_close(
Packit 87b942
  void *NotUsed,
Packit 87b942
  Tcl_Interp *interp,    /* The TCL interpreter that invoked this command */
Packit 87b942
  int argc,              /* Number of arguments */
Packit 87b942
  const char **argv      /* Text of each argument */
Packit 87b942
){
Packit 87b942
  Btree *pBt;
Packit 87b942
  int rc;
Packit 87b942
  if( argc!=2 ){
Packit 87b942
    Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
Packit 87b942
       " ID\"", 0);
Packit 87b942
    return TCL_ERROR;
Packit 87b942
  }
Packit 87b942
  pBt = sqlite3TestTextToPtr(argv[1]);
Packit 87b942
  rc = sqlite3BtreeClose(pBt);
Packit 87b942
  if( rc!=SQLITE_OK ){
Packit 87b942
    Tcl_AppendResult(interp, sqlite3ErrName(rc), 0);
Packit 87b942
    return TCL_ERROR;
Packit 87b942
  }
Packit 87b942
  nRefSqlite3--;
Packit 87b942
  if( nRefSqlite3==0 ){
Packit 87b942
    sqlite3_mutex_leave(sDb.mutex);
Packit 87b942
    sqlite3_mutex_free(sDb.mutex);
Packit 87b942
    sDb.mutex = 0;
Packit 87b942
    sDb.pVfs = 0;
Packit 87b942
  }
Packit 87b942
  return TCL_OK;
Packit 87b942
}
Packit 87b942
Packit 87b942
Packit 87b942
/*
Packit 87b942
** Usage:   btree_begin_transaction ID
Packit 87b942
**
Packit 87b942
** Start a new transaction
Packit 87b942
*/
Packit 87b942
static int SQLITE_TCLAPI btree_begin_transaction(
Packit 87b942
  void *NotUsed,
Packit 87b942
  Tcl_Interp *interp,    /* The TCL interpreter that invoked this command */
Packit 87b942
  int argc,              /* Number of arguments */
Packit 87b942
  const char **argv      /* Text of each argument */
Packit 87b942
){
Packit 87b942
  Btree *pBt;
Packit 87b942
  int rc;
Packit 87b942
  if( argc!=2 ){
Packit 87b942
    Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
Packit 87b942
       " ID\"", 0);
Packit 87b942
    return TCL_ERROR;
Packit 87b942
  }
Packit 87b942
  pBt = sqlite3TestTextToPtr(argv[1]);
Packit 87b942
  sqlite3BtreeEnter(pBt);
Packit 87b942
  rc = sqlite3BtreeBeginTrans(pBt, 1);
Packit 87b942
  sqlite3BtreeLeave(pBt);
Packit 87b942
  if( rc!=SQLITE_OK ){
Packit 87b942
    Tcl_AppendResult(interp, sqlite3ErrName(rc), 0);
Packit 87b942
    return TCL_ERROR;
Packit 87b942
  }
Packit 87b942
  return TCL_OK;
Packit 87b942
}
Packit 87b942
Packit 87b942
/*
Packit 87b942
** Usage:   btree_pager_stats ID
Packit 87b942
**
Packit 87b942
** Returns pager statistics
Packit 87b942
*/
Packit 87b942
static int SQLITE_TCLAPI btree_pager_stats(
Packit 87b942
  void *NotUsed,
Packit 87b942
  Tcl_Interp *interp,    /* The TCL interpreter that invoked this command */
Packit 87b942
  int argc,              /* Number of arguments */
Packit 87b942
  const char **argv      /* Text of each argument */
Packit 87b942
){
Packit 87b942
  Btree *pBt;
Packit 87b942
  int i;
Packit 87b942
  int *a;
Packit 87b942
Packit 87b942
  if( argc!=2 ){
Packit 87b942
    Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
Packit 87b942
       " ID\"", 0);
Packit 87b942
    return TCL_ERROR;
Packit 87b942
  }
Packit 87b942
  pBt = sqlite3TestTextToPtr(argv[1]);
Packit 87b942
 
Packit 87b942
  /* Normally in this file, with a b-tree handle opened using the 
Packit 87b942
  ** [btree_open] command it is safe to call sqlite3BtreeEnter() directly.
Packit 87b942
  ** But this function is sometimes called with a btree handle obtained
Packit 87b942
  ** from an open SQLite connection (using [btree_from_db]). In this case
Packit 87b942
  ** we need to obtain the mutex for the controlling SQLite handle before
Packit 87b942
  ** it is safe to call sqlite3BtreeEnter().
Packit 87b942
  */
Packit 87b942
  sqlite3_mutex_enter(pBt->db->mutex);
Packit 87b942
Packit 87b942
  sqlite3BtreeEnter(pBt);
Packit 87b942
  a = sqlite3PagerStats(sqlite3BtreePager(pBt));
Packit 87b942
  for(i=0; i<11; i++){
Packit 87b942
    static char *zName[] = {
Packit 87b942
      "ref", "page", "max", "size", "state", "err",
Packit 87b942
      "hit", "miss", "ovfl", "read", "write"
Packit 87b942
    };
Packit 87b942
    char zBuf[100];
Packit 87b942
    Tcl_AppendElement(interp, zName[i]);
Packit 87b942
    sqlite3_snprintf(sizeof(zBuf), zBuf,"%d",a[i]);
Packit 87b942
    Tcl_AppendElement(interp, zBuf);
Packit 87b942
  }
Packit 87b942
  sqlite3BtreeLeave(pBt);
Packit 87b942
Packit 87b942
  /* Release the mutex on the SQLite handle that controls this b-tree */
Packit 87b942
  sqlite3_mutex_leave(pBt->db->mutex);
Packit 87b942
  return TCL_OK;
Packit 87b942
}
Packit 87b942
Packit 87b942
/*
Packit 87b942
** Usage:   btree_cursor ID TABLENUM WRITEABLE
Packit 87b942
**
Packit 87b942
** Create a new cursor.  Return the ID for the cursor.
Packit 87b942
*/
Packit 87b942
static int SQLITE_TCLAPI btree_cursor(
Packit 87b942
  void *NotUsed,
Packit 87b942
  Tcl_Interp *interp,    /* The TCL interpreter that invoked this command */
Packit 87b942
  int argc,              /* Number of arguments */
Packit 87b942
  const char **argv      /* Text of each argument */
Packit 87b942
){
Packit 87b942
  Btree *pBt;
Packit 87b942
  int iTable;
Packit 87b942
  BtCursor *pCur;
Packit 87b942
  int rc = SQLITE_OK;
Packit 87b942
  int wrFlag;
Packit 87b942
  char zBuf[30];
Packit 87b942
Packit 87b942
  if( argc!=4 ){
Packit 87b942
    Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
Packit 87b942
       " ID TABLENUM WRITEABLE\"", 0);
Packit 87b942
    return TCL_ERROR;
Packit 87b942
  }
Packit 87b942
  pBt = sqlite3TestTextToPtr(argv[1]);
Packit 87b942
  if( Tcl_GetInt(interp, argv[2], &iTable) ) return TCL_ERROR;
Packit 87b942
  if( Tcl_GetBoolean(interp, argv[3], &wrFlag) ) return TCL_ERROR;
Packit 87b942
  if( wrFlag ) wrFlag = BTREE_WRCSR;
Packit 87b942
  pCur = (BtCursor *)ckalloc(sqlite3BtreeCursorSize());
Packit 87b942
  memset(pCur, 0, sqlite3BtreeCursorSize());
Packit 87b942
  sqlite3_mutex_enter(pBt->db->mutex);
Packit 87b942
  sqlite3BtreeEnter(pBt);
Packit 87b942
#ifndef SQLITE_OMIT_SHARED_CACHE
Packit 87b942
  rc = sqlite3BtreeLockTable(pBt, iTable, !!wrFlag);
Packit 87b942
#endif
Packit 87b942
  if( rc==SQLITE_OK ){
Packit 87b942
    rc = sqlite3BtreeCursor(pBt, iTable, wrFlag, 0, pCur);
Packit 87b942
  }
Packit 87b942
  sqlite3BtreeLeave(pBt);
Packit 87b942
  sqlite3_mutex_leave(pBt->db->mutex);
Packit 87b942
  if( rc ){
Packit 87b942
    ckfree((char *)pCur);
Packit 87b942
    Tcl_AppendResult(interp, sqlite3ErrName(rc), 0);
Packit 87b942
    return TCL_ERROR;
Packit 87b942
  }
Packit 87b942
  sqlite3_snprintf(sizeof(zBuf), zBuf,"%p", pCur);
Packit 87b942
  Tcl_AppendResult(interp, zBuf, 0);
Packit 87b942
  return SQLITE_OK;
Packit 87b942
}
Packit 87b942
Packit 87b942
/*
Packit 87b942
** Usage:   btree_close_cursor ID
Packit 87b942
**
Packit 87b942
** Close a cursor opened using btree_cursor.
Packit 87b942
*/
Packit 87b942
static int SQLITE_TCLAPI btree_close_cursor(
Packit 87b942
  void *NotUsed,
Packit 87b942
  Tcl_Interp *interp,    /* The TCL interpreter that invoked this command */
Packit 87b942
  int argc,              /* Number of arguments */
Packit 87b942
  const char **argv      /* Text of each argument */
Packit 87b942
){
Packit 87b942
  BtCursor *pCur;
Packit 87b942
  int rc;
Packit 87b942
Packit 87b942
  if( argc!=2 ){
Packit 87b942
    Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
Packit 87b942
       " ID\"", 0);
Packit 87b942
    return TCL_ERROR;
Packit 87b942
  }
Packit 87b942
  pCur = sqlite3TestTextToPtr(argv[1]);
Packit 87b942
#if SQLITE_THREADSAFE>0
Packit 87b942
  {
Packit 87b942
    Btree *pBt = pCur->pBtree;
Packit 87b942
    sqlite3_mutex_enter(pBt->db->mutex);
Packit 87b942
    sqlite3BtreeEnter(pBt);
Packit 87b942
    rc = sqlite3BtreeCloseCursor(pCur);
Packit 87b942
    sqlite3BtreeLeave(pBt);
Packit 87b942
    sqlite3_mutex_leave(pBt->db->mutex);
Packit 87b942
  }
Packit 87b942
#else
Packit 87b942
  rc = sqlite3BtreeCloseCursor(pCur);
Packit 87b942
#endif
Packit 87b942
  ckfree((char *)pCur);
Packit 87b942
  if( rc ){
Packit 87b942
    Tcl_AppendResult(interp, sqlite3ErrName(rc), 0);
Packit 87b942
    return TCL_ERROR;
Packit 87b942
  }
Packit 87b942
  return SQLITE_OK;
Packit 87b942
}
Packit 87b942
Packit 87b942
/*
Packit 87b942
** Usage:   btree_next ID
Packit 87b942
**
Packit 87b942
** Move the cursor to the next entry in the table.  Return 0 on success
Packit 87b942
** or 1 if the cursor was already on the last entry in the table or if
Packit 87b942
** the table is empty.
Packit 87b942
*/
Packit 87b942
static int SQLITE_TCLAPI btree_next(
Packit 87b942
  void *NotUsed,
Packit 87b942
  Tcl_Interp *interp,    /* The TCL interpreter that invoked this command */
Packit 87b942
  int argc,              /* Number of arguments */
Packit 87b942
  const char **argv      /* Text of each argument */
Packit 87b942
){
Packit 87b942
  BtCursor *pCur;
Packit 87b942
  int rc;
Packit 87b942
  int res = 0;
Packit 87b942
  char zBuf[100];
Packit 87b942
Packit 87b942
  if( argc!=2 ){
Packit 87b942
    Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
Packit 87b942
       " ID\"", 0);
Packit 87b942
    return TCL_ERROR;
Packit 87b942
  }
Packit 87b942
  pCur = sqlite3TestTextToPtr(argv[1]);
Packit 87b942
  sqlite3BtreeEnter(pCur->pBtree);
Packit 87b942
  rc = sqlite3BtreeNext(pCur, 0);
Packit 87b942
  if( rc==SQLITE_DONE ){
Packit 87b942
    res = 1;
Packit 87b942
    rc = SQLITE_OK;
Packit 87b942
  }
Packit 87b942
  sqlite3BtreeLeave(pCur->pBtree);
Packit 87b942
  if( rc ){
Packit 87b942
    Tcl_AppendResult(interp, sqlite3ErrName(rc), 0);
Packit 87b942
    return TCL_ERROR;
Packit 87b942
  }
Packit 87b942
  sqlite3_snprintf(sizeof(zBuf),zBuf,"%d",res);
Packit 87b942
  Tcl_AppendResult(interp, zBuf, 0);
Packit 87b942
  return SQLITE_OK;
Packit 87b942
}
Packit 87b942
Packit 87b942
/*
Packit 87b942
** Usage:   btree_first ID
Packit 87b942
**
Packit 87b942
** Move the cursor to the first entry in the table.  Return 0 if the
Packit 87b942
** cursor was left point to something and 1 if the table is empty.
Packit 87b942
*/
Packit 87b942
static int SQLITE_TCLAPI btree_first(
Packit 87b942
  void *NotUsed,
Packit 87b942
  Tcl_Interp *interp,    /* The TCL interpreter that invoked this command */
Packit 87b942
  int argc,              /* Number of arguments */
Packit 87b942
  const char **argv      /* Text of each argument */
Packit 87b942
){
Packit 87b942
  BtCursor *pCur;
Packit 87b942
  int rc;
Packit 87b942
  int res = 0;
Packit 87b942
  char zBuf[100];
Packit 87b942
Packit 87b942
  if( argc!=2 ){
Packit 87b942
    Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
Packit 87b942
       " ID\"", 0);
Packit 87b942
    return TCL_ERROR;
Packit 87b942
  }
Packit 87b942
  pCur = sqlite3TestTextToPtr(argv[1]);
Packit 87b942
  sqlite3BtreeEnter(pCur->pBtree);
Packit 87b942
  rc = sqlite3BtreeFirst(pCur, &res;;
Packit 87b942
  sqlite3BtreeLeave(pCur->pBtree);
Packit 87b942
  if( rc ){
Packit 87b942
    Tcl_AppendResult(interp, sqlite3ErrName(rc), 0);
Packit 87b942
    return TCL_ERROR;
Packit 87b942
  }
Packit 87b942
  sqlite3_snprintf(sizeof(zBuf),zBuf,"%d",res);
Packit 87b942
  Tcl_AppendResult(interp, zBuf, 0);
Packit 87b942
  return SQLITE_OK;
Packit 87b942
}
Packit 87b942
Packit 87b942
/*
Packit 87b942
** Usage:   btree_eof ID
Packit 87b942
**
Packit 87b942
** Return TRUE if the given cursor is not pointing at a valid entry.
Packit 87b942
** Return FALSE if the cursor does point to a valid entry.
Packit 87b942
*/
Packit 87b942
static int SQLITE_TCLAPI btree_eof(
Packit 87b942
  void *NotUsed,
Packit 87b942
  Tcl_Interp *interp,    /* The TCL interpreter that invoked this command */
Packit 87b942
  int argc,              /* Number of arguments */
Packit 87b942
  const char **argv      /* Text of each argument */
Packit 87b942
){
Packit 87b942
  BtCursor *pCur;
Packit 87b942
  int rc;
Packit 87b942
  char zBuf[50];
Packit 87b942
Packit 87b942
  if( argc!=2 ){
Packit 87b942
    Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
Packit 87b942
       " ID\"", 0);
Packit 87b942
    return TCL_ERROR;
Packit 87b942
  }
Packit 87b942
  pCur = sqlite3TestTextToPtr(argv[1]);
Packit 87b942
  sqlite3BtreeEnter(pCur->pBtree);
Packit 87b942
  rc = sqlite3BtreeEof(pCur);
Packit 87b942
  sqlite3BtreeLeave(pCur->pBtree);
Packit 87b942
  sqlite3_snprintf(sizeof(zBuf),zBuf, "%d", rc);
Packit 87b942
  Tcl_AppendResult(interp, zBuf, 0);
Packit 87b942
  return SQLITE_OK;
Packit 87b942
}
Packit 87b942
Packit 87b942
/*
Packit 87b942
** Usage:   btree_payload_size ID
Packit 87b942
**
Packit 87b942
** Return the number of bytes of payload
Packit 87b942
*/
Packit 87b942
static int SQLITE_TCLAPI btree_payload_size(
Packit 87b942
  void *NotUsed,
Packit 87b942
  Tcl_Interp *interp,    /* The TCL interpreter that invoked this command */
Packit 87b942
  int argc,              /* Number of arguments */
Packit 87b942
  const char **argv      /* Text of each argument */
Packit 87b942
){
Packit 87b942
  BtCursor *pCur;
Packit 87b942
  u32 n;
Packit 87b942
  char zBuf[50];
Packit 87b942
Packit 87b942
  if( argc!=2 ){
Packit 87b942
    Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
Packit 87b942
       " ID\"", 0);
Packit 87b942
    return TCL_ERROR;
Packit 87b942
  }
Packit 87b942
  pCur = sqlite3TestTextToPtr(argv[1]);
Packit 87b942
  sqlite3BtreeEnter(pCur->pBtree);
Packit 87b942
  n = sqlite3BtreePayloadSize(pCur);
Packit 87b942
  sqlite3BtreeLeave(pCur->pBtree);
Packit 87b942
  sqlite3_snprintf(sizeof(zBuf),zBuf, "%u", n);
Packit 87b942
  Tcl_AppendResult(interp, zBuf, 0);
Packit 87b942
  return SQLITE_OK;
Packit 87b942
}
Packit 87b942
Packit 87b942
/*
Packit 87b942
** usage:   varint_test  START  MULTIPLIER  COUNT  INCREMENT
Packit 87b942
**
Packit 87b942
** This command tests the putVarint() and getVarint()
Packit 87b942
** routines, both for accuracy and for speed.
Packit 87b942
**
Packit 87b942
** An integer is written using putVarint() and read back with
Packit 87b942
** getVarint() and varified to be unchanged.  This repeats COUNT
Packit 87b942
** times.  The first integer is START*MULTIPLIER.  Each iteration
Packit 87b942
** increases the integer by INCREMENT.
Packit 87b942
**
Packit 87b942
** This command returns nothing if it works.  It returns an error message
Packit 87b942
** if something goes wrong.
Packit 87b942
*/
Packit 87b942
static int SQLITE_TCLAPI btree_varint_test(
Packit 87b942
  void *NotUsed,
Packit 87b942
  Tcl_Interp *interp,    /* The TCL interpreter that invoked this command */
Packit 87b942
  int argc,              /* Number of arguments */
Packit 87b942
  const char **argv      /* Text of each argument */
Packit 87b942
){
Packit 87b942
  u32 start, mult, count, incr;
Packit 87b942
  u64 in, out;
Packit 87b942
  int n1, n2, i, j;
Packit 87b942
  unsigned char zBuf[100];
Packit 87b942
  if( argc!=5 ){
Packit 87b942
    Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
Packit 87b942
       " START MULTIPLIER COUNT INCREMENT\"", 0);
Packit 87b942
    return TCL_ERROR;
Packit 87b942
  }
Packit 87b942
  if( Tcl_GetInt(interp, argv[1], (int*)&start) ) return TCL_ERROR;
Packit 87b942
  if( Tcl_GetInt(interp, argv[2], (int*)&mult) ) return TCL_ERROR;
Packit 87b942
  if( Tcl_GetInt(interp, argv[3], (int*)&count) ) return TCL_ERROR;
Packit 87b942
  if( Tcl_GetInt(interp, argv[4], (int*)&incr) ) return TCL_ERROR;
Packit 87b942
  in = start;
Packit 87b942
  in *= mult;
Packit 87b942
  for(i=0; i<(int)count; i++){
Packit 87b942
    char zErr[200];
Packit 87b942
    n1 = putVarint(zBuf, in);
Packit 87b942
    if( n1>9 || n1<1 ){
Packit 87b942
      sqlite3_snprintf(sizeof(zErr), zErr,
Packit 87b942
         "putVarint returned %d - should be between 1 and 9", n1);
Packit 87b942
      Tcl_AppendResult(interp, zErr, 0);
Packit 87b942
      return TCL_ERROR;
Packit 87b942
    }
Packit 87b942
    n2 = getVarint(zBuf, &out;;
Packit 87b942
    if( n1!=n2 ){
Packit 87b942
      sqlite3_snprintf(sizeof(zErr), zErr,
Packit 87b942
          "putVarint returned %d and getVarint returned %d", n1, n2);
Packit 87b942
      Tcl_AppendResult(interp, zErr, 0);
Packit 87b942
      return TCL_ERROR;
Packit 87b942
    }
Packit 87b942
    if( in!=out ){
Packit 87b942
      sqlite3_snprintf(sizeof(zErr), zErr,
Packit 87b942
          "Wrote 0x%016llx and got back 0x%016llx", in, out);
Packit 87b942
      Tcl_AppendResult(interp, zErr, 0);
Packit 87b942
      return TCL_ERROR;
Packit 87b942
    }
Packit 87b942
    if( (in & 0xffffffff)==in ){
Packit 87b942
      u32 out32;
Packit 87b942
      n2 = getVarint32(zBuf, out32);
Packit 87b942
      out = out32;
Packit 87b942
      if( n1!=n2 ){
Packit 87b942
        sqlite3_snprintf(sizeof(zErr), zErr,
Packit 87b942
          "putVarint returned %d and GetVarint32 returned %d", 
Packit 87b942
                  n1, n2);
Packit 87b942
        Tcl_AppendResult(interp, zErr, 0);
Packit 87b942
        return TCL_ERROR;
Packit 87b942
      }
Packit 87b942
      if( in!=out ){
Packit 87b942
        sqlite3_snprintf(sizeof(zErr), zErr,
Packit 87b942
          "Wrote 0x%016llx and got back 0x%016llx from GetVarint32",
Packit 87b942
            in, out);
Packit 87b942
        Tcl_AppendResult(interp, zErr, 0);
Packit 87b942
        return TCL_ERROR;
Packit 87b942
      }
Packit 87b942
    }
Packit 87b942
Packit 87b942
    /* In order to get realistic timings, run getVarint 19 more times.
Packit 87b942
    ** This is because getVarint is called about 20 times more often
Packit 87b942
    ** than putVarint.
Packit 87b942
    */
Packit 87b942
    for(j=0; j<19; j++){
Packit 87b942
      getVarint(zBuf, &out;;
Packit 87b942
    }
Packit 87b942
    in += incr;
Packit 87b942
  }
Packit 87b942
  return TCL_OK;
Packit 87b942
}
Packit 87b942
Packit 87b942
/*
Packit 87b942
** usage:   btree_from_db  DB-HANDLE
Packit 87b942
**
Packit 87b942
** This command returns the btree handle for the main database associated
Packit 87b942
** with the database-handle passed as the argument. Example usage:
Packit 87b942
**
Packit 87b942
** sqlite3 db test.db
Packit 87b942
** set bt [btree_from_db db]
Packit 87b942
*/
Packit 87b942
static int SQLITE_TCLAPI btree_from_db(
Packit 87b942
  void *NotUsed,
Packit 87b942
  Tcl_Interp *interp,    /* The TCL interpreter that invoked this command */
Packit 87b942
  int argc,              /* Number of arguments */
Packit 87b942
  const char **argv      /* Text of each argument */
Packit 87b942
){
Packit 87b942
  char zBuf[100];
Packit 87b942
  Tcl_CmdInfo info;
Packit 87b942
  sqlite3 *db;
Packit 87b942
  Btree *pBt;
Packit 87b942
  int iDb = 0;
Packit 87b942
Packit 87b942
  if( argc!=2 && argc!=3 ){
Packit 87b942
    Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
Packit 87b942
       " DB-HANDLE ?N?\"", 0);
Packit 87b942
    return TCL_ERROR;
Packit 87b942
  }
Packit 87b942
Packit 87b942
  if( 1!=Tcl_GetCommandInfo(interp, argv[1], &info) ){
Packit 87b942
    Tcl_AppendResult(interp, "No such db-handle: \"", argv[1], "\"", 0);
Packit 87b942
    return TCL_ERROR;
Packit 87b942
  }
Packit 87b942
  if( argc==3 ){
Packit 87b942
    iDb = atoi(argv[2]);
Packit 87b942
  }
Packit 87b942
Packit 87b942
  db = *((sqlite3 **)info.objClientData);
Packit 87b942
  assert( db );
Packit 87b942
Packit 87b942
  pBt = db->aDb[iDb].pBt;
Packit 87b942
  sqlite3_snprintf(sizeof(zBuf), zBuf, "%p", pBt);
Packit 87b942
  Tcl_SetResult(interp, zBuf, TCL_VOLATILE);
Packit 87b942
  return TCL_OK;
Packit 87b942
}
Packit 87b942
Packit 87b942
/*
Packit 87b942
** Usage:   btree_ismemdb ID
Packit 87b942
**
Packit 87b942
** Return true if the B-Tree is currently stored entirely in memory.
Packit 87b942
*/
Packit 87b942
static int SQLITE_TCLAPI btree_ismemdb(
Packit 87b942
  void *NotUsed,
Packit 87b942
  Tcl_Interp *interp,    /* The TCL interpreter that invoked this command */
Packit 87b942
  int argc,              /* Number of arguments */
Packit 87b942
  const char **argv      /* Text of each argument */
Packit 87b942
){
Packit 87b942
  Btree *pBt;
Packit 87b942
  int res;
Packit 87b942
  sqlite3_file *pFile;
Packit 87b942
Packit 87b942
  if( argc!=2 ){
Packit 87b942
    Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
Packit 87b942
       " ID\"", 0);
Packit 87b942
    return TCL_ERROR;
Packit 87b942
  }
Packit 87b942
  pBt = sqlite3TestTextToPtr(argv[1]);
Packit 87b942
  sqlite3_mutex_enter(pBt->db->mutex);
Packit 87b942
  sqlite3BtreeEnter(pBt);
Packit 87b942
  pFile = sqlite3PagerFile(sqlite3BtreePager(pBt));
Packit 87b942
  res = (pFile->pMethods==0);
Packit 87b942
  sqlite3BtreeLeave(pBt);
Packit 87b942
  sqlite3_mutex_leave(pBt->db->mutex);
Packit 87b942
  Tcl_SetObjResult(interp, Tcl_NewBooleanObj(res));
Packit 87b942
  return SQLITE_OK;
Packit 87b942
}
Packit 87b942
Packit 87b942
/*
Packit 87b942
** usage:   btree_set_cache_size ID NCACHE
Packit 87b942
**
Packit 87b942
** Set the size of the cache used by btree $ID.
Packit 87b942
*/
Packit 87b942
static int SQLITE_TCLAPI btree_set_cache_size(
Packit 87b942
  void *NotUsed,
Packit 87b942
  Tcl_Interp *interp,    /* The TCL interpreter that invoked this command */
Packit 87b942
  int argc,              /* Number of arguments */
Packit 87b942
  const char **argv      /* Text of each argument */
Packit 87b942
){
Packit 87b942
  int nCache;
Packit 87b942
  Btree *pBt;
Packit 87b942
  
Packit 87b942
  if( argc!=3 ){
Packit 87b942
    Tcl_AppendResult(
Packit 87b942
        interp, "wrong # args: should be \"", argv[0], " BT NCACHE\"", 0);
Packit 87b942
    return TCL_ERROR;
Packit 87b942
  }
Packit 87b942
  pBt = sqlite3TestTextToPtr(argv[1]);
Packit 87b942
  if( Tcl_GetInt(interp, argv[2], &nCache) ) return TCL_ERROR;
Packit 87b942
Packit 87b942
  sqlite3_mutex_enter(pBt->db->mutex);
Packit 87b942
  sqlite3BtreeEnter(pBt);
Packit 87b942
  sqlite3BtreeSetCacheSize(pBt, nCache);
Packit 87b942
  sqlite3BtreeLeave(pBt);
Packit 87b942
  sqlite3_mutex_leave(pBt->db->mutex);
Packit 87b942
  return TCL_OK;
Packit 87b942
}      
Packit 87b942
Packit 87b942
/*
Packit 87b942
** usage:   btree_insert CSR ?KEY? VALUE
Packit 87b942
**
Packit 87b942
** Set the size of the cache used by btree $ID.
Packit 87b942
*/
Packit 87b942
static int SQLITE_TCLAPI btree_insert(
Packit 87b942
  ClientData clientData,
Packit 87b942
  Tcl_Interp *interp,
Packit 87b942
  int objc,
Packit 87b942
  Tcl_Obj *const objv[]
Packit 87b942
){
Packit 87b942
  BtCursor *pCur;
Packit 87b942
  int rc;
Packit 87b942
  BtreePayload x;
Packit 87b942
Packit 87b942
  if( objc!=4 && objc!=3 ){
Packit 87b942
    Tcl_WrongNumArgs(interp, 1, objv, "?-intkey? CSR KEY VALUE");
Packit 87b942
    return TCL_ERROR;
Packit 87b942
  }
Packit 87b942
Packit 87b942
  memset(&x, 0, sizeof(x));
Packit 87b942
  if( objc==4 ){
Packit 87b942
    if( Tcl_GetIntFromObj(interp, objv[2], &rc) ) return TCL_ERROR;
Packit 87b942
    x.nKey = rc;
Packit 87b942
    x.pData = (void*)Tcl_GetByteArrayFromObj(objv[3], &x.nData);
Packit 87b942
  }else{
Packit 87b942
    x.pKey = (void*)Tcl_GetByteArrayFromObj(objv[2], &rc);
Packit 87b942
    x.nKey = rc;
Packit 87b942
  }
Packit 87b942
  pCur = (BtCursor*)sqlite3TestTextToPtr(Tcl_GetString(objv[1]));
Packit 87b942
Packit 87b942
  sqlite3_mutex_enter(pCur->pBtree->db->mutex);
Packit 87b942
  sqlite3BtreeEnter(pCur->pBtree);
Packit 87b942
  rc = sqlite3BtreeInsert(pCur, &x, 0, 0);
Packit 87b942
  sqlite3BtreeLeave(pCur->pBtree);
Packit 87b942
  sqlite3_mutex_leave(pCur->pBtree->db->mutex);
Packit 87b942
Packit 87b942
  Tcl_ResetResult(interp);
Packit 87b942
  if( rc ){
Packit 87b942
    Tcl_AppendResult(interp, sqlite3ErrName(rc), 0);
Packit 87b942
    return TCL_ERROR;
Packit 87b942
  }
Packit 87b942
  return TCL_OK;
Packit 87b942
}
Packit 87b942
Packit 87b942
Packit 87b942
/*
Packit 87b942
** Register commands with the TCL interpreter.
Packit 87b942
*/
Packit 87b942
int Sqlitetest3_Init(Tcl_Interp *interp){
Packit 87b942
  static struct {
Packit 87b942
     char *zName;
Packit 87b942
     Tcl_CmdProc *xProc;
Packit 87b942
  } aCmd[] = {
Packit 87b942
     { "btree_open",               (Tcl_CmdProc*)btree_open               },
Packit 87b942
     { "btree_close",              (Tcl_CmdProc*)btree_close              },
Packit 87b942
     { "btree_begin_transaction",  (Tcl_CmdProc*)btree_begin_transaction  },
Packit 87b942
     { "btree_pager_stats",        (Tcl_CmdProc*)btree_pager_stats        },
Packit 87b942
     { "btree_cursor",             (Tcl_CmdProc*)btree_cursor             },
Packit 87b942
     { "btree_close_cursor",       (Tcl_CmdProc*)btree_close_cursor       },
Packit 87b942
     { "btree_next",               (Tcl_CmdProc*)btree_next               },
Packit 87b942
     { "btree_eof",                (Tcl_CmdProc*)btree_eof                },
Packit 87b942
     { "btree_payload_size",       (Tcl_CmdProc*)btree_payload_size       },
Packit 87b942
     { "btree_first",              (Tcl_CmdProc*)btree_first              },
Packit 87b942
     { "btree_varint_test",        (Tcl_CmdProc*)btree_varint_test        },
Packit 87b942
     { "btree_from_db",            (Tcl_CmdProc*)btree_from_db            },
Packit 87b942
     { "btree_ismemdb",            (Tcl_CmdProc*)btree_ismemdb            },
Packit 87b942
     { "btree_set_cache_size",     (Tcl_CmdProc*)btree_set_cache_size     }
Packit 87b942
  };
Packit 87b942
  int i;
Packit 87b942
Packit 87b942
  for(i=0; i
Packit 87b942
    Tcl_CreateCommand(interp, aCmd[i].zName, aCmd[i].xProc, 0, 0);
Packit 87b942
  }
Packit 87b942
Packit 87b942
  Tcl_CreateObjCommand(interp, "btree_insert", btree_insert, 0, 0);
Packit 87b942
Packit 87b942
  return TCL_OK;
Packit 87b942
}