/ Check-in [3ba77313]
Login

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

Overview
Comment:Enhance the %q, %Q, and %w printf conversions so that the precisions specifies the length of the input.
Downloads: Tarball | ZIP archive | SQL archive
Timelines: family | ancestors | descendants | both | trunk
Files: files | file ages | folders
SHA1: 3ba773132d3baeb87acaee538b8fb0b0f4293673
User & Date: drh 2009-11-25 16:53:38
Context
2009-11-25
18:03
Initial check-in of code that inserts tokenizations of the values for bound parameters into the output of sqlite3_trace(). check-in: 545cfb3b user: drh tags: trunk
16:53
Enhance the %q, %Q, and %w printf conversions so that the precisions specifies the length of the input. check-in: 3ba77313 user: drh tags: trunk
2009-11-24
16:26
Fix a tracing macro in the VDBE in the VColumn opcode. check-in: cb74b81b user: drh tags: trunk
Changes
Hide Diffs Unified Diffs Ignore Whitespace Patch

Changes to src/printf.c.

641
642
643
644
645
646
647
648
649
650
651
652
653
654

655
656
657
658
659
660
661
662
...
664
665
666
667
668
669
670
671

672
673
674
675
676
677
678

679
680
681
682
683
684
685
686
        }else{
          length = sqlite3Strlen30(bufpt);
        }
        break;
      case etSQLESCAPE:
      case etSQLESCAPE2:
      case etSQLESCAPE3: {
        int i, j, n, isnull;
        int needQuote;
        char ch;
        char q = ((xtype==etSQLESCAPE3)?'"':'\'');   /* Quote character */
        char *escarg = va_arg(ap,char*);
        isnull = escarg==0;
        if( isnull ) escarg = (xtype==etSQLESCAPE2 ? "NULL" : "(NULL)");

        for(i=n=0; (ch=escarg[i])!=0; i++){
          if( ch==q )  n++;
        }
        needQuote = !isnull && xtype==etSQLESCAPE2;
        n += i + 1 + needQuote*2;
        if( n>etBUFSIZE ){
          bufpt = zExtra = sqlite3Malloc( n );
          if( bufpt==0 ){
................................................................................
            return;
          }
        }else{
          bufpt = buf;
        }
        j = 0;
        if( needQuote ) bufpt[j++] = q;
        for(i=0; (ch=escarg[i])!=0; i++){

          bufpt[j++] = ch;
          if( ch==q ) bufpt[j++] = ch;
        }
        if( needQuote ) bufpt[j++] = q;
        bufpt[j] = 0;
        length = j;
        /* The precision is ignored on %q and %Q */

        /* if( precision>=0 && precision<length ) length = precision; */
        break;
      }
      case etTOKEN: {
        Token *pToken = va_arg(ap, Token*);
        if( pToken ){
          sqlite3StrAccumAppend(pAccum, (const char*)pToken->z, pToken->n);
        }







|






>
|







 







|
>
|





|
>
|







641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
...
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
        }else{
          length = sqlite3Strlen30(bufpt);
        }
        break;
      case etSQLESCAPE:
      case etSQLESCAPE2:
      case etSQLESCAPE3: {
        int i, j, k, n, isnull;
        int needQuote;
        char ch;
        char q = ((xtype==etSQLESCAPE3)?'"':'\'');   /* Quote character */
        char *escarg = va_arg(ap,char*);
        isnull = escarg==0;
        if( isnull ) escarg = (xtype==etSQLESCAPE2 ? "NULL" : "(NULL)");
        k = precision;
        for(i=n=0; (ch=escarg[i])!=0 && k!=0; i++, k--){
          if( ch==q )  n++;
        }
        needQuote = !isnull && xtype==etSQLESCAPE2;
        n += i + 1 + needQuote*2;
        if( n>etBUFSIZE ){
          bufpt = zExtra = sqlite3Malloc( n );
          if( bufpt==0 ){
................................................................................
            return;
          }
        }else{
          bufpt = buf;
        }
        j = 0;
        if( needQuote ) bufpt[j++] = q;
        k = i;
        for(i=0; i<k; i++){
          bufpt[j++] = ch = escarg[i];
          if( ch==q ) bufpt[j++] = ch;
        }
        if( needQuote ) bufpt[j++] = q;
        bufpt[j] = 0;
        length = j;
        /* The precision in %q and %Q means how many input characters to
        ** consume, not the length of the output...
        ** if( precision>=0 && precision<length ) length = precision; */
        break;
      }
      case etTOKEN: {
        Token *pToken = va_arg(ap, Token*);
        if( pToken ){
          sqlite3StrAccumAppend(pAccum, (const char*)pToken->z, pToken->n);
        }

Changes to test/printf.test.

3502
3503
3504
3505
3506
3507
3508





































3509
3510
3511
3512
3513
3514
3515
} {1 2 A NULL pointer in %q: '(NULL)'}
do_test printf-4.3 {
  sqlite3_mprintf_str {%d %d A quoted string: %Q} 1 2 {Hi Y'all}
} {1 2 A quoted string: 'Hi Y''all'}
do_test printf-4.4 {
  sqlite3_mprintf_str {%d %d A NULL pointer in %%Q: %Q} 1 2
} {1 2 A NULL pointer in %Q: NULL}






































do_test printf-5.1 {
  set x [sqlite3_mprintf_str {%d %d %100000s} 0 0 {Hello}]
  string length $x
} {344}
do_test printf-5.2 {
  sqlite3_mprintf_str {%d %d (%-10.10s) %} -9 -10 {HelloHelloHello}







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







3502
3503
3504
3505
3506
3507
3508
3509
3510
3511
3512
3513
3514
3515
3516
3517
3518
3519
3520
3521
3522
3523
3524
3525
3526
3527
3528
3529
3530
3531
3532
3533
3534
3535
3536
3537
3538
3539
3540
3541
3542
3543
3544
3545
3546
3547
3548
3549
3550
3551
3552
} {1 2 A NULL pointer in %q: '(NULL)'}
do_test printf-4.3 {
  sqlite3_mprintf_str {%d %d A quoted string: %Q} 1 2 {Hi Y'all}
} {1 2 A quoted string: 'Hi Y''all'}
do_test printf-4.4 {
  sqlite3_mprintf_str {%d %d A NULL pointer in %%Q: %Q} 1 2
} {1 2 A NULL pointer in %Q: NULL}
do_test printf-4.5 {
  sqlite3_mprintf_str {%d %d A quoted string: '%.10q'} 1 2 {Hi Y'all}
} {1 2 A quoted string: 'Hi Y''all'}
do_test printf-4.6 {
  sqlite3_mprintf_str {%d %d A quoted string: '%.9q'} 1 2 {Hi Y'all}
} {1 2 A quoted string: 'Hi Y''all'}
do_test printf-4.7 {
  sqlite3_mprintf_str {%d %d A quoted string: '%.8q'} 1 2 {Hi Y'all}
} {1 2 A quoted string: 'Hi Y''all'}
do_test printf-4.8 {
  sqlite3_mprintf_str {%d %d A quoted string: '%.7q'} 1 2 {Hi Y'all}
} {1 2 A quoted string: 'Hi Y''al'}
do_test printf-4.9 {
  sqlite3_mprintf_str {%d %d A quoted string: '%.6q'} 1 2 {Hi Y'all}
} {1 2 A quoted string: 'Hi Y''a'}
do_test printf-4.10 {
  sqlite3_mprintf_str {%d %d A quoted string: '%.5q'} 1 2 {Hi Y'all}
} {1 2 A quoted string: 'Hi Y'''}
do_test printf-4.11 {
  sqlite3_mprintf_str {%d %d A quoted string: '%.4q'} 1 2 {Hi Y'all}
} {1 2 A quoted string: 'Hi Y'}
do_test printf-4.12 {
  sqlite3_mprintf_str {%d %d A quoted string: '%.3q'} 1 2 {Hi Y'all}
} {1 2 A quoted string: 'Hi '}
do_test printf-4.13 {
  sqlite3_mprintf_str {%d %d A quoted string: '%.2q'} 1 2 {Hi Y'all}
} {1 2 A quoted string: 'Hi'}
do_test printf-4.14 {
  sqlite3_mprintf_str {%d %d A quoted string: '%.1q'} 1 2 {Hi Y'all}
} {1 2 A quoted string: 'H'}
do_test printf-4.15 {
  sqlite3_mprintf_str {%d %d A quoted string: '%.0q'} 1 2 {Hi Y'all}
} {1 2 A quoted string: ''}
do_test printf-4.16 {
  sqlite3_mprintf_str {%d A quoted string: '%.*q'} 1 6 {Hi Y'all}
} {1 A quoted string: 'Hi Y''a'}


do_test printf-5.1 {
  set x [sqlite3_mprintf_str {%d %d %100000s} 0 0 {Hello}]
  string length $x
} {344}
do_test printf-5.2 {
  sqlite3_mprintf_str {%d %d (%-10.10s) %} -9 -10 {HelloHelloHello}