/ Check-in [e82eb722]
Login
SQLite training in Houston TX on 2019-11-05 (details)
Part of the 2019 Tcl Conference

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

Overview
Comment:Ensure blob values survive the ".dump" command of the shell. (CVS 1531)
Downloads: Tarball | ZIP archive | SQL archive
Timelines: family | ancestors | descendants | both | trunk
Files: files | file ages | folders
SHA1: e82eb722b0e0b223ddaf7d85669792c33594f9da
User & Date: danielk1977 2004-06-05 08:04:36
Context
2004-06-05
10:22
Add the sqlite3_set_auxdata() and sqlite3_get_auxdata() APIs. (CVS 1532) check-in: c2899b43 user: danielk1977 tags: trunk
08:04
Ensure blob values survive the ".dump" command of the shell. (CVS 1531) check-in: e82eb722 user: danielk1977 tags: trunk
00:01
Critical bugs fixed in btree.c. Incompatible file format change. Unrelated comment fix in select.c (CVS 1530) check-in: cb1ffabf user: drh tags: trunk
Changes
Hide Diffs Unified Diffs Ignore Whitespace Patch

Changes to main.mk.

56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
#
LIBOBJ = attach.o auth.o btree.o build.o date.o delete.o \
         expr.o func.o hash.o insert.o \
         main.o opcodes.o os_mac.o os_unix.o os_win.o \
         pager.o parse.o pragma.o printf.o random.o \
         select.o table.o tokenize.o trigger.o update.o util.o vacuum.o \
         vdbe.o vdbeapi.o vdbeaux.o vdbemem.o \
         where.o tclsqlite.o utf.o legacy.o

# All of the source code files.
#
SRC = \
  $(TOP)/src/attach.c \
  $(TOP)/src/auth.c \
  $(TOP)/src/btree.c \







|







56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
#
LIBOBJ = attach.o auth.o btree.o build.o date.o delete.o \
         expr.o func.o hash.o insert.o \
         main.o opcodes.o os_mac.o os_unix.o os_win.o \
         pager.o parse.o pragma.o printf.o random.o \
         select.o table.o tokenize.o trigger.o update.o util.o vacuum.o \
         vdbe.o vdbeapi.o vdbeaux.o vdbemem.o \
         where.o utf.o legacy.o

# All of the source code files.
#
SRC = \
  $(TOP)/src/attach.c \
  $(TOP)/src/auth.c \
  $(TOP)/src/btree.c \

Changes to src/os_win.c.

365
366
367
368
369
370
371








372
373
374
375
376
377
378
** N_LOCKBYTE is the number of bytes available for doing the locking.
** The first byte used to hold the lock while the lock is changing does
** not count toward this number.  FIRST_LOCKBYTE is the address of
** the first byte in the range of bytes used for locking.
*/
#define N_LOCKBYTE       10239
#define FIRST_LOCKBYTE   (0xffffffff - N_LOCKBYTE)









/*
** Change the status of the lock on the file "id" to be a readlock.
** If the file was write locked, then this reduces the lock to a read.
** If the file was read locked, then this acquires a new read lock.
**
** Return SQLITE_OK on success and SQLITE_BUSY on failure.  If this







>
>
>
>
>
>
>
>







365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
** N_LOCKBYTE is the number of bytes available for doing the locking.
** The first byte used to hold the lock while the lock is changing does
** not count toward this number.  FIRST_LOCKBYTE is the address of
** the first byte in the range of bytes used for locking.
*/
#define N_LOCKBYTE       10239
#define FIRST_LOCKBYTE   (0xffffffff - N_LOCKBYTE)

int sqlite3OsLock(OsFile *id, int locktype){
  return SQLITE_OK;
}

int sqlite3OsCheckWriteLock(OsFile *id){
  return 0;
}

