1
0
mirror of https://github.com/sqlite/sqlite.git synced 2025-11-14 00:22:38 +03:00

Add the printf() SQL function.

FossilOrigin-Name: a1bb62f91a85af0584100c3ad77877a949c30cca
This commit is contained in:
drh
2013-12-17 16:10:57 +00:00
7 changed files with 207 additions and 43 deletions

View File

@@ -1,5 +1,5 @@
C Allow\sthe\sSQLITE_DETERMINISTIC\sflag\sto\sbe\sORed\sinto\sthe\spreferred\stext\sencoding\nof\sapplication-defined\sfunctions,\sto\smark\sthe\sfunction\sas\sdeterministic. C Add\sthe\sprintf()\sSQL\sfunction.
D 2013-12-14T13:44:22.886 D 2013-12-17T16:10:57.193
F Makefile.arm-wince-mingw32ce-gcc d6df77f1f48d690bd73162294bbba7f59507c72f F Makefile.arm-wince-mingw32ce-gcc d6df77f1f48d690bd73162294bbba7f59507c72f
F Makefile.in 2ef13430cd359f7b361bb863504e227b25cc7f81 F Makefile.in 2ef13430cd359f7b361bb863504e227b25cc7f81
F Makefile.linux-gcc 91d710bdc4998cb015f39edf3cb314ec4f4d7e23 F Makefile.linux-gcc 91d710bdc4998cb015f39edf3cb314ec4f4d7e23
@@ -178,7 +178,7 @@ F src/delete.c b36db1f79ee50eaca979660c9dd36437f5410b93
F src/expr.c 31a2b65339f6c3795d4cfa5e99798cd72f9fdfdf F src/expr.c 31a2b65339f6c3795d4cfa5e99798cd72f9fdfdf
F src/fault.c 160a0c015b6c2629d3899ed2daf63d75754a32bb F src/fault.c 160a0c015b6c2629d3899ed2daf63d75754a32bb
F src/fkey.c 2ab0f5384b70594468ef3ac5c7ed8ca24bfd17d5 F src/fkey.c 2ab0f5384b70594468ef3ac5c7ed8ca24bfd17d5
F src/func.c fed87f35cf4da4a798b726d84abefc209b48d831 F src/func.c 6325ac2ec10833ccf4d5c36d323709221d37ea19
F src/global.c 1d7bb7ea8254ae6a68ed9bfaf65fcb3d1690b486 F src/global.c 1d7bb7ea8254ae6a68ed9bfaf65fcb3d1690b486
F src/hash.c ac3470bbf1ca4ae4e306a8ecb0fdf1731810ffe4 F src/hash.c ac3470bbf1ca4ae4e306a8ecb0fdf1731810ffe4
F src/hash.h 8890a25af81fb85a9ad7790d32eedab4b994da22 F src/hash.h 8890a25af81fb85a9ad7790d32eedab4b994da22
@@ -215,7 +215,7 @@ F src/pcache.h a5e4f5d9f5d592051d91212c5949517971ae6222
F src/pcache1.c 57fee9a9a617218f5037afbbe49b09da65bde56b F src/pcache1.c 57fee9a9a617218f5037afbbe49b09da65bde56b
F src/pragma.c 5ab7279d132143feb77f773688a24ab05da75fd7 F src/pragma.c 5ab7279d132143feb77f773688a24ab05da75fd7
F src/prepare.c 359d1a1e9c9bd4488e4dd3a1aaaf2d2ebb9bb768 F src/prepare.c 359d1a1e9c9bd4488e4dd3a1aaaf2d2ebb9bb768
F src/printf.c ba8b28e9d4ce984430e9f33f6ef1c85a1826d1dd F src/printf.c 85d07756e45d7496d19439dcae3e6e9e0090f269
F src/random.c 0b2dbc37fdfbfa6bd455b091dfcef5bdb32dba68 F src/random.c 0b2dbc37fdfbfa6bd455b091dfcef5bdb32dba68
F src/resolve.c 7eda9097b29fcf3d2b42fdc17d1de672134e09b6 F src/resolve.c 7eda9097b29fcf3d2b42fdc17d1de672134e09b6
F src/rowset.c 64655f1a627c9c212d9ab497899e7424a34222e0 F src/rowset.c 64655f1a627c9c212d9ab497899e7424a34222e0
@@ -224,7 +224,7 @@ F src/shell.c 18924f6ccfa70da98bf9e388bab512c0fd1e792e
F src/sqlite.h.in 4ef56464aeaa3785a2c5ca37fb3a0fb229d68b2e F src/sqlite.h.in 4ef56464aeaa3785a2c5ca37fb3a0fb229d68b2e
F src/sqlite3.rc 11094cc6a157a028b301a9f06b3d03089ea37c3e F src/sqlite3.rc 11094cc6a157a028b301a9f06b3d03089ea37c3e
F src/sqlite3ext.h 886f5a34de171002ad46fae8c36a7d8051c190fc F src/sqlite3ext.h 886f5a34de171002ad46fae8c36a7d8051c190fc
F src/sqliteInt.h 3c1c14a551b019c94e1addcb67d92dd14a62e058 F src/sqliteInt.h b7e9da87740488671cfe4c70038a8eef3a1d317e
F src/sqliteLimit.h 164b0e6749d31e0daa1a4589a169d31c0dec7b3d F src/sqliteLimit.h 164b0e6749d31e0daa1a4589a169d31c0dec7b3d
F src/status.c 7ac05a5c7017d0b9f0b4bcd701228b784f987158 F src/status.c 7ac05a5c7017d0b9f0b4bcd701228b784f987158
F src/table.c 2cd62736f845d82200acfa1287e33feb3c15d62e F src/table.c 2cd62736f845d82200acfa1287e33feb3c15d62e
@@ -288,7 +288,7 @@ F src/vdbeaux.c a22cbd91b24503b82690cb03324ffec9f4ef63f6
F src/vdbeblob.c 8cd05a5630e6d5563ad017bf82edaf812b28acde F src/vdbeblob.c 8cd05a5630e6d5563ad017bf82edaf812b28acde
F src/vdbemem.c 0e69351b2c6ff7d8b638688c0ae336a26befa6b2 F src/vdbemem.c 0e69351b2c6ff7d8b638688c0ae336a26befa6b2
F src/vdbesort.c 9d83601f9d6243fe70dd0169a2820c5ddfd48147 F src/vdbesort.c 9d83601f9d6243fe70dd0169a2820c5ddfd48147
F src/vdbetrace.c f7eb148eb3b4fa3401b20024630dcb43d322e73c F src/vdbetrace.c 6f52bc0c51e144b7efdcfb2a8f771167a8816767
F src/vtab.c 21b932841e51ebd7d075e2d0ad1415dce8d2d5fd F src/vtab.c 21b932841e51ebd7d075e2d0ad1415dce8d2d5fd
F src/wal.c 7dc3966ef98b74422267e7e6e46e07ff6c6eb1b4 F src/wal.c 7dc3966ef98b74422267e7e6e46e07ff6c6eb1b4
F src/wal.h df01efe09c5cb8c8e391ff1715cca294f89668a4 F src/wal.h df01efe09c5cb8c8e391ff1715cca294f89668a4
@@ -739,6 +739,7 @@ F test/permutations.test af3278cbea3a19e025d5169be8193ff48dc3f862
F test/pragma.test e882183ecd21d064cec5c7aaea174fbd36293429 F test/pragma.test e882183ecd21d064cec5c7aaea174fbd36293429
F test/pragma2.test aea7b3d82c76034a2df2b38a13745172ddc0bc13 F test/pragma2.test aea7b3d82c76034a2df2b38a13745172ddc0bc13
F test/printf.test ec9870c4dce8686a37818e0bf1aba6e6a1863552 F test/printf.test ec9870c4dce8686a37818e0bf1aba6e6a1863552
F test/printf2.test 2f0978059768bb039d3ee09466bdcd06fc7a6a86
F test/progress.test a282973d1d17f08071bc58a77d6b80f2a81c354d F test/progress.test a282973d1d17f08071bc58a77d6b80f2a81c354d
F test/ptrchng.test ef1aa72d6cf35a2bbd0869a649b744e9d84977fc F test/ptrchng.test ef1aa72d6cf35a2bbd0869a649b744e9d84977fc
F test/queryonly.test 5f653159e0f552f0552d43259890c1089391dcca F test/queryonly.test 5f653159e0f552f0552d43259890c1089391dcca
@@ -1146,7 +1147,8 @@ F tool/vdbe-compress.tcl 0cf56e9263a152b84da86e75a5c0cdcdb7a47891
F tool/warnings-clang.sh f6aa929dc20ef1f856af04a730772f59283631d4 F tool/warnings-clang.sh f6aa929dc20ef1f856af04a730772f59283631d4
F tool/warnings.sh d1a6de74685f360ab718efda6265994b99bbea01 F tool/warnings.sh d1a6de74685f360ab718efda6265994b99bbea01
F tool/win/sqlite.vsix 030f3eeaf2cb811a3692ab9c14d021a75ce41fff F tool/win/sqlite.vsix 030f3eeaf2cb811a3692ab9c14d021a75ce41fff
P bc5febef921bd12ca7760e9d07d3be0e67140320 P 5716fc2341ddd8cf64139e7168597f864da4e10b 3375571a5e267744c19a7c310840256cec57a242
R 08fd6b0f6ffb77c364a2bec4efb57810 R 2f73ea36e182ebaad881490b3d78bb71
T +closed 3375571a5e267744c19a7c310840256cec57a242
U drh U drh
Z d2313ea9b793ebbfa6428f7e8b022d58 Z 3980fde025c24face9a02012ab95cda1

