Many hyperlinks are disabled.
Use anonymous login to enable hyperlinks.

Overview
Comment:Add "PRAGMA bt_page_dump" to access a specific bt xControl() command. This is probably a temporary solution.
Downloads: Tarball | ZIP archive
Timelines: family | ancestors | descendants | both | trunk
Files: files | file ages | folders
SHA1: d00d7c08d195d21f0846411537da6a14f855df68
User & Date: dan 2013-10-22 19:04:17.847
Context
2013-10-23
19:31
Progress on reading and writing frames from and to the log file. check-in: 5ba2ff0701 user: dan tags: trunk
2013-10-22
19:04
Add "PRAGMA bt_page_dump" to access a specific bt xControl() command. This is probably a temporary solution. check-in: d00d7c08d1 user: dan tags: trunk
16:20
More logging code. check-in: 94016fe5e8 user: dan tags: trunk
Changes
Unified Diff Ignore Whitespace Patch
Changes to src/bt.h.
114
115
116
117
118
119
120






























121
int sqlite4BtCsrData(bt_cursor *pCsr, int, int, const void **ppV, int *pnV);

int sqlite4BtReplace(bt_db*, const void *pK, int nK, const void *pV, int nV);
int sqlite4BtDelete(bt_cursor*);

int sqlite4BtSetCookie(bt_db*, unsigned int iVal);
int sqlite4BtGetCookie(bt_db*, unsigned int *piVal);






































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>

114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
int sqlite4BtCsrData(bt_cursor *pCsr, int, int, const void **ppV, int *pnV);

int sqlite4BtReplace(bt_db*, const void *pK, int nK, const void *pV, int nV);
int sqlite4BtDelete(bt_cursor*);

int sqlite4BtSetCookie(bt_db*, unsigned int iVal);
int sqlite4BtGetCookie(bt_db*, unsigned int *piVal);

/*
** Append a human readable representation of the b-tree page passed via
** arguments a+n to the buffer passed as the first argument. If argument
** pgno is non-zero it is included in the output.
*/
int sqlite4BtDebugPage(sqlite4_buffer*, unsigned int pgno, char *a, int n);

/*
** kvstore xControl() method.
**
** BT_CONTROL_INFO:
**   If the second argument to sqlite4BtControl() is BT_CONTROL_INFO, then
**   the third is expected to be a pointer to an instance of type bt_info.
**   The "output" buffer must already be initialized. Before 
**   sqlite4BtControl() returns it appends debugging information to the
**   buffer. The specific information appended depends on the eType and
**   pgno member variables.
*/
int sqlite4BtControl(bt_db*, int op, void *pArg);

#define BT_CONTROL_INFO 7706389
typedef struct bt_info bt_info;
struct bt_info {
  int eType;
  unsigned int pgno;
  sqlite4_buffer output;
};



Changes to src/bt_main.c.
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
#ifndef MIN
# define MIN(a,b) (((a)<(b))?(a):(b))
#endif
#ifndef MAX
# define MAX(a,b) (((a)>(b))?(a):(b))
#endif

/* #define BT_STDERR_DEBUG 1 */

struct bt_db {
  sqlite4_env *pEnv;              /* SQLite environment */
  BtPager *pPager;                /* Underlying page-based database */
  bt_cursor *pAllCsr;             /* List of all open cursors */
};








|







28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
#ifndef MIN
# define MIN(a,b) (((a)<(b))?(a):(b))
#endif
#ifndef MAX
# define MAX(a,b) (((a)>(b))?(a):(b))
#endif

#define BT_STDERR_DEBUG 1

struct bt_db {
  sqlite4_env *pEnv;              /* SQLite environment */
  BtPager *pPager;                /* Underlying page-based database */
  bt_cursor *pAllCsr;             /* List of all open cursors */
};

338
339
340
341
342
343
344



345



346








347
348
349

350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378




















379
380
381
382
383
384
385

  return pgno;
}

/*
**************************************************************************/




#ifndef NDEBUG



#include <stdio.h>