/*
** Change the status of the lock on the file "id" to be a readlock.
** If the file was write locked, then this reduces the lock to a read.
** If the file was read locked, then this acquires a new read lock.
**
** Return SQLITE_OK on success and SQLITE_BUSY on failure.  If this

Changes to src/shell.c.

8
9
10
11
12
13
14
15
16
17
18
19

20
21
22
23
24
25
26
...
439
440
441
442
443
444
445
446























































































































447
448
449
450
451
452
453




454

455




456

457
458
459
460
461
462
463
464
465
466
467





468




















































469
470
471
472
473
474
475
...
519
520
521
522
523
524
525



526
527
528
529
530
531
532
....
1059
1060
1061
1062
1063
1064
1065
1066
1067
1068
1069
1070
1071
1072
1073
**    May you find forgiveness for yourself and forgive others.
**    May you share freely, never taking more than you give.
**
*************************************************************************
** This file contains code to implement the "sqlite" command line
** utility for accessing SQLite databases.
**
** $Id: shell.c,v 1.101 2004/05/31 23:56:43 danielk1977 Exp $
*/
#include <stdlib.h>
#include <string.h>
#include <stdio.h>

#include "sqlite3.h"
#include <ctype.h>

#if !defined(_WIN32) && !defined(WIN32) && !defined(__MACOS__)
# include <signal.h>
# include <pwd.h>
# include <unistd.h>
................................................................................
  for(i=0; zName[i]; i++){
    z[n++] = zName[i];
    if( zName[i]=='\'' ) z[n++] = '\'';
  }
  if( needQuote ) z[n++] = '\'';
  z[n] = 0;
}
























































































































/*
** This is a different callback routine used for dumping the database.
** Each row received by this callback consists of a table name,
** the table type ("index" or "table") and SQL to create the table.
** This routine should print text sufficient to recreate the table.
*/
static int dump_callback(void *pArg, int nArg, char **azArg, char **azCol){




  struct callback_data *p = (struct callback_data *)pArg;

  if( nArg!=3 ) return 1;




  fprintf(p->out, "%s;\n", azArg[2]);

  if( strcmp(azArg[1],"table")==0 ){
    struct callback_data d2;
    d2 = *p;
    d2.mode = MODE_Insert;
    d2.zDestTable = 0;
    set_table_name(&d2, azArg[0]);
    sqlite3_exec_printf(p->db,
       "SELECT * FROM '%q'",
       callback, &d2, 0, azArg[0]
    );
    set_table_name(&d2, 0);





  }




















































  return 0;
}

/*
** Text of a help message
*/
static char zHelp[] =
................................................................................
    db = p->db;
#endif
    if( SQLITE_OK!=sqlite3_errcode(db) ){
      fprintf(stderr,"Unable to open database \"%s\": %s\n", 
          p->zDbFilename, sqlite3_errmsg(db));
      exit(1);
    }



  }
}

/*
** If an input line begins with "." then invoke this routine to
** process that line.
**
................................................................................
      if( rc || zErrMsg ){
        if( in!=0 && !p->echoOn ) printf("%s\n",zSql);
        if( zErrMsg!=0 ){
          printf("SQL error: %s\n", zErrMsg);
          sqlite3_free(zErrMsg);
          zErrMsg = 0;
        }else{
          printf("SQL error: %s\n", sqlite3ErrStr(rc));
        }
      }
      free(zSql);
      zSql = 0;
      nSql = 0;
    }
  }







|




>







 








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







>
>
>
>

>

>
>
>
>
|
>
|
<
<
<
<
<
<
<
<
<
<
>
>
>
>
>
|
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>







 







>
>
>







 







|







8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
...
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587










588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
...
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
....
1239
1240
1241
1242
1243
1244
1245
1246
1247
1248
1249
1250
1251
1252
1253
**    May you find forgiveness for yourself and forgive others.
**    May you share freely, never taking more than you give.
**
*************************************************************************
** This file contains code to implement the "sqlite" command line
** utility for accessing SQLite databases.
**
** $Id: shell.c,v 1.102 2004/06/05 08:04:44 danielk1977 Exp $
*/
#include <stdlib.h>
#include <string.h>
#include <stdio.h>
#include <assert.h>
#include "sqlite3.h"
#include <ctype.h>

