示例#1
0
// Handle GO after a statement in SQL Server
bool SqlParser::SqlServerGoDelimiter(bool just_remove)
{
	if(Source(SQL_SQL_SERVER, SQL_SYBASE) == false || Target(SQL_SQL_SERVER, SQL_SYBASE) == true)
		return false;

	Token *stmt_end = GetLastToken();

	// Optional ; can go before GO
	Token *semi = GetNextCharToken(';', L';');

	Token *go = GetNextWordToken("GO", L"GO", 2);

	if(go == NULL)
	{
		// ; is processed at statement parser
		if(semi != NULL)
			PushBack(semi);

		return false;
	}

	// The delimiter ; does not already exist, add it otherwise just remove GO
	if(semi == NULL && just_remove == false)
		AppendNoFormat(stmt_end, ";", L";", 1);

	Token::Change(go, " ", L" ", 1);

	return true;
}
示例#2
0
// Return last token 
Token* SqlParser::GetLastToken(Token *last)
{
	if(last != NULL)
		return last;

	return GetLastToken();
}
示例#3
0
// Add statement delimiter if not set when source is SQL Server, Sybase ASE
void SqlParser::SqlServerAddStmtDelimiter(bool force)
{
	if(Source(SQL_SQL_SERVER, SQL_SYBASE) == false)
		return;

	// Add the delimiter in statements in procedural block only
	if(_spl_scope == 0 && force == false)
	{
		// Special case when a single statement followed by GO, then add ; even if we are no inside procedure scope
		if(!LookNext("GO", L"GO", 2))
			return;
	}

	// Check if the delimiter already set
	Token *semi = GetNextCharToken(';', L';');

	if(semi != NULL)
	{
		PushBack(semi);
		return;
	}

	// Do not set if comma followed
	Token *comma = GetNextCharToken(',', L',');

	if(comma != NULL)
	{
		PushBack(comma);
		return;
	}

	AppendNoFormat(GetLastToken(), ";", L";", 1);
}
示例#4
0
// 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;
}
示例#5
0
// Get the specified character token or the last selected
Token* SqlParser::GetNextCharOrLastToken(const char ch, const wchar_t wch)
{
	Token *out = GetNextCharToken(ch, wch);

	// Not found
	if(out == NULL)
		out = GetLastToken();

	return out;
}
示例#6
0
// SQL Server, Sybase ASE EXEC procedure statement
void SqlParser::ParseSqlServerExecProcedure(Token *execute, Token *name)
{
	if(execute == NULL || name == NULL)
		return;

	ConvertIdentifier(name, SQL_IDENT_OBJECT);

	if(Target(SQL_MARIADB, SQL_MYSQL))
		TOKEN_CHANGE(execute, "CALL");

	int params = 0;

	// Parse parameters
	// Sybase ASE does not use () around parameters
	while(true)
	{
		Token *next = GetNextToken();

		if(next == NULL)
			break;

		// If there are no params, we can have conflict with next statement as there may be no delimiters in Transact-SQL
		// If there is at least one parameter, no conflict is possible for subsequent params as comma defines whether it exists or not
		if(params == 0 && !IsValidAlias(next))
		{
			PushBack(next);
			break;
		}

		ConvertIdentifier(next, SQL_IDENT_VAR);

		// OUTPUT qualifier can be specified for parameter in Sybase ASE
		Token *output = GetNext("OUTPUT", L"OUTPUT", 6);

		if(output != NULL && Target(SQL_MARIADB, SQL_MYSQL))
			Token::Remove(output);

		Token *comma = GetNext(',', L',');

		if(comma == NULL)
			break;

		params++;
	}

	// When there are no parameters MySQL, MariaDB allow as CALL name() and CALL name
	if(params > 0)
	{		
		if(Target(SQL_MARIADB, SQL_MYSQL))
		{
			APPEND_NOFMT(name, "(");
			APPEND_NOFMT(GetLastToken(), ")");
		}
	}
}
示例#7
0
// Teradata HELP STATISTICS statement
bool SqlParser::ParseTeradataHelpStatistics(Token *help, Token *statistics)
{
	if(help == NULL || statistics == NULL)
		return false;

	// Table name
	Token *table_name = GetNextIdentToken(SQL_IDENT_OBJECT);

	// Comment for other databases
	if(_target != SQL_TERADATA)
		Comment(help, Nvl(GetNext(';', L';'), GetLastToken()));

	return true;
}
示例#8
0
// DB2 RESULT_SET_LOCATOR declaration
bool SqlParser::ParseDb2ResultSetLocatorDeclaration(Token *declare, Token *name, Token *result_set_locator)
{
	if(result_set_locator == NULL)
		return false;

	// VARYING keyword
	/*Token *varying */ (void) GetNextWordToken("VARYING", L"VARYING", 7);

	_spl_declared_rs_locators.Add(name);

	// Remove the entire declaration for other databases
	if(_target != SQL_DB2)
		Token::Remove(declare, Nvl(GetNextCharToken(';', L';'), GetLastToken()));

	return true;
}
示例#9
0
// Any Transact-SQL statement can be followed by ; and GO, any combination of them or nothing at all
void SqlParser::SqlServerDelimiter()
{
	if(Source(SQL_SQL_SERVER, SQL_SYBASE) == false || Target(SQL_SQL_SERVER, SQL_SYBASE) == true)
		return;

	Token *last = GetLastToken();

	// Optional ; can go before GO
	Token *semi = GetNextCharToken(';', L';');

	// Optional GO to terminate the batch
	Token *go = GetNextWordToken("GO", L"GO", 2);

	// No ; delimiter
	if(semi == NULL)
		AppendNoFormat(last, ";", L";", 1);

	Token::Remove(go);
}
示例#10
0
// 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;
}
示例#11
0
// 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;
}
示例#12
0
// 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;
}
示例#13
0
// 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;
}
示例#14
0
// 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;
}