static void printPage(FILE *f, u32 pgno, u8 *aData, int nData){
  int i;
  int nCell = (int)btCellCount(aData, nData);

  fprintf(f, "Page %d: ", pgno);
  fprintf(f, "nCell=%d ", nCell);
  fprintf(f, "iFree=%d ", (int)btFreeOffset(aData, nData));
  fprintf(f, "flags=%d ", (int)btFlags(aData));
  if( btFlags(aData) & BT_PGFLAGS_INTERNAL ){
    fprintf(f, "rchild=%d ", (int)btGetU32(&aData[1]));
  }
  fprintf(f, "cell-offsets=(");
  for(i=0; i<nCell; i++){
    u8 *ptr = btCellPtrFind(aData, nData, i);
    fprintf(f, "%s%d", i==0?"":" ", (int)btGetU16(ptr));
  }
  fprintf(f, ")\n");

  for(i=0; i<nCell; i++){
    int nKey;
    int j;
    u8 *pCell = btCellFind(aData, nData, i);
    fprintf(f, "  Key %d: ", i);
    pCell += sqlite4BtVarintGet32(pCell, &nKey);
    for(j=0; j<nKey; j++){
      fprintf(f, "%02X", (int)pCell[j]);
    }
    if( btFlags(aData) & BT_PGFLAGS_INTERNAL ){
      fprintf(f, "  child=%d ", (int)btGetU32(&pCell[j]));
    }
    fprintf(f, "\n");
  }
}




















int printPgdataToStderr(u32 pgno, u8 *aData, int nData){
  printPage(stderr, pgno, aData, nData);
  return 0;
}

int printPgToStderr(BtPage *pPg){
  printPage(stderr, sqlite4BtPagePgno(pPg), sqlite4BtPageData(pPg), 1024);







>
>
>
|
>
>
>
|
>
>
>
>
>
>
>
>
|


>
|
|
|
|

|

|


|

|





|


|


|

|


>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>







338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420

  return pgno;
}

/*
**************************************************************************/

static void btBufPrintf(sqlite4_buffer *pBuf, const char *zFormat, ...){
  char *zAppend;
  va_list ap;

  va_start(ap, zFormat);
  zAppend = sqlite4_vmprintf(0, zFormat, ap);
  va_end(ap);

  sqlite4_buffer_append(pBuf, zAppend, strlen(zAppend));
  sqlite4_free(0, zAppend);
}

/*
** Append a human-readable interpretation of the b-tree page in aData/nData
** to buffer pBuf.
*/
static void btPageToAscii(u32 pgno, u8 *aData, int nData, sqlite4_buffer *pBuf){
  int i;
  int nCell = (int)btCellCount(aData, nData);

  btBufPrintf(pBuf, "Page %d: ", pgno);
  btBufPrintf(pBuf, "nCell=%d ", nCell);
  btBufPrintf(pBuf, "iFree=%d ", (int)btFreeOffset(aData, nData));
  btBufPrintf(pBuf, "flags=%d ", (int)btFlags(aData));
  if( btFlags(aData) & BT_PGFLAGS_INTERNAL ){
    btBufPrintf(pBuf, "rchild=%d ", (int)btGetU32(&aData[1]));
  }
  btBufPrintf(pBuf, "cell-offsets=(");
  for(i=0; i<nCell; i++){
    u8 *ptr = btCellPtrFind(aData, nData, i);
    btBufPrintf(pBuf, "%s%d", i==0?"":" ", (int)btGetU16(ptr));
  }
  btBufPrintf(pBuf, ")\n");

  for(i=0; i<nCell; i++){
    int nKey;
    int j;
    u8 *pCell = btCellFind(aData, nData, i);
    btBufPrintf(pBuf, "  Key %d: ", i);
    pCell += sqlite4BtVarintGet32(pCell, &nKey);
    for(j=0; j<nKey; j++){
      btBufPrintf(pBuf, "%02X", (int)pCell[j]);
    }
    if( btFlags(aData) & BT_PGFLAGS_INTERNAL ){
      btBufPrintf(pBuf, "  child=%d ", (int)btGetU32(&pCell[j]));
    }
    btBufPrintf(pBuf, "\n");
  }
}

int sqlite4BtDebugPage(sqlite4_buffer *pBuf, u32 pgno, char *aData, int nData){
  btPageToAscii(pgno, (u8*)aData, nData, pBuf);
  return SQLITE4_OK;
}

#ifndef NDEBUG
#include <stdio.h>

static void printPage(FILE *f, u32 pgno, u8 *aData, int nData){
  sqlite4_buffer buf;

  sqlite4_buffer_init(&buf, 0);
  btPageToAscii(pgno, aData, nData, &buf);
  sqlite4_buffer_append(&buf, "", 1);

  fprintf(f, "%s", (char*)buf.p);
  sqlite4_buffer_clear(&buf);
}

int printPgdataToStderr(u32 pgno, u8 *aData, int nData){
  printPage(stderr, pgno, aData, nData);
  return 0;
}

