SQLite

Check-in [eca1398eaa]
Login

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

Overview
Comment:Add the %z format to the sqlite_mprintf() and related functions. (CVS 1028)
Downloads: Tarball | ZIP archive
Timelines: family | ancestors | descendants | both | trunk
Files: files | file ages | folders
SHA1: eca1398eaac67d772aff2676a470d9a6d96a93ca
User & Date: drh 2003-06-16 03:08:19.000
Context
2003-06-16
19:18
Fix compiler errors and warnings win SQLITE_OMIT_AUTHORIZATION is defined. Ticket #353. (CVS 1029) (check-in: 6920b633c2 user: drh tags: trunk)
03:08
Add the %z format to the sqlite_mprintf() and related functions. (CVS 1028) (check-in: eca1398eaa user: drh tags: trunk)
00:40
Do not flatten a subquery which is the right term of a LEFT OUTER JOIN if the subquery contains a WHERE clause. Ticket #350. (CVS 1027) (check-in: dd8943e858 user: drh tags: trunk)
Changes
Unified Diff Ignore Whitespace Patch
Changes to src/printf.c.
62
63
64
65
66
67
68

69
70
71
72
73
74
75
enum et_type {    /* The type of the format field */
   etRADIX,            /* Integer types.  %d, %x, %o, and so forth */
   etFLOAT,            /* Floating point.  %f */
   etEXP,              /* Exponentional notation. %e and %E */
   etGENERIC,          /* Floating or exponential, depending on exponent. %g */
   etSIZE,             /* Return number of characters processed so far. %n */
   etSTRING,           /* Strings. %s */

   etPERCENT,          /* Percent symbol. %% */
   etCHARX,            /* Characters. %c */
   etERROR,            /* Used to indicate no such conversion type */
/* The rest are extensions, not normally found in printf() */
   etCHARLIT,          /* Literal characters.  %' */
   etSQLESCAPE,        /* Strings with '\'' doubled.  %q */
   etSQLESCAPE2,       /* Strings with '\'' doubled and enclosed in '',







>







62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
enum et_type {    /* The type of the format field */
   etRADIX,            /* Integer types.  %d, %x, %o, and so forth */
   etFLOAT,            /* Floating point.  %f */
   etEXP,              /* Exponentional notation. %e and %E */
   etGENERIC,          /* Floating or exponential, depending on exponent. %g */
   etSIZE,             /* Return number of characters processed so far. %n */
   etSTRING,           /* Strings. %s */
   etDYNSTRING,        /* Dynamically allocated strings. %z */
   etPERCENT,          /* Percent symbol. %% */
   etCHARX,            /* Characters. %c */
   etERROR,            /* Used to indicate no such conversion type */
/* The rest are extensions, not normally found in printf() */
   etCHARLIT,          /* Literal characters.  %' */
   etSQLESCAPE,        /* Strings with '\'' doubled.  %q */
   etSQLESCAPE2,       /* Strings with '\'' doubled and enclosed in '',
93
94
95
96
97
98
99

100
101
102
103
104
105
106
/*
** The following table is searched linearly, so it is good to put the
** most frequently used conversion types first.
*/
static et_info fmtinfo[] = {
  { 'd',  10,  "0123456789",       1,    0, etRADIX,      },
  { 's',   0,  0,                  0,    0, etSTRING,     }, 

  { 'q',   0,  0,                  0,    0, etSQLESCAPE,  },
  { 'Q',   0,  0,                  0,    0, etSQLESCAPE2, },
  { 'c',   0,  0,                  0,    0, etCHARX,      },
  { 'o',   8,  "01234567",         0,  "0", etRADIX,      },
  { 'u',  10,  "0123456789",       0,    0, etRADIX,      },
  { 'x',  16,  "0123456789abcdef", 0, "x0", etRADIX,      },
  { 'X',  16,  "0123456789ABCDEF", 0, "X0", etRADIX,      },







>







94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
/*
** The following table is searched linearly, so it is good to put the
** most frequently used conversion types first.
*/
static et_info fmtinfo[] = {
  { 'd',  10,  "0123456789",       1,    0, etRADIX,      },
  { 's',   0,  0,                  0,    0, etSTRING,     }, 
  { 'z',   0,  0,                  0,    0, etDYNSTRING,  }, 
  { 'q',   0,  0,                  0,    0, etSQLESCAPE,  },
  { 'Q',   0,  0,                  0,    0, etSQLESCAPE2, },
  { 'c',   0,  0,                  0,    0, etCHARX,      },
  { 'o',   8,  "01234567",         0,  "0", etRADIX,      },
  { 'u',  10,  "0123456789",       0,    0, etRADIX,      },
  { 'x',  16,  "0123456789abcdef", 0, "x0", etRADIX,      },
  { 'X',  16,  "0123456789ABCDEF", 0, "X0", etRADIX,      },
545
546
547
548
549
550
551

552
553




554
555
556
557
558
559
560
          length = precision;
        }else{
          length =1;
        }
        bufpt = buf;
        break;
      case etSTRING:

        bufpt = va_arg(ap,char*);
        if( bufpt==0 ) bufpt = "(null)";




        length = strlen(bufpt);
        if( precision>=0 && precision<length ) length = precision;
        break;
      case etSQLESCAPE:
      case etSQLESCAPE2:
        {
          int i, j, n, c, isnull;







>

|
>
>
>
>







547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
          length = precision;
        }else{
          length =1;
        }
        bufpt = buf;
        break;
      case etSTRING:
      case etDYNSTRING:
        bufpt = va_arg(ap,char*);
        if( bufpt==0 ){
          bufpt = "";
        }else if( xtype==etDYNSTRING ){
          zExtra = bufpt;
        }
        length = strlen(bufpt);
        if( precision>=0 && precision<length ) length = precision;
        break;
      case etSQLESCAPE:
      case etSQLESCAPE2:
        {
          int i, j, n, c, isnull;
628
629
630
631
632
633
634



635

636
637
638
639
640
641
642
          (*func)(arg,spaces,etSPACESIZE);
          nspace -= etSPACESIZE;
        }
        if( nspace>0 ) (*func)(arg,spaces,nspace);
      }
    }
    if( zExtra ){



      sqliteFree(zExtra);

    }
  }/* End for loop over the format string */
  return errorflag ? -1 : count;
} /* End of function */