#if !defined(_WIN32) && !defined(WIN32) && !defined(__MACOS__)
# include <signal.h>
# include <pwd.h>
# include <unistd.h>
................................................................................
  for(i=0; zName[i]; i++){
    z[n++] = zName[i];
    if( zName[i]=='\'' ) z[n++] = '\'';
  }
  if( needQuote ) z[n++] = '\'';
  z[n] = 0;
}

/* zIn is either a pointer to a NULL-terminated string in memory obtained
** from malloc(), or a NULL pointer. The string pointed to by zAppend is
** added to zIn, and the result returned in memory obtained from malloc().
** zIn, if it was not NULL, is freed.
**
** If the third argument, quote, is not '\0', then it is used as a 
** quote character for zAppend.
*/
static char * appendText(char *zIn, char const *zAppend, char quote){
  int len;
  int i;
  int nAppend = strlen(zAppend);
  int nIn = (zIn?strlen(zIn):0);

  len = nAppend+nIn+1;
  if( quote ){
    len += 2;
    for(i=0; i<nAppend; i++){
      if( zAppend[i]==quote ) len++;
    }
  }

  zIn = (char *)realloc(zIn, len);
  if( !zIn ){
    return 0;
  }

  if( quote ){
    char *zCsr = &zIn[nIn];
    *zCsr++ = quote;
    for(i=0; i<nAppend; i++){
      *zCsr++ = zAppend[i];
      if( zAppend[i]==quote ) *zCsr++ = quote;
    }
    *zCsr++ = quote;
    *zCsr++ = '\0';
    assert( (zCsr-zIn)==len );
  }else{
    memcpy(&zIn[nIn], zAppend, nAppend);
    zIn[len-1] = '\0';
  }

  return zIn;
}

/* This function implements the SQL scalar function dump_literal()used by
 * the '.dump' built-in. It takes one argument and returns the fully quoted
** literal version of the argument depending on the type.
**
** Type          Example
** -----------------------
** NULL          "NULL"
** INTEGER       "0"
** REAL          "0.0"
** TEXT          "'abc'"
** BLOB          "X'89AB'"
**
*/
static void dump_literalFunc(
  sqlite3_context *context,
  int argc,
  sqlite3_value **argv
){
  static const char hexdigits[] = { 
      '0', '1', '2', '3', '4', '5', '6', '7',
      '8', '9', 'A', 'B', 'C', 'D', 'E', 'F' 
  };
  assert( argc==1 );

  switch( sqlite3_value_type(argv[0]) ){
    case SQLITE_NULL:
      sqlite3_result_text(context, "NULL", -1, 0);
      break;
    case SQLITE_INTEGER:
      sqlite3_result_text(context, sqlite3_value_text(argv[0]), -1, 1);
      break;
    case SQLITE_FLOAT: {
      char zBuf[40];
      sprintf(zBuf, "%.15g", sqlite3_value_double(argv[0]));
      sqlite3_result_text(context, zBuf, -1, 1);
      break;
    }
    case SQLITE_TEXT: {
      char *zText;
      zText = appendText(0, sqlite3_value_text(argv[0]), '\'');
      if( !zText ){
        sqlite3_result_error(context, "out of memory", -1);
      }else{
        sqlite3_result_text(context, zText, -1, 1);
        free(zText);
      }
      break;
    }
    case SQLITE_BLOB: {
      char *zText = 0;
      int nBlob = sqlite3_value_bytes(argv[0]);
      char const *zBlob = sqlite3_value_blob(argv[0]);

      zText = (char *)malloc((2*nBlob)+4); 
      if( !zText ){
        sqlite3_result_error(context, "out of memory", -1);
      }else{
        int i;
        for(i=0; i<nBlob; i++){
          zText[(i*2)+2] = hexdigits[(zBlob[i]>>4)&0x0F];
          zText[(i*2)+3] = hexdigits[(zBlob[i])&0x0F];
        }
        zText[(nBlob*2)+2] = '\'';
        zText[(nBlob*2)+3] = '\0';
        zText[0] = 'X';
        zText[1] = '\'';
        sqlite3_result_text(context, zText, -1, 1);
        free(zText);
      }
      break;
    }
  }
}

