extensions/sqlite/sqlite-source/complete.c
author Scott Ehlert <ds@alliedmods.net>
Sun Mar 30 07:00:22 2008 +0000 (2008-03-30)
changeset 1952 b7aa2b626807
permissions -rw-r--r--
Spring Cleaning, Part Ichi (1)
Various minor things done to project files
Updated sample extension project file and updated makefile to the new unified version (more changes likely on the way)
Updated regex project file and makefile
ds@1952
     1
/*
ds@1952
     2
** 2001 September 15
ds@1952
     3
**
ds@1952
     4
** The author disclaims copyright to this source code.  In place of
ds@1952
     5
** a legal notice, here is a blessing:
ds@1952
     6
**
ds@1952
     7
**    May you do good and not evil.
ds@1952
     8
**    May you find forgiveness for yourself and forgive others.
ds@1952
     9
**    May you share freely, never taking more than you give.
ds@1952
    10
**
ds@1952
    11
*************************************************************************
ds@1952
    12
** An tokenizer for SQL
ds@1952
    13
**
ds@1952
    14
** This file contains C code that implements the sqlite3_complete() API.
ds@1952
    15
** This code used to be part of the tokenizer.c source file.  But by
ds@1952
    16
** separating it out, the code will be automatically omitted from
ds@1952
    17
** static links that do not use it.
ds@1952
    18
**
ds@1952
    19
** $Id$
ds@1952
    20
*/
ds@1952
    21
#include "sqliteInt.h"
ds@1952
    22
#ifndef SQLITE_OMIT_COMPLETE
ds@1952
    23
ds@1952
    24
/*
ds@1952
    25
** This is defined in tokenize.c.  We just have to import the definition.
ds@1952
    26
*/
ds@1952
    27
#ifndef SQLITE_AMALGAMATION
ds@1952
    28
#ifdef SQLITE_ASCII
ds@1952
    29
extern const char sqlite3IsAsciiIdChar[];
ds@1952
    30
#define IdChar(C)  (((c=C)&0x80)!=0 || (c>0x1f && sqlite3IsAsciiIdChar[c-0x20]))
ds@1952
    31
#endif
ds@1952
    32
#ifdef SQLITE_EBCDIC
ds@1952
    33
extern const char sqlite3IsEbcdicIdChar[];
ds@1952
    34
#define IdChar(C)  (((c=C)>=0x42 && sqlite3IsEbcdicIdChar[c-0x40]))
ds@1952
    35
#endif
ds@1952
    36
#endif /* SQLITE_AMALGAMATION */
ds@1952
    37
ds@1952
    38
ds@1952
    39
/*
ds@1952
    40
** Token types used by the sqlite3_complete() routine.  See the header
ds@1952
    41
** comments on that procedure for additional information.
ds@1952
    42
*/
ds@1952
    43
#define tkSEMI    0
ds@1952
    44
#define tkWS      1
ds@1952
    45
#define tkOTHER   2
ds@1952
    46
#define tkEXPLAIN 3
ds@1952
    47
#define tkCREATE  4
ds@1952
    48
#define tkTEMP    5
ds@1952
    49
#define tkTRIGGER 6
ds@1952
    50
#define tkEND     7
ds@1952
    51
ds@1952
    52
