My version of output_Csv (3.5.4)  is missing conditional check.
static void output_csv(struct callback_data *p, const char *z, int bSep){
  FILE *out = p->out;
  if( z==0 ){
    fprintf(out,"%s",p->nullvalue);
  }else{
    int i;
    for(i=0; z[i]; i++){
      if( needCsvQuote[((unsigned char*)z)[i]] ){
        i = 0;
        break;
      }
    }


Maybe your runtime library id different than the source code?

HTH,
Ken




Dennis Cote <[EMAIL PROTECTED]> wrote: Frank van Vugt wrote:
> 
> I'll look into it tomorrow, but was under the impression that:
> 
> * when using .mode csv, the separator _always_ is a comma
> 
> * when one wants a different separator, one has to use .separator ... in 
> combination with .mode list
> 
> 
> needCsvQuote() is called from output_csv(), which is called when in csv-mode 
> only
> 

Frank,

You are on to something here.

The following trace from sqlite shows the problem.

SQLite version 3.5.4
Enter ".help" for instructions
sqlite> create table t(a, b, c);
sqlite> insert into t values(1, 2, 3);
sqlite> insert into t values('10', '200', '3000');
sqlite> insert into t values('1,000', '2,000', '3,000');
sqlite> insert into t values(1.0, '20 0' , '3|0');
sqlite> insert into t values( 'one_with,a_comma', 'long "quoted" bit''s 
& pieces
', 'one with a
    ...>  CR');
sqlite> .mode csv
sqlite> select * from t;
1,2,3
10,200,3000
1,000,2,000,3,000
1.0,"20 0",3|0
one_with,a_comma,"long ""quoted"" bit's & pieces","one with a
  CR"
sqlite> select typeof(a), typeof(b), typeof(c) from t;
integer,integer,integer
text,text,text
text,text,text
real,text,text
text,text,text

The third and fifth rows contains strings with embedded commas that are 
not quoted in the output even though they should be.

SQLite does indeed seem to be quoting only fields that contain 
characters in the needCsvQuote array (as in the fourth and fifth rows), 
even though the code in output_csv() does seem to check for the 
separator correctly.

static void output_csv(struct callback_data *p, const char *z, int bSep){
   FILE *out = p->out;
   if( z==0 ){
     fprintf(out,"%s",p->nullvalue);
   }else{
     int i;
     int nSep = strlen(p->separator);
     for(i=0; z[i]; i++){
       if( needCsvQuote[((unsigned char*)z)[i]]
          || (z[i]==p->separator[0] &&
              (nSep==1 || memcmp(z, p->separator, nSep)==0)) ){
         i = 0;
         break;
       }
     }
     if( i==0 ){
       putc('"', out);
       for(i=0; z[i]; i++){
         if( z[i]=='"' ) putc('"', out);
         putc(z[i], out);
       }
       putc('"', out);
     }else{
       fprintf(out, "%s", z);
     }
   }
   if( bSep ){
     fprintf(p->out, p->separator);
   }
}

It is using the correct separator string, a single comma, since the 
commas in the output are produced by the last fprintf() call at the end 
of output_csv(). I can't see where the logic is wrong. It should be 
caught by the combination of the z[i]==p->separator[0] test and the 
nSep==1 test, but the output is definitely wrong.

Can someone else spot the error?

During a bad call p->Separator is "," and z is "1,000", but the output 
appears to come from the fprintf(out, "%s", z) line.

BTW, as a minor style issue, I think the last fprintf() call should use 
out rather than p->out for the first argument for consistency reasons if 
nothing else.

Dennis Cote

-----------------------------------------------------------------------------
To unsubscribe, send email to [EMAIL PROTECTED]
-----------------------------------------------------------------------------


Reply via email to