int printPgToStderr(BtPage *pPg){
  printPage(stderr, sqlite4BtPagePgno(pPg), sqlite4BtPageData(pPg), 1024);
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
  const int pgsz = sqlite4BtPagerPagesize(pPager);
  u8 *aData;
  u8 *pCell;
  u8 *pOvfl = 0;
  int iCell = pCsr->aiCell[pCsr->nPg-1];
  int n;
  int rc = SQLITE4_OK;
  int e = 0;
  
  aData = (u8*)sqlite4BtPageData(pCsr->apPage[pCsr->nPg-1]);
  assert( btCellCount(aData, pgsz)>iCell );
  pCell = btCellFind(aData, pgsz, iCell);
  pCell += sqlite4BtVarintGet32(pCell, &n);

  if( n==0 ){







<







946
947
948
949
950
951
952

953
954
955
956
957
958
959
  const int pgsz = sqlite4BtPagerPagesize(pPager);
  u8 *aData;
  u8 *pCell;
  u8 *pOvfl = 0;
  int iCell = pCsr->aiCell[pCsr->nPg-1];
  int n;
  int rc = SQLITE4_OK;

  
  aData = (u8*)sqlite4BtPageData(pCsr->apPage[pCsr->nPg-1]);
  assert( btCellCount(aData, pgsz)>iCell );
  pCell = btCellFind(aData, pgsz, iCell);
  pCell += sqlite4BtVarintGet32(pCell, &n);

  if( n==0 ){
2310
2311
2312
2313
2314
2315
2316
2317



























int sqlite4BtSetCookie(bt_db *db, unsigned int iVal){
  return sqlite4BtPagerSetCookie(db->pPager, iVal);
}

int sqlite4BtGetCookie(bt_db *db, unsigned int *piVal){
  return sqlite4BtPagerGetCookie(db->pPager, piVal);
}




































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
2344
2345
2346
2347
2348
2349
2350
2351
2352
2353
2354
2355
2356
2357
2358
2359
2360
2361
2362
2363
2364
2365
2366
2367
2368
2369
2370
2371
2372
2373
2374
2375
2376
2377
2378
int sqlite4BtSetCookie(bt_db *db, unsigned int iVal){
  return sqlite4BtPagerSetCookie(db->pPager, iVal);
}

int sqlite4BtGetCookie(bt_db *db, unsigned int *piVal){
  return sqlite4BtPagerGetCookie(db->pPager, piVal);
}

int sqlite4BtControl(bt_db *db, int op, void *pArg){
  int rc = SQLITE4_OK;
  switch( op ){
    case BT_CONTROL_INFO: {
      bt_info *pInfo = (bt_info*)pArg;
      int iTrans = sqlite4BtTransactionLevel(db);
      if( iTrans==0 ) rc = sqlite4BtBegin(db, 1);
      if( rc==SQLITE4_OK ){
        BtPage *pPg = 0;
        rc = sqlite4BtPageGet(db->pPager, pInfo->pgno, &pPg);
        if( rc==SQLITE4_OK ){
          u8 *aData;
          int nData;
          aData = sqlite4BtPageData(pPg);
          nData = sqlite4BtPagerPagesize(db->pPager);
          btPageToAscii(pInfo->pgno, aData, nData, &pInfo->output);
          sqlite4_buffer_append(&pInfo->output, "", 1);
          sqlite4BtPageRelease(pPg);
        }
        if( iTrans==0 ) rc = sqlite4BtCommit(db, 0);
      }
    }
  }

  return rc;
}

Changes to src/kvbt.c.
215
216
217
218
219
220
221

222
223
224
225
226
227
228
229
*/
static int btClose(KVStore *pKVStore){
  KVBt *p = (KVBt *)pKVStore;
  return sqlite4BtClose(p->pDb);
}

static int btControl(KVStore *pKVStore, int op, void *pArg){

  return SQLITE4_OK;
}

static int btGetMeta(KVStore *pKVStore, unsigned int *piVal){
  KVBt *p = (KVBt *)pKVStore;
  return sqlite4BtGetCookie(p->pDb, piVal);
}








>
|







215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
*/
static int btClose(KVStore *pKVStore){
  KVBt *p = (KVBt *)pKVStore;
  return sqlite4BtClose(p->pDb);
}

static int btControl(KVStore *pKVStore, int op, void *pArg){
  KVBt *p = (KVBt *)pKVStore;
  return sqlite4BtControl(p->pDb, op, pArg);
}

static int btGetMeta(KVStore *pKVStore, unsigned int *piVal){
  KVBt *p = (KVBt *)pKVStore;
  return sqlite4BtGetCookie(p->pDb, piVal);
}

Changes to src/pragma.c.
8
9
10
11
12
13
14

15
16
17
18
19
20
21
**    May you find forgiveness for yourself and forgive others.
**    May you share freely, never taking more than you give.
**
*************************************************************************
** This file contains code used to implement the PRAGMA command.
*/
#include "sqliteInt.h"


/*
** Interpret the given string as a boolean value.
*/
u8 sqlite4GetBoolean(const char *z){
                             /* 123456789 12345 */
  static const char zText[] = "onoffalseyestrue";







>







8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
**    May you find forgiveness for yourself and forgive others.
**    May you share freely, never taking more than you give.
**
*************************************************************************
** This file contains code used to implement the PRAGMA command.
*/
#include "sqliteInt.h"
#include "bt.h"

/*
** Interpret the given string as a boolean value.
*/
u8 sqlite4GetBoolean(const char *z){
                             /* 123456789 12345 */
  static const char zText[] = "onoffalseyestrue";
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
    sqlite4VdbeAddOp4(v, OP_HaltIfNull, SQLITE4_CONSTRAINT, OE_Abort,
                         r2, "value may not be null", P4_STATIC);
    sqlite4VdbeAddOp1(v, OP_ToBlob, r2);
    sqlite4VdbeAddOp0(v, OP_OpenWrite);
    sqlite4VdbeAddOp3(v, OP_Insert, 0, r2, r1);
    sqlite4VdbeAddOp0(v, OP_Halt);
  }else
#endif /* SQLITE4_DEBUG

  /*
  **   PRAGMA integrity_check
  **
  ** Check that for each table, the content of any auxilliary indexes are 
  ** consistent with the primary key index.
  */







|







662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
    sqlite4VdbeAddOp4(v, OP_HaltIfNull, SQLITE4_CONSTRAINT, OE_Abort,
                         r2, "value may not be null", P4_STATIC);
    sqlite4VdbeAddOp1(v, OP_ToBlob, r2);
    sqlite4VdbeAddOp0(v, OP_OpenWrite);
    sqlite4VdbeAddOp3(v, OP_Insert, 0, r2, r1);
    sqlite4VdbeAddOp0(v, OP_Halt);
  }else
#endif /* SQLITE4_DEBUG */

  /*
  **   PRAGMA integrity_check
  **
  ** Check that for each table, the content of any auxilliary indexes are 
  ** consistent with the primary key index.
  */
866
867
868
869
870
871
872





















873
874
875
876
877
878
879
880
881
882
883
884
      sqlite4VdbeChangeP1(v, addr, iDb);
      sqlite4VdbeChangeP1(v, addr+1, iDb);
      sqlite4VdbeSetNumCols(v, 1);
      sqlite4VdbeSetColName(v, 0, COLNAME_NAME, zPragma, SQLITE4_TRANSIENT);
    }
  }else






















 
  {/* Empty ELSE clause */}



 pragma_out:
  sqlite4DbFree(db, zPragma);
  /* sqlite4DbFree(db, zRight); */
  sqlite4ExprListDelete(db, pList);
}

