/ Check-in [f2643315]
Login

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

Overview
Comment:Improved \n and \r escapes in the ext/misc/dbdump.c utility function. The implementation of dbdump.c now matches the implementation in the CLI.
Downloads: Tarball | ZIP archive | SQL archive
Timelines: family | ancestors | descendants | both | trunk
Files: files | file ages | folders
SHA3-256:f2643315bb41a71eebd79f5d671f9163187e299a52ff8a481186f1e8fa7e5262
User & Date: drh 2017-04-12 17:38:24
Context
2017-04-12
17:50
Update fts5 to support "<colset> : ( <expr> )" for column filtering, as well as "<colset> : NEAR(...)" and "<colset> : <phrase>". check-in: c847543f user: dan tags: trunk
17:38
Improved \n and \r escapes in the ext/misc/dbdump.c utility function. The implementation of dbdump.c now matches the implementation in the CLI. check-in: f2643315 user: drh tags: trunk
2017-04-11
20:48
Avoid updating unaffected indexes on a table as part of an UPDATE that requires foreign key processing in some cases. check-in: 7aae5c0f user: dan tags: trunk
Changes
Hide Diffs Unified Diffs Ignore Whitespace Patch

Changes to ext/misc/dbdump.c.

320
321
322
323
324
325
326
327

328



















329
330


331
332
333
334
335
336
337
338
339
340
341









342









343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367


368
369
370

371
372

373
374







375
376
377
378
379
380
381
...
491
492
493
494
495
496
497

498
499
500
501
502
503
504
505
  z = sqlite3_vmprintf(zFormat, ap);
  va_end(ap);
  p->xCallback(z, p->pArg);
  sqlite3_free(z);
}

/*
** Output the given string as a quoted string using SQL quoting conventions.

**



















** The "\n" and "\r" characters are converted to char(10) and char(13)
** to prevent them from being transformed by end-of-line translators.


*/
static void output_quoted_string(DState *p, const unsigned char *z){
  int i;
  char c;
  int inQuote = 0;
  int bStarted = 0;

  for(i=0; (c = z[i])!=0 && c!='\'' && c!='\n' && c!='\r'; i++){}
  if( c==0 ){
    output_formatted(p, "'%s'", z);
    return;









  }









  while( *z ){
    for(i=0; (c = z[i])!=0 && c!='\n' && c!='\r' && c!='\''; i++){}
    if( c=='\'' ) i++;
    if( i ){
      if( !inQuote ){
        if( bStarted ) p->xCallback("||", p->pArg);
        p->xCallback("'", p->pArg);
        inQuote = 1;
      }
      output_formatted(p, "%.*s", i, z);
      z += i;
      bStarted = 1;
    }
    if( c=='\'' ){
      p->xCallback("'", p->pArg);
      continue;
    }
    if( inQuote ){
      p->xCallback("'", p->pArg);
      inQuote = 0;
    }
    if( c==0 ){
      break;
    }
    for(i=0; (c = z[i])=='\r' || c=='\n'; i++){


      if( bStarted ) p->xCallback("||", p->pArg);
      output_formatted(p, "char(%d)", c);
      bStarted = 1;

    }
    z += i;

  }
  if( inQuote ) p->xCallback("'", p->pArg);







}

