/ Check-in [272dc74f]
Login
SQLite training in Houston TX on 2019-11-05 (details)
Part of the 2019 Tcl Conference

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

Overview
Comment:Get rid of the hash table used to track IN operators in the sqlite3_normalized_sql() implementation. Use simple integer variables instead.
Downloads: Tarball | ZIP archive | SQL archive
Timelines: family | ancestors | descendants | both | trunk
Files: files | file ages | folders
SHA3-256: 272dc74fd0304d6a28aaa8798d13e2f950c1a24d92d17519e3c32aef86714586
User & Date: drh 2018-12-05 23:56:02
Context
2018-12-06
01:08
Fix a missing mutex in the sqlite3_normalized_sql() interface when it is called on a prepared statement that did not previously have a computed normalization of the input SQL. check-in: 1a1a59c6 user: drh tags: trunk
00:05
Merge ALTER TABLE and sqlite3_normalized_sql() fixes from trunk. check-in: acf10b3f user: drh tags: begin-concurrent
2018-12-05
23:56
Get rid of the hash table used to track IN operators in the sqlite3_normalized_sql() implementation. Use simple integer variables instead. check-in: 272dc74f user: drh tags: trunk
23:45
The sqlite3_normalized_sql() interface should not be transforming quoted identifier names into wildcards. Fix this, and at the same time simplify the code substantially. check-in: e8540377 user: drh tags: trunk
Changes
Hide Diffs Unified Diffs Ignore Whitespace Patch

Changes to src/prepare.c.

789
790
791
792
793
794
795
796

797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
...
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840

841
842
843

844
845
846
847
848
849
850
...
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
  int nZ;                /* Size of the output string in bytes */
  int i;                 /* Next character to read from zSql[] */
  int j;                 /* Next character to fill in on z[] */
  int tokenType = 0;     /* Type of the next token */
  int prevTokenType = 0; /* Type of the previous token, except spaces */
  int n;                 /* Size of the next token */
  int nParen = 0;        /* Nesting level of parenthesis */
  Hash inHash;           /* Table of parenthesis levels to output index. */


  db = sqlite3VdbeDb(pVdbe);
  assert( db!=0 );
  if( zSql==0 ) return 0;
  nZ = estimateNormalizedSize(zSql, nSql);
  z = sqlite3DbMallocRawNN(db, nZ);
  if( z==0 ) goto normalizeError;
  sqlite3HashInit(&inHash);
  for(i=j=0; i<nSql && zSql[i]; i+=n){
    int flags = 0;
    if( tokenType!=TK_SPACE ) prevTokenType = tokenType;
    n = sqlite3GetTokenNormalized((unsigned char*)zSql+i, &tokenType, &flags);
    switch( tokenType ){
      case TK_SPACE: {
        break;
................................................................................
        break;
      }
      case TK_LP:
      case TK_RP: {
        if( tokenType==TK_LP ){
          nParen++;
          if( prevTokenType==TK_IN ){
            assert( nParen<nSql );
            sqlite3HashInsert(&inHash, zSql+nParen, SQLITE_INT_TO_PTR(j));
          }
        }else{
          int jj;
          assert( nParen<nSql );
          jj = SQLITE_PTR_TO_INT(sqlite3HashFind(&inHash, zSql+nParen));
          if( jj>0 ){
            sqlite3HashInsert(&inHash, zSql+nParen, 0);
            assert( jj+6<nZ );
            memcpy(z+jj+1, "?,?,?", 5);
            j = jj+6;

            assert( nZ-1-j>=0 );
            assert( nZ-1-j<nZ );
            memset(z+j, 0, nZ-1-j);

          }
          nParen--;
        }
        assert( nParen>=0 );
        /* Fall through */
      }
      case TK_MINUS:
................................................................................
          }
        }
        if( j>0 && sqlite3IsIdChar(z[j-1]) && sqlite3IsIdChar(zSql[i]) ){
          z[j++] = ' ';
        }
        if( tokenType==TK_ID ){
          int i2 = i, n2 = n;
          if( nParen>0 ){
            assert( nParen<nSql );
            sqlite3HashInsert(&inHash, zSql+nParen, 0);
          }
          if( flags&SQLITE_TOKEN_QUOTED ){ i2++; n2-=2; }
        }
        copyNormalizedToken(zSql, i, n, flags, z, &j);
        break;
      }
    }
  }
  assert( j<nZ && "one" );
  while( j>0 && z[j-1]==' ' ){ j--; }
  if( j>0 && z[j-1]!=';' ){ z[j++] = ';'; }
  z[j] = 0;
  assert( j<nZ && "two" );
  sqlite3HashClear(&inHash);
  return z;