#endif /* SQLITE4_OMIT_PRAGMA */







>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>












867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
      sqlite4VdbeChangeP1(v, addr, iDb);
      sqlite4VdbeChangeP1(v, addr+1, iDb);
      sqlite4VdbeSetNumCols(v, 1);
      sqlite4VdbeSetColName(v, 0, COLNAME_NAME, zPragma, SQLITE4_TRANSIENT);
    }
  }else

  /*
  ** TODO: This is temporary. There should be some generic way to
  ** pass PRAGMA commands through to KV stores.
  */
  if( sqlite4_stricmp(zPragma, "bt_page_dump")==0 && zRight ){
    bt_info info;
    memset(&info, 0, sizeof(info));
    info.pgno = sqlite4Atoi(zRight);
    sqlite4_buffer_init(&info.output, sqlite4_db_env(db)->pMM);

    rc = sqlite4_kvstore_control(db, zDb, BT_CONTROL_INFO, (void*)&info);
    if( rc==SQLITE4_OK ){
      sqlite4VdbeSetNumCols(v, 1);
      sqlite4VdbeSetColName(v, 0, COLNAME_NAME, "info", SQLITE4_STATIC);
      sqlite4VdbeAddOp2(v, OP_String8, 0, 1);
      sqlite4VdbeChangeP4(v, -1, (char*)info.output.p, P4_TRANSIENT);
      sqlite4VdbeAddOp2(v, OP_ResultRow, 1, 1);
    }
    sqlite4_buffer_clear(&info.output);
  }else

 
  {/* Empty ELSE clause */}



 pragma_out:
  sqlite4DbFree(db, zPragma);
  /* sqlite4DbFree(db, zRight); */
  sqlite4ExprListDelete(db, pList);
}

#endif /* SQLITE4_OMIT_PRAGMA */