/*
ds@1952
    53
** Return TRUE if the given SQL string ends in a semicolon.
ds@1952
    54
**
ds@1952
    55
** Special handling is require for CREATE TRIGGER statements.
ds@1952
    56
** Whenever the CREATE TRIGGER keywords are seen, the statement
ds@1952
    57
** must end with ";END;".
ds@1952
    58
**
ds@1952
    59
** This implementation uses a state machine with 7 states:
ds@1952
    60
**
ds@1952
    61
**   (0) START     At the beginning or end of an SQL statement.  This routine
ds@1952
    62
**                 returns 1 if it ends in the START state and 0 if it ends
ds@1952
    63
**                 in any other state.
ds@1952
    64
**
ds@1952
    65
**   (1) NORMAL    We are in the middle of statement which ends with a single
ds@1952
    66
**                 semicolon.
ds@1952
    67
**
ds@1952
    68
**   (2) EXPLAIN   The keyword EXPLAIN has been seen at the beginning of 
ds@1952
    69
**                 a statement.
ds@1952
    70
**
ds@1952
    71
**   (3) CREATE    The keyword CREATE has been seen at the beginning of a
ds@1952
    72
**                 statement, possibly preceeded by EXPLAIN and/or followed by
ds@1952
    73
**                 TEMP or TEMPORARY
ds@1952
    74
**
ds@1952
    75
**   (4) TRIGGER   We are in the middle of a trigger definition that must be
ds@1952
    76
**                 ended by a semicolon, the keyword END, and another semicolon.
ds@1952
    77
**
ds@1952
    78
**   (5) SEMI      We've seen the first semicolon in the ";END;" that occurs at
ds@1952
    79
**                 the end of a trigger definition.
ds@1952
    80
**
ds@1952
    81
**   (6) END       We've seen the ";END" of the ";END;" that occurs at the end
ds@1952
    82
**                 of a trigger difinition.
ds@1952
    83
**
ds@1952
    84
** Transitions between states above are determined by tokens extracted
ds@1952
    85
** from the input.  The following tokens are significant:
ds@1952
    86
**
ds@1952
    87
**   (0) tkSEMI      A semicolon.
ds@1952
    88
**   (1) tkWS        Whitespace
ds@1952
    89
**   (2) tkOTHER     Any other SQL token.
ds@1952
    90
**   (3) tkEXPLAIN   The "explain" keyword.
ds@1952
    91
**   (4) tkCREATE    The "create" keyword.
ds@1952
    92
**   (5) tkTEMP      The "temp" or "temporary" keyword.
ds@1952
    93
**   (6) tkTRIGGER   The "trigger" keyword.
ds@1952
    94
**   (7) tkEND       The "end" keyword.
ds@1952
    95
**
ds@1952
    96
** Whitespace never causes a state transition and is always ignored.
ds@1952
    97
**
ds@1952
    98
** If we compile with SQLITE_OMIT_TRIGGER, all of the computation needed
ds@1952
    99
** to recognize the end of a trigger can be omitted.  All we have to do
ds@1952
   100
** is look for a semicolon that is not part of an string or comment.
ds@1952
   101
*/
ds@1952
   102