/*
** This is an sqlite3_exec callback routine used for dumping the database.
** Each row received by this callback consists of a table name,
** the table type ("index" or "table") and SQL to create the table.
** This routine should print text sufficient to recreate the table.
................................................................................
              break;
            }
            case SQLITE_NULL: {
              p->xCallback("NULL", p->pArg);
              break;
            }
            case SQLITE_TEXT: {

              output_quoted_string(p, sqlite3_column_text(pStmt,i));
              break;
            }
            case SQLITE_BLOB: {
              int nByte = sqlite3_column_bytes(pStmt,i);
              unsigned char *a = (unsigned char*)sqlite3_column_blob(pStmt,i);
              int j;
              p->xCallback("x'", p->pArg);







|
>

>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
|
<
>
>

|


<
<
<


|
<
>
>
>
>
>
>
>
>
>
|
>
>
>
>
>
>
>
>
>
|
|
|
|
<
<
<
<
<
|
|
<
|
|
|
|
|
<
<
<
<
|
|
|
<
>
>
|
<
<
>
|
<
>
|
|
>
>
>
>
>
>
>







 







>
|







320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349

350
351
352
353
354
355



356
357
358

359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381





382
383

384
385
386
387
388




389
390
391

392
393
394


395
396

397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
...
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
  z = sqlite3_vmprintf(zFormat, ap);
  va_end(ap);
  p->xCallback(z, p->pArg);
  sqlite3_free(z);
}

/*
** Find a string that is not found anywhere in z[].  Return a pointer
** to that string.
**
** Try to use zA and zB first.  If both of those are already found in z[]
** then make up some string and store it in the buffer zBuf.
*/
static const char *unused_string(
  const char *z,                    /* Result must not appear anywhere in z */
  const char *zA, const char *zB,   /* Try these first */
  char *zBuf                        /* Space to store a generated string */
){
  unsigned i = 0;
  if( strstr(z, zA)==0 ) return zA;
  if( strstr(z, zB)==0 ) return zB;
  do{
    sqlite3_snprintf(20,zBuf,"(%s%u)", zA, i++);
  }while( strstr(z,zBuf)!=0 );
  return zBuf;
}

/*
** Output the given string as a quoted string using SQL quoting conventions.
** Additionallly , escape the "\n" and "\r" characters so that they do not

** get corrupted by end-of-line translation facilities in some operating
** systems.
*/
static void output_quoted_escaped_string(DState *p, const char *z){
  int i;
  char c;



  for(i=0; (c = z[i])!=0 && c!='\'' && c!='\n' && c!='\r'; i++){}
  if( c==0 ){
    output_formatted(p,"'%s'",z);

  }else{
    const char *zNL = 0;
    const char *zCR = 0;
    int nNL = 0;
    int nCR = 0;
    char zBuf1[20], zBuf2[20];
    for(i=0; z[i]; i++){
      if( z[i]=='\n' ) nNL++;
      if( z[i]=='\r' ) nCR++;
    }
    if( nNL ){
      p->xCallback("replace(", p->pArg);
      zNL = unused_string(z, "\\n", "\\012", zBuf1);
    }
    if( nCR ){
      p->xCallback("replace(", p->pArg);
      zCR = unused_string(z, "\\r", "\\015", zBuf2);
    }
    p->xCallback("'", p->pArg);
    while( *z ){
      for(i=0; (c = z[i])!=0 && c!='\n' && c!='\r' && c!='\''; i++){}
      if( c=='\'' ) i++;
      if( i ){





        output_formatted(p, "%.*s", i, z);
        z += i;

      }
      if( c=='\'' ){
        p->xCallback("'", p->pArg);
        continue;
      }




      if( c==0 ){
        break;
      }

      z++;
      if( c=='\n' ){
        p->xCallback(zNL, p->pArg);


        continue;
      }

      p->xCallback(zCR, p->pArg);
    }
    p->xCallback("'", p->pArg);
    if( nCR ){
      output_formatted(p, ",'%s',char(13))", zCR);
    }
    if( nNL ){
      output_formatted(p, ",'%s',char(10))", zNL);
    }
  }
}

/*
** This is an sqlite3_exec callback routine used for dumping the database.
** Each row received by this callback consists of a table name,
** the table type ("index" or "table") and SQL to create the table.
** This routine should print text sufficient to recreate the table.
................................................................................
              break;
            }
            case SQLITE_NULL: {
              p->xCallback("NULL", p->pArg);
              break;
            }
            case SQLITE_TEXT: {
              output_quoted_escaped_string(p, 
                   (const char*)sqlite3_column_text(pStmt,i));
              break;
            }
            case SQLITE_BLOB: {
              int nByte = sqlite3_column_bytes(pStmt,i);
              unsigned char *a = (unsigned char*)sqlite3_column_blob(pStmt,i);
              int j;
              p->xCallback("x'", p->pArg);