normalizeError:
  sqlite3DbFree(db, z);
  sqlite3HashClear(&inHash);
  return 0;
}
#endif /* SQLITE_ENABLE_NORMALIZE */

/*
** Rerun the compilation of a statement after a schema change.
**







|
>







<







 







|
|


|
<
<
<
<
|
|
<
>



>







 







|
<
<
<












<




<







789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804

805
806
807
808
809
810
811
...
822
823
824
825
826
827
828
829
830
831
832
833




834
835

836
837
838
839
840
841
842
843
844
845
846
847
...
879
880
881
882
883
884
885
886



887
888
889
890
891
892
893
894
895
896
897
898

899
900
901
902

903
904
905
906
907
908
909
  int nZ;                /* Size of the output string in bytes */
  int i;                 /* Next character to read from zSql[] */
  int j;                 /* Next character to fill in on z[] */
  int tokenType = 0;     /* Type of the next token */
  int prevTokenType = 0; /* Type of the previous token, except spaces */
  int n;                 /* Size of the next token */
  int nParen = 0;        /* Nesting level of parenthesis */
  int iStartIN = 0;      /* Start of RHS of IN operator in z[] */
  int nParenAtIN = 0;    /* Value of nParent at start of RHS of IN operator */

  db = sqlite3VdbeDb(pVdbe);
  assert( db!=0 );
  if( zSql==0 ) return 0;
  nZ = estimateNormalizedSize(zSql, nSql);
  z = sqlite3DbMallocRawNN(db, nZ);
  if( z==0 ) goto normalizeError;

  for(i=j=0; i<nSql && zSql[i]; i+=n){
    int flags = 0;
    if( tokenType!=TK_SPACE ) prevTokenType = tokenType;
    n = sqlite3GetTokenNormalized((unsigned char*)zSql+i, &tokenType, &flags);
    switch( tokenType ){
      case TK_SPACE: {
        break;
................................................................................
        break;
      }
      case TK_LP:
      case TK_RP: {
        if( tokenType==TK_LP ){
          nParen++;
          if( prevTokenType==TK_IN ){
            iStartIN = j;
            nParenAtIN = nParen;
          }
        }else{
          if( iStartIN>0 && nParen==nParenAtIN ){




            assert( iStartIN+6<nZ );
            memcpy(z+iStartIN+1, "?,?,?", 5);

            j = iStartIN+6;
            assert( nZ-1-j>=0 );
            assert( nZ-1-j<nZ );
            memset(z+j, 0, nZ-1-j);
            iStartIN = 0;
          }
          nParen--;
        }
        assert( nParen>=0 );
        /* Fall through */
      }
      case TK_MINUS:
................................................................................
          }
        }
        if( j>0 && sqlite3IsIdChar(z[j-1]) && sqlite3IsIdChar(zSql[i]) ){
          z[j++] = ' ';
        }
        if( tokenType==TK_ID ){
          int i2 = i, n2 = n;
          if( nParen==nParenAtIN ) iStartIN = 0;



          if( flags&SQLITE_TOKEN_QUOTED ){ i2++; n2-=2; }
        }
        copyNormalizedToken(zSql, i, n, flags, z, &j);
        break;
      }
    }
  }
  assert( j<nZ && "one" );
  while( j>0 && z[j-1]==' ' ){ j--; }
  if( j>0 && z[j-1]!=';' ){ z[j++] = ';'; }
  z[j] = 0;
  assert( j<nZ && "two" );

  return z;

normalizeError:
  sqlite3DbFree(db, z);

  return 0;
}
#endif /* SQLITE_ENABLE_NORMALIZE */

/*
** Rerun the compilation of a statement after a schema change.
**