mirror of
https://github.com/sqlite/sqlite.git
synced 2025-11-06 15:49:35 +03:00
Ensure blob values survive the ".dump" command of the shell. (CVS 1531)
FossilOrigin-Name: e82eb722b0e0b223ddaf7d85669792c33594f9da
This commit is contained in:
2
main.mk
2
main.mk
@@ -60,7 +60,7 @@ LIBOBJ = attach.o auth.o btree.o build.o date.o delete.o \
|
|||||||
pager.o parse.o pragma.o printf.o random.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 \
|
select.o table.o tokenize.o trigger.o update.o util.o vacuum.o \
|
||||||
vdbe.o vdbeapi.o vdbeaux.o vdbemem.o \
|
vdbe.o vdbeapi.o vdbeaux.o vdbemem.o \
|
||||||
where.o tclsqlite.o utf.o legacy.o
|
where.o utf.o legacy.o
|
||||||
|
|
||||||
# All of the source code files.
|
# All of the source code files.
|
||||||
#
|
#
|
||||||
|
|||||||
18
manifest
18
manifest
@@ -1,5 +1,5 @@
|
|||||||
C Critical\sbugs\sfixed\sin\sbtree.c.\s\sIncompatible\sfile\sformat\schange.\s\sUnrelated\ncomment\sfix\sin\sselect.c\s(CVS\s1530)
|
C Ensure\sblob\svalues\ssurvive\sthe\s".dump"\scommand\sof\sthe\sshell.\s(CVS\s1531)
|
||||||
D 2004-06-05T00:01:45
|
D 2004-06-05T08:04:36
|
||||||
F Makefile.in ab7b0d5118e2da97bac66be8684a1034e3500f5a
|
F Makefile.in ab7b0d5118e2da97bac66be8684a1034e3500f5a
|
||||||
F Makefile.linux-gcc b86a99c493a5bfb402d1d9178dcdc4bd4b32f906
|
F Makefile.linux-gcc b86a99c493a5bfb402d1d9178dcdc4bd4b32f906
|
||||||
F README f1de682fbbd94899d50aca13d387d1b3fd3be2dd
|
F README f1de682fbbd94899d50aca13d387d1b3fd3be2dd
|
||||||
@@ -16,7 +16,7 @@ F doc/lemon.html f0f682f50210928c07e562621c3b7e8ab912a538
|
|||||||
F doc/report1.txt a031aaf37b185e4fa540223cb516d3bccec7eeac
|
F doc/report1.txt a031aaf37b185e4fa540223cb516d3bccec7eeac
|
||||||
F install-sh 9d4de14ab9fb0facae2f48780b874848cbf2f895
|
F install-sh 9d4de14ab9fb0facae2f48780b874848cbf2f895
|
||||||
F ltmain.sh f6b283068efa69f06eb8aa1fe4bddfdbdeb35826
|
F ltmain.sh f6b283068efa69f06eb8aa1fe4bddfdbdeb35826
|
||||||
F main.mk b717f9861a3acdd3a4e81fc59731a393bf6a0c6e
|
F main.mk 126f1ca2190fa19cc9944f54943cf3431891c330
|
||||||
F mkdll.sh 68d34a961a1fdfa15ef27fc4f4740be583112124
|
F mkdll.sh 68d34a961a1fdfa15ef27fc4f4740be583112124
|
||||||
F publish.sh 2e579b7474d57b6debcead93c73a49eb8cb81718
|
F publish.sh 2e579b7474d57b6debcead93c73a49eb8cb81718
|
||||||
F spec.template a38492f1c1dd349fc24cb0565e08afc53045304b
|
F spec.template a38492f1c1dd349fc24cb0565e08afc53045304b
|
||||||
@@ -45,7 +45,7 @@ F src/os_mac.c b823874690615ace0dd520d3ad1fe8bfd864b7e0
|
|||||||
F src/os_mac.h 51d2445f47e182ed32d3bd6937f81070c6fd9bd4
|
F src/os_mac.h 51d2445f47e182ed32d3bd6937f81070c6fd9bd4
|
||||||
F src/os_unix.c a4feb70b23fa5272f53cd2c74588484b54294800
|
F src/os_unix.c a4feb70b23fa5272f53cd2c74588484b54294800
|
||||||
F src/os_unix.h 7999f2246c6347707e98f7078871ea8ca605df3f
|
F src/os_unix.h 7999f2246c6347707e98f7078871ea8ca605df3f
|
||||||
F src/os_win.c 92b51a38437b98d8aa3ac05b57c71e1d1092e5be
|
F src/os_win.c 0f895f0491a983740c08af8e5d1986f3bc4629a4
|
||||||
F src/os_win.h 5d41af24caaef6c13a2d8e2399caa1c57d45c84d
|
F src/os_win.h 5d41af24caaef6c13a2d8e2399caa1c57d45c84d
|
||||||
F src/pager.c 944f6b071279887574081281f27bb2af88b42905
|
F src/pager.c 944f6b071279887574081281f27bb2af88b42905
|
||||||
F src/pager.h 0c7b5ac45c69e690c45d160d03bdc8fbd2d4657b
|
F src/pager.h 0c7b5ac45c69e690c45d160d03bdc8fbd2d4657b
|
||||||
@@ -54,7 +54,7 @@ F src/pragma.c 1b58d852b84b36a8b84e2245dd29b63c377414ec
|
|||||||
F src/printf.c ef750e8e2398ca7e8b58be991075f08c6a7f0e53
|
F src/printf.c ef750e8e2398ca7e8b58be991075f08c6a7f0e53
|
||||||
F src/random.c eff68e3f257e05e81eae6c4d50a51eb88beb4ff3
|
F src/random.c eff68e3f257e05e81eae6c4d50a51eb88beb4ff3
|
||||||
F src/select.c 02d711160100ef3a730060f7cfb5bc85fde06d72
|
F src/select.c 02d711160100ef3a730060f7cfb5bc85fde06d72
|
||||||
F src/shell.c a9e2ad8f6c1d39b04bad61a0ec655e9a3a360b50
|
F src/shell.c 79af86d39b2149c7f16219fcbe636e7c2da9df8e
|
||||||
F src/sqlite.h.in 8236db65bc6d8f5f47dc5a5e86c4a9bce42f2adf
|
F src/sqlite.h.in 8236db65bc6d8f5f47dc5a5e86c4a9bce42f2adf
|
||||||
F src/sqliteInt.h 99f2b4ff4ed28123890a0c71359fec3d2c5901c9
|
F src/sqliteInt.h 99f2b4ff4ed28123890a0c71359fec3d2c5901c9
|
||||||
F src/table.c af14284fa36c8d41f6829e3f2819dce07d3e2de2
|
F src/table.c af14284fa36c8d41f6829e3f2819dce07d3e2de2
|
||||||
@@ -215,7 +215,7 @@ F www/support.tcl 1801397edd271cc39a2aadd54e701184b5181248
|
|||||||
F www/tclsqlite.tcl 19191cf2a1010eaeff74c51d83fd5f5a4d899075
|
F www/tclsqlite.tcl 19191cf2a1010eaeff74c51d83fd5f5a4d899075
|
||||||
F www/vdbe.tcl 59288db1ac5c0616296b26dce071c36cb611dfe9
|
F www/vdbe.tcl 59288db1ac5c0616296b26dce071c36cb611dfe9
|
||||||
F www/whentouse.tcl a8335bce47cc2fddb07f19052cb0cb4d9129a8e4
|
F www/whentouse.tcl a8335bce47cc2fddb07f19052cb0cb4d9129a8e4
|
||||||
P d2f69e5ef2f261a00bb8427a4e2a1638ecfd17a9
|
P cb1ffabf86996ab20dfffcb5f133fa9a9b56bbe2
|
||||||
R eb52d3018295ee3de4004fb563723044
|
R ea7bd988d55c4ea96c95b0dedf76ecab
|
||||||
U drh
|
U danielk1977
|
||||||
Z ceec225131100608a50f7e5d2660779f
|
Z 4e22795b8cf7e800bcb3f1d60cd6c40a
|
||||||
|
|||||||
@@ -1 +1 @@
|
|||||||
cb1ffabf86996ab20dfffcb5f133fa9a9b56bbe2
|
e82eb722b0e0b223ddaf7d85669792c33594f9da
|
||||||
@@ -370,6 +370,14 @@ int isNT(void){
|
|||||||
#define N_LOCKBYTE 10239
|
#define N_LOCKBYTE 10239
|
||||||
#define FIRST_LOCKBYTE (0xffffffff - N_LOCKBYTE)
|
#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.
|
** 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 write locked, then this reduces the lock to a read.
|
||||||
|
|||||||
208
src/shell.c
208
src/shell.c
@@ -12,11 +12,12 @@
|
|||||||
** This file contains code to implement the "sqlite" command line
|
** This file contains code to implement the "sqlite" command line
|
||||||
** utility for accessing SQLite databases.
|
** utility for accessing SQLite databases.
|
||||||
**
|
**
|
||||||
** $Id: shell.c,v 1.101 2004/05/31 23:56:43 danielk1977 Exp $
|
** $Id: shell.c,v 1.102 2004/06/05 08:04:44 danielk1977 Exp $
|
||||||
*/
|
*/
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
|
#include <assert.h>
|
||||||
#include "sqlite3.h"
|
#include "sqlite3.h"
|
||||||
#include <ctype.h>
|
#include <ctype.h>
|
||||||
|
|
||||||
@@ -444,6 +445,125 @@ static void set_table_name(struct callback_data *p, const char *zName){
|
|||||||
z[n] = 0;
|
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.
|
** This is a different callback routine used for dumping the database.
|
||||||
** Each row received by this callback consists of a table name,
|
** Each row received by this callback consists of a table name,
|
||||||
@@ -451,21 +571,78 @@ static void set_table_name(struct callback_data *p, const char *zName){
|
|||||||
** This routine should print text sufficient to recreate the table.
|
** This routine should print text sufficient to recreate the table.
|
||||||
*/
|
*/
|
||||||
static int dump_callback(void *pArg, int nArg, char **azArg, char **azCol){
|
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;
|
struct callback_data *p = (struct callback_data *)pArg;
|
||||||
|
|
||||||
if( nArg!=3 ) return 1;
|
if( nArg!=3 ) return 1;
|
||||||
fprintf(p->out, "%s;\n", azArg[2]);
|
zTable = azArg[0];
|
||||||
if( strcmp(azArg[1],"table")==0 ){
|
zType = azArg[1];
|
||||||
struct callback_data d2;
|
zSql = azArg[2];
|
||||||
d2 = *p;
|
|
||||||
d2.mode = MODE_Insert;
|
fprintf(p->out, "%s;\n", zSql);
|
||||||
d2.zDestTable = 0;
|
|
||||||
set_table_name(&d2, azArg[0]);
|
if( strcmp(zType, "table")==0 ){
|
||||||
sqlite3_exec_printf(p->db,
|
sqlite3_stmt *pTableInfo = 0;
|
||||||
"SELECT * FROM '%q'",
|
sqlite3_stmt *pSelect = 0;
|
||||||
callback, &d2, 0, azArg[0]
|
char *zSelect = 0;
|
||||||
);
|
char *zTableInfo = 0;
|
||||||
set_table_name(&d2, 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;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -523,6 +700,9 @@ static void open_db(struct callback_data *p){
|
|||||||
p->zDbFilename, sqlite3_errmsg(db));
|
p->zDbFilename, sqlite3_errmsg(db));
|
||||||
exit(1);
|
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);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1063,7 +1243,7 @@ static void process_input(struct callback_data *p, FILE *in){
|
|||||||
sqlite3_free(zErrMsg);
|
sqlite3_free(zErrMsg);
|
||||||
zErrMsg = 0;
|
zErrMsg = 0;
|
||||||
}else{
|
}else{
|
||||||
printf("SQL error: %s\n", sqlite3ErrStr(rc));
|
printf("SQL error: %s\n", sqlite3_errmsg(p->db));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
free(zSql);
|
free(zSql);
|
||||||
|
|||||||
Reference in New Issue
Block a user