/* This structure is used to store state information about the







>
>
>
|
>







635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
          (*func)(arg,spaces,etSPACESIZE);
          nspace -= etSPACESIZE;
        }
        if( nspace>0 ) (*func)(arg,spaces,nspace);
      }
    }
    if( zExtra ){
      if( xtype==etDYNSTRING ){
        free(zExtra);
      }else{
        sqliteFree(zExtra);
      }
    }
  }/* End for loop over the format string */
  return errorflag ? -1 : count;
} /* End of function */


/* This structure is used to store state information about the
Changes to src/test1.c.
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
**    May you share freely, never taking more than you give.
**
*************************************************************************
** Code for testing the printf() interface to SQLite.  This code
** is not included in the SQLite library.  It is used for automated
** testing of the SQLite library.
**
** $Id: test1.c,v 1.24 2003/04/26 13:19:39 drh Exp $
*/
#include "sqliteInt.h"
#include "tcl.h"
#include "os.h"
#include <stdlib.h>
#include <string.h>








|







9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
**    May you share freely, never taking more than you give.
**
*************************************************************************
** Code for testing the printf() interface to SQLite.  This code
** is not included in the SQLite library.  It is used for automated
** testing of the SQLite library.
**
** $Id: test1.c,v 1.25 2003/06/16 03:08:19 drh Exp $
*/
#include "sqliteInt.h"
#include "tcl.h"
#include "os.h"
#include <stdlib.h>
#include <string.h>

156
157
158
159
160
161
162
























163
164
165
166
167
168
169
  sprintf(zBuf, "%d", rc);
  Tcl_AppendElement(interp, zBuf);
  Tcl_AppendElement(interp, rc==SQLITE_OK ? Tcl_DStringValue(&str) : zErr);
  Tcl_DStringFree(&str);
  if( zErr ) free(zErr);
  return TCL_OK;
}

























/*
** Usage:  sqlite_get_table_printf  DB  FORMAT  STRING
**
** Invoke the sqlite_get_table_printf() interface using the open database
** DB.  The SQL is the string FORMAT.  The format string should contain
** one %s or %q.  STRING is the value inserted into %s or %q.







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







156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
  sprintf(zBuf, "%d", rc);
  Tcl_AppendElement(interp, zBuf);
  Tcl_AppendElement(interp, rc==SQLITE_OK ? Tcl_DStringValue(&str) : zErr);
  Tcl_DStringFree(&str);
  if( zErr ) free(zErr);
  return TCL_OK;
}

/*
** Usage:  sqlite_mprintf_z_test  SEPARATOR  ARG0  ARG1 ...
**
** Test the %z format of mprintf().  Use multiple mprintf() calls to 
** concatenate arg0 through argn using separator as the separator.
** Return the result.
*/
static int test_mprintf_z(
  void *NotUsed,
  Tcl_Interp *interp,    /* The TCL interpreter that invoked this command */
  int argc,              /* Number of arguments */
  char **argv            /* Text of each argument */
){
  char *zResult = 0;
  int i;

  for(i=2; i<argc; i++){
    zResult = sqlite_mprintf("%z%s%s", zResult, argv[1], argv[i]);
  }
  Tcl_AppendResult(interp, zResult, 0);
  sqlite_freemem(zResult);
  return TCL_OK;
}