int sqlite3_complete(const char *zSql){
ds@1952
   103
  u8 state = 0;   /* Current state, using numbers defined in header comment */
ds@1952
   104
  u8 token;       /* Value of the next token */
ds@1952
   105
ds@1952
   106
#ifndef SQLITE_OMIT_TRIGGER
ds@1952
   107
  /* A complex statement machine used to detect the end of a CREATE TRIGGER
ds@1952
   108
  ** statement.  This is the normal case.
ds@1952
   109
  */
ds@1952
   110
  static const u8 trans[7][8] = {
ds@1952
   111
                     /* Token:                                                */
ds@1952
   112
     /* State:       **  SEMI  WS  OTHER EXPLAIN  CREATE  TEMP  TRIGGER  END  */
ds@1952
   113
     /* 0   START: */ {    0,  0,     1,      2,      3,    1,       1,   1,  },
ds@1952
   114
     /* 1  NORMAL: */ {    0,  1,     1,      1,      1,    1,       1,   1,  },
ds@1952
   115
     /* 2 EXPLAIN: */ {    0,  2,     1,      1,      3,    1,       1,   1,  },
ds@1952
   116
     /* 3  CREATE: */ {    0,  3,     1,      1,      1,    3,       4,   1,  },
ds@1952
   117
     /* 4 TRIGGER: */ {    5,  4,     4,      4,      4,    4,       4,   4,  },
ds@1952
   118
     /* 5    SEMI: */ {    5,  5,     4,      4,      4,    4,       4,   6,  },
ds@1952
   119
     /* 6     END: */ {    0,  6,     4,      4,      4,    4,       4,   4,  },
ds@1952
   120
  };
ds@1952
   121
#else
ds@1952
   122
  /* If triggers are not suppored by this compile then the statement machine
ds@1952
   123
  ** used to detect the end of a statement is much simplier
ds@1952
   124
  */
ds@1952
   125
  static const u8 trans[2][3] = {
ds@1952
   126
                     /* Token:           */
ds@1952
   127
     /* State:       **  SEMI  WS  OTHER */
ds@1952
   128
     /* 0   START: */ {    0,  0,     1, },
ds@1952
   129
     /* 1  NORMAL: */ {    0,  1,     1, },
ds@1952
   130
  };
ds@1952
   131
#endif /* SQLITE_OMIT_TRIGGER */
ds@1952
   132
ds@1952
   133
  while( *zSql ){
ds@1952
   134
    switch( *zSql ){
ds@1952
   135
      case ';': {  /* A semicolon */
ds@1952
   136
        token = tkSEMI;
ds@1952
   137
        break;
ds@1952
   138
      }
ds@1952
   139
      case ' ':
ds@1952
   140
      case '\r':
ds@1952
   141
      case '\t':
ds@1952
   142
      case '\n':
ds@1952
   143
      case '\f': {  /* White space is ignored */
ds@1952
   144
        token = tkWS;
ds@1952
   145
        break;
ds@1952
   146
      }
ds@1952
   147
      case '/': {   /* C-style comments */
ds@1952
   148
        if( zSql[1]!='*' ){
ds@1952
   149
          token = tkOTHER;
ds@1952
   150
          break;
ds@1952
   151
        }
ds@1952
   152
        zSql += 2;
ds@1952
   153
        while( zSql[0] && (zSql[0]!='*' || zSql[1]!='/') ){ zSql++; }
ds@1952
   154
        if( zSql[0]==0 ) return 0;
ds@1952
   155
        zSql++;
ds@1952
   156
        token = tkWS;
ds@1952
   157
        break;
ds@1952
   158
      }
ds@1952
   159
      case '-': {   /* SQL-style comments from "--" to end of line */
ds@1952
   160
        if( zSql[1]!='-' ){
ds@1952
   161
          token = tkOTHER;
ds@1952
   162
          break;
ds@1952
   163
        }
ds@1952
   164
        while( *zSql && *zSql!='\n' ){ zSql++; }
ds@1952
   165
        if( *zSql==0 ) return state==0;
ds@1952
   166
        token = tkWS;
ds@1952
   167
        break;
ds@1952
   168
      }
ds@1952
   169
      case '[': {   /* Microsoft-style identifiers in [...] */
ds@1952
   170
        zSql++;
ds@1952
   171
        while( *zSql && *zSql!=']' ){ zSql++; }
ds@1952
   172
        if( *zSql==0 ) return 0;
ds@1952
   173
        token = tkOTHER;
ds@1952
   174
        break;
ds@1952
   175
      }
ds@1952
   176
      case '`':     /* Grave-accent quoted symbols used by MySQL */
ds@1952
   177
      case '"':     /* single- and double-quoted strings */
ds@1952
   178
      case '\'': {
ds@1952
   179
        int c = *zSql;
ds@1952
   180
        zSql++;
ds@1952
   181
        while( *zSql && *zSql!=c ){ zSql++; }
ds@1952
   182
        if( *zSql==0 ) return 0;
ds@1952
   183
        token = tkOTHER;
ds@1952
   184
        break;
ds@1952
   185
      }
ds@1952
   186
      default: {
ds@1952
   187
        int c;
ds@1952
   188
        if( IdChar((u8)*zSql) ){
ds@1952
   189
          /* Keywords and unquoted identifiers */
ds@1952
   190
          int nId;
ds@1952
   191
          for(nId=1; IdChar(zSql[nId]); nId++){}
ds@1952
   192
#ifdef SQLITE_OMIT_TRIGGER
ds@1952
   193
          token = tkOTHER;
ds@1952
   194
#else
ds@1952
   195
          switch( *zSql ){
ds@1952
   196
            case 'c': case 'C': {
ds@1952
   197
              if( nId==6 && sqlite3StrNICmp(zSql, "create", 6)==0 ){
ds@1952
   198
                token = tkCREATE;
ds@1952
   199
              }else{
ds@1952
   200
                token = tkOTHER;
ds@1952
   201
              }
ds@1952
   202
              break;
ds@1952
   203
            }
ds@1952
   204
            case 't': case 'T': {
ds@1952
   205
              if( nId==7 && sqlite3StrNICmp(zSql, "trigger", 7)==0 ){
ds@1952
   206
                token = tkTRIGGER;
ds@1952
   207
              }else if( nId==4 && sqlite3StrNICmp(zSql, "temp", 4)==0 ){
ds@1952
   208
                token = tkTEMP;
ds@1952
   209
              }else if( nId==9 && sqlite3StrNICmp(zSql, "temporary", 9)==0 ){
ds@1952
   210
                token = tkTEMP;
ds@1952
   211
              }else{
ds@1952
   212
                token = tkOTHER;
ds@1952
   213
              }
ds@1952
   214
              break;
ds@1952
   215
            }
ds@1952
   216
            case 'e':  case 'E': {
ds@1952
   217
              if( nId==3 && sqlite3StrNICmp(zSql, "end", 3)==0 ){
ds@1952
   218
                token = tkEND;
ds@1952
   219
              }else
ds@1952
   220
#ifndef SQLITE_OMIT_EXPLAIN
ds@1952
   221
              if( nId==7 && sqlite3StrNICmp(zSql, "explain", 7)==0 ){
ds@1952
   222
                token = tkEXPLAIN;
ds@1952
   223
              }else
ds@1952
   224
#endif
ds@1952
   225
              {
ds@1952
   226
                token = tkOTHER;
ds@1952
   227
              }
ds@1952
   228
              break;
ds@1952
   229
            }
ds@1952
   230
            default: {
ds@1952
   231
              token = tkOTHER;
ds@1952
   232
              break;
ds@1952
   233
            }
ds@1952
   234
          }
ds@1952
   235
#endif /* SQLITE_OMIT_TRIGGER */
ds@1952
   236
          zSql += nId-1;
ds@1952
   237
        }else{
ds@1952
   238
          /* Operators and special symbols */
ds@1952
   239
          token = tkOTHER;
ds@1952
   240
        }
ds@1952
   241
        break;
ds@1952
   242
      }
ds@1952
   243
    }
ds@1952
   244
    state = trans[state][token];
ds@1952
   245
    zSql++;
ds@1952
   246
  }
ds@1952
   247
  return state==0;
ds@1952
   248
}
ds@1952
   249