/*
** This is a different callback routine used for dumping the database.
** Each row received by this callback consists of a table name,
** the table type ("index" or "table") and SQL to create the table.
** This routine should print text sufficient to recreate the table.
*/
static int dump_callback(void *pArg, int nArg, char **azArg, char **azCol){
  int rc;
  const char *zTable;
  const char *zType;
  const char *zSql;
  struct callback_data *p = (struct callback_data *)pArg;

  if( nArg!=3 ) return 1;
  zTable = azArg[0];
  zType = azArg[1];
  zSql = azArg[2];
  
  fprintf(p->out, "%s;\n", zSql);

  if( strcmp(zType, "table")==0 ){










    sqlite3_stmt *pTableInfo = 0;
    sqlite3_stmt *pSelect = 0;
    char *zSelect = 0;
    char *zTableInfo = 0;
    char *zTmp = 0;
   
    zTableInfo = appendText(zTableInfo, "PRAGMA table_info(", 0);
    zTableInfo = appendText(zTableInfo, zTable, '"');
    zTableInfo = appendText(zTableInfo, ");", 0);

    rc = sqlite3_prepare(p->db, zTableInfo, -1, &pTableInfo, 0);
    if( zTableInfo ) free(zTableInfo);
    if( rc!=SQLITE_OK || !pTableInfo ){
      return 1;
    }

    zSelect = appendText(zSelect, "SELECT 'INSERT INTO ' || ", 0);
    zTmp = appendText(zTmp, zTable, '"');
    if( zTmp ){
      zSelect = appendText(zSelect, zTmp, '\'');
    }
    zSelect = appendText(zSelect, " || ' VALUES(' || ", 0);
    rc = sqlite3_step(pTableInfo);
    while( rc==SQLITE_ROW ){
      zSelect = appendText(zSelect, "dump_literal(", 0);
      zSelect = appendText(zSelect, sqlite3_column_text(pTableInfo, 1), '"');
      rc = sqlite3_step(pTableInfo);
      if( rc==SQLITE_ROW ){
        zSelect = appendText(zSelect, ") || ', ' || ", 0);
      }else{
        zSelect = appendText(zSelect, ") ", 0);
      }
    }
    rc = sqlite3_finalize(pTableInfo);
    if( rc!=SQLITE_OK ){
      if( zSelect ) free(zSelect);
      return 1;
    }
    zSelect = appendText(zSelect, "|| ')' FROM  ", 0);
    zSelect = appendText(zSelect, zTable, '"');

    rc = sqlite3_prepare(p->db, zSelect, -1, &pSelect, 0);
    if( zSelect ) free(zSelect);
    if( rc!=SQLITE_OK || !pSelect ){
      return 1;
    }

    rc = sqlite3_step(pSelect);
    while( rc==SQLITE_ROW ){
      fprintf(p->out, "%s;\n", sqlite3_column_text(pSelect, 0));
      rc = sqlite3_step(pSelect);
    }
    rc = sqlite3_finalize(pSelect);
    if( rc!=SQLITE_OK ){
      return 1;
    }
  }

  return 0;
}

/*
** Text of a help message
*/
static char zHelp[] =
................................................................................
    db = p->db;
#endif
    if( SQLITE_OK!=sqlite3_errcode(db) ){
      fprintf(stderr,"Unable to open database \"%s\": %s\n", 
          p->zDbFilename, sqlite3_errmsg(db));
      exit(1);
    }

    /* Add the 'dump_literal' SQL function used by .dump */
    sqlite3_create_function(db,"dump_literal",1,0,0,0,dump_literalFunc,0,0);
  }
}

/*
** If an input line begins with "." then invoke this routine to
** process that line.
**
................................................................................
      if( rc || zErrMsg ){
        if( in!=0 && !p->echoOn ) printf("%s\n",zSql);
        if( zErrMsg!=0 ){
          printf("SQL error: %s\n", zErrMsg);
          sqlite3_free(zErrMsg);
          zErrMsg = 0;
        }else{
          printf("SQL error: %s\n", sqlite3_errmsg(p->db));
        }
      }
      free(zSql);
      zSql = 0;
      nSql = 0;
    }
  }