Beispiel #1
0
// In DB2 trigger, column can be assigned without NEW correlation name
void SqlParser::Db2TriggerCorrelatedName(Token *var)
{
	if(var == NULL)
		return;

	bool exists = false;

	// Do not convert if the target name already set
	if(var->t_len > 0)
		return;

	if((_spl_new_correlation_name == NULL && Token::Compare(var, "NEW.", L"NEW.", 0, 4) == true) ||
		(Token::Compare(var, _spl_new_correlation_name, 3) == true && Token::Compare(var, ".", L".", 3, 1) == true))
		exists = true;

	if(exists)
		return;

	// In Oracle correlation name must be specified
	if(_target == SQL_ORACLE)
	{
		PrependNoFormat(var, ":", L":", 1);

		if(_spl_new_correlation_name != NULL)
			PrependCopy(var, _spl_new_correlation_name);
		else
			Prepend(var, "NEW", L"NEW", 3);

		PrependNoFormat(var, ".", L".", 1);
	}
}
Beispiel #2
0
Token* SqlParser::PrependNoFormat(Token *token, TokenStr *str)
{
	if(token == NULL || str == NULL)
		return NULL;

	return PrependNoFormat(token, str->str.c_str(), str->wstr.c_str(), str->len);
}
Beispiel #3
0
void SqlParser::PrependSpaceCopy(Token *token, Token *first, Token *last, bool prepend_removed)
{
	if(token == NULL)
		return;

	PrependCopy(token, first, last, prepend_removed);
	PrependNoFormat(token, " ", L" ", 1);
}
Beispiel #4
0
// Change the token and add spaces around it if they do not exist
void SqlParser::ChangeWithSpacesAround(Token *token, const char *new_str, const wchar_t *new_wstr, int len, Token *format)
{
	if(token == NULL)
		return;

	if(token->prev != NULL && token->prev->IsBlank() == false)
		PrependNoFormat(token, " ", L" ", 1);

	if(token->next != NULL && token->next->IsBlank() == false)
		AppendNoFormat(token, " ", L" ", 1);

	Token::Change(token, new_str, new_wstr, len, format);
}
Beispiel #5
0
// Convert DB2 identifier
bool SqlParser::ConvertDb2Identifier(Token *token, int expected_type)
{
	// Column, variable or parameter name
	if(expected_type == SQL_IDENT_COLVAR)
	{
		// Check for new.column in a trigger
		if(_spl_scope == SQL_SCOPE_TRIGGER && Token::Compare(token, "new.", L"new.", 0, 4) == true)
		{
			// Use :new.column in Oracle
			if(_target == SQL_ORACLE)
				PrependNoFormat(token, ":", L":", 1);
		}
	}

	return true;
}
Beispiel #6
0
// VALUES NEXTVAL seq INTO var pattern
bool SqlParser::Db2ValuesNextValIntoPattern(Token *values)
{
	if(values == NULL || _target != SQL_ORACLE)
		return false;

	// NEXTVAL keyword
	Token *nextval = GetNextWordToken("NEXTVAL", L"NEXTVAL", 7);

	if(nextval == NULL)
		return false;

	// FOR keyword
	Token *for_ = GetNextWordToken("FOR", L"FOR", 3);

	// Sequence name
	Token *seq_name = GetNextToken(for_);

	// INTO keyword
	Token *into = GetNextWordToken(seq_name, "INTO", L"INTO", 4);

	// Variable name
	Token *var = GetNextToken(into);

	if(var == NULL)
	{
		PushBack(nextval);
		return false;
	}

	// SELECT seq.NEXTVAL INTO var FROM dual in Oracle
	if(_target == SQL_ORACLE)
	{
		Token::Change(values, "SELECT", L"SELECT", 6);

		PrependCopy(nextval, seq_name);
		PrependNoFormat(nextval, ".", L".", 1);

		Token::Remove(for_, seq_name);

		Append(var, " FROM ", L" FROM ", 6, values);
		AppendNoFormat(var, "dual", L"dual", 4);
	}

	return true;
}
Beispiel #7
0
// 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;
}
Beispiel #8
0
// Parse DB2 partitioning clause
bool SqlParser::ParseDb2PartitioningClause(Token *partition, Token *by)
{
	if(partition == NULL || by == NULL)
		return false;

	// RANGE is optional in DB2 z/OS
	Token *range = GetNextWordToken("RANGE", L"RANGE", 5);

	// RANGE keyword is required for Oracle
	if(range == NULL && _target == SQL_ORACLE)
		Append(by, " RANGE", L" RANGE", 6);

	/*Token *open */ (void) GetNextCharToken('(', L'(');

	// Comma separated list of columns
	while(true)
	{
		Token *column = GetNextToken();

		if(column == NULL)
			break;

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

		if(comma == NULL)
			break;
	}

	/*Token *close */ (void) GetNextCharToken(')', L')');

	/*Token *open2 */ (void) GetNextCharToken('(', L'(');

	// Comma separated list of partition definitions
	while(true)
	{
		// PARTITION keyword
		Token *partition2 = GetNextWordToken("PARTITION", L"PARTITION", 9);

		if(partition2 == NULL)
			break;

		// Partition number
		Token *num = GetNextToken();

		if(num == NULL)
			break;

		// In Oracle a partition name is required so prepend 'p' to each number
		if(_target == SQL_ORACLE)
			PrependNoFormat(num, "p", L"p", 1);

		// ENDING [AT]
		Token *ending = GetNextWordToken("ENDING", L"ENDING", 6);
		Token *at = GetNextWordToken("AT", L"AT", 2);

		// VALUES LESS THAN in Oracle
		if(_target == SQL_ORACLE)
		{
			Token::Change(ending, "VALUES LESS THAN", L"VALUES LESS THAN", 16);
			Token::Remove(at);
		}

		// Each value is in ()
		/*Token *open3 */ (void) GetNextCharToken('(', L'(');

		/*Token *limit */ (void) GetNextToken();

		/*Token *close3 */ (void) GetNextCharToken(')', L')');
		
		Token *comma = GetNextCharToken(',', L',');

		if(comma == NULL)
			break;
	}

	/*Token *close2 */ (void) GetNextCharToken(')', L')');

	return true;
}
Beispiel #9
0
void SqlParser::Comment(const char *word, const wchar_t *w_word, int len, Token *first, Token *last)
{
	PrependNoFormat(first, "/* ", L"/* ", 3);
	PrependNoFormat(first, word, w_word, len);
	AppendNoFormat(last, " */", L" */", 3);
}
Beispiel #10
0
void SqlParser::CommentNoSpaces(Token *first, Token *last)
{
	PrependNoFormat(first, "/*", L"/*", 2);
	AppendNoFormat(Nvl(last, first), "*/", L"*/", 2); 
}