/*
** Usage:  sqlite_get_table_printf  DB  FORMAT  STRING
**
** Invoke the sqlite_get_table_printf() interface using the open database
** DB.  The SQL is the string FORMAT.  The format string should contain
** one %s or %q.  STRING is the value inserted into %s or %q.
775
776
777
778
779
780
781

782
783
784
785
786
787
788
  static struct {
     char *zName;
     Tcl_CmdProc *xProc;
  } aCmd[] = {
     { "sqlite_mprintf_int",             (Tcl_CmdProc*)sqlite_mprintf_int    },
     { "sqlite_mprintf_str",             (Tcl_CmdProc*)sqlite_mprintf_str    },
     { "sqlite_mprintf_double",          (Tcl_CmdProc*)sqlite_mprintf_double },

     { "sqlite_open",                    (Tcl_CmdProc*)sqlite_test_open      },
     { "sqlite_last_insert_rowid",       (Tcl_CmdProc*)test_last_rowid       },
     { "sqlite_exec_printf",             (Tcl_CmdProc*)test_exec_printf      },
     { "sqlite_get_table_printf",        (Tcl_CmdProc*)test_get_table_printf },
     { "sqlite_close",                   (Tcl_CmdProc*)sqlite_test_close     },
     { "sqlite_create_function",         (Tcl_CmdProc*)test_create_function  },
     { "sqlite_create_aggregate",        (Tcl_CmdProc*)test_create_aggregate },







>







799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
  static struct {
     char *zName;
     Tcl_CmdProc *xProc;
  } aCmd[] = {
     { "sqlite_mprintf_int",             (Tcl_CmdProc*)sqlite_mprintf_int    },
     { "sqlite_mprintf_str",             (Tcl_CmdProc*)sqlite_mprintf_str    },
     { "sqlite_mprintf_double",          (Tcl_CmdProc*)sqlite_mprintf_double },
     { "sqlite_mprintf_z_test",          (Tcl_CmdProc*)test_mprintf_z        },
     { "sqlite_open",                    (Tcl_CmdProc*)sqlite_test_open      },
     { "sqlite_last_insert_rowid",       (Tcl_CmdProc*)test_last_rowid       },
     { "sqlite_exec_printf",             (Tcl_CmdProc*)test_exec_printf      },
     { "sqlite_get_table_printf",        (Tcl_CmdProc*)test_get_table_printf },
     { "sqlite_close",                   (Tcl_CmdProc*)sqlite_test_close     },
     { "sqlite_create_function",         (Tcl_CmdProc*)test_create_function  },
     { "sqlite_create_aggregate",        (Tcl_CmdProc*)test_create_aggregate },
Changes to test/printf.test.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
# 2001 September 15
#
# 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 sqlite_*_printf() interface.
#
# $Id: printf.test,v 1.5 2002/06/16 04:56:37 chw Exp $

set testdir [file dirname $argv0]
source $testdir/tester.tcl

set n 1
foreach v {1 2 5 10 99 100 1000000 999999999 0 -1 -2 -5 -10 -99 -100 -9999999} {
  do_test printf-1.$n.1 [subst {













|







1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
# 2001 September 15
#
# 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 sqlite_*_printf() interface.
#
# $Id: printf.test,v 1.6 2003/06/16 03:08:19 drh Exp $

set testdir [file dirname $argv0]
source $testdir/tester.tcl

set n 1
foreach v {1 2 5 10 99 100 1000000 999999999 0 -1 -2 -5 -10 -99 -100 -9999999} {
  do_test printf-1.$n.1 [subst {
107
108
109
110
111
112
113




114
do_test printf-5.2 {
  sqlite_mprintf_str {%d %d (%-10.10s) %} -9 -10 {HelloHelloHello}
} {-9 -10 (HelloHello) %}
do_test printf-5.3 {
  sqlite_mprintf_str {%% %d %d (%=10s)} 5 6 Hello
} {% 5 6 (  Hello   )}





finish_test







>
>
>
>

107
108
109
110
111
112
113
114
115
116
117
118
do_test printf-5.2 {
  sqlite_mprintf_str {%d %d (%-10.10s) %} -9 -10 {HelloHelloHello}
} {-9 -10 (HelloHello) %}
do_test printf-5.3 {
  sqlite_mprintf_str {%% %d %d (%=10s)} 5 6 Hello
} {% 5 6 (  Hello   )}

do_test printf-6.1 {
  sqlite_mprintf_z_test , one two three four five six
} {,one,two,three,four,five,six}

finish_test