ds@1952
   250
#ifndef SQLITE_OMIT_UTF16
ds@1952
   251
/*
ds@1952
   252
** This routine is the same as the sqlite3_complete() routine described
ds@1952
   253
** above, except that the parameter is required to be UTF-16 encoded, not
ds@1952
   254
** UTF-8.
ds@1952
   255
*/
ds@1952
   256
int sqlite3_complete16(const void *zSql){
ds@1952
   257
  sqlite3_value *pVal;
ds@1952
   258
  char const *zSql8;
ds@1952
   259
  int rc = SQLITE_NOMEM;
ds@1952
   260
ds@1952
   261
  pVal = sqlite3ValueNew(0);
ds@1952
   262
  sqlite3ValueSetStr(pVal, -1, zSql, SQLITE_UTF16NATIVE, SQLITE_STATIC);
ds@1952
   263
  zSql8 = sqlite3ValueText(pVal, SQLITE_UTF8);
ds@1952
   264
  if( zSql8 ){
ds@1952
   265
    rc = sqlite3_complete(zSql8);
ds@1952
   266
  }
ds@1952
   267
  sqlite3ValueFree(pVal);
ds@1952
   268
  return sqlite3ApiExit(0, rc);
ds@1952
   269
}
ds@1952
   270
#endif /* SQLITE_OMIT_UTF16 */
ds@1952
   271
#endif /* SQLITE_OMIT_COMPLETE */