View File

@@ -1 +1 @@
5716fc2341ddd8cf64139e7168597f864da4e10b a1bb62f91a85af0584100c3ad77877a949c30cca

View File

@@ -218,6 +218,32 @@ static void instrFunc(
sqlite3_result_int(context, N); sqlite3_result_int(context, N);
} }
/*
** Implementation of the printf() function.
*/
static void printfFunc(
sqlite3_context *context,
int argc,
sqlite3_value **argv
){
PrintfArguments x;
StrAccum str;
const char *zFormat;
int n;
if( argc>=1 && (zFormat = (const char*)sqlite3_value_text(argv[0]))!=0 ){
x.nArg = argc-1;
x.nUsed = 0;
x.apArg = argv+1;
sqlite3StrAccumInit(&str, 0, 0, SQLITE_MAX_LENGTH);
str.db = sqlite3_context_db_handle(context);
sqlite3XPrintf(&str, SQLITE_PRINTF_SQLFUNC, zFormat, &x);
n = str.nChar;
sqlite3_result_text(context, sqlite3StrAccumFinish(&str), n,
SQLITE_DYNAMIC);
}
}
/* /*
** Implementation of the substr() function. ** Implementation of the substr() function.
** **
@@ -1648,6 +1674,7 @@ void sqlite3RegisterGlobalFunctions(void){
FUNCTION(instr, 2, 0, 0, instrFunc ), FUNCTION(instr, 2, 0, 0, instrFunc ),
FUNCTION(substr, 2, 0, 0, substrFunc ), FUNCTION(substr, 2, 0, 0, substrFunc ),
FUNCTION(substr, 3, 0, 0, substrFunc ), FUNCTION(substr, 3, 0, 0, substrFunc ),
FUNCTION(printf, -1, 0, 0, printfFunc ),
FUNCTION(unicode, 1, 0, 0, unicodeFunc ), FUNCTION(unicode, 1, 0, 0, unicodeFunc ),
FUNCTION(char, -1, 0, 0, charFunc ), FUNCTION(char, -1, 0, 0, charFunc ),
FUNCTION(abs, 1, 0, 0, absFunc ), FUNCTION(abs, 1, 0, 0, absFunc ),

View File

@@ -151,11 +151,28 @@ void sqlite3AppendSpace(StrAccum *pAccum, int N){
/* /*
** Set the StrAccum object to an error mode. ** Set the StrAccum object to an error mode.
*/ */
void setStrAccumError(StrAccum *p, u8 eError){ static void setStrAccumError(StrAccum *p, u8 eError){
p->accError = eError; p->accError = eError;
p->nAlloc = 0; p->nAlloc = 0;
} }
/*
** Extra argument values from a PrintfArguments object
*/
static sqlite3_int64 getIntArg(PrintfArguments *p){
if( p->nArg<=p->nUsed ) return 0;
return sqlite3_value_int64(p->apArg[p->nUsed++]);
}
static double getDoubleArg(PrintfArguments *p){
if( p->nArg<=p->nUsed ) return 0.0;
return sqlite3_value_double(p->apArg[p->nUsed++]);
}
static char *getTextArg(PrintfArguments *p){
if( p->nArg<=p->nUsed ) return 0;
return (char*)sqlite3_value_text(p->apArg[p->nUsed++]);
}
/* /*
** On machines with a small stack size, you can redefine the ** On machines with a small stack size, you can redefine the
** SQLITE_PRINT_BUF_SIZE to be something smaller, if desired. ** SQLITE_PRINT_BUF_SIZE to be something smaller, if desired.
@@ -169,10 +186,10 @@ void setStrAccumError(StrAccum *p, u8 eError){
** Render a string given by "fmt" into the StrAccum object. ** Render a string given by "fmt" into the StrAccum object.
*/ */
void sqlite3VXPrintf( void sqlite3VXPrintf(
StrAccum *pAccum, /* Accumulate results here */ StrAccum *pAccum, /* Accumulate results here */
int useExtended, /* Allow extended %-conversions */ u32 bFlags, /* SQLITE_PRINTF_* flags */
const char *fmt, /* Format string */ const char *fmt, /* Format string */
va_list ap /* arguments */ va_list ap /* arguments */
){ ){
int c; /* Next character in the format string */ int c; /* Next character in the format string */
char *bufpt; /* Pointer to the conversion buffer */ char *bufpt; /* Pointer to the conversion buffer */
@@ -190,6 +207,8 @@ void sqlite3VXPrintf(
etByte flag_longlong; /* True if the "ll" flag is present */ etByte flag_longlong; /* True if the "ll" flag is present */
etByte done; /* Loop termination flag */ etByte done; /* Loop termination flag */
etByte xtype = 0; /* Conversion paradigm */ etByte xtype = 0; /* Conversion paradigm */
u8 bArgList; /* True for SQLITE_PRINTF_SQLFUNC */
u8 useIntern; /* Ok to use internal conversions (ex: %T) */
char prefix; /* Prefix character. "+" or "-" or " " or '\0'. */ char prefix; /* Prefix character. "+" or "-" or " " or '\0'. */
sqlite_uint64 longvalue; /* Value for integer types */ sqlite_uint64 longvalue; /* Value for integer types */
LONGDOUBLE_TYPE realvalue; /* Value for real types */ LONGDOUBLE_TYPE realvalue; /* Value for real types */
@@ -204,9 +223,18 @@ void sqlite3VXPrintf(
etByte flag_dp; /* True if decimal point should be shown */ etByte flag_dp; /* True if decimal point should be shown */
etByte flag_rtz; /* True if trailing zeros should be removed */ etByte flag_rtz; /* True if trailing zeros should be removed */
#endif #endif
PrintfArguments *pArgList = 0; /* Arguments for SQLITE_PRINTF_SQLFUNC */
char buf[etBUFSIZE]; /* Conversion buffer */ char buf[etBUFSIZE]; /* Conversion buffer */
bufpt = 0; bufpt = 0;
if( bFlags ){
if( (bArgList = (bFlags & SQLITE_PRINTF_SQLFUNC))!=0 ){
pArgList = va_arg(ap, PrintfArguments*);
}
useIntern = bFlags & SQLITE_PRINTF_INTERNAL;
}else{
bArgList = useIntern = 0;
}
for(; (c=(*fmt))!=0; ++fmt){ for(; (c=(*fmt))!=0; ++fmt){
if( c!='%' ){ if( c!='%' ){
int amt; int amt;
@@ -238,7 +266,11 @@ void sqlite3VXPrintf(
/* Get the field width */ /* Get the field width */
width = 0; width = 0;
if( c=='*' ){ if( c=='*' ){
width = va_arg(ap,int); if( bArgList ){
width = (int)getIntArg(pArgList);
}else{
width = va_arg(ap,int);
}
if( width<0 ){ if( width<0 ){
flag_leftjustify = 1; flag_leftjustify = 1;
width = -width; width = -width;
@@ -255,7 +287,11 @@ void sqlite3VXPrintf(
precision = 0; precision = 0;
c = *++fmt; c = *++fmt;
if( c=='*' ){ if( c=='*' ){
precision = va_arg(ap,int); if( bArgList ){
precision = (int)getIntArg(pArgList);
}else{
precision = va_arg(ap,int);
}
if( precision<0 ) precision = -precision; if( precision<0 ) precision = -precision;
c = *++fmt; c = *++fmt;
}else{ }else{
@@ -286,7 +322,7 @@ void sqlite3VXPrintf(
for(idx=0; idx<ArraySize(fmtinfo); idx++){ for(idx=0; idx<ArraySize(fmtinfo); idx++){
if( c==fmtinfo[idx].fmttype ){ if( c==fmtinfo[idx].fmttype ){
infop = &fmtinfo[idx]; infop = &fmtinfo[idx];
if( useExtended || (infop->flags & FLAG_INTERN)==0 ){ if( useIntern || (infop->flags & FLAG_INTERN)==0 ){
xtype = infop->type; xtype = infop->type;
}else{ }else{
return; return;
@@ -326,7 +362,9 @@ void sqlite3VXPrintf(
case etRADIX: case etRADIX:
if( infop->flags & FLAG_SIGNED ){ if( infop->flags & FLAG_SIGNED ){
i64 v; i64 v;
if( flag_longlong ){ if( bArgList ){
v = getIntArg(pArgList);
}else if( flag_longlong ){
v = va_arg(ap,i64); v = va_arg(ap,i64);
}else if( flag_long ){ }else if( flag_long ){
v = va_arg(ap,long int); v = va_arg(ap,long int);
@@ -347,7 +385,9 @@ void sqlite3VXPrintf(
else prefix = 0; else prefix = 0;
} }
}else{ }else{
if( flag_longlong ){ if( bArgList ){
longvalue = (u64)getIntArg(pArgList);
}else if( flag_longlong ){
longvalue = va_arg(ap,u64); longvalue = va_arg(ap,u64);
}else if( flag_long ){ }else if( flag_long ){
longvalue = va_arg(ap,unsigned long int); longvalue = va_arg(ap,unsigned long int);
@@ -407,7 +447,11 @@ void sqlite3VXPrintf(
case etFLOAT: case etFLOAT:
case etEXP: case etEXP:
case etGENERIC: case etGENERIC:
realvalue = va_arg(ap,double); if( bArgList ){
realvalue = getDoubleArg(pArgList);
}else{
realvalue = va_arg(ap,double);
}
#ifdef SQLITE_OMIT_FLOATING_POINT #ifdef SQLITE_OMIT_FLOATING_POINT
length = 0; length = 0;
#else #else
@@ -562,7 +606,9 @@ void sqlite3VXPrintf(
#endif /* !defined(SQLITE_OMIT_FLOATING_POINT) */ #endif /* !defined(SQLITE_OMIT_FLOATING_POINT) */
break; break;
case etSIZE: case etSIZE:
*(va_arg(ap,int*)) = pAccum->nChar; if( !bArgList ){
*(va_arg(ap,int*)) = pAccum->nChar;
}
length = width = 0; length = width = 0;
break; break;
case etPERCENT: case etPERCENT:
@@ -571,7 +617,12 @@ void sqlite3VXPrintf(
length = 1; length = 1;
break; break;
case etCHARX: case etCHARX:
c = va_arg(ap,int); if( bArgList ){
bufpt = getTextArg(pArgList);
c = bufpt ? bufpt[0] : 0;
}else{
c = va_arg(ap,int);
}
buf[0] = (char)c; buf[0] = (char)c;
if( precision>=0 ){ if( precision>=0 ){
for(idx=1; idx<precision; idx++) buf[idx] = (char)c; for(idx=1; idx<precision; idx++) buf[idx] = (char)c;
@@ -583,10 +634,14 @@ void sqlite3VXPrintf(
break; break;
case etSTRING: case etSTRING:
case etDYNSTRING: case etDYNSTRING:
bufpt = va_arg(ap,char*); if( bArgList ){
bufpt = getTextArg(pArgList);
}else{
bufpt = va_arg(ap,char*);
}
if( bufpt==0 ){ if( bufpt==0 ){
bufpt = ""; bufpt = "";
}else if( xtype==etDYNSTRING ){ }else if( xtype==etDYNSTRING && !bArgList ){
zExtra = bufpt; zExtra = bufpt;
} }
if( precision>=0 ){ if( precision>=0 ){
@@ -602,7 +657,13 @@ void sqlite3VXPrintf(
int needQuote; int needQuote;
char ch; char ch;
char q = ((xtype==etSQLESCAPE3)?'"':'\''); /* Quote character */ char q = ((xtype==etSQLESCAPE3)?'"':'\''); /* Quote character */
char *escarg = va_arg(ap,char*); char *escarg;
if( bArgList ){
escarg = getTextArg(pArgList);
}else{
escarg = va_arg(ap,char*);
}
isnull = escarg==0; isnull = escarg==0;
if( isnull ) escarg = (xtype==etSQLESCAPE2 ? "NULL" : "(NULL)"); if( isnull ) escarg = (xtype==etSQLESCAPE2 ? "NULL" : "(NULL)");
k = precision; k = precision;
@@ -637,6 +698,7 @@ void sqlite3VXPrintf(
} }
case etTOKEN: { case etTOKEN: {
Token *pToken = va_arg(ap, Token*); Token *pToken = va_arg(ap, Token*);
assert( bArgList==0 );
if( pToken && pToken->n ){ if( pToken && pToken->n ){
sqlite3StrAccumAppend(pAccum, (const char*)pToken->z, pToken->n); sqlite3StrAccumAppend(pAccum, (const char*)pToken->z, pToken->n);
} }
@@ -647,6 +709,7 @@ void sqlite3VXPrintf(
SrcList *pSrc = va_arg(ap, SrcList*); SrcList *pSrc = va_arg(ap, SrcList*);
int k = va_arg(ap, int); int k = va_arg(ap, int);
struct SrcList_item *pItem = &pSrc->a[k]; struct SrcList_item *pItem = &pSrc->a[k];
assert( bArgList==0 );
assert( k>=0 && k<pSrc->nSrc ); assert( k>=0 && k<pSrc->nSrc );
if( pItem->zDatabase ){ if( pItem->zDatabase ){
sqlite3StrAccumAppendAll(pAccum, pItem->zDatabase); sqlite3StrAccumAppendAll(pAccum, pItem->zDatabase);
@@ -810,7 +873,7 @@ char *sqlite3VMPrintf(sqlite3 *db, const char *zFormat, va_list ap){
sqlite3StrAccumInit(&acc, zBase, sizeof(zBase), sqlite3StrAccumInit(&acc, zBase, sizeof(zBase),
db->aLimit[SQLITE_LIMIT_LENGTH]); db->aLimit[SQLITE_LIMIT_LENGTH]);
acc.db = db; acc.db = db;
sqlite3VXPrintf(&acc, 1, zFormat, ap); sqlite3VXPrintf(&acc, SQLITE_PRINTF_INTERNAL, zFormat, ap);
z = sqlite3StrAccumFinish(&acc); z = sqlite3StrAccumFinish(&acc);
if( acc.accError==STRACCUM_NOMEM ){ if( acc.accError==STRACCUM_NOMEM ){
db->mallocFailed = 1; db->mallocFailed = 1;
@@ -966,14 +1029,12 @@ void sqlite3DebugPrintf(const char *zFormat, ...){
} }
#endif #endif
#ifndef SQLITE_OMIT_TRACE
/* /*
** variable-argument wrapper around sqlite3VXPrintf(). ** variable-argument wrapper around sqlite3VXPrintf().
*/ */
void sqlite3XPrintf(StrAccum *p, const char *zFormat, ...){ void sqlite3XPrintf(StrAccum *p, u32 bFlags, const char *zFormat, ...){
va_list ap; va_list ap;
va_start(ap,zFormat); va_start(ap,zFormat);
sqlite3VXPrintf(p, 1, zFormat, ap); sqlite3VXPrintf(p, bFlags, zFormat, ap);
va_end(ap); va_end(ap);
} }
#endif

View File

@@ -742,6 +742,7 @@ typedef struct LookasideSlot LookasideSlot;
typedef struct Module Module; typedef struct Module Module;
typedef struct NameContext NameContext; typedef struct NameContext NameContext;
typedef struct Parse Parse; typedef struct Parse Parse;
typedef struct PrintfArguments PrintfArguments;
typedef struct RowSet RowSet; typedef struct RowSet RowSet;
typedef struct Savepoint Savepoint; typedef struct Savepoint Savepoint;
typedef struct Select Select; typedef struct Select Select;
@@ -2764,10 +2765,20 @@ void sqlite3StatusSet(int, int);
# define sqlite3IsNaN(X) 0 # define sqlite3IsNaN(X) 0
#endif #endif
void sqlite3VXPrintf(StrAccum*, int, const char*, va_list); /*
#ifndef SQLITE_OMIT_TRACE ** An instance of the following structure holds information about SQL
void sqlite3XPrintf(StrAccum*, const char*, ...); ** functions arguments that are the parameters to the printf() function.
#endif */
struct PrintfArguments {
int nArg; /* Total number of arguments */
int nUsed; /* Number of arguments used so far */
sqlite3_value **apArg; /* The argument values */
};
#define SQLITE_PRINTF_INTERNAL 0x01
#define SQLITE_PRINTF_SQLFUNC 0x02
void sqlite3VXPrintf(StrAccum*, u32, const char*, va_list);
void sqlite3XPrintf(StrAccum*, u32, const char*, ...);
char *sqlite3MPrintf(sqlite3*,const char*, ...); char *sqlite3MPrintf(sqlite3*,const char*, ...);
char *sqlite3VMPrintf(sqlite3*,const char*, va_list); char *sqlite3VMPrintf(sqlite3*,const char*, va_list);
char *sqlite3MAppendf(sqlite3*,char*,const char*,...); char *sqlite3MAppendf(sqlite3*,char*,const char*,...);

View File

@@ -125,9 +125,9 @@ char *sqlite3VdbeExpandSql(
if( pVar->flags & MEM_Null ){ if( pVar->flags & MEM_Null ){
sqlite3StrAccumAppend(&out, "NULL", 4); sqlite3StrAccumAppend(&out, "NULL", 4);
}else if( pVar->flags & MEM_Int ){ }else if( pVar->flags & MEM_Int ){
sqlite3XPrintf(&out, "%lld", pVar->u.i); sqlite3XPrintf(&out, 0, "%lld", pVar->u.i);
}else if( pVar->flags & MEM_Real ){ }else if( pVar->flags & MEM_Real ){
sqlite3XPrintf(&out, "%!.15g", pVar->r); sqlite3XPrintf(&out, 0, "%!.15g", pVar->r);
}else if( pVar->flags & MEM_Str ){ }else if( pVar->flags & MEM_Str ){
int nOut; /* Number of bytes of the string text to include in output */ int nOut; /* Number of bytes of the string text to include in output */
#ifndef SQLITE_OMIT_UTF16 #ifndef SQLITE_OMIT_UTF16
@@ -148,15 +148,17 @@ char *sqlite3VdbeExpandSql(
while( nOut<pVar->n && (pVar->z[nOut]&0xc0)==0x80 ){ nOut++; } while( nOut<pVar->n && (pVar->z[nOut]&0xc0)==0x80 ){ nOut++; }
} }
#endif #endif
sqlite3XPrintf(&out, "'%.*q'", nOut, pVar->z); sqlite3XPrintf(&out, 0, "'%.*q'", nOut, pVar->z);
#ifdef SQLITE_TRACE_SIZE_LIMIT #ifdef SQLITE_TRACE_SIZE_LIMIT
if( nOut<pVar->n ) sqlite3XPrintf(&out, "/*+%d bytes*/", pVar->n-nOut); if( nOut<pVar->n ){
sqlite3XPrintf(&out, 0, "/*+%d bytes*/", pVar->n-nOut);
}
#endif #endif
#ifndef SQLITE_OMIT_UTF16 #ifndef SQLITE_OMIT_UTF16
if( enc!=SQLITE_UTF8 ) sqlite3VdbeMemRelease(&utf8); if( enc!=SQLITE_UTF8 ) sqlite3VdbeMemRelease(&utf8);
#endif #endif
}else if( pVar->flags & MEM_Zero ){ }else if( pVar->flags & MEM_Zero ){
sqlite3XPrintf(&out, "zeroblob(%d)", pVar->u.nZero); sqlite3XPrintf(&out, 0, "zeroblob(%d)", pVar->u.nZero);
}else{ }else{
int nOut; /* Number of bytes of the blob to include in output */ int nOut; /* Number of bytes of the blob to include in output */
assert( pVar->flags & MEM_Blob ); assert( pVar->flags & MEM_Blob );
@@ -166,11 +168,13 @@ char *sqlite3VdbeExpandSql(
if( nOut>SQLITE_TRACE_SIZE_LIMIT ) nOut = SQLITE_TRACE_SIZE_LIMIT; if( nOut>SQLITE_TRACE_SIZE_LIMIT ) nOut = SQLITE_TRACE_SIZE_LIMIT;
#endif #endif
for(i=0; i<nOut; i++){ for(i=0; i<nOut; i++){
sqlite3XPrintf(&out, "%02x", pVar->z[i]&0xff); sqlite3XPrintf(&out, 0, "%02x", pVar->z[i]&0xff);
} }
sqlite3StrAccumAppend(&out, "'", 1); sqlite3StrAccumAppend(&out, "'", 1);
#ifdef SQLITE_TRACE_SIZE_LIMIT #ifdef SQLITE_TRACE_SIZE_LIMIT
if( nOut<pVar->n ) sqlite3XPrintf(&out, "/*+%d bytes*/", pVar->n-nOut); if( nOut<pVar->n ){
sqlite3XPrintf(&out, 0, "/*+%d bytes*/", pVar->n-nOut);
}
#endif #endif
} }
} }
@@ -229,7 +233,7 @@ void sqlite3ExplainPrintf(Vdbe *pVdbe, const char *zFormat, ...){
sqlite3AppendSpace(&p->str, p->aIndent[n-1]); sqlite3AppendSpace(&p->str, p->aIndent[n-1]);
} }
va_start(ap, zFormat); va_start(ap, zFormat);
sqlite3VXPrintf(&p->str, 1, zFormat, ap); sqlite3VXPrintf(&p->str, SQLITE_PRINTF_INTERNAL, zFormat, ap);
va_end(ap); va_end(ap);
} }
} }

59
test/printf2.test Normal file
View File

@@ -0,0 +1,59 @@
# 2013-12-17
#
# The author disclaims copyright to this source code. In place of
# a legal notice, here is a blessing:
#
# May you do good and not evil.
# May you find forgiveness for yourself and forgive others.
# May you share freely, never taking more than you give.
#
#***********************************************************************
# This file implements regression tests for SQLite library. The
# focus of this file is testing the printf() SQL function.
#
set testdir [file dirname $argv0]
source $testdir/tester.tcl
do_execsql_test printf2-1.1 {
SELECT printf();
} {{}}
do_execsql_test printf2-1.2 {
SELECT printf('hello');
} {hello}
do_execsql_test printf2-1.3 {
SELECT printf('%d,%d,%d',55,-11,3421);
} {55,-11,3421}
do_execsql_test printf2-1.4 {
SELECT printf('%d,%d,%d',55,'-11',3421);
} {55,-11,3421}
do_execsql_test printf2-1.5 {
SELECT printf('%d,%d,%d,%d',55,'-11',3421);
} {55,-11,3421,0}
do_execsql_test printf2-1.6 {
SELECT printf('%.2f',3.141592653);
} {3.14}
do_execsql_test printf2-1.7 {
SELECT printf('%.*f',2,3.141592653);
} {3.14}
do_execsql_test printf2-1.8 {
SELECT printf('%*.*f',5,2,3.141592653);
} {{ 3.14}}
do_execsql_test printf2-1.9 {
SELECT printf('%d',314159.2653);
} {314159}
do_execsql_test printf2-1.10 {
SELECT printf('%lld',314159.2653);
} {314159}
do_execsql_test printf2-1.11 {
SELECT printf('%lld%n',314159.2653,'hi');
} {314159}
do_execsql_test printf2-1.12 {
SELECT printf('%.*z',5,'abcdefghijklmnop');
} {abcde}
do_execsql_test printf2-1.13 {
SELECT printf('%c','abcdefghijklmnop');
} {a}
finish_test