/ Check-in [839a6df9]
Login

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

Overview
Comment:Fix the %c format character in sqlite3VXPrintf() so that it correctly handles precisions larger than 70.
Downloads: Tarball | ZIP archive | SQL archive
Timelines: family | ancestors | descendants | both | branch-3.8.7
Files: files | file ages | folders
SHA1: 839a6df9f98b90fb593534a62145d9c913540bae
User & Date: drh 2014-11-12 14:12:28
Context
2014-11-13
13:42
When a transaction or savepoint rollback occurs, save the positions of all open read-cursors so that they can be restored following the rollback operation. Cherry-pick of check-in [dd03a2802f3f27] check-in: 402780a9 user: drh tags: branch-3.8.7
2014-11-12
14:12
Fix the %c format character in sqlite3VXPrintf() so that it correctly handles precisions larger than 70. check-in: 839a6df9 user: drh tags: branch-3.8.7
14:07
Make sure that NULL results from OP_Column are fully and completely NULL and do not have the MEM_Ephem bit set. Fix for ticket [094d39a4c95ee4]. check-in: e1017745 user: drh tags: branch-3.8.7
2014-10-29
18:20
Fix the %c format character in sqlite3VXPrintf() so that it correctly handles precisions larger than 70. check-in: 08a27440 user: drh tags: trunk
Changes
Hide Diffs Unified Diffs Ignore Whitespace Patch

Changes to src/printf.c.

208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
...
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
...
616
617
618
619
620
621
622
623
624
625
626
627
628
629



630
631
632
633
634
635
636
...
723
724
725
726
727
728
729
730
731
732
733

734


735
736
737
738
739
740
741
...
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
  u8 useIntern;              /* Ok to use internal conversions (ex: %T) */
  char prefix;               /* Prefix character.  "+" or "-" or " " or '\0'. */
  sqlite_uint64 longvalue;   /* Value for integer types */
  LONGDOUBLE_TYPE realvalue; /* Value for real types */
  const et_info *infop;      /* Pointer to the appropriate info structure */
  char *zOut;                /* Rendering buffer */
  int nOut;                  /* Size of the rendering buffer */
  char *zExtra;              /* Malloced memory used by some conversion */
#ifndef SQLITE_OMIT_FLOATING_POINT
  int  exp, e2;              /* exponent of real numbers */
  int nsd;                   /* Number of significant digits returned */
  double rounder;            /* Used for rounding floating point values */
  etByte flag_dp;            /* True if decimal point should be shown */
  etByte flag_rtz;           /* True if trailing zeros should be removed */
#endif
................................................................................
          xtype = infop->type;
        }else{
          return;
        }
        break;
      }
    }
    zExtra = 0;

    /*
    ** At this point, variables are initialized as follows:
    **
    **   flag_alternateform          TRUE if a '#' is present.
    **   flag_altform2               TRUE if a '!' is present.
    **   flag_plussign               TRUE if a '+' is present.
................................................................................
      case etCHARX:
        if( bArgList ){
          bufpt = getTextArg(pArgList);
          c = bufpt ? bufpt[0] : 0;
        }else{
          c = va_arg(ap,int);
        }
        buf[0] = (char)c;
        if( precision>=0 ){
          for(idx=1; idx<precision; idx++) buf[idx] = (char)c;
          length = precision;
        }else{
          length =1;
        }



        bufpt = buf;
        break;
      case etSTRING:
      case etDYNSTRING:
        if( bArgList ){
          bufpt = getTextArg(pArgList);
        }else{
................................................................................
    }/* End switch over the format type */
    /*
    ** The text of the conversion is pointed to by "bufpt" and is
    ** "length" characters long.  The field width is "width".  Do
    ** the output.
    */
    width -= length;
    if( width>0 && !flag_leftjustify ) sqlite3AppendSpace(pAccum, width);
    sqlite3StrAccumAppend(pAccum, bufpt, length);
    if( width>0 && flag_leftjustify ) sqlite3AppendSpace(pAccum, width);


    if( zExtra ) sqlite3_free(zExtra);


  }/* End for loop over the format string */
} /* End of function */

