From 2268626c20260e88cab9b7830f8a06101fa7172a Mon Sep 17 00:00:00 2001 From: Nick Galbreath Date: Sun, 25 Aug 2013 15:30:19 +0900 Subject: [PATCH] libinjection sync --- apache2/libinjection/libinjection.h | 14 +- apache2/libinjection/libinjection_sqli.c | 381 ++++++---- apache2/libinjection/libinjection_sqli_data.h | 719 ++++++++---------- 3 files changed, 568 insertions(+), 546 deletions(-) diff --git a/apache2/libinjection/libinjection.h b/apache2/libinjection/libinjection.h index 4e5690d8..21059604 100644 --- a/apache2/libinjection/libinjection.h +++ b/apache2/libinjection/libinjection.h @@ -19,7 +19,7 @@ extern "C" { * See python's normalized version * http://www.python.org/dev/peps/pep-0386/#normalizedversion */ -#define LIBINJECTION_VERSION "3.4.1" +#define LIBINJECTION_VERSION "3.5.3" /** * Libinjection's sqli module makes a "normalized" @@ -37,6 +37,13 @@ extern "C" { #define LIBINJECTION_SQLI_MAX_TOKENS 5 #endif +#if LIBINJECTION_SQLI_MAX_TOKENS >= 8 +#define LIBINJECTION_SQLI_BUFFER_SZ (LIBINJECTION_SQLI_MAX_TOKENS + 1) +#else +#define LIBINJECTION_SQLI_BUFFER_SZ 8 +#endif + + enum lookup_type { FLAG_NONE = 0, FLAG_QUOTE_NONE = 1 << 1, @@ -119,7 +126,7 @@ typedef struct libinjection_sqli_state { /* MAX TOKENS + 1 since we use one extra token * to determine the type of the previous token */ - stoken_t tokenvec[LIBINJECTION_SQLI_MAX_TOKENS + 1]; + stoken_t tokenvec[LIBINJECTION_SQLI_BUFFER_SZ]; /* * Pointer to token position in tokenvec, above @@ -129,8 +136,9 @@ typedef struct libinjection_sqli_state { /* * fingerprint pattern c-string * +1 for ending null + * Mimimum of 8 bytes to add gcc's -fstack-protector to work */ - char fingerprint[LIBINJECTION_SQLI_MAX_TOKENS + 1]; + char fingerprint[LIBINJECTION_SQLI_BUFFER_SZ]; /* * Line number of code that said decided if the input was SQLi or diff --git a/apache2/libinjection/libinjection_sqli.c b/apache2/libinjection/libinjection_sqli.c index cda40ed0..91e34a65 100644 --- a/apache2/libinjection/libinjection_sqli.c +++ b/apache2/libinjection/libinjection_sqli.c @@ -24,6 +24,7 @@ #define CHAR_NULL '\0' #define CHAR_SINGLE '\'' #define CHAR_DOUBLE '"' +#define CHAR_TICK '`' /* faster than calling out to libc isdigit */ #define ISDIGIT(a) ((unsigned)((a) - '0') <= 9) @@ -57,6 +58,9 @@ typedef enum { TYPE_COLLATE = (int)'A', TYPE_LEFTPARENS = (int)'(', TYPE_RIGHTPARENS = (int)')', /* not used? */ + TYPE_LEFTBRACE = (int)'{', + TYPE_RIGHTBRACE = (int)'}', + TYPE_DOT = (int)'.', TYPE_COMMA = (int)',', TYPE_COLON = (int)':', TYPE_SEMICOLON = (int)';', @@ -105,7 +109,7 @@ memchr2(const char *haystack, size_t haystack_len, char c0, char c1) if (cur[1] == c1) { return cur; } else { - cur += 2; //(c0 == c1) ? 1 : 2; + cur += 2; /* (c0 == c1) ? 1 : 2; */ } } else { cur += 1; @@ -120,14 +124,11 @@ memchr2(const char *haystack, size_t haystack_len, char c0, char c1) static const char * my_memmem(const char* haystack, size_t hlen, const char* needle, size_t nlen) { - const char* cur = NULL; - const char* last = NULL; - - if(nlen < 1 || needle == NULL || haystack == NULL) - return NULL; - - last = haystack + hlen - nlen; - + assert(haystack); + assert(needle); + assert(nlen > 1); + const char* cur; + const char* last = haystack + hlen - nlen; for (cur = haystack; cur <= last; ++cur) { if (cur[0] == needle[0] && memcmp(cur, needle, nlen) == 0) { return cur; @@ -135,6 +136,7 @@ my_memmem(const char* haystack, size_t hlen, const char* needle, size_t nlen) } return NULL; } + /** Find largest string containing certain characters. * * C Standard library 'strspn' only works for 'c-strings' (null terminated) @@ -216,7 +218,7 @@ static int cstrcasecmp(const char *a, const char *b, size_t n) return -1; } } - //printf("off the edge\n"); + return (*a == 0) ? 0 : 1; } @@ -329,7 +331,7 @@ static int st_is_unary_op(const stoken_t * st) case 2: return str[0] == '!' && str[1] == '!'; case 3: - return cstrcasecmp("NOT", str, len) == 0; + return cstrcasecmp("NOT", str, 3) == 0; default: return FALSE; } @@ -485,7 +487,6 @@ static size_t parse_slash(sfilter * sf) const char* cur = cs + pos; char ctype = TYPE_COMMENT; size_t pos1 = pos + 1; - const char *ptr; if (pos1 == slen || cs[pos1] != '*') { return parse_operator1(sf); } @@ -493,12 +494,17 @@ static size_t parse_slash(sfilter * sf) /* * skip over initial '/x' */ - ptr = memchr2(cur + 2, slen - (pos + 2), '*', '/'); - if (ptr == NULL) { + const char* ptr = memchr2(cur + 2, slen - (pos + 2), '*', '/'); + + /* + * (ptr == NULL) causes false positive in cppcheck 1.61 + * casting to type seems to fix it + */ + if (ptr == (const char*) NULL) { /* till end of line */ clen = slen - pos; } else { - clen = (ptr +2) - cur; + clen = (ptr + 2) - cur; } /* @@ -704,35 +710,6 @@ static size_t parse_estring(sfilter * sf) return parse_string_core(cs, slen, pos, sf->current, CHAR_SINGLE, 2); } -/** MySQL ad-hoc character encoding - * - * if something starts with a underscore - * check to see if it's in this form - * _[a-z0-9] and if it's a character encoding - * If not, let the normal 'word parser' - * handle it. - */ -static size_t parse_underscore(sfilter *sf) -{ - char ch; - const char *cs = sf->s; - size_t slen = sf->slen; - size_t pos = sf->pos; - - size_t xlen = strlenspn(cs + pos + 1, slen - pos - 1, - "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"); - if (xlen == 0) { - return parse_word(sf); - } - st_assign(sf->current, TYPE_BAREWORD, pos, xlen, cs + pos); - ch = sf->lookup(sf, LOOKUP_TYPE, sf->current->val, sf->current->len); - if (ch == TYPE_SQLTYPE) { - sf->current->type = TYPE_SQLTYPE; - return xlen + 1; - } - return parse_word(sf); -} - static size_t parse_ustring(sfilter * sf) { const char *cs = sf->s; @@ -774,7 +751,11 @@ static size_t parse_qstring_core(sfilter * sf, int offset) } ch = cs[pos + 2]; - if (ch < 33 || ch > 127) { + + /* the ch > 127 is un-needed since + * we assume char is signed + */ + if (ch < 33 /* || ch > 127 */) { return parse_word(sf); } switch (ch) { @@ -884,7 +865,7 @@ static size_t parse_word(sfilter * sf) const char *cs = sf->s; size_t pos = sf->pos; size_t wlen = strlencspn(cs + pos, sf->slen - pos, - " <>:\\?=@!#~+-*/&|^%(),';\t\n\v\f\r\"\000"); + " {}<>:\\?=@!#~+-*/&|^%(),';\t\n\v\f\r\"\000"); st_assign(sf->current, TYPE_BAREWORD, pos, wlen, cs + pos); @@ -914,7 +895,6 @@ static size_t parse_word(sfilter * sf) if (wlen < LIBINJECTION_SQLI_TOKEN_SIZE) { ch = sf->lookup(sf, LOOKUP_WORD, sf->current->val, wlen); - if (ch == CHAR_NULL) { ch = TYPE_BAREWORD; } @@ -929,7 +909,7 @@ static size_t parse_word(sfilter * sf) */ static size_t parse_tick(sfilter* sf) { - size_t pos = parse_string_core(sf->s, sf->slen, sf->pos, sf->current, '`', 1); + size_t pos = parse_string_core(sf->s, sf->slen, sf->pos, sf->current, CHAR_TICK, 1); /* we could check to see if start and end of * of string are both "`", i.e. make sure we have @@ -948,7 +928,7 @@ static size_t parse_tick(sfilter* sf) /* otherwise it's a 'n' type -- mysql treats * everything as a bare word */ - sf->current->type = TYPE_STRING; + sf->current->type = TYPE_BAREWORD; } return pos; } @@ -1091,6 +1071,9 @@ static size_t parse_number(sfilter * sf) const char *cs = sf->s; const size_t slen = sf->slen; size_t pos = sf->pos; + int have_dot = 0; + int have_e = 0; + int have_exp = 0; /* cs[pos] == '0' has 1/10 chance of being true, * while pos+1< slen is almost always true @@ -1120,23 +1103,27 @@ static size_t parse_number(sfilter * sf) } if (pos < slen && cs[pos] == '.') { + have_dot = 1; pos += 1; while (pos < slen && ISDIGIT(cs[pos])) { pos += 1; } if (pos - start == 1) { - st_assign_char(sf->current, TYPE_BAREWORD, start, 1, '.'); + /* only one character read so far */ + st_assign_char(sf->current, TYPE_DOT, start, 1, '.'); return pos; } } if (pos < slen) { if (cs[pos] == 'E' || cs[pos] == 'e') { + have_e = 1; pos += 1; if (pos < slen && (cs[pos] == '+' || cs[pos] == '-')) { pos += 1; } while (pos < slen && ISDIGIT(cs[pos])) { + have_exp = 1; pos += 1; } } @@ -1145,13 +1132,36 @@ static size_t parse_number(sfilter * sf) /* oracle's ending float or double suffix * http://docs.oracle.com/cd/B19306_01/server.102/b14200/sql_elements003.htm#i139891 */ - if (pos < slen) { - if (cs[pos] == 'd' || cs[pos] == 'D' || cs[pos] == 'f' || cs[pos] == 'F') { + if (pos < slen && (cs[pos] == 'd' || cs[pos] == 'D' || cs[pos] == 'f' || cs[pos] == 'F')) { + if (pos + 1 == slen) { + /* line ends evaluate "... 1.2f$" as '1.2f' */ pos += 1; + } else if ((char_is_white(cs[pos+1]) || cs[pos+1] == ';')) { + /* + * easy case, evaluate "... 1.2f ... as '1.2f' + */ + pos += 1; + } else if (cs[pos+1] == 'u' || cs[pos+1] == 'U') { + /* + * a bit of a hack but makes '1fUNION' parse as '1f UNION' + */ + pos += 1; + } else { + /* it's like "123FROM" */ + /* parse as "123" only */ } } - st_assign(sf->current, TYPE_NUMBER, start, pos - start, cs + start); + if (have_dot == 1 && have_e == 1 && have_exp == 0) { + /* very special form of + * "1234.e" + * "10.10E" + * ".E" + * this is a WORD not a number!! */ + st_assign(sf->current, TYPE_BAREWORD, start, pos - start, cs + start); + } else { + st_assign(sf->current, TYPE_NUMBER, start, pos - start, cs + start); + } return pos; } @@ -1235,12 +1245,15 @@ void libinjection_sqli_init(sfilter * sf, const char *s, size_t len, int flags) void libinjection_sqli_reset(sfilter * sf, int flags) { + ptr_lookup_fn lookup = sf->lookup;; + void *userdata = sf->userdata; + if (flags == 0) { flags = FLAG_QUOTE_NONE | FLAG_SQL_ANSI; } libinjection_sqli_init(sf, sf->s, sf->slen, flags); - sf->lookup = sf->lookup; - sf->userdata = sf->userdata; + sf->lookup = lookup; + sf->userdata = userdata; } void libinjection_sqli_callback(sfilter * sf, ptr_lookup_fn fn, void* userdata) @@ -1280,14 +1293,20 @@ static int syntax_merge_words(sfilter * sf,stoken_t * a, stoken_t * b) /* first token is of right type? */ if (! - (a->type == TYPE_KEYWORD || a->type == TYPE_BAREWORD || a->type == TYPE_OPERATOR || - a->type == TYPE_UNION || a->type == TYPE_EXPRESSION || a->type == TYPE_SQLTYPE)) { + (a->type == TYPE_KEYWORD || + a->type == TYPE_BAREWORD || + a->type == TYPE_OPERATOR || + a->type == TYPE_UNION || + a->type == TYPE_FUNCTION || + a->type == TYPE_EXPRESSION || + a->type == TYPE_SQLTYPE)) { return CHAR_NULL; } if (b->type != TYPE_KEYWORD && b->type != TYPE_BAREWORD && b->type != TYPE_OPERATOR && b->type != TYPE_SQLTYPE && b->type != TYPE_LOGIC_OPERATOR && + b->type != TYPE_FUNCTION && b->type != TYPE_UNION && b->type != TYPE_EXPRESSION) { return CHAR_NULL; } @@ -1351,7 +1370,54 @@ int libinjection_sqli_fold(sfilter * sf) } while (1) { - FOLD_DEBUG + FOLD_DEBUG; + + /* do we have all the max number of tokens? if so do + * some special cases for 5 tokens + */ + if (pos >= LIBINJECTION_SQLI_MAX_TOKENS) { + if ( + ( + sf->tokenvec[0].type == TYPE_NUMBER && + (sf->tokenvec[1].type == TYPE_OPERATOR || sf->tokenvec[1].type == TYPE_COMMA) && + sf->tokenvec[2].type == TYPE_LEFTPARENS && + sf->tokenvec[3].type == TYPE_NUMBER && + sf->tokenvec[4].type == TYPE_RIGHTPARENS + ) || + ( + sf->tokenvec[0].type == TYPE_BAREWORD && + sf->tokenvec[1].type == TYPE_OPERATOR && + sf->tokenvec[2].type == TYPE_LEFTPARENS && + (sf->tokenvec[3].type == TYPE_BAREWORD || sf->tokenvec[3].type == TYPE_NUMBER) && + sf->tokenvec[4].type == TYPE_RIGHTPARENS + ) || + ( + sf->tokenvec[0].type == TYPE_NUMBER && + sf->tokenvec[1].type == TYPE_RIGHTPARENS && + sf->tokenvec[2].type == TYPE_COMMA && + sf->tokenvec[3].type == TYPE_LEFTPARENS && + sf->tokenvec[4].type == TYPE_NUMBER + ) + ) + { + if (pos > LIBINJECTION_SQLI_MAX_TOKENS) { + //printf("TRUNCATE pos = %lu vs. %lu\n", pos, LIBINJECTION_SQLI_MAX_TOKENS); + st_copy(&(sf->tokenvec[1]), &(sf->tokenvec[LIBINJECTION_SQLI_MAX_TOKENS])); + pos = 2; + left = 0; + } else { + //printf("HEREIAM\n"); + pos = 1; + left = 0; + } + } + } + + if (! more || left >= LIBINJECTION_SQLI_MAX_TOKENS) { + left = pos; + break; + } + /* get up to two tokens */ while (more && pos <= LIBINJECTION_SQLI_MAX_TOKENS && (pos - left) < 2) { sf->current = &(sf->tokenvec[pos]); @@ -1365,11 +1431,11 @@ int libinjection_sqli_fold(sfilter * sf) } } } - FOLD_DEBUG + FOLD_DEBUG; /* did we get 2 tokens? if not then we are done */ if (pos - left < 2) { left = pos; - break; + continue; } /* FOLD: "ss" -> "s" @@ -1399,15 +1465,15 @@ int libinjection_sqli_fold(sfilter * sf) sf->tokenvec[left+1].type = TYPE_TSQL; left += 2; continue; /* reparse everything, but we probably can advance left, and pos */ - } else if ((sf->tokenvec[left].type ==TYPE_OPERATOR || sf->tokenvec[left].type ==TYPE_LOGIC_OPERATOR) && + } else if ((sf->tokenvec[left].type ==TYPE_OPERATOR || + sf->tokenvec[left].type ==TYPE_LOGIC_OPERATOR) && st_is_unary_op(&sf->tokenvec[left+1])) { pos -= 1; sf->stats_folds += 1; - if (left > 0) { - left -= 1; - } + left = 0; continue; - } else if (sf->tokenvec[left].type ==TYPE_LEFTPARENS && st_is_unary_op(&sf->tokenvec[left+1])) { + } else if (sf->tokenvec[left].type ==TYPE_LEFTPARENS && + st_is_unary_op(&sf->tokenvec[left+1])) { pos -= 1; sf->stats_folds += 1; if (left > 0) { @@ -1444,9 +1510,10 @@ int libinjection_sqli_fold(sfilter * sf) cstrcasecmp("LOCALTIMESTAMP", sf->tokenvec[left].val, sf->tokenvec[left].len) == 0 )) { - // pos is the same - // other conversions need to go here... for instance - // password CAN be a function, coalese CAN be a function + /* pos is the same + * other conversions need to go here... for instance + * password CAN be a function, coalese CAN be a function + */ sf->tokenvec[left].type = TYPE_FUNCTION; continue; } else if (sf->tokenvec[left].type == TYPE_KEYWORD && ( @@ -1478,8 +1545,10 @@ int libinjection_sqli_fold(sfilter * sf) */ continue; } else if (sf->tokenvec[left].type == TYPE_SQLTYPE && - (sf->tokenvec[left+1].type == TYPE_BAREWORD || sf->tokenvec[left+1].type == TYPE_NUMBER || - sf->tokenvec[left+1].type == TYPE_VARIABLE || sf->tokenvec[left+1].type == TYPE_STRING)) { + (sf->tokenvec[left+1].type == TYPE_BAREWORD || + sf->tokenvec[left+1].type == TYPE_NUMBER || + sf->tokenvec[left+1].type == TYPE_VARIABLE || + sf->tokenvec[left+1].type == TYPE_STRING)) { st_copy(&sf->tokenvec[left], &sf->tokenvec[left+1]); pos -= 1; sf->stats_folds += 1; @@ -1506,12 +1575,37 @@ int libinjection_sqli_fold(sfilter * sf) } left = 0; continue; + } else if (sf->tokenvec[left].type == TYPE_LEFTPARENS && + sf->tokenvec[left+1].type == TYPE_LEFTPARENS) { + pos -= 1; + sf->stats_folds += 1; + continue; + } else if (sf->tokenvec[left].type == TYPE_RIGHTPARENS && + sf->tokenvec[left+1].type == TYPE_RIGHTPARENS) { + pos -= 1; + sf->stats_folds += 1; + continue; + } else if (sf->tokenvec[left].type == TYPE_LEFTBRACE && + sf->tokenvec[left+1].type == TYPE_BAREWORD) { + /* weird ODBC / MYSQL {foo expr} --> expr + * but for this rule we just strip away the "{ foo" part + */ + if (left > 0) { + left -= 1; + } + pos -= 2; + sf->stats_folds += 2; + continue; + } else if (sf->tokenvec[left+1].type == TYPE_RIGHTBRACE) { + pos -= 1; + sf->stats_folds += 1; + continue; } /* all cases of handing 2 tokens is done and nothing matched. Get one more token */ - FOLD_DEBUG + FOLD_DEBUG; while (more && pos <= LIBINJECTION_SQLI_MAX_TOKENS && pos - left < 3) { sf->current = &(sf->tokenvec[pos]); more = libinjection_sqli_tokenize(sf); @@ -1528,7 +1622,7 @@ int libinjection_sqli_fold(sfilter * sf) /* do we have three tokens? If not then we are done */ if (pos -left < 3) { left = pos; - break; + continue; } /* @@ -1553,25 +1647,37 @@ int libinjection_sqli_fold(sfilter * sf) continue; } else if (sf->tokenvec[left].type == TYPE_VARIABLE && sf->tokenvec[left+1].type == TYPE_OPERATOR && - (sf->tokenvec[left+2].type == TYPE_VARIABLE || sf->tokenvec[left+2].type == TYPE_NUMBER || + (sf->tokenvec[left+2].type == TYPE_VARIABLE || + sf->tokenvec[left+2].type == TYPE_NUMBER || sf->tokenvec[left+2].type == TYPE_BAREWORD)) { pos -= 2; continue; - } else if ((sf->tokenvec[left].type == TYPE_BAREWORD || sf->tokenvec[left].type == TYPE_NUMBER ) && + } else if ((sf->tokenvec[left].type == TYPE_BAREWORD || + sf->tokenvec[left].type == TYPE_NUMBER ) && sf->tokenvec[left+1].type == TYPE_OPERATOR && - (sf->tokenvec[left+2].type == TYPE_NUMBER || sf->tokenvec[left+2].type == TYPE_BAREWORD)) { + (sf->tokenvec[left+2].type == TYPE_NUMBER || + sf->tokenvec[left+2].type == TYPE_BAREWORD)) { pos -= 2; continue; - } else if ((sf->tokenvec[left].type == TYPE_BAREWORD || sf->tokenvec[left].type == TYPE_NUMBER || - sf->tokenvec[left].type == TYPE_VARIABLE || sf->tokenvec[left].type == TYPE_STRING) && - sf->tokenvec[left+1].type == TYPE_OPERATOR && streq(sf->tokenvec[left+1].val, "::") && + } else if ((sf->tokenvec[left].type == TYPE_BAREWORD || + sf->tokenvec[left].type == TYPE_NUMBER || + sf->tokenvec[left].type == TYPE_VARIABLE || + sf->tokenvec[left].type == TYPE_STRING) && + sf->tokenvec[left+1].type == TYPE_OPERATOR && + streq(sf->tokenvec[left+1].val, "::") && sf->tokenvec[left+2].type == TYPE_SQLTYPE) { pos -= 2; sf->stats_folds += 2; continue; - } else if ((sf->tokenvec[left].type == TYPE_BAREWORD || sf->tokenvec[left].type == TYPE_NUMBER || sf->tokenvec[left].type == TYPE_STRING) && + } else if ((sf->tokenvec[left].type == TYPE_BAREWORD || + sf->tokenvec[left].type == TYPE_NUMBER || + sf->tokenvec[left].type == TYPE_STRING || + sf->tokenvec[left].type == TYPE_VARIABLE) && sf->tokenvec[left+1].type == TYPE_COMMA && - (sf->tokenvec[left+2].type == TYPE_NUMBER || sf->tokenvec[left+2].type == TYPE_BAREWORD || sf->tokenvec[left+2].type == TYPE_STRING)) { + (sf->tokenvec[left+2].type == TYPE_NUMBER || + sf->tokenvec[left+2].type == TYPE_BAREWORD || + sf->tokenvec[left+2].type == TYPE_STRING || + sf->tokenvec[left+2].type == TYPE_VARIABLE)) { pos -= 2; if (left > 0) { left -= 1; @@ -1597,8 +1703,9 @@ int libinjection_sqli_fold(sfilter * sf) sf->tokenvec[left+2].type == TYPE_VARIABLE || sf->tokenvec[left+2].type == TYPE_STRING || sf->tokenvec[left+2].type == TYPE_FUNCTION )) { - // remove unary operators - // select - 1 + /* remove unary operators + * select - 1 + */ st_copy(&sf->tokenvec[left+1], &sf->tokenvec[left+2]); pos -= 1; continue; @@ -1622,14 +1729,22 @@ int libinjection_sqli_fold(sfilter * sf) assert(pos >= 3); pos -= 3; continue; - } else if ((sf->tokenvec[left].type == TYPE_BAREWORD || sf->tokenvec[left].type == TYPE_STRING)&& - (sf->tokenvec[left+1].type == TYPE_BAREWORD && sf->tokenvec[left+1].val[0] == '.') && - (sf->tokenvec[left+2].type == TYPE_BAREWORD || sf->tokenvec[left].type == TYPE_STRING)) { + } else if ((sf->tokenvec[left].type == TYPE_BAREWORD) && + (sf->tokenvec[left+1].type == TYPE_DOT) && + (sf->tokenvec[left+2].type == TYPE_BAREWORD)) { /* ignore the '.n' - * typically is this dabasename.table + * typically is this databasename.table */ + assert(pos >= 3); pos -= 2; continue; + } else if ((sf->tokenvec[left].type == TYPE_EXPRESSION) && + (sf->tokenvec[left+1].type == TYPE_DOT) && + (sf->tokenvec[left+2].type == TYPE_BAREWORD)) { + /* select . `foo` --> select `foo` */ + st_copy(&sf->tokenvec[left+1], &sf->tokenvec[left+2]); + pos -= 1; + continue; } @@ -1679,6 +1794,23 @@ const char* libinjection_sqli_fingerprint(sfilter * sql_state, int flags) libinjection_sqli_reset(sql_state, flags); tlen = libinjection_sqli_fold(sql_state); + + /* Check for magic PHP backquote comment + * If: + * * last token is of type "bareword" + * * And is quoted in a backtick + * * And isn't closed + * * And it's empty? + * Then convert it to comment + */ + if (tlen > 2 && + sql_state->tokenvec[tlen-1].type == TYPE_BAREWORD && + sql_state->tokenvec[tlen-1].str_open == CHAR_TICK && + sql_state->tokenvec[tlen-1].len == 0 && + sql_state->tokenvec[tlen-1].str_close == CHAR_NULL) { + sql_state->tokenvec[tlen-1].type = TYPE_COMMENT; + } + for (i = 0; i < tlen; ++i) { sql_state->fingerprint[i] = sql_state->tokenvec[i].type; } @@ -1709,6 +1841,7 @@ const char* libinjection_sqli_fingerprint(sfilter * sql_state, int flags) sql_state->tokenvec[1].type = CHAR_NULL; } + return sql_state->fingerprint; } @@ -1736,10 +1869,13 @@ char libinjection_sqli_lookup_word(sfilter *sql_state, int lookup_type, int libinjection_sqli_blacklist(sfilter* sql_state) { - char fp2[LIBINJECTION_SQLI_MAX_TOKENS + 2]; + /* + * use minimum of 8 bytes to make sure gcc -fstack-protector + * works correctly + */ + char fp2[LIBINJECTION_SQLI_MAX_TOKENS + 2 < 8 ? 8 : LIBINJECTION_SQLI_MAX_TOKENS + 2]; char ch; size_t i; - int patmatch = 0; size_t len = strlen(sql_state->fingerprint); if (len < 1) { @@ -1764,7 +1900,7 @@ int libinjection_sqli_blacklist(sfilter* sql_state) } fp2[i+1] = '\0'; - patmatch = is_keyword(fp2, len + 1) == TYPE_FINGERPRINT; + int patmatch = is_keyword(fp2, len + 1) == TYPE_FINGERPRINT; /* * No match. @@ -1793,6 +1929,21 @@ int libinjection_sqli_not_whitelist(sfilter* sql_state) char ch; size_t tlen = strlen(sql_state->fingerprint); + if (tlen > 1 && sql_state->fingerprint[tlen-1] == TYPE_COMMENT) { + /* + * if ending comment is contains 'sp_password' then it's sqli! + * MS Audit log appearantly ignores anything with + * 'sp_password' in it. Unable to find primary refernece to + * this "feature" of SQL Server but seems to be known sqli + * technique + */ + if (my_memmem(sql_state->s, sql_state->slen, + "sp_password", strlen("sp_password"))) { + sql_state->reason = __LINE__; + return TRUE; + } + } + switch (tlen) { case 2:{ /* @@ -1825,20 +1976,6 @@ int libinjection_sqli_not_whitelist(sfilter* sql_state) return FALSE; } - /* - * if ending comment is contains 'sp_password' then it's sqli! - * MS Audit log appearantly ignores anything with - * 'sp_password' in it. Unable to find primary refernece to - * this "feature" of SQL Server but seems to be known sqli - * technique - */ - if (sql_state->tokenvec[1].type == TYPE_COMMENT && - my_memmem(sql_state->tokenvec[1].val, sql_state->tokenvec[1].len, - "sp_password", strlen("sp_password"))) { - sql_state->reason = __LINE__; - return TRUE; - } - /* * for fingerprint like 'nc', only comments of /x are treated * as SQL... ending comments of "--" and "#" are not sqli @@ -1859,19 +1996,6 @@ int libinjection_sqli_not_whitelist(sfilter* sql_state) return TRUE; } - /* - * if 'oc' then input must be 'CASE/x' - * used in HPP attack - */ - if (sql_state->tokenvec[0].type == TYPE_OPERATOR && - sql_state->tokenvec[1].type == TYPE_COMMENT && - sql_state->tokenvec[1].val[0] == '/' && - cstrcasecmp("CASE", sql_state->tokenvec[0].val, sql_state->tokenvec[0].len) != 0) - { - sql_state->reason = __LINE__; - return FALSE; - } - /** * there are some odd base64-looking query string values * 1234-ABCDEFEhfhihwuefi-- @@ -1955,8 +2079,11 @@ int libinjection_sqli_not_whitelist(sfilter* sql_state) */ sql_state->reason = __LINE__; return FALSE; - } else if (streq(sql_state->fingerprint, "s&n") || streq(sql_state->fingerprint, "n&1") || streq(sql_state->fingerprint, "1&1") || - streq(sql_state->fingerprint, "1&v") || streq(sql_state->fingerprint, "1&s")) { + } else if (streq(sql_state->fingerprint, "s&n") || + streq(sql_state->fingerprint, "n&1") || + streq(sql_state->fingerprint, "1&1") || + streq(sql_state->fingerprint, "1&v") || + streq(sql_state->fingerprint, "1&s")) { /* 'sexy and 17' not sqli * 'sexy and 17<18' sqli */ @@ -1964,12 +2091,6 @@ int libinjection_sqli_not_whitelist(sfilter* sql_state) sql_state->reason = __LINE__; return FALSE; } - } else if (streq(sql_state->fingerprint, "so1")) { - if (sql_state->tokenvec[0].str_open != CHAR_NULL) { - /* "foo" -1 is ok, foo"-1 is not */ - sql_state->reason = __LINE__; - return FALSE; - } } else if (sql_state->tokenvec[1].type == TYPE_KEYWORD) { if ((sql_state->tokenvec[1].len < 5) || cstrcasecmp("INTO", sql_state->tokenvec[1].val, 4)) { @@ -1983,18 +2104,6 @@ int libinjection_sqli_not_whitelist(sfilter* sql_state) break; } /* case 3 */ case 4: - if (streq(sql_state->fingerprint, "s&1s")) { - /* look for ...foo" and 1=1 ` - * where the ending string is actually a comment in - * php mysql magic land. This check is needed - * since normal non sqli text often folds to - * s&1s.. this check figures that out - */ - if (sql_state->stats_tokens == 4) { - sql_state->reason = __LINE__; - return FALSE; - } - } case 5: { /* nothing right now */ break; diff --git a/apache2/libinjection/libinjection_sqli_data.h b/apache2/libinjection/libinjection_sqli_data.h index 49e910cc..20e1a5f6 100644 --- a/apache2/libinjection/libinjection_sqli_data.h +++ b/apache2/libinjection/libinjection_sqli_data.h @@ -24,7 +24,6 @@ static size_t parse_word(sfilter * sf); static size_t parse_var(sfilter * sf); static size_t parse_number(sfilter * sf); static size_t parse_tick(sfilter * sf); -static size_t parse_underscore(sfilter * sf); static size_t parse_ustring(sfilter * sf); static size_t parse_qstring(sfilter * sf); static size_t parse_nqstring(sfilter * sf); @@ -130,7 +129,7 @@ static const pt2Function char_parse_map[] = { &parse_backslash, /* 92 */ &parse_other, /* 93 */ &parse_operator1, /* 94 */ - &parse_underscore, /* 95 */ + &parse_word, /* 95 */ &parse_tick, /* 96 */ &parse_word, /* 97 */ &parse_bstring, /* 98 */ @@ -158,9 +157,9 @@ static const pt2Function char_parse_map[] = { &parse_xstring, /* 120 */ &parse_word, /* 121 */ &parse_word, /* 122 */ - &parse_other, /* 123 */ + &parse_char, /* 123 */ &parse_operator2, /* 124 */ - &parse_other, /* 125 */ + &parse_char, /* 125 */ &parse_operator1, /* 126 */ &parse_white, /* 127 */ }; @@ -192,7 +191,6 @@ static const keyword_t sql_keywords[] = { {"0&((SO", 'F'}, {"0&((V)", 'F'}, {"0&((VO", 'F'}, - {"0&(1))", 'F'}, {"0&(1)O", 'F'}, {"0&(1)U", 'F'}, {"0&(1O(", 'F'}, @@ -206,14 +204,12 @@ static const keyword_t sql_keywords[] = { {"0&(F(N", 'F'}, {"0&(F(S", 'F'}, {"0&(F(V", 'F'}, - {"0&(N))", 'F'}, {"0&(N)O", 'F'}, {"0&(N)U", 'F'}, {"0&(NO(", 'F'}, {"0&(NOF", 'F'}, {"0&(NOS", 'F'}, {"0&(NOV", 'F'}, - {"0&(S))", 'F'}, {"0&(S)O", 'F'}, {"0&(S)U", 'F'}, {"0&(SO(", 'F'}, @@ -222,7 +218,6 @@ static const keyword_t sql_keywords[] = { {"0&(SON", 'F'}, {"0&(SOS", 'F'}, {"0&(SOV", 'F'}, - {"0&(V))", 'F'}, {"0&(V)O", 'F'}, {"0&(V)U", 'F'}, {"0&(VO(", 'F'}, @@ -260,7 +255,6 @@ static const keyword_t sql_keywords[] = { {"0&F((N", 'F'}, {"0&F((S", 'F'}, {"0&F((V", 'F'}, - {"0&F())", 'F'}, {"0&F()O", 'F'}, {"0&F()U", 'F'}, {"0&F(1)", 'F'}, @@ -354,16 +348,6 @@ static const keyword_t sql_keywords[] = { {"0&VUEN", 'F'}, {"0&VUES", 'F'}, {"0&VUEV", 'F'}, - {"0)))))", 'F'}, - {"0))))U", 'F'}, - {"0)))UE", 'F'}, - {"0))UE(", 'F'}, - {"0))UE1", 'F'}, - {"0))UEF", 'F'}, - {"0))UEK", 'F'}, - {"0))UEN", 'F'}, - {"0))UES", 'F'}, - {"0))UEV", 'F'}, {"0)UE((", 'F'}, {"0)UE(1", 'F'}, {"0)UE(F", 'F'}, @@ -425,7 +409,7 @@ static const keyword_t sql_keywords[] = { {"01&1&S", 'F'}, {"01&1&V", 'F'}, {"01&1)&", 'F'}, - {"01&1))", 'F'}, + {"01&1)O", 'F'}, {"01&1)U", 'F'}, {"01&1;", 'F'}, {"01&1;C", 'F'}, @@ -497,6 +481,7 @@ static const keyword_t sql_keywords[] = { {"01&F((", 'F'}, {"01&F()", 'F'}, {"01&F(1", 'F'}, + {"01&F(E", 'F'}, {"01&F(F", 'F'}, {"01&F(N", 'F'}, {"01&F(S", 'F'}, @@ -532,7 +517,7 @@ static const keyword_t sql_keywords[] = { {"01&N&S", 'F'}, {"01&N&V", 'F'}, {"01&N)&", 'F'}, - {"01&N))", 'F'}, + {"01&N)O", 'F'}, {"01&N)U", 'F'}, {"01&N;", 'F'}, {"01&N;C", 'F'}, @@ -571,7 +556,7 @@ static const keyword_t sql_keywords[] = { {"01&S&S", 'F'}, {"01&S&V", 'F'}, {"01&S)&", 'F'}, - {"01&S))", 'F'}, + {"01&S)O", 'F'}, {"01&S)U", 'F'}, {"01&S1", 'F'}, {"01&S1;", 'F'}, @@ -614,6 +599,12 @@ static const keyword_t sql_keywords[] = { {"01&SV;", 'F'}, {"01&SVC", 'F'}, {"01&SVO", 'F'}, + {"01&T((", 'F'}, + {"01&T(1", 'F'}, + {"01&T(F", 'F'}, + {"01&T(N", 'F'}, + {"01&T(S", 'F'}, + {"01&T(V", 'F'}, {"01&V", 'F'}, {"01&V&(", 'F'}, {"01&V&1", 'F'}, @@ -622,7 +613,7 @@ static const keyword_t sql_keywords[] = { {"01&V&S", 'F'}, {"01&V&V", 'F'}, {"01&V)&", 'F'}, - {"01&V))", 'F'}, + {"01&V)O", 'F'}, {"01&V)U", 'F'}, {"01&V;", 'F'}, {"01&V;C", 'F'}, @@ -712,53 +703,6 @@ static const keyword_t sql_keywords[] = { {"01)&VF", 'F'}, {"01)&VO", 'F'}, {"01)&VU", 'F'}, - {"01))&(", 'F'}, - {"01))&1", 'F'}, - {"01))&F", 'F'}, - {"01))&N", 'F'}, - {"01))&S", 'F'}, - {"01))&V", 'F'}, - {"01)))&", 'F'}, - {"01))))", 'F'}, - {"01))),", 'F'}, - {"01)));", 'F'}, - {"01)))B", 'F'}, - {"01)))E", 'F'}, - {"01)))K", 'F'}, - {"01)))O", 'F'}, - {"01)))U", 'F'}, - {"01)),(", 'F'}, - {"01));E", 'F'}, - {"01));T", 'F'}, - {"01))B(", 'F'}, - {"01))B1", 'F'}, - {"01))BF", 'F'}, - {"01))BN", 'F'}, - {"01))BS", 'F'}, - {"01))BV", 'F'}, - {"01))E(", 'F'}, - {"01))E1", 'F'}, - {"01))EF", 'F'}, - {"01))EK", 'F'}, - {"01))EN", 'F'}, - {"01))ES", 'F'}, - {"01))EV", 'F'}, - {"01))K(", 'F'}, - {"01))K1", 'F'}, - {"01))KB", 'F'}, - {"01))KF", 'F'}, - {"01))KN", 'F'}, - {"01))KS", 'F'}, - {"01))KU", 'F'}, - {"01))KV", 'F'}, - {"01))O(", 'F'}, - {"01))O1", 'F'}, - {"01))OF", 'F'}, - {"01))ON", 'F'}, - {"01))OS", 'F'}, - {"01))OV", 'F'}, - {"01))U(", 'F'}, - {"01))UE", 'F'}, {"01),((", 'F'}, {"01),(1", 'F'}, {"01),(F", 'F'}, @@ -893,7 +837,6 @@ static const keyword_t sql_keywords[] = { {"01)O1O", 'F'}, {"01)O1U", 'F'}, {"01)OF(", 'F'}, - {"01)ON", 'F'}, {"01)ON&", 'F'}, {"01)ON)", 'F'}, {"01)ON;", 'F'}, @@ -960,7 +903,6 @@ static const keyword_t sql_keywords[] = { {"01,F(S", 'F'}, {"01,F(T", 'F'}, {"01,F(V", 'F'}, - {"01,V))", 'F'}, {"01,V),", 'F'}, {"01,V)O", 'F'}, {"01,VB(", 'F'}, @@ -983,6 +925,7 @@ static const keyword_t sql_keywords[] = { {"01;E1,", 'F'}, {"01;E1;", 'F'}, {"01;E1C", 'F'}, + {"01;E1K", 'F'}, {"01;E1O", 'F'}, {"01;E1T", 'F'}, {"01;EF(", 'F'}, @@ -1003,11 +946,13 @@ static const keyword_t sql_keywords[] = { {"01;ES,", 'F'}, {"01;ES;", 'F'}, {"01;ESC", 'F'}, + {"01;ESK", 'F'}, {"01;ESO", 'F'}, {"01;EST", 'F'}, {"01;EV,", 'F'}, {"01;EV;", 'F'}, {"01;EVC", 'F'}, + {"01;EVK", 'F'}, {"01;EVO", 'F'}, {"01;EVT", 'F'}, {"01;N:T", 'F'}, @@ -1022,6 +967,7 @@ static const keyword_t sql_keywords[] = { {"01;T1;", 'F'}, {"01;T1C", 'F'}, {"01;T1F", 'F'}, + {"01;T1K", 'F'}, {"01;T1O", 'F'}, {"01;T1T", 'F'}, {"01;T;", 'F'}, @@ -1040,7 +986,6 @@ static const keyword_t sql_keywords[] = { {"01;TN1", 'F'}, {"01;TN;", 'F'}, {"01;TNC", 'F'}, - {"01;TNE", 'F'}, {"01;TNF", 'F'}, {"01;TNK", 'F'}, {"01;TNN", 'F'}, @@ -1053,6 +998,7 @@ static const keyword_t sql_keywords[] = { {"01;TS;", 'F'}, {"01;TSC", 'F'}, {"01;TSF", 'F'}, + {"01;TSK", 'F'}, {"01;TSO", 'F'}, {"01;TST", 'F'}, {"01;TT(", 'F'}, @@ -1065,6 +1011,7 @@ static const keyword_t sql_keywords[] = { {"01;TV;", 'F'}, {"01;TVC", 'F'}, {"01;TVF", 'F'}, + {"01;TVK", 'F'}, {"01;TVO", 'F'}, {"01;TVT", 'F'}, {"01A(((", 'F'}, @@ -1364,11 +1311,11 @@ static const keyword_t sql_keywords[] = { {"01F(((", 'F'}, {"01F(()", 'F'}, {"01F((1", 'F'}, + {"01F((E", 'F'}, {"01F((F", 'F'}, {"01F((N", 'F'}, {"01F((S", 'F'}, {"01F((V", 'F'}, - {"01F())", 'F'}, {"01F()1", 'F'}, {"01F()F", 'F'}, {"01F()K", 'F'}, @@ -1380,6 +1327,13 @@ static const keyword_t sql_keywords[] = { {"01F(1)", 'F'}, {"01F(1N", 'F'}, {"01F(1O", 'F'}, + {"01F(E(", 'F'}, + {"01F(E1", 'F'}, + {"01F(EF", 'F'}, + {"01F(EK", 'F'}, + {"01F(EN", 'F'}, + {"01F(ES", 'F'}, + {"01F(EV", 'F'}, {"01F(F(", 'F'}, {"01F(N)", 'F'}, {"01F(N,", 'F'}, @@ -1394,7 +1348,6 @@ static const keyword_t sql_keywords[] = { {"01K((N", 'F'}, {"01K((S", 'F'}, {"01K((V", 'F'}, - {"01K(1)", 'F'}, {"01K(1O", 'F'}, {"01K(F(", 'F'}, {"01K(N)", 'F'}, @@ -1409,14 +1362,6 @@ static const keyword_t sql_keywords[] = { {"01K)&N", 'F'}, {"01K)&S", 'F'}, {"01K)&V", 'F'}, - {"01K))&", 'F'}, - {"01K)))", 'F'}, - {"01K));", 'F'}, - {"01K))B", 'F'}, - {"01K))E", 'F'}, - {"01K))K", 'F'}, - {"01K))O", 'F'}, - {"01K))U", 'F'}, {"01K);E", 'F'}, {"01K);T", 'F'}, {"01K)B(", 'F'}, @@ -1582,9 +1527,6 @@ static const keyword_t sql_keywords[] = { {"01N(SO", 'F'}, {"01N(V)", 'F'}, {"01N(VO", 'F'}, - {"01N)))", 'F'}, - {"01N))N", 'F'}, - {"01N))U", 'F'}, {"01N)UE", 'F'}, {"01N,F(", 'F'}, {"01NE((", 'F'}, @@ -1609,24 +1551,6 @@ static const keyword_t sql_keywords[] = { {"01NF(N", 'F'}, {"01NF(S", 'F'}, {"01NF(V", 'F'}, - {"01NO((", 'F'}, - {"01NO(1", 'F'}, - {"01NO(F", 'F'}, - {"01NO(N", 'F'}, - {"01NO(S", 'F'}, - {"01NO(V", 'F'}, - {"01NOF(", 'F'}, - {"01NOS(", 'F'}, - {"01NOS1", 'F'}, - {"01NOSF", 'F'}, - {"01NOSO", 'F'}, - {"01NOSU", 'F'}, - {"01NOSV", 'F'}, - {"01NOV(", 'F'}, - {"01NOVF", 'F'}, - {"01NOVO", 'F'}, - {"01NOVS", 'F'}, - {"01NOVU", 'F'}, {"01NU((", 'F'}, {"01NU(E", 'F'}, {"01NUE", 'F'}, @@ -1722,13 +1646,13 @@ static const keyword_t sql_keywords[] = { {"01OS&K", 'F'}, {"01OS&N", 'F'}, {"01OS&S", 'F'}, + {"01OS&T", 'F'}, {"01OS&U", 'F'}, {"01OS&V", 'F'}, {"01OS((", 'F'}, {"01OS(E", 'F'}, {"01OS(U", 'F'}, {"01OS)&", 'F'}, - {"01OS))", 'F'}, {"01OS),", 'F'}, {"01OS);", 'F'}, {"01OS)B", 'F'}, @@ -1814,6 +1738,7 @@ static const keyword_t sql_keywords[] = { {"01OT(F", 'F'}, {"01OT(N", 'F'}, {"01OT(S", 'F'}, + {"01OT(T", 'F'}, {"01OT(V", 'F'}, {"01OU((", 'F'}, {"01OU(E", 'F'}, @@ -1827,13 +1752,13 @@ static const keyword_t sql_keywords[] = { {"01OV&K", 'F'}, {"01OV&N", 'F'}, {"01OV&S", 'F'}, + {"01OV&T", 'F'}, {"01OV&U", 'F'}, {"01OV&V", 'F'}, {"01OV((", 'F'}, {"01OV(E", 'F'}, {"01OV(U", 'F'}, {"01OV)&", 'F'}, - {"01OV))", 'F'}, {"01OV),", 'F'}, {"01OV);", 'F'}, {"01OV)B", 'F'}, @@ -2015,6 +1940,7 @@ static const keyword_t sql_keywords[] = { {"01UENC", 'F'}, {"01UENF", 'F'}, {"01UENK", 'F'}, + {"01UENN", 'F'}, {"01UENO", 'F'}, {"01UENS", 'F'}, {"01UENU", 'F'}, @@ -2192,7 +2118,6 @@ static const keyword_t sql_keywords[] = { {"0E((VO", 'F'}, {"0E((VS", 'F'}, {"0E(1)&", 'F'}, - {"0E(1))", 'F'}, {"0E(1),", 'F'}, {"0E(1)1", 'F'}, {"0E(1)F", 'F'}, @@ -2205,7 +2130,6 @@ static const keyword_t sql_keywords[] = { {"0E(1,F", 'F'}, {"0E(1F(", 'F'}, {"0E(1N)", 'F'}, - {"0E(1NO", 'F'}, {"0E(1O(", 'F'}, {"0E(1OF", 'F'}, {"0E(1OS", 'F'}, @@ -2244,7 +2168,6 @@ static const keyword_t sql_keywords[] = { {"0E(N(S", 'F'}, {"0E(N(V", 'F'}, {"0E(N)&", 'F'}, - {"0E(N))", 'F'}, {"0E(N),", 'F'}, {"0E(N)1", 'F'}, {"0E(N)F", 'F'}, @@ -2263,7 +2186,6 @@ static const keyword_t sql_keywords[] = { {"0E(NOS", 'F'}, {"0E(NOV", 'F'}, {"0E(S)&", 'F'}, - {"0E(S))", 'F'}, {"0E(S),", 'F'}, {"0E(S)1", 'F'}, {"0E(S)F", 'F'}, @@ -2286,7 +2208,6 @@ static const keyword_t sql_keywords[] = { {"0E(SV)", 'F'}, {"0E(SVO", 'F'}, {"0E(V)&", 'F'}, - {"0E(V))", 'F'}, {"0E(V),", 'F'}, {"0E(V)1", 'F'}, {"0E(V)F", 'F'}, @@ -2306,18 +2227,6 @@ static const keyword_t sql_keywords[] = { {"0E1&((", 'F'}, {"0E1&(E", 'F'}, {"0E1)", 'F'}, - {"0E1))", 'F'}, - {"0E1)))", 'F'}, - {"0E1))1", 'F'}, - {"0E1));", 'F'}, - {"0E1))C", 'F'}, - {"0E1))F", 'F'}, - {"0E1))K", 'F'}, - {"0E1))N", 'F'}, - {"0E1))O", 'F'}, - {"0E1))S", 'F'}, - {"0E1))U", 'F'}, - {"0E1))V", 'F'}, {"0E1);", 'F'}, {"0E1);C", 'F'}, {"0E1)C", 'F'}, @@ -2368,14 +2277,11 @@ static const keyword_t sql_keywords[] = { {"0E1KV)", 'F'}, {"0E1KVK", 'F'}, {"0E1KVO", 'F'}, + {"0E1N)U", 'F'}, {"0E1N;", 'F'}, {"0E1N;C", 'F'}, {"0E1NC", 'F'}, {"0E1NKN", 'F'}, - {"0E1NO(", 'F'}, - {"0E1NOF", 'F'}, - {"0E1NOS", 'F'}, - {"0E1NOV", 'F'}, {"0E1O((", 'F'}, {"0E1O(1", 'F'}, {"0E1O(E", 'F'}, @@ -2392,6 +2298,7 @@ static const keyword_t sql_keywords[] = { {"0E1OSF", 'F'}, {"0E1OSK", 'F'}, {"0E1OSO", 'F'}, + {"0E1OSU", 'F'}, {"0E1OSV", 'F'}, {"0E1OV&", 'F'}, {"0E1OV(", 'F'}, @@ -2401,9 +2308,17 @@ static const keyword_t sql_keywords[] = { {"0E1OVK", 'F'}, {"0E1OVO", 'F'}, {"0E1OVS", 'F'}, + {"0E1OVU", 'F'}, {"0E1S;", 'F'}, {"0E1S;C", 'F'}, {"0E1SC", 'F'}, + {"0E1UE(", 'F'}, + {"0E1UE1", 'F'}, + {"0E1UEF", 'F'}, + {"0E1UEK", 'F'}, + {"0E1UEN", 'F'}, + {"0E1UES", 'F'}, + {"0E1UEV", 'F'}, {"0E1V", 'F'}, {"0E1V;", 'F'}, {"0E1V;C", 'F'}, @@ -2428,7 +2343,6 @@ static const keyword_t sql_keywords[] = { {"0EF((S", 'F'}, {"0EF((V", 'F'}, {"0EF()&", 'F'}, - {"0EF())", 'F'}, {"0EF(),", 'F'}, {"0EF()1", 'F'}, {"0EF()F", 'F'}, @@ -2436,6 +2350,7 @@ static const keyword_t sql_keywords[] = { {"0EF()N", 'F'}, {"0EF()O", 'F'}, {"0EF()S", 'F'}, + {"0EF()U", 'F'}, {"0EF()V", 'F'}, {"0EF(1)", 'F'}, {"0EF(1,", 'F'}, @@ -2495,7 +2410,6 @@ static const keyword_t sql_keywords[] = { {"0EK(VS", 'F'}, {"0EK1&(", 'F'}, {"0EK1)", 'F'}, - {"0EK1))", 'F'}, {"0EK1);", 'F'}, {"0EK1)C", 'F'}, {"0EK1)K", 'F'}, @@ -2512,11 +2426,11 @@ static const keyword_t sql_keywords[] = { {"0EK1KS", 'F'}, {"0EK1KV", 'F'}, {"0EK1N", 'F'}, + {"0EK1N)", 'F'}, {"0EK1N;", 'F'}, {"0EK1NC", 'F'}, {"0EK1NF", 'F'}, {"0EK1NK", 'F'}, - {"0EK1NO", 'F'}, {"0EK1O(", 'F'}, {"0EK1OF", 'F'}, {"0EK1OS", 'F'}, @@ -2526,6 +2440,7 @@ static const keyword_t sql_keywords[] = { {"0EK1SC", 'F'}, {"0EK1SF", 'F'}, {"0EK1SK", 'F'}, + {"0EK1UE", 'F'}, {"0EK1V", 'F'}, {"0EK1V;", 'F'}, {"0EK1VC", 'F'}, @@ -2550,7 +2465,6 @@ static const keyword_t sql_keywords[] = { {"0EKN(S", 'F'}, {"0EKN(V", 'F'}, {"0EKN)", 'F'}, - {"0EKN))", 'F'}, {"0EKN);", 'F'}, {"0EKN)C", 'F'}, {"0EKN)K", 'F'}, @@ -2572,6 +2486,7 @@ static const keyword_t sql_keywords[] = { {"0EKNKN", 'F'}, {"0EKNKS", 'F'}, {"0EKNKV", 'F'}, + {"0EKNUE", 'F'}, {"0EKO((", 'F'}, {"0EKO(1", 'F'}, {"0EKO(F", 'F'}, @@ -2581,7 +2496,6 @@ static const keyword_t sql_keywords[] = { {"0EKOK(", 'F'}, {"0EKS&(", 'F'}, {"0EKS)", 'F'}, - {"0EKS))", 'F'}, {"0EKS);", 'F'}, {"0EKS)C", 'F'}, {"0EKS)K", 'F'}, @@ -2609,6 +2523,7 @@ static const keyword_t sql_keywords[] = { {"0EKSON", 'F'}, {"0EKSOS", 'F'}, {"0EKSOV", 'F'}, + {"0EKSUE", 'F'}, {"0EKSV", 'F'}, {"0EKSV;", 'F'}, {"0EKSVC", 'F'}, @@ -2617,7 +2532,6 @@ static const keyword_t sql_keywords[] = { {"0EKSVO", 'F'}, {"0EKV&(", 'F'}, {"0EKV)", 'F'}, - {"0EKV))", 'F'}, {"0EKV);", 'F'}, {"0EKV)C", 'F'}, {"0EKV)K", 'F'}, @@ -2645,6 +2559,7 @@ static const keyword_t sql_keywords[] = { {"0EKVSF", 'F'}, {"0EKVSK", 'F'}, {"0EKVSO", 'F'}, + {"0EKVUE", 'F'}, {"0EN&((", 'F'}, {"0EN&(E", 'F'}, {"0EN(((", 'F'}, @@ -2660,18 +2575,6 @@ static const keyword_t sql_keywords[] = { {"0EN(V)", 'F'}, {"0EN(VO", 'F'}, {"0EN)", 'F'}, - {"0EN))", 'F'}, - {"0EN)))", 'F'}, - {"0EN))1", 'F'}, - {"0EN));", 'F'}, - {"0EN))C", 'F'}, - {"0EN))F", 'F'}, - {"0EN))K", 'F'}, - {"0EN))N", 'F'}, - {"0EN))O", 'F'}, - {"0EN))S", 'F'}, - {"0EN))U", 'F'}, - {"0EN))V", 'F'}, {"0EN);", 'F'}, {"0EN);C", 'F'}, {"0EN)C", 'F'}, @@ -2746,6 +2649,7 @@ static const keyword_t sql_keywords[] = { {"0ENOSF", 'F'}, {"0ENOSK", 'F'}, {"0ENOSO", 'F'}, + {"0ENOSU", 'F'}, {"0ENOSV", 'F'}, {"0ENOV&", 'F'}, {"0ENOV(", 'F'}, @@ -2755,6 +2659,14 @@ static const keyword_t sql_keywords[] = { {"0ENOVK", 'F'}, {"0ENOVO", 'F'}, {"0ENOVS", 'F'}, + {"0ENOVU", 'F'}, + {"0ENUE(", 'F'}, + {"0ENUE1", 'F'}, + {"0ENUEF", 'F'}, + {"0ENUEK", 'F'}, + {"0ENUEN", 'F'}, + {"0ENUES", 'F'}, + {"0ENUEV", 'F'}, {"0EO(((", 'F'}, {"0EO((1", 'F'}, {"0EO((F", 'F'}, @@ -2775,18 +2687,6 @@ static const keyword_t sql_keywords[] = { {"0ES&((", 'F'}, {"0ES&(E", 'F'}, {"0ES)", 'F'}, - {"0ES))", 'F'}, - {"0ES)))", 'F'}, - {"0ES))1", 'F'}, - {"0ES));", 'F'}, - {"0ES))C", 'F'}, - {"0ES))F", 'F'}, - {"0ES))K", 'F'}, - {"0ES))N", 'F'}, - {"0ES))O", 'F'}, - {"0ES))S", 'F'}, - {"0ES))U", 'F'}, - {"0ES))V", 'F'}, {"0ES);", 'F'}, {"0ES);C", 'F'}, {"0ES)C", 'F'}, @@ -2861,6 +2761,7 @@ static const keyword_t sql_keywords[] = { {"0ESO1N", 'F'}, {"0ESO1O", 'F'}, {"0ESO1S", 'F'}, + {"0ESO1U", 'F'}, {"0ESO1V", 'F'}, {"0ESOF(", 'F'}, {"0ESON&", 'F'}, @@ -2871,6 +2772,7 @@ static const keyword_t sql_keywords[] = { {"0ESONF", 'F'}, {"0ESONK", 'F'}, {"0ESONO", 'F'}, + {"0ESONU", 'F'}, {"0ESOS&", 'F'}, {"0ESOS(", 'F'}, {"0ESOS)", 'F'}, @@ -2879,6 +2781,7 @@ static const keyword_t sql_keywords[] = { {"0ESOSF", 'F'}, {"0ESOSK", 'F'}, {"0ESOSO", 'F'}, + {"0ESOSU", 'F'}, {"0ESOSV", 'F'}, {"0ESOV&", 'F'}, {"0ESOV(", 'F'}, @@ -2888,6 +2791,14 @@ static const keyword_t sql_keywords[] = { {"0ESOVK", 'F'}, {"0ESOVO", 'F'}, {"0ESOVS", 'F'}, + {"0ESOVU", 'F'}, + {"0ESUE(", 'F'}, + {"0ESUE1", 'F'}, + {"0ESUEF", 'F'}, + {"0ESUEK", 'F'}, + {"0ESUEN", 'F'}, + {"0ESUES", 'F'}, + {"0ESUEV", 'F'}, {"0ESV", 'F'}, {"0ESV;", 'F'}, {"0ESV;C", 'F'}, @@ -2898,18 +2809,6 @@ static const keyword_t sql_keywords[] = { {"0EV&((", 'F'}, {"0EV&(E", 'F'}, {"0EV)", 'F'}, - {"0EV))", 'F'}, - {"0EV)))", 'F'}, - {"0EV))1", 'F'}, - {"0EV));", 'F'}, - {"0EV))C", 'F'}, - {"0EV))F", 'F'}, - {"0EV))K", 'F'}, - {"0EV))N", 'F'}, - {"0EV))O", 'F'}, - {"0EV))S", 'F'}, - {"0EV))U", 'F'}, - {"0EV))V", 'F'}, {"0EV);", 'F'}, {"0EV);C", 'F'}, {"0EV)C", 'F'}, @@ -2970,6 +2869,7 @@ static const keyword_t sql_keywords[] = { {"0EVKVK", 'F'}, {"0EVKVO", 'F'}, {"0EVN", 'F'}, + {"0EVN)U", 'F'}, {"0EVN;", 'F'}, {"0EVN;C", 'F'}, {"0EVNC", 'F'}, @@ -2994,6 +2894,7 @@ static const keyword_t sql_keywords[] = { {"0EVOSF", 'F'}, {"0EVOSK", 'F'}, {"0EVOSO", 'F'}, + {"0EVOSU", 'F'}, {"0EVOSV", 'F'}, {"0EVS", 'F'}, {"0EVS;", 'F'}, @@ -3005,6 +2906,13 @@ static const keyword_t sql_keywords[] = { {"0EVSON", 'F'}, {"0EVSOS", 'F'}, {"0EVSOV", 'F'}, + {"0EVUE(", 'F'}, + {"0EVUE1", 'F'}, + {"0EVUEF", 'F'}, + {"0EVUEK", 'F'}, + {"0EVUEN", 'F'}, + {"0EVUES", 'F'}, + {"0EVUEV", 'F'}, {"0F((((", 'F'}, {"0F((()", 'F'}, {"0F(((1", 'F'}, @@ -3016,7 +2924,6 @@ static const keyword_t sql_keywords[] = { {"0F(((T", 'F'}, {"0F(((V", 'F'}, {"0F(()&", 'F'}, - {"0F(())", 'F'}, {"0F((),", 'F'}, {"0F(()1", 'F'}, {"0F(();", 'F'}, @@ -3062,23 +2969,8 @@ static const keyword_t sql_keywords[] = { {"0F()&K", 'F'}, {"0F()&N", 'F'}, {"0F()&S", 'F'}, + {"0F()&T", 'F'}, {"0F()&V", 'F'}, - {"0F())&", 'F'}, - {"0F()))", 'F'}, - {"0F()),", 'F'}, - {"0F())1", 'F'}, - {"0F());", 'F'}, - {"0F())A", 'F'}, - {"0F())B", 'F'}, - {"0F())C", 'F'}, - {"0F())E", 'F'}, - {"0F())F", 'F'}, - {"0F())K", 'F'}, - {"0F())N", 'F'}, - {"0F())O", 'F'}, - {"0F())S", 'F'}, - {"0F())U", 'F'}, - {"0F())V", 'F'}, {"0F(),(", 'F'}, {"0F(),1", 'F'}, {"0F(),F", 'F'}, @@ -3170,7 +3062,6 @@ static const keyword_t sql_keywords[] = { {"0F()VU", 'F'}, {"0F(1)", 'F'}, {"0F(1)&", 'F'}, - {"0F(1))", 'F'}, {"0F(1),", 'F'}, {"0F(1)1", 'F'}, {"0F(1);", 'F'}, @@ -3198,6 +3089,8 @@ static const keyword_t sql_keywords[] = { {"0F(E(N", 'F'}, {"0F(E(S", 'F'}, {"0F(E(V", 'F'}, + {"0F(E1)", 'F'}, + {"0F(E1K", 'F'}, {"0F(E1O", 'F'}, {"0F(EF(", 'F'}, {"0F(EK(", 'F'}, @@ -3206,8 +3099,14 @@ static const keyword_t sql_keywords[] = { {"0F(EKN", 'F'}, {"0F(EKS", 'F'}, {"0F(EKV", 'F'}, + {"0F(EN)", 'F'}, + {"0F(ENK", 'F'}, {"0F(ENO", 'F'}, + {"0F(ES)", 'F'}, + {"0F(ESK", 'F'}, {"0F(ESO", 'F'}, + {"0F(EV)", 'F'}, + {"0F(EVK", 'F'}, {"0F(EVO", 'F'}, {"0F(F((", 'F'}, {"0F(F()", 'F'}, @@ -3222,7 +3121,6 @@ static const keyword_t sql_keywords[] = { {"0F(K,F", 'F'}, {"0F(N)", 'F'}, {"0F(N)&", 'F'}, - {"0F(N))", 'F'}, {"0F(N),", 'F'}, {"0F(N)1", 'F'}, {"0F(N);", 'F'}, @@ -3246,7 +3144,6 @@ static const keyword_t sql_keywords[] = { {"0F(NOV", 'F'}, {"0F(S)", 'F'}, {"0F(S)&", 'F'}, - {"0F(S))", 'F'}, {"0F(S),", 'F'}, {"0F(S)1", 'F'}, {"0F(S);", 'F'}, @@ -3270,7 +3167,6 @@ static const keyword_t sql_keywords[] = { {"0F(SON", 'F'}, {"0F(SOS", 'F'}, {"0F(SOV", 'F'}, - {"0F(T))", 'F'}, {"0F(T),", 'F'}, {"0F(T,(", 'F'}, {"0F(T,1", 'F'}, @@ -3280,7 +3176,6 @@ static const keyword_t sql_keywords[] = { {"0F(T,V", 'F'}, {"0F(V)", 'F'}, {"0F(V)&", 'F'}, - {"0F(V))", 'F'}, {"0F(V),", 'F'}, {"0F(V)1", 'F'}, {"0F(V);", 'F'}, @@ -3319,7 +3214,6 @@ static const keyword_t sql_keywords[] = { {"0K((SO", 'F'}, {"0K((V)", 'F'}, {"0K((VO", 'F'}, - {"0K(1))", 'F'}, {"0K(1),", 'F'}, {"0K(1)A", 'F'}, {"0K(1)K", 'F'}, @@ -3335,7 +3229,6 @@ static const keyword_t sql_keywords[] = { {"0K(F(N", 'F'}, {"0K(F(S", 'F'}, {"0K(F(V", 'F'}, - {"0K(N))", 'F'}, {"0K(N),", 'F'}, {"0K(N)A", 'F'}, {"0K(N)K", 'F'}, @@ -3344,7 +3237,6 @@ static const keyword_t sql_keywords[] = { {"0K(NOF", 'F'}, {"0K(NOS", 'F'}, {"0K(NOV", 'F'}, - {"0K(S))", 'F'}, {"0K(S),", 'F'}, {"0K(S)A", 'F'}, {"0K(S)K", 'F'}, @@ -3355,7 +3247,6 @@ static const keyword_t sql_keywords[] = { {"0K(SON", 'F'}, {"0K(SOS", 'F'}, {"0K(SOV", 'F'}, - {"0K(V))", 'F'}, {"0K(V),", 'F'}, {"0K(V)A", 'F'}, {"0K(V)K", 'F'}, @@ -3424,7 +3315,6 @@ static const keyword_t sql_keywords[] = { {"0KF((N", 'F'}, {"0KF((S", 'F'}, {"0KF((V", 'F'}, - {"0KF())", 'F'}, {"0KF(),", 'F'}, {"0KF()A", 'F'}, {"0KF()K", 'F'}, @@ -3640,7 +3530,7 @@ static const keyword_t sql_keywords[] = { {"0N&1&S", 'F'}, {"0N&1&V", 'F'}, {"0N&1)&", 'F'}, - {"0N&1))", 'F'}, + {"0N&1)O", 'F'}, {"0N&1)U", 'F'}, {"0N&1;", 'F'}, {"0N&1;C", 'F'}, @@ -3709,6 +3599,7 @@ static const keyword_t sql_keywords[] = { {"0N&F((", 'F'}, {"0N&F()", 'F'}, {"0N&F(1", 'F'}, + {"0N&F(E", 'F'}, {"0N&F(F", 'F'}, {"0N&F(N", 'F'}, {"0N&F(S", 'F'}, @@ -3743,7 +3634,7 @@ static const keyword_t sql_keywords[] = { {"0N&N&S", 'F'}, {"0N&N&V", 'F'}, {"0N&N)&", 'F'}, - {"0N&N))", 'F'}, + {"0N&N)O", 'F'}, {"0N&N)U", 'F'}, {"0N&N;C", 'F'}, {"0N&N;E", 'F'}, @@ -3776,7 +3667,7 @@ static const keyword_t sql_keywords[] = { {"0N&S&S", 'F'}, {"0N&S&V", 'F'}, {"0N&S)&", 'F'}, - {"0N&S))", 'F'}, + {"0N&S)O", 'F'}, {"0N&S)U", 'F'}, {"0N&S1", 'F'}, {"0N&S1;", 'F'}, @@ -3819,6 +3710,12 @@ static const keyword_t sql_keywords[] = { {"0N&SV;", 'F'}, {"0N&SVC", 'F'}, {"0N&SVO", 'F'}, + {"0N&T((", 'F'}, + {"0N&T(1", 'F'}, + {"0N&T(F", 'F'}, + {"0N&T(N", 'F'}, + {"0N&T(S", 'F'}, + {"0N&T(V", 'F'}, {"0N&V", 'F'}, {"0N&V&(", 'F'}, {"0N&V&1", 'F'}, @@ -3827,7 +3724,7 @@ static const keyword_t sql_keywords[] = { {"0N&V&S", 'F'}, {"0N&V&V", 'F'}, {"0N&V)&", 'F'}, - {"0N&V))", 'F'}, + {"0N&V)O", 'F'}, {"0N&V)U", 'F'}, {"0N&V;", 'F'}, {"0N&V;C", 'F'}, @@ -3883,7 +3780,6 @@ static const keyword_t sql_keywords[] = { {"0N((U(", 'F'}, {"0N((V)", 'F'}, {"0N((VO", 'F'}, - {"0N(1))", 'F'}, {"0N(1)F", 'F'}, {"0N(1)O", 'F'}, {"0N(1)U", 'F'}, @@ -3901,7 +3797,6 @@ static const keyword_t sql_keywords[] = { {"0N(F(N", 'F'}, {"0N(F(S", 'F'}, {"0N(F(V", 'F'}, - {"0N(S))", 'F'}, {"0N(S)1", 'F'}, {"0N(S)F", 'F'}, {"0N(S)N", 'F'}, @@ -3917,7 +3812,6 @@ static const keyword_t sql_keywords[] = { {"0N(SOV", 'F'}, {"0N(U((", 'F'}, {"0N(U(E", 'F'}, - {"0N(V))", 'F'}, {"0N(V)1", 'F'}, {"0N(V)F", 'F'}, {"0N(V)N", 'F'}, @@ -3972,53 +3866,6 @@ static const keyword_t sql_keywords[] = { {"0N)&VF", 'F'}, {"0N)&VO", 'F'}, {"0N)&VU", 'F'}, - {"0N))&(", 'F'}, - {"0N))&1", 'F'}, - {"0N))&F", 'F'}, - {"0N))&N", 'F'}, - {"0N))&S", 'F'}, - {"0N))&V", 'F'}, - {"0N)))&", 'F'}, - {"0N))))", 'F'}, - {"0N))),", 'F'}, - {"0N)));", 'F'}, - {"0N)))B", 'F'}, - {"0N)))E", 'F'}, - {"0N)))K", 'F'}, - {"0N)))O", 'F'}, - {"0N)))U", 'F'}, - {"0N)),(", 'F'}, - {"0N));E", 'F'}, - {"0N));T", 'F'}, - {"0N))B(", 'F'}, - {"0N))B1", 'F'}, - {"0N))BF", 'F'}, - {"0N))BN", 'F'}, - {"0N))BS", 'F'}, - {"0N))BV", 'F'}, - {"0N))E(", 'F'}, - {"0N))E1", 'F'}, - {"0N))EF", 'F'}, - {"0N))EK", 'F'}, - {"0N))EN", 'F'}, - {"0N))ES", 'F'}, - {"0N))EV", 'F'}, - {"0N))K(", 'F'}, - {"0N))K1", 'F'}, - {"0N))KB", 'F'}, - {"0N))KF", 'F'}, - {"0N))KN", 'F'}, - {"0N))KS", 'F'}, - {"0N))KU", 'F'}, - {"0N))KV", 'F'}, - {"0N))O(", 'F'}, - {"0N))O1", 'F'}, - {"0N))OF", 'F'}, - {"0N))ON", 'F'}, - {"0N))OS", 'F'}, - {"0N))OV", 'F'}, - {"0N))U(", 'F'}, - {"0N))UE", 'F'}, {"0N),((", 'F'}, {"0N),(1", 'F'}, {"0N),(F", 'F'}, @@ -4218,7 +4065,6 @@ static const keyword_t sql_keywords[] = { {"0N,F(S", 'F'}, {"0N,F(T", 'F'}, {"0N,F(V", 'F'}, - {"0N,V))", 'F'}, {"0N,V),", 'F'}, {"0N,V)O", 'F'}, {"0N,V,(", 'F'}, @@ -4285,6 +4131,7 @@ static const keyword_t sql_keywords[] = { {"0N;E1,", 'F'}, {"0N;E1;", 'F'}, {"0N;E1C", 'F'}, + {"0N;E1K", 'F'}, {"0N;E1O", 'F'}, {"0N;E1T", 'F'}, {"0N;EF(", 'F'}, @@ -4305,11 +4152,13 @@ static const keyword_t sql_keywords[] = { {"0N;ES,", 'F'}, {"0N;ES;", 'F'}, {"0N;ESC", 'F'}, + {"0N;ESK", 'F'}, {"0N;ESO", 'F'}, {"0N;EST", 'F'}, {"0N;EV,", 'F'}, {"0N;EV;", 'F'}, {"0N;EVC", 'F'}, + {"0N;EVK", 'F'}, {"0N;EVO", 'F'}, {"0N;EVT", 'F'}, {"0N;N:T", 'F'}, @@ -4324,6 +4173,7 @@ static const keyword_t sql_keywords[] = { {"0N;T1;", 'F'}, {"0N;T1C", 'F'}, {"0N;T1F", 'F'}, + {"0N;T1K", 'F'}, {"0N;T1O", 'F'}, {"0N;T1T", 'F'}, {"0N;T;", 'F'}, @@ -4355,6 +4205,7 @@ static const keyword_t sql_keywords[] = { {"0N;TS;", 'F'}, {"0N;TSC", 'F'}, {"0N;TSF", 'F'}, + {"0N;TSK", 'F'}, {"0N;TSO", 'F'}, {"0N;TST", 'F'}, {"0N;TT(", 'F'}, @@ -4367,6 +4218,7 @@ static const keyword_t sql_keywords[] = { {"0N;TV;", 'F'}, {"0N;TVC", 'F'}, {"0N;TVF", 'F'}, + {"0N;TVK", 'F'}, {"0N;TVO", 'F'}, {"0N;TVT", 'F'}, {"0NA(((", 'F'}, @@ -4640,7 +4492,6 @@ static const keyword_t sql_keywords[] = { {"0NF((N", 'F'}, {"0NF((S", 'F'}, {"0NF((V", 'F'}, - {"0NF())", 'F'}, {"0NF()1", 'F'}, {"0NF()F", 'F'}, {"0NF()K", 'F'}, @@ -4652,6 +4503,7 @@ static const keyword_t sql_keywords[] = { {"0NF(1)", 'F'}, {"0NF(1N", 'F'}, {"0NF(1O", 'F'}, + {"0NF(E1", 'F'}, {"0NF(F(", 'F'}, {"0NF(N)", 'F'}, {"0NF(N,", 'F'}, @@ -4681,14 +4533,6 @@ static const keyword_t sql_keywords[] = { {"0NK)&N", 'F'}, {"0NK)&S", 'F'}, {"0NK)&V", 'F'}, - {"0NK))&", 'F'}, - {"0NK)))", 'F'}, - {"0NK));", 'F'}, - {"0NK))B", 'F'}, - {"0NK))E", 'F'}, - {"0NK))K", 'F'}, - {"0NK))O", 'F'}, - {"0NK))U", 'F'}, {"0NK);E", 'F'}, {"0NK);T", 'F'}, {"0NK)B(", 'F'}, @@ -4919,13 +4763,13 @@ static const keyword_t sql_keywords[] = { {"0NOS&K", 'F'}, {"0NOS&N", 'F'}, {"0NOS&S", 'F'}, + {"0NOS&T", 'F'}, {"0NOS&U", 'F'}, {"0NOS&V", 'F'}, {"0NOS((", 'F'}, {"0NOS(E", 'F'}, {"0NOS(U", 'F'}, {"0NOS)&", 'F'}, - {"0NOS))", 'F'}, {"0NOS),", 'F'}, {"0NOS);", 'F'}, {"0NOS)B", 'F'}, @@ -5011,6 +4855,7 @@ static const keyword_t sql_keywords[] = { {"0NOT(F", 'F'}, {"0NOT(N", 'F'}, {"0NOT(S", 'F'}, + {"0NOT(T", 'F'}, {"0NOT(V", 'F'}, {"0NOU((", 'F'}, {"0NOU(E", 'F'}, @@ -5023,13 +4868,13 @@ static const keyword_t sql_keywords[] = { {"0NOV&K", 'F'}, {"0NOV&N", 'F'}, {"0NOV&S", 'F'}, + {"0NOV&T", 'F'}, {"0NOV&U", 'F'}, {"0NOV&V", 'F'}, {"0NOV((", 'F'}, {"0NOV(E", 'F'}, {"0NOV(U", 'F'}, {"0NOV)&", 'F'}, - {"0NOV))", 'F'}, {"0NOV),", 'F'}, {"0NOV);", 'F'}, {"0NOV)B", 'F'}, @@ -5299,17 +5144,129 @@ static const keyword_t sql_keywords[] = { {"0NUVO(", 'F'}, {"0NUVOF", 'F'}, {"0NUVOS", 'F'}, + {"0O((((", 'F'}, + {"0O(((1", 'F'}, + {"0O(((F", 'F'}, + {"0O(((N", 'F'}, + {"0O(((S", 'F'}, + {"0O(((V", 'F'}, + {"0O((1)", 'F'}, + {"0O((1O", 'F'}, + {"0O((F(", 'F'}, + {"0O((N)", 'F'}, + {"0O((NO", 'F'}, + {"0O((S)", 'F'}, + {"0O((SO", 'F'}, + {"0O((V)", 'F'}, + {"0O((VO", 'F'}, + {"0O(1)O", 'F'}, + {"0O(1)U", 'F'}, + {"0O(1O(", 'F'}, + {"0O(1OF", 'F'}, + {"0O(1OS", 'F'}, + {"0O(1OV", 'F'}, + {"0O(F((", 'F'}, + {"0O(F()", 'F'}, + {"0O(F(1", 'F'}, + {"0O(F(F", 'F'}, + {"0O(F(N", 'F'}, + {"0O(F(S", 'F'}, + {"0O(F(V", 'F'}, + {"0O(N)O", 'F'}, + {"0O(N)U", 'F'}, + {"0O(NO(", 'F'}, + {"0O(NOF", 'F'}, + {"0O(NOS", 'F'}, + {"0O(NOV", 'F'}, + {"0O(S)O", 'F'}, + {"0O(S)U", 'F'}, + {"0O(SO(", 'F'}, + {"0O(SO1", 'F'}, + {"0O(SOF", 'F'}, + {"0O(SON", 'F'}, + {"0O(SOS", 'F'}, + {"0O(SOV", 'F'}, + {"0O(V)O", 'F'}, + {"0O(V)U", 'F'}, + {"0O(VO(", 'F'}, + {"0O(VOF", 'F'}, + {"0O(VOS", 'F'}, + {"0O1O((", 'F'}, + {"0O1O(1", 'F'}, + {"0O1O(F", 'F'}, + {"0O1O(N", 'F'}, + {"0O1O(S", 'F'}, + {"0O1O(V", 'F'}, + {"0O1OF(", 'F'}, + {"0O1OSO", 'F'}, + {"0O1OSU", 'F'}, + {"0O1OVO", 'F'}, + {"0O1OVU", 'F'}, + {"0O1UE(", 'F'}, + {"0O1UE1", 'F'}, + {"0O1UEF", 'F'}, + {"0O1UEK", 'F'}, + {"0O1UEN", 'F'}, + {"0O1UES", 'F'}, + {"0O1UEV", 'F'}, {"0OF(((", 'F'}, + {"0OF(()", 'F'}, {"0OF((1", 'F'}, {"0OF((F", 'F'}, {"0OF((N", 'F'}, {"0OF((S", 'F'}, {"0OF((V", 'F'}, + {"0OF()O", 'F'}, + {"0OF()U", 'F'}, + {"0OF(1)", 'F'}, {"0OF(1O", 'F'}, {"0OF(F(", 'F'}, + {"0OF(N)", 'F'}, {"0OF(NO", 'F'}, + {"0OF(S)", 'F'}, {"0OF(SO", 'F'}, + {"0OF(V)", 'F'}, {"0OF(VO", 'F'}, + {"0ONO((", 'F'}, + {"0ONO(1", 'F'}, + {"0ONO(F", 'F'}, + {"0ONO(N", 'F'}, + {"0ONO(S", 'F'}, + {"0ONO(V", 'F'}, + {"0ONOF(", 'F'}, + {"0ONOSO", 'F'}, + {"0ONOSU", 'F'}, + {"0ONOVO", 'F'}, + {"0ONOVU", 'F'}, + {"0ONUE(", 'F'}, + {"0ONUE1", 'F'}, + {"0ONUEF", 'F'}, + {"0ONUEK", 'F'}, + {"0ONUEN", 'F'}, + {"0ONUES", 'F'}, + {"0ONUEV", 'F'}, + {"0OSO((", 'F'}, + {"0OSO(1", 'F'}, + {"0OSO(F", 'F'}, + {"0OSO(N", 'F'}, + {"0OSO(S", 'F'}, + {"0OSO(V", 'F'}, + {"0OSO1O", 'F'}, + {"0OSO1U", 'F'}, + {"0OSOF(", 'F'}, + {"0OSONO", 'F'}, + {"0OSONU", 'F'}, + {"0OSOSO", 'F'}, + {"0OSOSU", 'F'}, + {"0OSOVO", 'F'}, + {"0OSOVU", 'F'}, + {"0OSUE(", 'F'}, + {"0OSUE1", 'F'}, + {"0OSUEF", 'F'}, + {"0OSUEK", 'F'}, + {"0OSUEN", 'F'}, + {"0OSUES", 'F'}, + {"0OSUEV", 'F'}, {"0OUE((", 'F'}, {"0OUE(1", 'F'}, {"0OUE(F", 'F'}, @@ -5331,6 +5288,22 @@ static const keyword_t sql_keywords[] = { {"0OUESO", 'F'}, {"0OUEV,", 'F'}, {"0OUEVO", 'F'}, + {"0OVO((", 'F'}, + {"0OVO(1", 'F'}, + {"0OVO(F", 'F'}, + {"0OVO(N", 'F'}, + {"0OVO(S", 'F'}, + {"0OVO(V", 'F'}, + {"0OVOF(", 'F'}, + {"0OVOSO", 'F'}, + {"0OVOSU", 'F'}, + {"0OVUE(", 'F'}, + {"0OVUE1", 'F'}, + {"0OVUEF", 'F'}, + {"0OVUEK", 'F'}, + {"0OVUEN", 'F'}, + {"0OVUES", 'F'}, + {"0OVUEV", 'F'}, {"0S&(((", 'F'}, {"0S&((1", 'F'}, {"0S&((E", 'F'}, @@ -5371,7 +5344,7 @@ static const keyword_t sql_keywords[] = { {"0S&1&S", 'F'}, {"0S&1&V", 'F'}, {"0S&1)&", 'F'}, - {"0S&1))", 'F'}, + {"0S&1)O", 'F'}, {"0S&1)U", 'F'}, {"0S&1;", 'F'}, {"0S&1;C", 'F'}, @@ -5398,7 +5371,6 @@ static const keyword_t sql_keywords[] = { {"0S&1OO", 'F'}, {"0S&1OS", 'F'}, {"0S&1OV", 'F'}, - {"0S&1S", 'F'}, {"0S&1TN", 'F'}, {"0S&1U", 'F'}, {"0S&1U(", 'F'}, @@ -5442,6 +5414,7 @@ static const keyword_t sql_keywords[] = { {"0S&F((", 'F'}, {"0S&F()", 'F'}, {"0S&F(1", 'F'}, + {"0S&F(E", 'F'}, {"0S&F(F", 'F'}, {"0S&F(N", 'F'}, {"0S&F(S", 'F'}, @@ -5478,7 +5451,7 @@ static const keyword_t sql_keywords[] = { {"0S&N&S", 'F'}, {"0S&N&V", 'F'}, {"0S&N)&", 'F'}, - {"0S&N))", 'F'}, + {"0S&N)O", 'F'}, {"0S&N)U", 'F'}, {"0S&N;", 'F'}, {"0S&N;C", 'F'}, @@ -5517,7 +5490,7 @@ static const keyword_t sql_keywords[] = { {"0S&S&S", 'F'}, {"0S&S&V", 'F'}, {"0S&S)&", 'F'}, - {"0S&S))", 'F'}, + {"0S&S)O", 'F'}, {"0S&S)U", 'F'}, {"0S&S1", 'F'}, {"0S&S1;", 'F'}, @@ -5560,6 +5533,12 @@ static const keyword_t sql_keywords[] = { {"0S&SV;", 'F'}, {"0S&SVC", 'F'}, {"0S&SVO", 'F'}, + {"0S&T((", 'F'}, + {"0S&T(1", 'F'}, + {"0S&T(F", 'F'}, + {"0S&T(N", 'F'}, + {"0S&T(S", 'F'}, + {"0S&T(V", 'F'}, {"0S&V", 'F'}, {"0S&V&(", 'F'}, {"0S&V&1", 'F'}, @@ -5568,7 +5547,7 @@ static const keyword_t sql_keywords[] = { {"0S&V&S", 'F'}, {"0S&V&V", 'F'}, {"0S&V)&", 'F'}, - {"0S&V))", 'F'}, + {"0S&V)O", 'F'}, {"0S&V)U", 'F'}, {"0S&V;", 'F'}, {"0S&V;C", 'F'}, @@ -5658,53 +5637,6 @@ static const keyword_t sql_keywords[] = { {"0S)&VF", 'F'}, {"0S)&VO", 'F'}, {"0S)&VU", 'F'}, - {"0S))&(", 'F'}, - {"0S))&1", 'F'}, - {"0S))&F", 'F'}, - {"0S))&N", 'F'}, - {"0S))&S", 'F'}, - {"0S))&V", 'F'}, - {"0S)))&", 'F'}, - {"0S))))", 'F'}, - {"0S))),", 'F'}, - {"0S)));", 'F'}, - {"0S)))B", 'F'}, - {"0S)))E", 'F'}, - {"0S)))K", 'F'}, - {"0S)))O", 'F'}, - {"0S)))U", 'F'}, - {"0S)),(", 'F'}, - {"0S));E", 'F'}, - {"0S));T", 'F'}, - {"0S))B(", 'F'}, - {"0S))B1", 'F'}, - {"0S))BF", 'F'}, - {"0S))BN", 'F'}, - {"0S))BS", 'F'}, - {"0S))BV", 'F'}, - {"0S))E(", 'F'}, - {"0S))E1", 'F'}, - {"0S))EF", 'F'}, - {"0S))EK", 'F'}, - {"0S))EN", 'F'}, - {"0S))ES", 'F'}, - {"0S))EV", 'F'}, - {"0S))K(", 'F'}, - {"0S))K1", 'F'}, - {"0S))KB", 'F'}, - {"0S))KF", 'F'}, - {"0S))KN", 'F'}, - {"0S))KS", 'F'}, - {"0S))KU", 'F'}, - {"0S))KV", 'F'}, - {"0S))O(", 'F'}, - {"0S))O1", 'F'}, - {"0S))OF", 'F'}, - {"0S))ON", 'F'}, - {"0S))OS", 'F'}, - {"0S))OV", 'F'}, - {"0S))U(", 'F'}, - {"0S))UE", 'F'}, {"0S),((", 'F'}, {"0S),(1", 'F'}, {"0S),(F", 'F'}, @@ -5839,7 +5771,6 @@ static const keyword_t sql_keywords[] = { {"0S)O1O", 'F'}, {"0S)O1U", 'F'}, {"0S)OF(", 'F'}, - {"0S)ON", 'F'}, {"0S)ON&", 'F'}, {"0S)ON)", 'F'}, {"0S)ON;", 'F'}, @@ -5906,7 +5837,6 @@ static const keyword_t sql_keywords[] = { {"0S,F(S", 'F'}, {"0S,F(T", 'F'}, {"0S,F(V", 'F'}, - {"0S,V))", 'F'}, {"0S,V),", 'F'}, {"0S,V)O", 'F'}, {"0S,VB(", 'F'}, @@ -5927,10 +5857,6 @@ static const keyword_t sql_keywords[] = { {"0S1F(S", 'F'}, {"0S1F(V", 'F'}, {"0S1NC", 'F'}, - {"0S1NO(", 'F'}, - {"0S1NOF", 'F'}, - {"0S1NOS", 'F'}, - {"0S1NOV", 'F'}, {"0S1O((", 'F'}, {"0S1O(1", 'F'}, {"0S1O(F", 'F'}, @@ -5973,6 +5899,7 @@ static const keyword_t sql_keywords[] = { {"0S;E1,", 'F'}, {"0S;E1;", 'F'}, {"0S;E1C", 'F'}, + {"0S;E1K", 'F'}, {"0S;E1O", 'F'}, {"0S;E1T", 'F'}, {"0S;EF(", 'F'}, @@ -5993,11 +5920,13 @@ static const keyword_t sql_keywords[] = { {"0S;ES,", 'F'}, {"0S;ES;", 'F'}, {"0S;ESC", 'F'}, + {"0S;ESK", 'F'}, {"0S;ESO", 'F'}, {"0S;EST", 'F'}, {"0S;EV,", 'F'}, {"0S;EV;", 'F'}, {"0S;EVC", 'F'}, + {"0S;EVK", 'F'}, {"0S;EVO", 'F'}, {"0S;EVT", 'F'}, {"0S;N:T", 'F'}, @@ -6012,6 +5941,7 @@ static const keyword_t sql_keywords[] = { {"0S;T1;", 'F'}, {"0S;T1C", 'F'}, {"0S;T1F", 'F'}, + {"0S;T1K", 'F'}, {"0S;T1O", 'F'}, {"0S;T1T", 'F'}, {"0S;T;", 'F'}, @@ -6043,6 +5973,7 @@ static const keyword_t sql_keywords[] = { {"0S;TS;", 'F'}, {"0S;TSC", 'F'}, {"0S;TSF", 'F'}, + {"0S;TSK", 'F'}, {"0S;TSO", 'F'}, {"0S;TST", 'F'}, {"0S;TT(", 'F'}, @@ -6055,6 +5986,7 @@ static const keyword_t sql_keywords[] = { {"0S;TV;", 'F'}, {"0S;TVC", 'F'}, {"0S;TVF", 'F'}, + {"0S;TVK", 'F'}, {"0S;TVO", 'F'}, {"0S;TVT", 'F'}, {"0SA(((", 'F'}, @@ -6354,11 +6286,11 @@ static const keyword_t sql_keywords[] = { {"0SF(((", 'F'}, {"0SF(()", 'F'}, {"0SF((1", 'F'}, + {"0SF((E", 'F'}, {"0SF((F", 'F'}, {"0SF((N", 'F'}, {"0SF((S", 'F'}, {"0SF((V", 'F'}, - {"0SF())", 'F'}, {"0SF()1", 'F'}, {"0SF()F", 'F'}, {"0SF()K", 'F'}, @@ -6370,6 +6302,13 @@ static const keyword_t sql_keywords[] = { {"0SF(1)", 'F'}, {"0SF(1N", 'F'}, {"0SF(1O", 'F'}, + {"0SF(E(", 'F'}, + {"0SF(E1", 'F'}, + {"0SF(EF", 'F'}, + {"0SF(EK", 'F'}, + {"0SF(EN", 'F'}, + {"0SF(ES", 'F'}, + {"0SF(EV", 'F'}, {"0SF(F(", 'F'}, {"0SF(N)", 'F'}, {"0SF(N,", 'F'}, @@ -6399,14 +6338,6 @@ static const keyword_t sql_keywords[] = { {"0SK)&N", 'F'}, {"0SK)&S", 'F'}, {"0SK)&V", 'F'}, - {"0SK))&", 'F'}, - {"0SK)))", 'F'}, - {"0SK));", 'F'}, - {"0SK))B", 'F'}, - {"0SK))E", 'F'}, - {"0SK))K", 'F'}, - {"0SK))O", 'F'}, - {"0SK))U", 'F'}, {"0SK);E", 'F'}, {"0SK);T", 'F'}, {"0SK)B(", 'F'}, @@ -6606,13 +6537,13 @@ static const keyword_t sql_keywords[] = { {"0SO1&K", 'F'}, {"0SO1&N", 'F'}, {"0SO1&S", 'F'}, + {"0SO1&T", 'F'}, {"0SO1&U", 'F'}, {"0SO1&V", 'F'}, {"0SO1((", 'F'}, {"0SO1(E", 'F'}, {"0SO1(U", 'F'}, {"0SO1)&", 'F'}, - {"0SO1))", 'F'}, {"0SO1),", 'F'}, {"0SO1);", 'F'}, {"0SO1)B", 'F'}, @@ -6665,7 +6596,6 @@ static const keyword_t sql_keywords[] = { {"0SO1N,", 'F'}, {"0SO1NE", 'F'}, {"0SO1NF", 'F'}, - {"0SO1NO", 'F'}, {"0SO1NU", 'F'}, {"0SO1O(", 'F'}, {"0SO1OF", 'F'}, @@ -6737,6 +6667,7 @@ static const keyword_t sql_keywords[] = { {"0SON&K", 'F'}, {"0SON&N", 'F'}, {"0SON&S", 'F'}, + {"0SON&T", 'F'}, {"0SON&U", 'F'}, {"0SON&V", 'F'}, {"0SON((", 'F'}, @@ -6747,7 +6678,6 @@ static const keyword_t sql_keywords[] = { {"0SON(U", 'F'}, {"0SON(V", 'F'}, {"0SON)&", 'F'}, - {"0SON))", 'F'}, {"0SON),", 'F'}, {"0SON);", 'F'}, {"0SON)B", 'F'}, @@ -6828,13 +6758,13 @@ static const keyword_t sql_keywords[] = { {"0SOS&K", 'F'}, {"0SOS&N", 'F'}, {"0SOS&S", 'F'}, + {"0SOS&T", 'F'}, {"0SOS&U", 'F'}, {"0SOS&V", 'F'}, {"0SOS((", 'F'}, {"0SOS(E", 'F'}, {"0SOS(U", 'F'}, {"0SOS)&", 'F'}, - {"0SOS))", 'F'}, {"0SOS),", 'F'}, {"0SOS);", 'F'}, {"0SOS)B", 'F'}, @@ -6921,6 +6851,7 @@ static const keyword_t sql_keywords[] = { {"0SOT(F", 'F'}, {"0SOT(N", 'F'}, {"0SOT(S", 'F'}, + {"0SOT(T", 'F'}, {"0SOT(V", 'F'}, {"0SOU((", 'F'}, {"0SOU(E", 'F'}, @@ -6934,13 +6865,13 @@ static const keyword_t sql_keywords[] = { {"0SOV&K", 'F'}, {"0SOV&N", 'F'}, {"0SOV&S", 'F'}, + {"0SOV&T", 'F'}, {"0SOV&U", 'F'}, {"0SOV&V", 'F'}, {"0SOV((", 'F'}, {"0SOV(E", 'F'}, {"0SOV(U", 'F'}, {"0SOV)&", 'F'}, - {"0SOV))", 'F'}, {"0SOV),", 'F'}, {"0SOV);", 'F'}, {"0SOV)B", 'F'}, @@ -7241,6 +7172,7 @@ static const keyword_t sql_keywords[] = { {"0T(((F", 'F'}, {"0T(((N", 'F'}, {"0T(((S", 'F'}, + {"0T(((T", 'F'}, {"0T(((V", 'F'}, {"0T((1(", 'F'}, {"0T((1)", 'F'}, @@ -7263,21 +7195,21 @@ static const keyword_t sql_keywords[] = { {"0T((SN", 'F'}, {"0T((SO", 'F'}, {"0T((SV", 'F'}, + {"0T((T(", 'F'}, {"0T((V(", 'F'}, {"0T((V)", 'F'}, {"0T((VF", 'F'}, {"0T((VO", 'F'}, {"0T((VS", 'F'}, - {"0T(1))", 'F'}, {"0T(1)F", 'F'}, {"0T(1)O", 'F'}, {"0T(1)U", 'F'}, {"0T(1F(", 'F'}, {"0T(1N)", 'F'}, - {"0T(1NO", 'F'}, {"0T(1O(", 'F'}, {"0T(1OF", 'F'}, {"0T(1OS", 'F'}, + {"0T(1OT", 'F'}, {"0T(1OV", 'F'}, {"0T(1S)", 'F'}, {"0T(1V)", 'F'}, @@ -7294,7 +7226,6 @@ static const keyword_t sql_keywords[] = { {"0T(N(F", 'F'}, {"0T(N(S", 'F'}, {"0T(N(V", 'F'}, - {"0T(N))", 'F'}, {"0T(N)F", 'F'}, {"0T(N)O", 'F'}, {"0T(N)U", 'F'}, @@ -7304,10 +7235,10 @@ static const keyword_t sql_keywords[] = { {"0T(NO(", 'F'}, {"0T(NOF", 'F'}, {"0T(NOS", 'F'}, + {"0T(NOT", 'F'}, {"0T(NOV", 'F'}, {"0T(NS)", 'F'}, {"0T(NSO", 'F'}, - {"0T(S))", 'F'}, {"0T(S)F", 'F'}, {"0T(S)O", 'F'}, {"0T(S)U", 'F'}, @@ -7321,10 +7252,16 @@ static const keyword_t sql_keywords[] = { {"0T(SOF", 'F'}, {"0T(SON", 'F'}, {"0T(SOS", 'F'}, + {"0T(SOT", 'F'}, {"0T(SOV", 'F'}, {"0T(SV)", 'F'}, {"0T(SVO", 'F'}, - {"0T(V))", 'F'}, + {"0T(T((", 'F'}, + {"0T(T(1", 'F'}, + {"0T(T(F", 'F'}, + {"0T(T(N", 'F'}, + {"0T(T(S", 'F'}, + {"0T(T(V", 'F'}, {"0T(V)F", 'F'}, {"0T(V)O", 'F'}, {"0T(V)U", 'F'}, @@ -7332,6 +7269,7 @@ static const keyword_t sql_keywords[] = { {"0T(VO(", 'F'}, {"0T(VOF", 'F'}, {"0T(VOS", 'F'}, + {"0T(VOT", 'F'}, {"0T(VS)", 'F'}, {"0T(VSO", 'F'}, {"0T(VV)", 'F'}, @@ -7359,7 +7297,6 @@ static const keyword_t sql_keywords[] = { {"0TF((N", 'F'}, {"0TF((S", 'F'}, {"0TF((V", 'F'}, - {"0TF())", 'F'}, {"0TF()F", 'F'}, {"0TF()O", 'F'}, {"0TF(1)", 'F'}, @@ -7606,7 +7543,6 @@ static const keyword_t sql_keywords[] = { {"0UEKVC", 'F'}, {"0UEKVK", 'F'}, {"0UEKVO", 'F'}, - {"0UEN", 'F'}, {"0UEN((", 'F'}, {"0UEN()", 'F'}, {"0UEN,(", 'F'}, @@ -7714,7 +7650,7 @@ static const keyword_t sql_keywords[] = { {"0V&1&S", 'F'}, {"0V&1&V", 'F'}, {"0V&1)&", 'F'}, - {"0V&1))", 'F'}, + {"0V&1)O", 'F'}, {"0V&1)U", 'F'}, {"0V&1;", 'F'}, {"0V&1;C", 'F'}, @@ -7784,6 +7720,7 @@ static const keyword_t sql_keywords[] = { {"0V&F((", 'F'}, {"0V&F()", 'F'}, {"0V&F(1", 'F'}, + {"0V&F(E", 'F'}, {"0V&F(F", 'F'}, {"0V&F(N", 'F'}, {"0V&F(S", 'F'}, @@ -7820,7 +7757,7 @@ static const keyword_t sql_keywords[] = { {"0V&N&S", 'F'}, {"0V&N&V", 'F'}, {"0V&N)&", 'F'}, - {"0V&N))", 'F'}, + {"0V&N)O", 'F'}, {"0V&N)U", 'F'}, {"0V&N;", 'F'}, {"0V&N;C", 'F'}, @@ -7859,7 +7796,7 @@ static const keyword_t sql_keywords[] = { {"0V&S&S", 'F'}, {"0V&S&V", 'F'}, {"0V&S)&", 'F'}, - {"0V&S))", 'F'}, + {"0V&S)O", 'F'}, {"0V&S)U", 'F'}, {"0V&S1", 'F'}, {"0V&S1;", 'F'}, @@ -7902,6 +7839,12 @@ static const keyword_t sql_keywords[] = { {"0V&SV;", 'F'}, {"0V&SVC", 'F'}, {"0V&SVO", 'F'}, + {"0V&T((", 'F'}, + {"0V&T(1", 'F'}, + {"0V&T(F", 'F'}, + {"0V&T(N", 'F'}, + {"0V&T(S", 'F'}, + {"0V&T(V", 'F'}, {"0V&V", 'F'}, {"0V&V&(", 'F'}, {"0V&V&1", 'F'}, @@ -7910,7 +7853,7 @@ static const keyword_t sql_keywords[] = { {"0V&V&S", 'F'}, {"0V&V&V", 'F'}, {"0V&V)&", 'F'}, - {"0V&V))", 'F'}, + {"0V&V)O", 'F'}, {"0V&V)U", 'F'}, {"0V&V;", 'F'}, {"0V&V;C", 'F'}, @@ -8000,53 +7943,6 @@ static const keyword_t sql_keywords[] = { {"0V)&VF", 'F'}, {"0V)&VO", 'F'}, {"0V)&VU", 'F'}, - {"0V))&(", 'F'}, - {"0V))&1", 'F'}, - {"0V))&F", 'F'}, - {"0V))&N", 'F'}, - {"0V))&S", 'F'}, - {"0V))&V", 'F'}, - {"0V)))&", 'F'}, - {"0V))))", 'F'}, - {"0V))),", 'F'}, - {"0V)));", 'F'}, - {"0V)))B", 'F'}, - {"0V)))E", 'F'}, - {"0V)))K", 'F'}, - {"0V)))O", 'F'}, - {"0V)))U", 'F'}, - {"0V)),(", 'F'}, - {"0V));E", 'F'}, - {"0V));T", 'F'}, - {"0V))B(", 'F'}, - {"0V))B1", 'F'}, - {"0V))BF", 'F'}, - {"0V))BN", 'F'}, - {"0V))BS", 'F'}, - {"0V))BV", 'F'}, - {"0V))E(", 'F'}, - {"0V))E1", 'F'}, - {"0V))EF", 'F'}, - {"0V))EK", 'F'}, - {"0V))EN", 'F'}, - {"0V))ES", 'F'}, - {"0V))EV", 'F'}, - {"0V))K(", 'F'}, - {"0V))K1", 'F'}, - {"0V))KB", 'F'}, - {"0V))KF", 'F'}, - {"0V))KN", 'F'}, - {"0V))KS", 'F'}, - {"0V))KU", 'F'}, - {"0V))KV", 'F'}, - {"0V))O(", 'F'}, - {"0V))O1", 'F'}, - {"0V))OF", 'F'}, - {"0V))ON", 'F'}, - {"0V))OS", 'F'}, - {"0V))OV", 'F'}, - {"0V))U(", 'F'}, - {"0V))UE", 'F'}, {"0V),((", 'F'}, {"0V),(1", 'F'}, {"0V),(F", 'F'}, @@ -8240,7 +8136,6 @@ static const keyword_t sql_keywords[] = { {"0V,(SO", 'F'}, {"0V,(V)", 'F'}, {"0V,(VO", 'F'}, - {"0V,1))", 'F'}, {"0V,1),", 'F'}, {"0V,1)O", 'F'}, {"0V,1B(", 'F'}, @@ -8262,7 +8157,6 @@ static const keyword_t sql_keywords[] = { {"0V,F(S", 'F'}, {"0V,F(T", 'F'}, {"0V,F(V", 'F'}, - {"0V,N))", 'F'}, {"0V,N),", 'F'}, {"0V,N)O", 'F'}, {"0V,NB(", 'F'}, @@ -8276,7 +8170,6 @@ static const keyword_t sql_keywords[] = { {"0V,NOS", 'F'}, {"0V,NOV", 'F'}, {"0V,NUE", 'F'}, - {"0V,S))", 'F'}, {"0V,S),", 'F'}, {"0V,S)O", 'F'}, {"0V,SB(", 'F'}, @@ -8292,7 +8185,6 @@ static const keyword_t sql_keywords[] = { {"0V,SOS", 'F'}, {"0V,SOV", 'F'}, {"0V,SUE", 'F'}, - {"0V,V))", 'F'}, {"0V,V),", 'F'}, {"0V,V)O", 'F'}, {"0V,VB(", 'F'}, @@ -8315,6 +8207,7 @@ static const keyword_t sql_keywords[] = { {"0V;E1,", 'F'}, {"0V;E1;", 'F'}, {"0V;E1C", 'F'}, + {"0V;E1K", 'F'}, {"0V;E1O", 'F'}, {"0V;E1T", 'F'}, {"0V;EF(", 'F'}, @@ -8335,11 +8228,13 @@ static const keyword_t sql_keywords[] = { {"0V;ES,", 'F'}, {"0V;ES;", 'F'}, {"0V;ESC", 'F'}, + {"0V;ESK", 'F'}, {"0V;ESO", 'F'}, {"0V;EST", 'F'}, {"0V;EV,", 'F'}, {"0V;EV;", 'F'}, {"0V;EVC", 'F'}, + {"0V;EVK", 'F'}, {"0V;EVO", 'F'}, {"0V;EVT", 'F'}, {"0V;N:T", 'F'}, @@ -8354,6 +8249,7 @@ static const keyword_t sql_keywords[] = { {"0V;T1;", 'F'}, {"0V;T1C", 'F'}, {"0V;T1F", 'F'}, + {"0V;T1K", 'F'}, {"0V;T1O", 'F'}, {"0V;T1T", 'F'}, {"0V;T;", 'F'}, @@ -8385,6 +8281,7 @@ static const keyword_t sql_keywords[] = { {"0V;TS;", 'F'}, {"0V;TSC", 'F'}, {"0V;TSF", 'F'}, + {"0V;TSK", 'F'}, {"0V;TSO", 'F'}, {"0V;TST", 'F'}, {"0V;TT(", 'F'}, @@ -8397,6 +8294,7 @@ static const keyword_t sql_keywords[] = { {"0V;TV;", 'F'}, {"0V;TVC", 'F'}, {"0V;TVF", 'F'}, + {"0V;TVK", 'F'}, {"0V;TVO", 'F'}, {"0V;TVT", 'F'}, {"0VA(((", 'F'}, @@ -8696,11 +8594,11 @@ static const keyword_t sql_keywords[] = { {"0VF(((", 'F'}, {"0VF(()", 'F'}, {"0VF((1", 'F'}, + {"0VF((E", 'F'}, {"0VF((F", 'F'}, {"0VF((N", 'F'}, {"0VF((S", 'F'}, {"0VF((V", 'F'}, - {"0VF())", 'F'}, {"0VF()1", 'F'}, {"0VF()F", 'F'}, {"0VF()K", 'F'}, @@ -8712,6 +8610,13 @@ static const keyword_t sql_keywords[] = { {"0VF(1)", 'F'}, {"0VF(1N", 'F'}, {"0VF(1O", 'F'}, + {"0VF(E(", 'F'}, + {"0VF(E1", 'F'}, + {"0VF(EF", 'F'}, + {"0VF(EK", 'F'}, + {"0VF(EN", 'F'}, + {"0VF(ES", 'F'}, + {"0VF(EV", 'F'}, {"0VF(F(", 'F'}, {"0VF(N)", 'F'}, {"0VF(N,", 'F'}, @@ -8741,14 +8646,6 @@ static const keyword_t sql_keywords[] = { {"0VK)&N", 'F'}, {"0VK)&S", 'F'}, {"0VK)&V", 'F'}, - {"0VK))&", 'F'}, - {"0VK)))", 'F'}, - {"0VK));", 'F'}, - {"0VK))B", 'F'}, - {"0VK))E", 'F'}, - {"0VK))K", 'F'}, - {"0VK))O", 'F'}, - {"0VK))U", 'F'}, {"0VK);E", 'F'}, {"0VK);T", 'F'}, {"0VK)B(", 'F'}, @@ -8983,13 +8880,13 @@ static const keyword_t sql_keywords[] = { {"0VOS&K", 'F'}, {"0VOS&N", 'F'}, {"0VOS&S", 'F'}, + {"0VOS&T", 'F'}, {"0VOS&U", 'F'}, {"0VOS&V", 'F'}, {"0VOS((", 'F'}, {"0VOS(E", 'F'}, {"0VOS(U", 'F'}, {"0VOS)&", 'F'}, - {"0VOS))", 'F'}, {"0VOS),", 'F'}, {"0VOS);", 'F'}, {"0VOS)B", 'F'}, @@ -9076,6 +8973,7 @@ static const keyword_t sql_keywords[] = { {"0VOT(F", 'F'}, {"0VOT(N", 'F'}, {"0VOT(S", 'F'}, + {"0VOT(T", 'F'}, {"0VOT(V", 'F'}, {"0VOU((", 'F'}, {"0VOU(E", 'F'}, @@ -9295,6 +9193,7 @@ static const keyword_t sql_keywords[] = { {"ALTER TABLE", 'k'}, {"ANALYZE", 'k'}, {"AND", '&'}, + {"ANY", 'f'}, {"ANYARRAY", 't'}, {"ANYELEMENT", 't'}, {"ANYNONARRY", 't'}, @@ -9585,6 +9484,7 @@ static const keyword_t sql_keywords[] = { {"FROM", 'k'}, {"FROM_DAYS", 'f'}, {"FROM_UNIXTIME", 'f'}, + {"FULL JOIN", 'k'}, {"FULL OUTER", 'k'}, {"FULL OUTER JOIN", 'k'}, {"FULLTEXT", 'k'}, @@ -9626,6 +9526,8 @@ static const keyword_t sql_keywords[] = { {"IDENT_SEED", 'f'}, {"IF", 'f'}, {"IF EXISTS", 'f'}, + {"IF NOT", 'n'}, + {"IF NOT EXISTS", 'f'}, {"IFF", 'f'}, {"IFNULL", 'f'}, {"IGNORE", 'k'}, @@ -9774,6 +9676,7 @@ static const keyword_t sql_keywords[] = { {"NAME_CONST", 'f'}, {"NATURAL", 'n'}, {"NATURAL FULL", 'k'}, + {"NATURAL FULL OUTER JOIN", 'k'}, {"NATURAL INNER", 'k'}, {"NATURAL JOIN", 'k'}, {"NATURAL LEFT", 'k'}, @@ -9781,6 +9684,7 @@ static const keyword_t sql_keywords[] = { {"NATURAL LEFT OUTER JOIN", 'k'}, {"NATURAL OUTER", 'k'}, {"NATURAL RIGHT", 'k'}, + {"NATURAL RIGHT OUTER JOIN", 'k'}, {"NETMASK", 'f'}, {"NEXT VALUE", 'n'}, {"NEXT VALUE FOR", 'k'}, @@ -9986,6 +9890,7 @@ static const keyword_t sql_keywords[] = { {"SMALLDATETIMEFROMPARTS", 'f'}, {"SMALLINT", 't'}, {"SMALLSERIAL", 't'}, + {"SOME", 'f'}, {"SOUNDEX", 'f'}, {"SOUNDS", 'o'}, {"SOUNDS LIKE", 'o'}, @@ -10224,5 +10129,5 @@ static const keyword_t sql_keywords[] = { {"||", '&'}, {"~*", 'o'}, }; -static const size_t sql_keywords_sz = 10057; +static const size_t sql_keywords_sz = 9963; #endif