/ 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 Side-by-Side Diffs Ignore Whitespace Patch

Changes to src/printf.c.

   208    208     u8 useIntern;              /* Ok to use internal conversions (ex: %T) */
   209    209     char prefix;               /* Prefix character.  "+" or "-" or " " or '\0'. */
   210    210     sqlite_uint64 longvalue;   /* Value for integer types */
   211    211     LONGDOUBLE_TYPE realvalue; /* Value for real types */
   212    212     const et_info *infop;      /* Pointer to the appropriate info structure */
   213    213     char *zOut;                /* Rendering buffer */
   214    214     int nOut;                  /* Size of the rendering buffer */
   215         -  char *zExtra;              /* Malloced memory used by some conversion */
          215  +  char *zExtra = 0;          /* Malloced memory used by some conversion */
   216    216   #ifndef SQLITE_OMIT_FLOATING_POINT
   217    217     int  exp, e2;              /* exponent of real numbers */
   218    218     int nsd;                   /* Number of significant digits returned */
   219    219     double rounder;            /* Used for rounding floating point values */
   220    220     etByte flag_dp;            /* True if decimal point should be shown */
   221    221     etByte flag_rtz;           /* True if trailing zeros should be removed */
   222    222   #endif
................................................................................
   325    325             xtype = infop->type;
   326    326           }else{
   327    327             return;
   328    328           }
   329    329           break;
   330    330         }
   331    331       }
   332         -    zExtra = 0;
   333    332   
   334    333       /*
   335    334       ** At this point, variables are initialized as follows:
   336    335       **
   337    336       **   flag_alternateform          TRUE if a '#' is present.
   338    337       **   flag_altform2               TRUE if a '!' is present.
   339    338       **   flag_plussign               TRUE if a '+' is present.
................................................................................
   616    615         case etCHARX:
   617    616           if( bArgList ){
   618    617             bufpt = getTextArg(pArgList);
   619    618             c = bufpt ? bufpt[0] : 0;
   620    619           }else{
   621    620             c = va_arg(ap,int);
   622    621           }
   623         -        buf[0] = (char)c;
   624         -        if( precision>=0 ){
   625         -          for(idx=1; idx<precision; idx++) buf[idx] = (char)c;
   626         -          length = precision;
   627         -        }else{
   628         -          length =1;
          622  +        if( precision>1 ){
          623  +          width -= precision-1;
          624  +          if( width>1 && !flag_leftjustify ){
          625  +            sqlite3AppendChar(pAccum, width-1, ' ');
          626  +            width = 0;
          627  +          }
          628  +          sqlite3AppendChar(pAccum, precision-1, c);
   629    629           }
          630  +        length = 1;
          631  +        buf[0] = c;
   630    632           bufpt = buf;
   631    633           break;
   632    634         case etSTRING:
   633    635         case etDYNSTRING:
   634    636           if( bArgList ){
   635    637             bufpt = getTextArg(pArgList);
   636    638           }else{
................................................................................
   723    725       }/* End switch over the format type */
   724    726       /*
   725    727       ** The text of the conversion is pointed to by "bufpt" and is
   726    728       ** "length" characters long.  The field width is "width".  Do
   727    729       ** the output.
   728    730       */
   729    731       width -= length;
   730         -    if( width>0 && !flag_leftjustify ) sqlite3AppendSpace(pAccum, width);
          732  +    if( width>0 && !flag_leftjustify ) sqlite3AppendChar(pAccum, width, ' ');
   731    733       sqlite3StrAccumAppend(pAccum, bufpt, length);
   732         -    if( width>0 && flag_leftjustify ) sqlite3AppendSpace(pAccum, width);
          734  +    if( width>0 && flag_leftjustify ) sqlite3AppendChar(pAccum, width, ' ');
   733    735   
   734         -    if( zExtra ) sqlite3_free(zExtra);
          736  +    if( zExtra ){
          737  +      sqlite3_free(zExtra);
          738  +      zExtra = 0;
          739  +    }
   735    740     }/* End for loop over the format string */
   736    741   } /* End of function */
   737    742   
   738    743   /*
   739    744   ** Enlarge the memory allocation on a StrAccum object so that it is
   740    745   ** able to accept at least N more bytes of text.
   741    746   **
................................................................................
   780    785         return 0;
   781    786       }
   782    787     }
   783    788     return N;
   784    789   }
   785    790   
   786    791   /*
   787         -** Append N space characters to the given string buffer.
          792  +** Append N copies of character c to the given string buffer.
   788    793   */
   789         -void sqlite3AppendSpace(StrAccum *p, int N){
          794  +void sqlite3AppendChar(StrAccum *p, int N, char c){
   790    795     if( p->nChar+N >= p->nAlloc && (N = sqlite3StrAccumEnlarge(p, N))<=0 ) return;
   791         -  while( (N--)>0 ) p->zText[p->nChar++] = ' ';
          796  +  while( (N--)>0 ) p->zText[p->nChar++] = c;
   792    797   }
   793    798   
   794    799   /*
   795    800   ** The StrAccum "p" is not large enough to accept N new bytes of z[].
   796    801   ** So enlarge if first, then do the append.
   797    802   **
   798    803   ** This is a helper routine to sqlite3StrAccumAppend() that does special-case

Changes to src/sqliteInt.h.

  3535   3535   );
  3536   3536   int sqlite3ApiExit(sqlite3 *db, int);
  3537   3537   int sqlite3OpenTempDatabase(Parse *);
  3538   3538   
  3539   3539   void sqlite3StrAccumInit(StrAccum*, char*, int, int);
  3540   3540   void sqlite3StrAccumAppend(StrAccum*,const char*,int);
  3541   3541   void sqlite3StrAccumAppendAll(StrAccum*,const char*);
  3542         -void sqlite3AppendSpace(StrAccum*,int);
         3542  +void sqlite3AppendChar(StrAccum*,int,char);
  3543   3543   char *sqlite3StrAccumFinish(StrAccum*);
  3544   3544   void sqlite3StrAccumReset(StrAccum*);
  3545   3545   void sqlite3SelectDestInit(SelectDest*,int,int);
  3546   3546   Expr *sqlite3CreateColumnExpr(sqlite3 *, SrcList *, int, int);
  3547   3547   
  3548   3548   void sqlite3BackupRestart(sqlite3_backup *);
  3549   3549   void sqlite3BackupUpdate(sqlite3_backup *, Pgno, const u8 *);

Changes to test/printf2.test.

    90     90   # argument list, missing arguments are assumed to have a NULL value,
    91     91   # which is translated into 0 or 0.0 for numeric formats or an empty
    92     92   # string for %s.
    93     93   #
    94     94   do_execsql_test printf2-2.3 {
    95     95     SELECT printf('%s=(%d/%g/%s)',a) FROM t1 ORDER BY a;
    96     96   } {-1=(0/0/) 1=(0/0/) 1.5=(0/0/) abc=(0/0/)}
           97  +
           98  +# The precision of the %c conversion causes the character to repeat.
           99  +#
          100  +do_execsql_test printf2-3.1 {
          101  +  SELECT printf('|%110.100c|','*');
          102  +} {{|          ****************************************************************************************************|}}
          103  +do_execsql_test printf2-3.2 {
          104  +  SELECT printf('|%-110.100c|','*');
          105  +} {{|****************************************************************************************************          |}}
          106  +do_execsql_test printf2-3.3 {
          107  +  SELECT printf('|%9.8c|%-9.8c|','*','*');
          108  +} {{| ********|******** |}}
          109  +do_execsql_test printf2-3.4 {
          110  +  SELECT printf('|%8.8c|%-8.8c|','*','*');
          111  +} {|********|********|}
          112  +do_execsql_test printf2-3.5 {
          113  +  SELECT printf('|%7.8c|%-7.8c|','*','*');
          114  +} {|********|********|}
          115  +
          116  +
    97    117   
    98    118   
    99    119   finish_test