// Append the token with the specified value Token* SqlParser::Append(Token *token, const char *str, const wchar_t *wstr, int len, Token *format) { if(token == NULL) return NULL; Token *append = new Token(); if(format == NULL) *append = *token; else *append = *format; append->prev = NULL; append->next = NULL; append->t_str = NULL; append->t_wstr = NULL; append->t_len = 0; // If token starts with newline, add the same number of spaces before appended token if(str != NULL && str[0] == '\n') { // Add newline token first Token newline; #ifdef WIN32 newline.type = TOKEN_SYMBOL; newline.chr = '\r'; AppendCopy(token, &newline); #endif newline.type = TOKEN_SYMBOL; newline.chr = '\n'; AppendCopy(token, &newline); Token *prev = (format != NULL) ? format->prev : token->prev; // Copy all blankes while(prev != NULL && (prev->Compare(' ', L' ') == true || prev->Compare('\t', L'\t') == true)) { AppendCopy(token, prev); prev = prev->prev; } // Skip new line in the token Token::Change(append, str + 1, wstr + 1, len - 1); } else Token::Change(append, str, wstr, len); Append(token, append); return append; }
// MODIFIED BY option in EXPORT command bool SqlParser::Db2ParseModifiedByOptions(Token **colsep_out) { bool exists = false; Token *start = NULL; // Options while(true) { Token *next = GetNextToken(); if(next == NULL) break; if(start == NULL) start = next; // COLDELx where x is a single characater column delimiter if(next->Compare("COLDEL", L"COLDEL", 0, 6) == true) { Token *del = NULL; // x is a special punctuation character it is selected as a separate token if(next->len == 6) { del = GetNextToken(); if(colsep_out != NULL) *colsep_out = del; } exists = true; } else // NOCHARDEL if(next->Compare("NOCHARDEL", L"NOCHARDEL", 9) == true) { exists = true; } // Unknown option else { PushBack(next); break; } } if(exists == true) { // Remove options if(_target == SQL_ORACLE) Token::Remove(start, GetLastToken()); } return exists; }
// DB2 FETCH FIRST n ROWS ONLY clause in SELECT statement bool SqlParser::ParseDb2FetchFirstRowOnly(Token *fetch, Token **rowlimit_soptions, int *rowlimit) { if(fetch == NULL || Token::Compare(fetch, "FETCH", L"FETCH", 5) == false) return false; Token *first = GetNextWordToken("FIRST", L"FIRST", 5); if(first == NULL) return false; // Optional number of rows, meaning 1 row if skipped Token *num = GetNextToken(); Token *rows = NULL; if(num == NULL) return false; // Check if num already points to ROW or ROWS if(num->Compare("ROW", L"ROW", 3) == true || num->Compare("ROWS", L"ROWS", 4) == true) { rows = num; num = NULL; } // ROWS or ROW if(rows == NULL) rows = GetNextToken(); Token *only = GetNextWordToken("ONLY", L"ONLY", 4); if(only == NULL) return false; // Set rowlimit to output if(num == NULL && rowlimit != NULL) *rowlimit = 1; else if(num != NULL && rowlimit_soptions != NULL) *rowlimit_soptions = num; // ROWNUM is used in Oracle if(_target == SQL_ORACLE) { Token::Remove(fetch); Token::Remove(first, only); } return true; }
// In DB2 a number can be followed by size specifier K, M or G Token* SqlParser::Db2SizeSpecifier() { Token *spec = GetNextToken(); if(spec == NULL) return NULL; if(spec->Compare("K", L"K", 1) == false && spec->Compare("M", L"M", 1) == false && spec->Compare("G", L"G", 1) == false) { PushBack(spec); return NULL; } return spec; }
// Sybase ADS EXECUTE PROCEDURE statement bool SqlParser::ParseSybaseExecuteProcedureStatement(Token * /*execute*/) { Token *procedure = TOKEN_GETNEXTW("PROCEDURE"); if(procedure == NULL) return false; // Procedure name Token *name = GetNextIdentToken(); if(name == NULL) return false; // List of parameters, empty () when there are no params Token *open = TOKEN_GETNEXT('('); Token *close = NULL; if(open != NULL) { while(true) { Token *param = GetNextToken(); if(param == NULL) break; // () can be specified if(param->Compare(')', L')') == true) { PushBack(param); break; } ParseExpression(param); // Next parameter Token *comma = TOKEN_GETNEXT(','); if(comma == NULL) break; } close = TOKEN_GETNEXT(')'); } // SQL Server does not allow ( and ) if(_target == SQL_SQL_SERVER) { Token::Remove(open); Token::Remove(close); } if(_target != SQL_SYBASE_ADS) Token::Remove(procedure); return true; }
// Prepend the token with the specified value Token* SqlParser::Prepend(Token *token, const char *str, const wchar_t *wstr, int len, Token *format) { if(token == NULL) return NULL; Token *prepend = new Token(); // Define how to format the token if(format == NULL) *prepend = *token; else *prepend = *format; prepend->prev = NULL; prepend->next = NULL; prepend->t_str = NULL; prepend->t_wstr = NULL; prepend->t_len = 0; prepend->flags = TOKEN_INSERTED; Token::Change(prepend, str, wstr, len); Prepend(token, prepend); // If token ends with newline, add the same number of spaces after prepended token if(str != NULL && str[len - 1] == '\n') { Token *prev = token->prev; // Skip previously appended tokens while(prev != NULL && prev->flags & TOKEN_INSERTED) prev = prev->prev; // Copy all blanks and tabs before appended token after new line while(prev != NULL && (prev->Compare(' ', L' ') == true || prev->Compare('\t', L'\t') == true)) { AppendCopy(prepend, prev); prev = prev->prev; } } return prepend; }
// Parse Teradata CREATE TABLE storage clause bool SqlParser::ParseTeradataStorageClause(int obj_scope, Token *last_colname, Token *last_colend) { bool exists = false; while(true) { Token *next = GetNextToken(); if(next == NULL) break; // UNIQUE PRIMARY INDEX hash partitioning clause if(next->Compare("UNIQUE", L"UNIQUE", 6) == true) { Token *primary = GetNext("PRIMARY", L"PRIMARY", 7); if(primary != NULL) ParseTeradataPrimaryIndex(next, primary, obj_scope, last_colname, last_colend); exists = true; continue; } else // PRIMARY INDEX hash partitioning clause if(next->Compare("PRIMARY", L"PRIMARY", 7) == true) { ParseTeradataPrimaryIndex(NULL, next, obj_scope, last_colname, last_colend); exists = true; continue; } // Not a storage clause PushBack(next); break; } return exists; }
// Get next token and make sure it contains the specified word Token* SqlParser::GetNextWordToken(const char *str, const wchar_t *wstr, int len) { Token *token = GetNextToken(); if(token == NULL) return NULL; if(token->Compare(str, wstr, len) == true) return token; else PushBack(token); return NULL; }
// Get the next token and make sure if contains the specified char Token* SqlParser::GetNextCharToken(const char ch, const wchar_t wch) { Token *token = GetNextToken(); if(token == NULL) return NULL; if(token->Compare(ch, wch) == true) return token; else PushBack(token); return NULL; }
// Parse SQL Server CREATE TABLE storage clause bool SqlParser::ParseSqlServerStorageClause() { bool exists = false; while(true) { Token *next = GetNext(); if(next == NULL) break; // ON filegroup_name if(next->Compare("ON", L"ON", 2) == true) { // File group name Token *name = GetNext(); if(_target != SQL_SQL_SERVER) { // Remove clause if it is the default PRIMARY file group if(Token::Compare(name, "PRIMARY", L"PRIMARY", 7) == true || Token::Compare(name, "[PRIMARY]", L"[PRIMARY]", 9) == true) { Token::Remove(next, name); } } exists = true; } else { PushBack(next); break; } } return exists; }
// Set Removed flag for the token void Token::Remove(Token *token, bool remove_spaces_before) { if(token == NULL) return; token->flags |= TOKEN_REMOVED; Token *prev = token->prev; Token *next = token->next; if(prev == NULL) return; if(remove_spaces_before == true) { // Remove spaces token before the removed word (recursively), but only if there is a blank or ) , ; // after removed token (otherwise tokens can be merged) if(prev->Compare(' ', L' ') == true || prev->Compare('\t', L'\t') == true) { if(next != NULL) { if(next->IsBlank() == true || next->Compare(')', L')') == true || next->Compare(',', L',') == true || next->Compare(';', L';') == true) Remove(prev); } else // Next token can be not selected yet if(token->next_start != NULL && token->remain_size > 1) { const char *cur = token->next_start; if(*cur == ' ' || *cur == ')' || *cur == ',' || *cur == ';') Remove(prev); } } } // In case cases better to remove spaces after: "SET var = 1" to "var := 1" when SET is removed else { if(next != NULL && next->Compare(' ', L' ') == true) Remove(next); } }
// DB2 CREATE INDEX storage options bool SqlParser::ParseDb2CreateIndexOptions() { bool exists = false; while(true) { Token *next = GetNextToken(); if(next == NULL) break; // DB2 z/OS USING STOGROUP if(next->Compare("USING", L"USING", 5) == true) { Token *stogroup = GetNextWordToken("STOGROUP", L"STOGROUP", 8); if(stogroup != NULL) ParseDb2StogroupClause(NULL, next, stogroup, SQL_SCOPE_INDEX); exists = true; continue; } else // DB2 CLUSTER option if(next->Compare("CLUSTER", L"CLUSTER", 7) == true) { if(_target != SQL_DB2) Token::Remove(next); exists = true; continue; } else // DB2 for z/OS NOT CLUSTER, NOT PADDED if(next->Compare("NOT", L"NOT", 3) == true) { Token *cluster = GetNextWordToken("CLUSTER", L"CLUSTER", 7); Token *padded = NULL; if(cluster == NULL) padded = GetNextWordToken("PADDED", L"PADDED", 6); if(cluster != NULL || padded != NULL) { if(_target != SQL_DB2) { if(cluster != NULL) Token::Remove(next, cluster); else if(padded != NULL) Token::Remove(next, padded); } exists = true; continue; } } else // DB2 COMPRESS NO | YES option if(next->Compare("COMPRESS", L"COMPRESS", 8) == true) { Token *value = GetNextToken(); if(_target != SQL_DB2) Token::Remove(next, value); exists = true; continue; } else // DB2 ALLOW REVERSE SCAN if(next->Compare("ALLOW", L"ALLOW", 5) == true) { /*Token *reverse */ (void) GetNextWordToken("REVERSE", L"REVERSE", 7); Token *scan = GetNextWordToken("SCAN", L"SCAN", 4); if(_target != SQL_DB2) Token::Remove(next, scan); exists = true; continue; } else // DB2 PCTFREE if(next->Compare("PCTFREE", L"PCTFREE", 7) == true) { Token *value = GetNextToken(); int int_value = (value != NULL) ? value->GetInt() : 0; // WITH (FILLFACTOR = 100 - val) in Greenplum if(_target == SQL_GREENPLUM) { Token::Change(next, "WITH (FILLFACTOR =", L"WITH (FILLFACTOR =", 18); Token::Change(value, 100 - int_value); Append(value, ")", L")", 1); } else // Oracle supports PCTFREE if(Target(SQL_ORACLE, SQL_DB2) == false) Token::Remove(next, value); exists = true; continue; } else // DB2 MINPCTUSED if(next->Compare("MINPCTUSED", L"MINPCTUSED", 10) == true) { Token *value = GetNextToken(); if(_target != SQL_DB2) Token::Remove(next, value); exists = true; continue; } else // DB2 z/OS FREEPAGE num if(next->Compare("FREEPAGE", L"FREEPAGE", 8) == true) { Token *value = GetNextToken(); if(_target != SQL_DB2) Token::Remove(next, value); exists = true; continue; } else // DB2 z/OS BUFFERPOOL name if(next->Compare("BUFFERPOOL", L"BUFFERPOOL", 10) == true) { Token *name = GetNextToken(); if(_target != SQL_DB2) Token::Remove(next, name); exists = true; continue; } else // DB2 SPECIFICATION ONLY (index will be commented) if(next->Compare("SPECIFICATION", L"SPECIFICATION", 13) == true) { /*Token *only */ (void) GetNextWordToken("ONLY", L"ONLY", 4); exists = true; continue; } else // DB2 z/OS GBPCACHE CHANGED | ALL | NONE if(next->Compare("GBPCACHE", L"GBPCACHE", 8) == true) { Token *value = GetNextToken(); if(value != NULL) { if(_target != SQL_DB2) Token::Remove(next, value); exists = true; continue; } } else // DB2 z/OS CLOSE NO | YES if(next->Compare("CLOSE", L"CLOSE", 5) == true) { Token *value = GetNextToken(); if(value != NULL) { if(_target != SQL_DB2) Token::Remove(next, value); exists = true; continue; } } else // DB2 z/OS COPY YES | NO if(next->Compare("COPY", L"COPY", 4) == true) { Token *value = GetNextToken(); if(value != NULL) { if(_target != SQL_DB2) Token::Remove(next, value); exists = true; continue; } } else // DB2 z/OS PIECESIZE num [K | M | G] if(next->Compare("PIECESIZE", L"PIECESIZE", 9) == true) { Token *num = GetNextToken(); if(num != NULL) { // Size can be optionally followed by specifier K, M or G Token *spec = Db2SizeSpecifier(); if(_target != SQL_DB2) { Token::Remove(next, num); Token::Remove(spec); } exists = true; continue; } } else // DB2 for z/OS PADDED option if(next->Compare("PADDED", L"PADDED", 6) == true) { if(_target != SQL_DB2) Token::Remove(next); exists = true; continue; } // Not an index clause PushBack(next); break; } return exists; }
// Generate output void SqlParser::CreateOutputString(const char **output, int *out_size) { if(output == NULL) return; Token *token = _tokens.GetFirst(); int len = 0; int not_removed = 0; int removed = 0; // Calculate the output size in bytes and format output while(token != NULL) { bool r = false; bool n = false; // If token removed its target length is 0 len += token->GetTargetLength(); if(token->IsRemoved() == false) { r = token->Compare('\r', L'\r'); if(r == false) n = token->Compare('\n', L'\n'); } // Check if we need to remove newline (0D0A \r\n on Windows, 0D on Unix) if(r == true || n == true) { // String was not empty and all tokens removed if(not_removed == 0 && removed != 0) { Token::Remove(token); len--; // If current is \r and next is \n remove \n if(r == true && token->next != NULL && token->next->Compare('\n', L'\n') == true) { // Its size will be reduced in the next iteration Token::Remove(token->next); } // Remove all spaces in this empty line Token *cur = token->prev; while(cur != NULL) { // Remove until new line if(cur->Compare('\n', L'\n') || cur->Compare('\r', L'\r')) break; if(cur->IsBlank() == true && cur->IsRemoved() == false) { Token::Remove(cur); len--; } cur = cur->prev; } } not_removed = 0; removed = 0; } // Calculate the number of removed and not removed tokens in line else { if(token->IsBlank() == false) { if(token->IsRemoved() == true) removed++; else not_removed++; } } token = _tokens.GetNext(); } if(len == 0) { *output = NULL; if(out_size != NULL) *out_size = 0; return; } // Allocate buffer char *out = new char[len + 1]; *out = 0; token = _tokens.GetFirst(); int cur_len = 0; while(token != NULL) { token->AppendTarget(out, &cur_len); token = _tokens.GetNext(); } out[cur_len] = 0; *output = out; if(out_size != NULL) *out_size = cur_len; }
// Teradata CREATE TABLE options before column definition bool SqlParser::ParseTeradataTableOptions() { bool exists = false; // , goes after table name before even first option while(true) { Token *comma = GetNextCharToken(',', L','); if(comma == NULL) break; // Most options can start with NO keyword to disable option Token *no = GetNextWordToken("NO", L"NO", 2); Token *next = GetNextToken(); if(next == NULL) { if(no != NULL) PushBack(no); break; } // [NO] FALLBACK to store a row copy if(next->Compare("FALLBACK", L"FALLBACK", 8) == true) { if(_target != SQL_TERADATA) Token::Remove(comma, next); exists = true; continue; } else // [NO] BEFORE JOURNAL to store before image if(next->Compare("BEFORE", L"BEFORE", 6) == true) { Token *journal = GetNextWordToken("JOURNAL", L"JOURNAL", 7); if(_target != SQL_TERADATA && journal != NULL) Token::Remove(comma, journal); exists = true; continue; } else // [NO] AFTER JOURNAL to store after image if(next->Compare("AFTER", L"AFTER", 5) == true) { Token *journal = GetNextWordToken("JOURNAL", L"JOURNAL", 7); if(_target != SQL_TERADATA && journal != NULL) Token::Remove(comma, journal); exists = true; continue; } if(no != NULL) PushBack(no); break; } return exists; }
// DB2 CREATE DATABASE statement bool SqlParser::Db2CreateDatabase(Token *create, Token * /*database*/, Token * /*name*/) { bool exists = false; // CREATE DATABASE options while(true) { Token *next = GetNextToken(); if(next == NULL) break; // BUFFERPOOL name if(next->Compare("BUFFERPOOL", L"BUFFERPOOL", 10) == true) { Token *name = GetNextToken(); if(Target(SQL_DB2, SQL_ORACLE) == false) Token::Remove(next, name); exists = true; continue; } else // INDEXBP name if(next->Compare("INDEXBP", L"INDEXBP", 7) == true) { Token *name = GetNextToken(); if(Target(SQL_DB2, SQL_ORACLE) == false) Token::Remove(next, name); exists = true; continue; } else // STOGROUP name if(next->Compare("STOGROUP", L"STOGROUP", 8) == true) { Token *name = GetNextToken(); if(Target(SQL_DB2, SQL_ORACLE) == false) Token::Remove(next, name); exists = true; continue; } else // CCSID ASCII | EBCDIC | UNICODE if(next->Compare("CCSID", L"CCSID", 5) == true) { Token *code = GetNextToken(); if(Target(SQL_DB2, SQL_ORACLE) == false) Token::Remove(next, code); exists = true; continue; } PushBack(next); break; } // Comment the entire statement for Oracle if(_target == SQL_ORACLE) { Token *end = GetLastToken(GetNextCharToken(';', L';')); Comment(create, end); } return exists; }
// Get + or - as operator, not sign and number Token* SqlParser::GetNextPlusMinusAsOperatorToken(const char ch, const wchar_t wch) { Token *token = GetNextToken(); if(token == NULL) return NULL; // If + or - already returned as separate token then exit, for example when there is "+ var" if(token->Compare(ch, wch) == true) return token; // If a number follows + or - they will be in single token as +1, but check for + or - first if(token->Compare(ch, wch, 0) == false) { PushBack(token); return NULL; } // Change the first token to hold operator +/- token->type = TOKEN_SYMBOL; token->chr = ch; token->wchr = 0; token->str = NULL; token->wstr = NULL; // Rewind input pointer _next_start -= token->len - 1; _remain_size += token->len - 1; token->len = 0; token->next_start = _next_start; token->remain_size = _remain_size; /*// Separate +/- operator and number constant tokens Token *token2 = new Token(); *token2 = *token; token2->prev = NULL; token2->next = NULL; token2->t_str = NULL; token2->t_wstr = NULL; token2->t_len = 0; // Second token hold number (decrease size by 1) token2->type = TOKEN_WORD; token2->chr = 0; token2->wchr = 0; token2->str = token2->str + 1; token2->wstr = 0; token2->len = token2->len - 1; _tokens.Append(token, token2); // Allow number to be selected as the next token PushBack(token2); */ return token; }
// Various SET options such as SET CURRENT SCHEMA bool SqlParser::ParseDb2SetOptions(Token *set) { bool exists = false; if(set == NULL) return false; // CURRENT is optional (SET SCHEMA is allowed) Token *current = GetNextWordToken("CURRENT", L"CURRENT", 7); Token *option = GetNextToken(); if(option == NULL) { PushBack(current); return false; } // SET [CURRENT] PATH = list if(option->Compare("PATH", L"PATH", 4) == true) { // Optional = /*Token *equal */ (void) GetNextCharToken('=', L'='); // Comma-separated list of values while(true) { // Schema name /*Token *name */ (void) GetNextToken(); Token *comma = GetNextCharToken(',', L','); if(comma == NULL) break; } // Remove the statement in Oracle if(_target == SQL_ORACLE) Token::Remove(set, Nvl(GetNextCharToken(';', L';'), GetLastToken())); exists = true; } else // SET [CURRENT] SCHEMA = name if(option->Compare("SCHEMA", L"SCHEMA", 6) == true) { // Optional = Token *equal = GetNextCharToken('=', L'='); // Schema name /*Token *name */ (void) GetNextToken(); // ALTER SESSION SET CURRENT_SCHEMA = name in Oracle if(_target == SQL_ORACLE) { Prepend(set, "ALTER SESSION ", L"ALTER SESSION ", 14); Token::Remove(current); Token::Change(option, "CURRENT_SCHEMA", L"CURRENT_SCHEMA", 14); if(equal == NULL) AppendNoFormat(option, " =", L" =", 2); } exists = true; } // Not a SET option else { PushBack(option); PushBack(current); } return exists; }
// SQL Server index options WITH (PAD_INDEX = OFF, ...) bool SqlParser::ParseSqlServerIndexOptions(Token *token) { if(token == NULL) return false; bool exists = false; // Start with WITH keyword if(token->Compare("WITH", L"WITH", 4) == false) return false; // ( can be omitted if FILLFACTOR is only specified Token *open = GetNext('(', L'('); while(true) { bool remove = false; Token *option = GetNextToken(); if(option == NULL) break; // = between option name and value /*Token *equal */ (void) GetNext('=', L'='); Token *value = NULL; // ALLOW_PAGE_LOCKS = ON | OFF if(option->Compare("ALLOW_PAGE_LOCKS", L"ALLOW_PAGE_LOCKS", 16) == true) { value = GetNextToken(); if(_target != SQL_SQL_SERVER) remove = true; exists = true; } else // ALLOW_ROW_LOCKS = ON | OFF if(option->Compare("ALLOW_ROW_LOCKS", L"ALLOW_ROW_LOCKS", 15) == true) { value = GetNextToken(); if(_target != SQL_SQL_SERVER) remove = true; exists = true; } else // FILLFACTOR = num if(option->Compare("FILLFACTOR", L"FILLFACTOR", 10) == true) { value = GetNextToken(); if(_target != SQL_SQL_SERVER) remove = true; exists = true; } else // IGNORE_DUP_KEY = ON | OFF if(option->Compare("IGNORE_DUP_KEY", L"IGNORE_DUP_KEY", 14) == true) { value = GetNextToken(); if(_target != SQL_SQL_SERVER) remove = true; exists = true; } else // PAD_INDEX = ON | OFF if(option->Compare("PAD_INDEX", L"PAD_INDEX", 9) == true) { value = GetNextToken(); if(_target != SQL_SQL_SERVER) remove = true; exists = true; } else // STATISTICS_NORECOMPUTE = ON | OFF if(option->Compare("STATISTICS_NORECOMPUTE", L"STATISTICS_NORECOMPUTE", 22) == true) { value = GetNextToken(); if(_target != SQL_SQL_SERVER) remove = true; exists = true; } else { PushBack(option); break; } Token *comma = GetNext(',', L','); // Remove the option if(remove == true) { Token::Remove(option, value); Token::Remove(comma); } if(comma == NULL) break; } if(exists == false) { // PostgreSQL also has WITH ( ... option, so return open token PushBack(open); return false; } Token *close = GetNext(open, ')', L')'); // Remove WITH () if(_target != SQL_SQL_SERVER) { Token::Remove(token); Token::Remove(open); Token::Remove(close); } // Storage clause can follow ParseSqlServerStorageClause(); return exists; }
// Parse Informix CREATE TABLE storage clause bool SqlParser::ParseInformixStorageClause() { bool exists = false; while(true) { Token *next = GetNextToken(); if(next == NULL) break; // EXTENT SIZE num if(next->Compare("EXTENT", L"EXTENT", 6) == true) { Token *size = GetNextWordToken("SIZE", L"SIZE", 4); Token *num = GetNextToken(size); if(_target != SQL_INFORMIX && num != NULL) Token::Remove(next, num); exists = true; continue; } else // FRAGMENT BY partitioning clause if(next->Compare("FRAGMENT", L"FRAGMENT", 8) == true) { ParseInformixFragmentBy(next); exists = true; continue; } else // IN dbspace if(next->Compare("IN", L"IN", 2) == true) { // Get database space name Token *name = GetNextToken(); // TABLESPACE name in Oracle if(_target == SQL_ORACLE) Token::Change(next, "TABLESPACE", L"TABLESPACE", 10); else // DB2 also uses IN keyword to specify a tablespace if(Target(SQL_DB2, SQL_INFORMIX) == false) Token::Remove(next, name); exists = true; continue; } else // LOCK MODE PAGE | ROW | TABLE if(next->Compare("LOCK", L"LOCK", 4) == true) { Token *mode = GetNextWordToken("MODE", L"MODE", 4); Token *type = GetNextToken(mode); if(_target != SQL_INFORMIX && type != NULL) Token::Remove(next, type); exists = true; continue; } else // NEXT SIZE num if(next->Compare("NEXT", L"NEXT", 4) == true) { Token *size = GetNextWordToken("SIZE", L"SIZE", 4); Token *num = GetNextToken(size); if(_target != SQL_INFORMIX && num != NULL) Token::Remove(next, num); exists = true; continue; } // Not a storage clause PushBack(next); break; } return exists; }
// Parse Oracle CREATE TABLE, CREATE INDEX, PARTITION definition storage clause bool SqlParser::ParseOracleStorageClause(int stmt_scope) { bool exists = false; while(true) { Token *next = GetNextToken(); if(next == NULL) break; // SEGMENT CREATION IMMEDIATE | DEFERRED if(next->Compare("SEGMENT", L"SEGMENT", 7) == true) { Token *creation = GetNextWordToken("CREATION", L"CREATION", 8); Token *value = GetNextToken(); if(_target != SQL_ORACLE && creation != NULL) Token::Remove(next, value); exists = true; continue; } else // PCTFREE num if(next->Compare("PCTFREE", L"PCTFREE", 7) == true) { Token *value = GetNextNumberToken(); if(_target != SQL_ORACLE && value != NULL) Token::Remove(next, value); exists = true; continue; } else // PCTUSED num if(next->Compare("PCTUSED", L"PCTUSED", 7) == true) { Token *value = GetNextNumberToken(); if(_target != SQL_ORACLE && value != NULL) Token::Remove(next, value); exists = true; continue; } else // INITRANS num if(next->Compare("INITRANS", L"INITRANS", 8) == true) { Token *value = GetNextNumberToken(); if(_target != SQL_ORACLE && value != NULL) Token::Remove(next, value); exists = true; continue; } else // MAXTRANS num if(next->Compare("MAXTRANS", L"MAXTRANS", 8) == true) { Token *value = GetNextNumberToken(); if(_target != SQL_ORACLE && value != NULL) Token::Remove(next, value); exists = true; continue; } else // COMPRESS [BASIC] or COMPRESS num (for index-orginized tables and indexes) if(next->Compare("COMPRESS", L"COMPRESS", 8) == true) { // Optional BASIC keyword Token *basic = GetNextWordToken("BASIC", L"BASIC", 5); Token *num = NULL; // Check for a number if(basic == NULL) num = GetNextNumberToken(); if(_target != SQL_ORACLE) { Token::Remove(next); Token::Remove(basic); Token::Remove(num); } exists = true; continue; } else // NOCOMPRESS if(next->Compare("NOCOMPRESS", L"NOCOMPRESS", 10) == true) { if(_target != SQL_ORACLE) Token::Remove(next); exists = true; continue; } else // NOCACHE if(next->Compare("NOCACHE", L"NOCACHE", 7) == true) { if(_target != SQL_ORACLE) Token::Remove(next); exists = true; continue; } else // LOGGING if(next->Compare("LOGGING", L"LOGGING", 7) == true) { if(_target != SQL_ORACLE) Token::Remove(next); exists = true; continue; } else // NOLOGGING if(next->Compare("NOLOGGING", L"NOLOGGING", 9) == true) { if(_target != SQL_ORACLE) Token::Remove(next); exists = true; continue; } else // NOPARALLEL if(next->Compare("NOPARALLEL", L"NOPARALLEL", 10) == true) { if(_target != SQL_ORACLE) Token::Remove(next); exists = true; continue; } else // PARALLEL num if(next->Compare("PARALLEL", L"PARALLEL", 8) == true) { Token *value = GetNextNumberToken(); if(_target != SQL_ORACLE && value != NULL) Token::Remove(next, value); exists = true; continue; } else // NOMONITORING if(next->Compare("NOMONITORING", L"NOMONITORING", 12) == true) { if(_target != SQL_ORACLE) Token::Remove(next); exists = true; continue; } else // TABLESPACE name if(next->Compare("TABLESPACE", L"TABLESPACE", 10) == true) { Token *name = GetNextIdentToken(); // ON name if(_target == SQL_SQL_SERVER) Token::Change(next, "ON", L"ON", 2); else // IN name if(_target == SQL_DB2) Token::Change(next, "IN", L"IN", 2); else Token::Remove(next, name); exists = true; continue; } else // STORAGE () clause if(next->Compare("STORAGE", L"STORAGE", 7) == true) { exists = ParseOracleStorageClause(next); continue; } else // LOB (column) STORE AS (params) if(next->Compare("LOB", L"LOB", 3) == true) { if(ParseOracleLobStorageClause(next) == true) { exists = true; continue; } } else // Oracle partitioning clauses if(ParseOraclePartitions(next, stmt_scope) == true) { exists = true; continue; } else // COMPUTE STATISTICS if(next->Compare("COMPUTE", L"COMPUTE", 7) == true) { Token *statistics = GetNextWordToken("STATISTICS", L"STATISTICS", 10); // Remove if not Oracle if(_target != SQL_ORACLE) Token::Remove(next, statistics); exists = true; continue; } else // ENABLE ROW MOVEMENT if(next->Compare("ENABLE", L"ENABLE", 6) == true) { Token *row = GetNextWordToken("ROW", L"ROW", 3); if(row != NULL) { Token *movement = GetNextWordToken("MOVEMENT", L"MOVEMENT", 8); // Remove if not Oracle if(_target != SQL_ORACLE) Token::Remove(next, movement); exists = true; continue; } } else // REVERSE index or primary key storage attribute if(next->Compare("REVERSE", L"REVERSE", 7) == true) { // Remove if not Oracle if(_target != SQL_ORACLE) Token::Remove(next); exists = true; continue; } // Not an Oracle storage clause PushBack(next); break; } return exists; }
// Temporary table options bool SqlParser::ParseTempTableOptions(Token *table_name, Token **start_out, Token **end_out, bool *no_data) { bool exists = false; Token *start = NULL; while(true) { Token *next = GetNextToken(); if(next == NULL) break; if(start == NULL) start = next; // ON COMMIT PRESERVE | DELETE ROWS in Oracle, DB2; ON ROLLBACK PRESERVE | DELETE ROWS in DB2 if(next->Compare("ON", L"ON", 2) == true) { Token *commit = GetNextWordToken("COMMIT", L"COMMIT", 6); Token *rollback = NULL; if(commit == NULL) rollback = GetNextWordToken("ROLLBACK", L"ROLLBACK", 8); if(commit == NULL && rollback == NULL) break; Token *delete_ = GetNextWordToken("DELETE", L"DELETE", 6); Token *preserve = NULL; if(delete_ == NULL) preserve = GetNextWordToken("PRESERVE", L"PRESERVE", 8); Token *rows = GetNextWordToken("ROWS", L"ROWS", 4); if(_target == SQL_SQL_SERVER) Token::Remove(next, rows); else // Oracle does not support ON ROLLBACK, but DELETE ROWS in default on rollback if(_target == SQL_ORACLE && rollback != NULL) { if(delete_ != NULL) Token::Remove(next, rows); else Comment(next, rows); } exists = true; continue; } else // NOT LOGGED in DB2 if(next->Compare("NOT", L"NOT", 3) == true) { Token *logged = GetNextWordToken("LOGGED", L"LOGGED", 6); if(logged != NULL) { if(_target == SQL_ORACLE) Token::Remove(next, logged); exists = true; continue; } } else // WITH REPLACE, WITH NO DATA in DB2 if(next->Compare("WITH", L"WITH", 4) == true) { Token *replace = GetNextWordToken("REPLACE", L"REPLACE", 7); Token *no = NULL; if(replace == NULL) no = GetNextWordToken("NO", L"NO", 2); // WITH REPLACE in DB2 if(replace != NULL) { if(Target(SQL_DB2) == false) Token::Remove(next, replace); _spl_declared_tables_with_replace.Add(table_name); exists = true; continue; } else // WITH NO DATA in DB2 if(no != NULL) { Token *data = GetNextWordToken("DATA", L"DATA", 4); if(data != NULL) { if(_target == SQL_ORACLE) Token::Remove(next, data); if(no_data != NULL) *no_data = true; exists = true; continue; } } } else // DEFINITION ONLY in DB2 if(next->Compare("DEFINITION", L"DEFINITION", 10) == true) { Token *only = GetNextWordToken("ONLY", L"ONLY", 4); if(only != NULL) { if(_target == SQL_ORACLE) Token::Remove(next, only); if(no_data != NULL) *no_data = true; exists = true; continue; } } else // IN tablespace in DB2 if(next->Compare("IN", L"IN", 2) == true) { Token *tablespace_name = GetNextToken(); if(tablespace_name != NULL) { if(_target == SQL_ORACLE) Token::Remove(next, tablespace_name); exists = true; continue; } } // Not a temporary table clause PushBack(next); break; } if(exists == true) { if(start_out != NULL) *start_out = start; if(end_out != NULL) *end_out = GetLastToken(); } return exists; }
// Parse MySQL CREATE TABLE storage clause bool SqlParser::ParseMysqlStorageClause(Token *table_name, Token **id_start, Token **comment_out) { bool exists = false; // Auto_increment start value Token *auto_start = NULL; while(true) { Token *next = GetNextToken(); if(next == NULL) break; // ENGINE = type if(next->Compare("ENGINE", L"ENGINE", 6) == true) { // Equal sign = is optional in the clause Token *equal = GetNextCharToken('=', L'='); Token *type = GetNextToken(); if(_target != SQL_MYSQL) { Token::Remove(next); Token::Remove(equal); Token::Remove(type); } exists = true; continue; } else // AUTO_INCREMENT = start table option if(next->Compare("AUTO_INCREMENT", L"AUTO_INCREMENT", 14) == true) { // Equal sign = is optional in the clause Token *equal = GetNextCharToken('=', L'='); auto_start = GetNextNumberToken(); if(_target != SQL_MYSQL) { Token::Remove(next); Token::Remove(equal); Token::Remove(auto_start); } exists = true; continue; } else // DEFAULT CHARSET if(next->Compare("DEFAULT", L"DEFAULT", 7) == true) { Token *option = GetNextToken(); if(option == NULL) break; // CHARSET if(option->Compare("CHARSET", L"CHARSET", 7) == true) { Token *equal = GetNextCharToken('=', L'='); Token *value = GetNextIdentToken(); if(_target != SQL_MYSQL) Token::Remove(next, value); } else // CHARACTER SET if(option->Compare("CHARACTER", L"CHARACTER", 9) == true) { Token *set = GetNextWordToken("SET", L"SET", 3); Token *equal = GetNextCharToken('=', L'='); Token *value = GetNextIdentToken(); if(_target != SQL_MYSQL) Token::Remove(next, value); } exists = true; continue; } else // COLLATE = value if(next->Compare("COLLATE", L"COLLATE", 7) == true) { Token *equal = GetNextCharToken('=', L'='); Token *value = GetNextIdentToken(); if(_target != SQL_MYSQL) Token::Remove(next, value); exists = true; continue; } else // COMMENT = 'table comment' if(next->Compare("COMMENT", L"COMMENT", 7) == true) { // Equal sign = is optional in the clause Token *equal = GetNextCharToken('=', L'='); Token *text = GetNextToken(); if(comment_out != NULL) *comment_out = text; // Remove from CREATE TABLE if(_target != SQL_MYSQL) Token::Remove(next, text); exists = true; continue; } else // PACK_KEYS = 0 | 1 | DEFAULT if(next->Compare("PACK_KEYS", L"PACK_KEYS", 9) == true) { // Optional = Token *equal = GetNextCharToken('=', L'='); Token *value = GetNextToken(); if(_target != SQL_MYSQL) Token::Remove(next, value); exists = true; continue; } else // ROW_FORMAT = type | DEFAULT if(next->Compare("ROW_FORMAT", L"ROW_FORMAT", 10) == true) { // Optional = Token *equal = GetNextCharToken('=', L'='); Token *value = GetNextToken(); if(_target != SQL_MYSQL) Token::Remove(next, value); exists = true; continue; } // Not a MySQL stoage clause PushBack(next); break; } if(id_start != NULL) *id_start = auto_start; // Restart sequence for PostgreSQL and Greenplum if(auto_start != NULL && (_target == SQL_POSTGRESQL || _target == SQL_GREENPLUM)) { // Try to get ; Token *semi = GetNextCharToken(';', L';'); Token *last = (semi != NULL) ? semi : GetLastToken(); // Append ALTER SEQUENCE command Append(last, "\n\nALTER SEQUENCE ", L"\n\nALTER SEQUENCE ", 17); // Add sequence name Token *seq_name = AppendIdentifier(table_name, "_seq", L"_seq", 4); Append(last, seq_name); Append(last, " RESTART WITH ", L" RESTART WITH ", 14); AppendCopy(last, auto_start); Append(last, ";", L";", 1); } return exists; }
// DB2 identity options in GENERATED ALWAYS or BY DEFAULT AS IDENTITY bool SqlParser::ParseDb2GeneratedClause(Token *create, Token *table_name, Token *column, Token *generated, Token **id_col, Token **id_start, Token **id_inc, bool *id_default) { if(generated == NULL) return false; Token *always = GetNextWordToken("ALWAYS", L"ALWAYS", 6); Token *by = NULL; Token *default_ = NULL; if(always == NULL) { by = GetNextWordToken("BY", L"BY", 2); default_ = GetNextWordToken("DEFAULT", L"DEFAULT", 7); if(id_default != NULL) *id_default = true; } else { if(id_default != NULL) *id_default = false; } Token *as = GetNextWordToken("AS", L"AS", 2); Token *identity = GetNextWordToken("IDENTITY", L"IDENTITY", 8); // Identity parameters are optional Token *open = GetNextCharToken('(', L'('); Token *close = NULL; Token *start_with = NULL; Token *increment_by = NULL; while(true) { bool exists = false; if(open == NULL) break; Token *option = GetNextToken(); if(option == NULL) break; // START WITH if(option->Compare("START", L"START", 5) == true) { /*Token *with */ (void) GetNextWordToken("WITH", L"WITH", 4); start_with = GetNextNumberToken(); exists = true; continue; } else // INCREMENT BY if(option->Compare("INCREMENT", L"INCREMENT", 9) == true) { /*Token *by */ (void) GetNextWordToken("BY", L"BY", 2); increment_by = GetNextNumberToken(); exists = true; continue; } else // MINVALUE if(option->Compare("MINVALUE", L"MINVALUE", 8) == true) { /*Token *value */ (void) GetNextNumberToken(); exists = true; continue; } else // MAXVALUE if(option->Compare("MAXVALUE", L"MAXVALUE", 8) == true) { /*Token *value */ (void) GetNextNumberToken(); exists = true; continue; } else // NO CYCLE and NO ORDER if(option->Compare("NO", L"NO", 2) == true) { /*Token *attr */ (void) GetNextToken(); exists = true; continue; } else // CACHE if(option->Compare("CACHE", L"CACHE", 5) == true) { /*Token *value */ (void) GetNextNumberToken(); exists = true; continue; } else // CYCLE if(option->Compare("CYCLE", L"CYCLE", 5) == true) { exists = true; continue; } else // Looks like comma is optional if(option->Compare(',', L',') == true) { exists = true; continue; } PushBack(option); break; } if(open != NULL) close = GetNextCharToken(')', L')'); // IDENTITY(start, inc) in SQL Server if(_target == SQL_SQL_SERVER) { Token::Change(generated, "IDENTITY(", L"IDENTITY(", 9); AppendCopy(generated, start_with); if(increment_by != NULL) { Append(generated, ", ", L", ", 2); AppendCopy(generated, increment_by); } Append(generated, ")", L")", 1); if(always != NULL) Token::Remove(always, close); else Token::Remove(by, close); } else // Use a sequence and DEFAULT nextval for PostgreSQL and Greenplum if(_target == SQL_POSTGRESQL || _target == SQL_GREENPLUM) { TokenStr seq_name(table_name); AppendIdentifier(seq_name, "_seq", L"_seq", 4); // Generate CREATE SEQUENCE before CREATE TABLE Prepend(create, "CREATE SEQUENCE ", L"CREATE SEQUENCE ", 16); PrependNoFormat(create, &seq_name); if(start_with != NULL) { Prepend(create, " START WITH ", L" START WITH ", 12); PrependCopy(create, start_with); } if(increment_by != NULL) { Prepend(create, " INCREMENT BY ", L" INCREMENT BY ", 14); PrependCopy(create, increment_by); } Prepend(create, ";\n\n", L";\n\n", 3); // Generate DEFAULT nextval('tablename_seq') clause Token::Change(generated, "DEFAULT ", L"DEFAULT ", 8); Append(generated, "nextval ('", L"nextval ('", 10); AppendNoFormat(generated, &seq_name); Append(generated, "')", L"')", 2); if(always != NULL) Token::Remove(always, close); else Token::Remove(by, close); } else // Remove for other databases if(_target != SQL_DB2) { Token::Remove(generated); Token::Remove(always); Token::Remove(by, default_); Token::Remove(as, identity); Token::Remove(open, close); } if(id_col != NULL) *id_col = column; if(id_start != NULL) *id_start = start_with; if(id_inc != NULL) *id_inc = increment_by; return true; }
// Parse DB2 CREATE TABLE storage clause bool SqlParser::ParseDb2StorageClause() { bool exists = false; while(true) { Token *next = GetNextToken(); if(next == NULL) break; // IN tablespace if(next->Compare("IN", L"IN", 2) == true) { // Get tablespace name (can include database name: dbname.tbsname) Token *name = GetNextIdentToken(); // TABLESPACE name in Oracle if(_target == SQL_ORACLE) { Token::Change(next, "TABLESPACE", L"TABLESPACE", 10); // Name can contain database name, remove it ConvertIdentRemoveLeadingPart(name); } else if(_target != SQL_DB2) Token::Remove(next, name); exists = true; continue; } else // INDEX IN tablespace if(next->Compare("INDEX", L"INDEX", 5) == true) { Token *in = GetNextWordToken("IN", L"IN", 2); Token *name = GetNextIdentToken(); if(_target != SQL_DB2) Token::Remove(next, name); exists = true; continue; } else // COMPRESS YES | NO clause if(next->Compare("COMPRESS", L"COMPRESS", 8) == true) { Token *yesno = GetNextToken(); if(_target != SQL_DB2) Token::Remove(next, yesno); exists = true; continue; } else // CCSID ASCII | UNICODE | EBCDIC if(next->Compare("CCSID", L"CCSID", 5) == true) { Token *encoding = GetNextToken(); if(_target != SQL_DB2) Token::Remove(next, encoding); exists = true; continue; } else // DATA CAPTURE CHANGES | NONE if(next->Compare("DATA", L"DATA", 4) == true) { Token *capture = GetNextWordToken("CAPTURE", L"CAPTURE", 7); Token *option = NULL; if(capture != NULL) { option = GetNextToken(); if(_target != SQL_DB2) Token::Remove(next, option); exists = true; continue; } } else // DB2 z/OS AUDIT CHANGES | NONE | ALL if(next->Compare("AUDIT", L"AUDIT", 5) == true) { Token *option = GetNextToken(); if(_target != SQL_DB2) Token::Remove(next, option); exists = true; continue; } else // DB2 z/OS WITH RESTRICT ON DROP if(next->Compare("WITH", L"WITH", 4) == true) { Token *restrict = GetNextWordToken("RESTRICT", L"RESTRICT", 8); Token *on = NULL; Token *drop = NULL; if(restrict != NULL) { on = GetNextWordToken("ON", L"ON", 2); if(on != NULL) drop = GetNextWordToken("DROP", L"DROP", 4); if(_target != SQL_DB2) Token::Remove(next, drop); exists = true; continue; } } else // DB2 z/OS NOT VOLATILE if(next->Compare("NOT", L"NOT", 3) == true) { Token *volatile_ = GetNextWordToken("VOLATILE", L"VOLATILE", 8); if(volatile_ != NULL) { if(_target != SQL_DB2) Token::Remove(next, volatile_); exists = true; continue; } } else // DB2 z/OS VOLATILE if(next->Compare("VOLATILE", L"VOLATILE", 8) == true) { if(_target != SQL_DB2) Token::Remove(next); exists = true; continue; } else // DB2 z/OS APPEND NO | YES if(next->Compare("APPEND", L"APPEND", 6) == true) { Token *value = GetNextToken(); if(value != NULL) { if(_target != SQL_DB2) Token::Remove(next, value); exists = true; continue; } } else // PARTITION BY SIZE EVERY n G if(next->Compare("PARTITION", L"PARTITION", 9) == true) { Token *by = GetNextWordToken("BY", L"BY", 2); Token *size = GetNextWordToken(by, "SIZE", L"SIZE", 4); // Partition by size if(size != NULL) { // Optional EVERY n G Token *every = GetNextWordToken("EVERY", L"EVERY", 5); Token *num = GetNextToken(every); Token *g = GetNextWordToken("G", L"G", 1); if(_target != SQL_DB2) { Token::Remove(next, size); Token::Remove(every, num); Token::Remove(g); } exists = true; continue; } else if(ParseDb2PartitioningClause(next, by) == true) { exists = true; continue; } } // Not a DB2 storage clause PushBack(next); break; } return exists; }
// DB2 CREATE TABLESPACE bool SqlParser::ParseDb2CreateTablespace(Token *create, Token *tablespace) { if(create == NULL || tablespace == NULL) return false; // Tablespace name Token *name = GetNextToken(); if(name == NULL) return false; bool exists = false; while(true) { Token *next = GetNextToken(); if(next == NULL) break; // IN database if(next->Compare("IN", L"IN", 2) == true) { Token *database = GetNextToken(); if(database != NULL) { if(_target != SQL_DB2) Token::Remove(next, database); exists = true; continue; } } else // DB2 z/OS USING STOGROUP if(next->Compare("USING", L"USING", 5) == true) { Token *stogroup = GetNextWordToken("STOGROUP", L"STOGROUP", 8); if(stogroup != NULL) ParseDb2StogroupClause(name, next, stogroup, SQL_SCOPE_TABLESPACE); exists = true; continue; } else // DB2 COMPRESS NO | YES option if(next->Compare("COMPRESS", L"COMPRESS", 8) == true) { Token *value = GetNextToken(); if(_target != SQL_DB2) Token::Remove(next, value); exists = true; continue; } else // DB2 PCTFREE if(next->Compare("PCTFREE", L"PCTFREE", 7) == true) { Token *value = GetNextToken(); // Oracle does not support PCTFREE in CREATE TABLESPACE if(_target != SQL_DB2) Token::Remove(next, value); exists = true; continue; } else // DB2 z/OS FREEPAGE num if(next->Compare("FREEPAGE", L"FREEPAGE", 8) == true) { Token *value = GetNextToken(); if(_target != SQL_DB2) Token::Remove(next, value); exists = true; continue; } else // DB2 z/OS BUFFERPOOL name if(next->Compare("BUFFERPOOL", L"BUFFERPOOL", 10) == true) { Token *name = GetNextToken(); if(_target != SQL_DB2) Token::Remove(next, name); exists = true; continue; } else // DB2 z/OS GBPCACHE CHANGED | ALL | SYSTME | NONE if(next->Compare("GBPCACHE", L"GBPCACHE", 8) == true) { Token *value = GetNextToken(); if(value != NULL) { if(_target != SQL_DB2) Token::Remove(next, value); exists = true; continue; } } else // DB2 z/OS CLOSE NO | YES if(next->Compare("CLOSE", L"CLOSE", 5) == true) { Token *value = GetNextToken(); if(value != NULL) { if(_target != SQL_DB2) Token::Remove(next, value); exists = true; continue; } } else // DB2 z/OS COPY YES | NO if(next->Compare("COPY", L"COPY", 4) == true) { Token *value = GetNextToken(); if(value != NULL) { if(_target != SQL_DB2) Token::Remove(next, value); exists = true; continue; } } else // DB2 z/OS PIECESIZE num [K | M | G] if(next->Compare("PIECESIZE", L"PIECESIZE", 9) == true) { Token *num = GetNextToken(); if(num != NULL) { // Size can be optionally followed by specifier K, M or G Token *spec = Db2SizeSpecifier(); if(_target != SQL_DB2) { Token::Remove(next, num); Token::Remove(spec); } exists = true; continue; } } else // DB2 z/OS LOGGED option if(next->Compare("LOGGED", L"LOGGED", 6) == true) { if(_target == SQL_ORACLE) Token::Change(next, "LOGGING", L"LOGGING", 7); else if(_target != SQL_DB2) Token::Remove(next); exists = true; continue; } else // DB2 for z/OS NOT LOGGED if(next->Compare("NOT", L"NOT", 3) == true) { Token *logged = GetNextWordToken("LOGGED", L"LOGGED", 6); if(logged != NULL) { if(_target == SQL_ORACLE) { Token::Change(next, "NOLOGGING", L"NOLOGGING", 9); Token::Remove(logged); } else if(_target != SQL_DB2) Token::Remove(next, logged); exists = true; continue; } } else // DB2 z/OS TRACKMOD NO | YES if(next->Compare("TRACKMOD", L"TRACKMOD", 8) == true) { Token *value = GetNextToken(); if(value != NULL) { if(_target != SQL_DB2) Token::Remove(next, value); exists = true; continue; } } else // DB2 z/OS SEGSIZE num if(next->Compare("SEGSIZE", L"SEGSIZE", 7) == true) { Token *num = GetNextToken(); if(num != NULL) { if(_target != SQL_DB2) Token::Remove(next, num); exists = true; continue; } } else // DB2 z/OS LOCKSIZE ANY | TABLESPACE | TABLE | PAGE | ROW | LOB if(next->Compare("LOCKSIZE", L"LOCKSIZE", 8) == true) { Token *value = GetNextToken(); if(value != NULL) { if(_target != SQL_DB2) Token::Remove(next, value); exists = true; continue; } } else // DB2 for z/OS LOCKMAX num | SYSTEM if(next->Compare("LOCKMAX", L"LOCKMAX", 7) == true) { Token *value = GetNextToken(); if(value != NULL) { if(_target != SQL_DB2) Token::Remove(next, value); exists = true; continue; } } else // CCSID ASCII | UNICODE | EBCDIC if(next->Compare("CCSID", L"CCSID", 5) == true) { Token *encoding = GetNextToken(); if(_target != SQL_DB2) Token::Remove(next, encoding); exists = true; continue; } else // DB2 for z/OS MAXROWS num if(next->Compare("MAXROWS", L"MAXROWS", 7) == true) { Token *num = GetNextToken(); if(_target != SQL_DB2) Token::Remove(next, num); exists = true; continue; } PushBack(next); break; } return exists; }
// DB2 z/OS USING STOGROUP clause bool SqlParser::ParseDb2StogroupClause(Token *objname, Token *using_, Token *stogroup, int scope) { if(using_ == NULL || stogroup == NULL) return false; // STOGROUP name Token *name = GetNextToken(); if(name == NULL) return false; bool exists = false; // STOGROUP options while(true) { Token *next = GetNextToken(); if(next == NULL) break; // PRIQTY num if(next->Compare("PRIQTY", L"PRIQTY", 6) == true) { Token *num = GetNextToken(); if(_target != SQL_DB2) Token::Remove(next, num); exists = true; continue; } else // SECQTY num if(next->Compare("SECQTY", L"SECQTY", 6) == true) { Token *num = GetNextToken(); if(_target != SQL_DB2) Token::Remove(next, num); exists = true; continue; } else // ERASE NO | YES if(next->Compare("ERASE", L"ERASE", 5) == true) { Token *value = GetNextToken(); if(_target != SQL_DB2) Token::Remove(next, value); exists = true; continue; } PushBack(next); break; } // Set DATAFILE clause in CREATE TABLESPACE for Oracle if(_target == SQL_ORACLE && scope == SQL_SCOPE_TABLESPACE) { Token::Change(using_, "DATAFILE '", L"DATAFILE '", 10); // Use tablespace name as multiple tablespaces can be created in a single storage group AppendCopy(using_, objname); Append(using_, ".dbf'", L".dbf'", 5); Token::Remove(stogroup); Token::Remove(name); } else if(_target != SQL_DB2) Token::Remove(using_, name); return exists; }
// SQL Server SET options, SET ANSI_NULLS ON i.e bool SqlParser::ParseSqlServerSetOptions(Token *set) { if(set == NULL) return false; bool exists = false; bool comment = false; bool remove = false; Token *option = GetNextToken(); if(option == NULL) return false; // SET ANSI_NULLS ON | OFF if(option->Compare("ANSI_NULLS", L"ANSI_NULLS", 10) == true) { /*Token *value */ (void) GetNextToken(); if(_target != SQL_SQL_SERVER) comment = true; exists = true; } else // SET ANSI_PADDING ON | OFF if(option->Compare("ANSI_PADDING", L"ANSI_PADDING", 12) == true) { /*Token *value */ (void) GetNextToken(); if(_target != SQL_SQL_SERVER) comment = true; exists = true; } else // SET NOCOUNT ON | OFF if(option->Compare("NOCOUNT", L"NOCOUNT", 7) == true) { /*Token *value */ (void) GetNextToken(); if(_target != SQL_SQL_SERVER) remove = true; exists = true; } else // SET QUOTED_IDENTIFIER ON | OFF if(option->Compare("QUOTED_IDENTIFIER", L"QUOTED_IDENTIFIER", 17) == true) { /*Token *value */ (void) GetNextToken(); if(_target != SQL_SQL_SERVER) comment = true; exists = true; } // Not a SET option else PushBack(option); if(exists == true) { Token *last = Nvl(GetNextCharToken(';', L';'), GetLastToken()); if(comment == true) Comment(set, last); else if(remove == true) Token::Remove(set, last); // Remove following GO if any SqlServerGoDelimiter(true); } return exists; }