/*
** Enlarge the memory allocation on a StrAccum object so that it is
** able to accept at least N more bytes of text.
**
................................................................................
      return 0;
    }
  }
  return N;
}

/*
** Append N space characters to the given string buffer.
*/
void sqlite3AppendSpace(StrAccum *p, int N){
  if( p->nChar+N >= p->nAlloc && (N = sqlite3StrAccumEnlarge(p, N))<=0 ) return;
  while( (N--)>0 ) p->zText[p->nChar++] = ' ';
}

/*
** The StrAccum "p" is not large enough to accept N new bytes of z[].
** So enlarge if first, then do the append.
**
** This is a helper routine to sqlite3StrAccumAppend() that does special-case







|







 







<







 







|
|
|
|
|
|
|
>
>
>







 







|

|

>
|
>
>







 







|

|

|







208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
...
325
326
327
328
329
330
331

332
333
334
335
336
337
338
...
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
...
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
...
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
  u8 useIntern;              /* Ok to use internal conversions (ex: %T) */
  char prefix;               /* Prefix character.  "+" or "-" or " " or '\0'. */
  sqlite_uint64 longvalue;   /* Value for integer types */
  LONGDOUBLE_TYPE realvalue; /* Value for real types */
  const et_info *infop;      /* Pointer to the appropriate info structure */
  char *zOut;                /* Rendering buffer */
  int nOut;                  /* Size of the rendering buffer */
  char *zExtra = 0;          /* Malloced memory used by some conversion */
#ifndef SQLITE_OMIT_FLOATING_POINT
  int  exp, e2;              /* exponent of real numbers */
  int nsd;                   /* Number of significant digits returned */
  double rounder;            /* Used for rounding floating point values */
  etByte flag_dp;            /* True if decimal point should be shown */
  etByte flag_rtz;           /* True if trailing zeros should be removed */
#endif
................................................................................
          xtype = infop->type;
        }else{
          return;
        }
        break;
      }
    }


    /*
    ** At this point, variables are initialized as follows:
    **
    **   flag_alternateform          TRUE if a '#' is present.
    **   flag_altform2               TRUE if a '!' is present.
    **   flag_plussign               TRUE if a '+' is present.
................................................................................
      case etCHARX:
        if( bArgList ){
          bufpt = getTextArg(pArgList);
          c = bufpt ? bufpt[0] : 0;
        }else{
          c = va_arg(ap,int);
        }
        if( precision>1 ){
          width -= precision-1;
          if( width>1 && !flag_leftjustify ){
            sqlite3AppendChar(pAccum, width-1, ' ');
            width = 0;
          }
          sqlite3AppendChar(pAccum, precision-1, c);
        }
        length = 1;
        buf[0] = c;
        bufpt = buf;
        break;
      case etSTRING:
      case etDYNSTRING:
        if( bArgList ){
          bufpt = getTextArg(pArgList);
        }else{
................................................................................
    }/* End switch over the format type */
    /*
    ** The text of the conversion is pointed to by "bufpt" and is
    ** "length" characters long.  The field width is "width".  Do
    ** the output.
    */
    width -= length;
    if( width>0 && !flag_leftjustify ) sqlite3AppendChar(pAccum, width, ' ');
    sqlite3StrAccumAppend(pAccum, bufpt, length);
    if( width>0 && flag_leftjustify ) sqlite3AppendChar(pAccum, width, ' ');

    if( zExtra ){
      sqlite3_free(zExtra);
      zExtra = 0;
    }
  }/* End for loop over the format string */
} /* End of function */

/*
** Enlarge the memory allocation on a StrAccum object so that it is
** able to accept at least N more bytes of text.
**
................................................................................
      return 0;
    }
  }
  return N;
}

/*
** Append N copies of character c to the given string buffer.
*/
void sqlite3AppendChar(StrAccum *p, int N, char c){
  if( p->nChar+N >= p->nAlloc && (N = sqlite3StrAccumEnlarge(p, N))<=0 ) return;
  while( (N--)>0 ) p->zText[p->nChar++] = c;
}

/*
** The StrAccum "p" is not large enough to accept N new bytes of z[].
** So enlarge if first, then do the append.
**
** This is a helper routine to sqlite3StrAccumAppend() that does special-case

Changes to src/sqliteInt.h.

3535
3536
3537
3538
3539
3540
3541
3542
3543
3544
3545
3546
3547
3548
3549
);
int sqlite3ApiExit(sqlite3 *db, int);
int sqlite3OpenTempDatabase(Parse *);

void sqlite3StrAccumInit(StrAccum*, char*, int, int);
void sqlite3StrAccumAppend(StrAccum*,const char*,int);
void sqlite3StrAccumAppendAll(StrAccum*,const char*);
void sqlite3AppendSpace(StrAccum*,int);
char *sqlite3StrAccumFinish(StrAccum*);
void sqlite3StrAccumReset(StrAccum*);
void sqlite3SelectDestInit(SelectDest*,int,int);
Expr *sqlite3CreateColumnExpr(sqlite3 *, SrcList *, int, int);

void sqlite3BackupRestart(sqlite3_backup *);
void sqlite3BackupUpdate(sqlite3_backup *, Pgno, const u8 *);







|







3535
3536
3537
3538
3539
3540
3541
3542
3543
3544
3545
3546
3547
3548
3549
);
int sqlite3ApiExit(sqlite3 *db, int);
int sqlite3OpenTempDatabase(Parse *);

void sqlite3StrAccumInit(StrAccum*, char*, int, int);
void sqlite3StrAccumAppend(StrAccum*,const char*,int);
void sqlite3StrAccumAppendAll(StrAccum*,const char*);
void sqlite3AppendChar(StrAccum*,int,char);
char *sqlite3StrAccumFinish(StrAccum*);
void sqlite3StrAccumReset(StrAccum*);
void sqlite3SelectDestInit(SelectDest*,int,int);
Expr *sqlite3CreateColumnExpr(sqlite3 *, SrcList *, int, int);

void sqlite3BackupRestart(sqlite3_backup *);
void sqlite3BackupUpdate(sqlite3_backup *, Pgno, const u8 *);

Changes to test/printf2.test.

90
91
92
93
94
95
96




















97
98
99
# argument list, missing arguments are assumed to have a NULL value,
# which is translated into 0 or 0.0 for numeric formats or an empty
# string for %s.
#
do_execsql_test printf2-2.3 {
  SELECT printf('%s=(%d/%g/%s)',a) FROM t1 ORDER BY a;
} {-1=(0/0/) 1=(0/0/) 1.5=(0/0/) abc=(0/0/)}






















finish_test







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



90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
# argument list, missing arguments are assumed to have a NULL value,
# which is translated into 0 or 0.0 for numeric formats or an empty
# string for %s.
#
do_execsql_test printf2-2.3 {
  SELECT printf('%s=(%d/%g/%s)',a) FROM t1 ORDER BY a;
} {-1=(0/0/) 1=(0/0/) 1.5=(0/0/) abc=(0/0/)}

# The precision of the %c conversion causes the character to repeat.
#
do_execsql_test printf2-3.1 {
  SELECT printf('|%110.100c|','*');
} {{|          ****************************************************************************************************|}}
do_execsql_test printf2-3.2 {
  SELECT printf('|%-110.100c|','*');
} {{|****************************************************************************************************          |}}
do_execsql_test printf2-3.3 {
  SELECT printf('|%9.8c|%-9.8c|','*','*');
} {{| ********|******** |}}
do_execsql_test printf2-3.4 {
  SELECT printf('|%8.8c|%-8.8c|','*','*');
} {|********|********|}
do_execsql_test printf2-3.5 {
  SELECT printf('|%7.8c|%-7.8c|','*','*');
} {|********|********|}




finish_test