sqlparser/statements.cpp
// DB2, MySQL, Teradata DECLARE type HANDLER
DB2, MySQL, Teradata DECLARE type HANDLER
DB2 MySQL Teradata DECLARE type HANDLER
bool SqlParser::ParseDeclareHandler(Token *declare, Token *type)
{
	if(declare == NULL || type == NULL)
		return false;
	if(Source(SQL_DB2, SQL_MYSQL, SQL_TERADATA) == false)
		return false;
    STATS_DECL
	PL_STMS_STATS_V("DECLARE HANDLER", declare);
	bool continue_ = false;
	bool exit = false;
	bool undo = false;
	if(Token::Compare(type, "CONTINUE", L"CONTINUE", 8) == true)
		continue_ = true;
	else
	if(Token::Compare(type, "EXIT", L"EXIT", 4) == true)
		exit = true;
	else
	if(Token::Compare(type, "UNDO", L"UNDO", 4) == true)
		undo = true;
	if(continue_ == false && exit == false && undo == false)
		return false;
	Token *handler = GetNextWordToken("HANDLER", L"HANDLER", 7);
	Token *for_ = GetNextWordToken("FOR", L"FOR", 3);
	Token *not_ = NULL;
	Token *found = NULL;
	Token *sqlexception = NULL;
	Token *sqlwarning = NULL;
	Token *user = NULL;
	Token *sqlstate = NULL;
	Token *value = NULL;
	Token *sqlstate_value = NULL;
	while(true)
	{
		Token *condition = GetNextToken();
		if(condition == NULL)
			break;
		if(Token::Compare(condition, "NOT", L"NOT", 3) == true)
		{
			not_ = condition;
			found = GetNextWordToken("FOUND", L"FOUND", 5);
		}
		else
		if(Token::Compare(condition, "SQLEXCEPTION", L"SQLEXCEPTION", 12) == true)
			sqlexception = condition;
		else
		if(Token::Compare(condition, "SQLWARNING", L"SQLWARNING", 10) == true)
			sqlwarning = condition;
		else
		if(Token::Compare(condition, "SQLSTATE", L"SQLSTATE", 8) == true)
		{
			sqlstate = condition;
			value = GetNextWordToken("VALUE", L"VALUE", 5);
			sqlstate_value = GetNextToken();
		}
		else
		{
			user = condition;
			break;
		}
		Token *comma = GetNextCharToken(',', L',');
		if(comma == NULL)
			break;
		if(_target == SQL_ORACLE)
			Token::Remove(comma);
	}
	Token *begin = GetNextWordToken("BEGIN", L"BEGIN", 5);
	Token *end = NULL;
	bool frontier = (begin != NULL) ? true : false;
	ParseBlock(SQL_BLOCK_HANDLER, frontier, 0, NULL);
	if(begin != NULL)
		end = GetNextWordToken("END", L"END", 3);
	if(_target == SQL_ORACLE)
	{
		int cut_type = 0;
		Token *name = NULL;
		if(exit == true)
			Token::Change(declare, "WHEN", L"WHEN", 4);
		else
			Token::Remove(declare);
		if(sqlexception != NULL)
		{
			if(exit == true)
			{
				Token::Change(type, "OTHERS", L"OTHERS", 6);
				Token::Change(handler, "THEN", L"THEN", 4);
				cut_type = COPY_EXIT_HANDLER_SQLEXCEPTION;
			}
			else
			{
				Token::Remove(type);
				Token::Remove(handler);
				cut_type = COPY_CONTINUE_HANDLER_SQLEXCEPTION;
			}
		}
		else
		if(not_ != NULL)
		{
			if(exit == true)
			{
				Token::Change(type, "NO_DATA_FOUND", L"NO_DATA_FOUND", 13);
				Token::Change(handler, "THEN", L"THEN", 4);
				cut_type = COPY_EXIT_HANDLER_NOT_FOUND;
			}
			else
			{
				Token::Remove(type);
				Token::Remove(handler);
				cut_type = COPY_CONTINUE_HANDLER_NOT_FOUND;
			}
		}
		else
		if(sqlstate != NULL)
		{
			if(exit == true)
				cut_type = COPY_EXIT_HANDLER_FOR_SQLSTATE;
			else
				cut_type = COPY_CONTINUE_HANDLER_FOR_SQLSTATE;
			if(_source == SQL_TERADATA)
			{
				if(Token::Compare(sqlstate_value, "'23505'", L"'23505'", 7) == true)
				{
					Token::Change(sqlstate, "DUP_VAL_ON_INDEX THEN ", L"DUP_VAL_ON_INDEX THEN ", 22);
					Token::Remove(type);
					Token::Remove(handler);
					Token::Remove(value);
					Token::Remove(sqlstate_value);
				}
				else
				{
					Token::Change(type, "OTHERS THEN ", L"OTHERS THEN ", 12);
					Token::Remove(handler);
					Comment(sqlstate, sqlstate_value);
					Token::Remove(value);					
				}
			}
		}
		else
		if(user != NULL)
		{
			name = user;
			Token::Remove(type);
			Token::Remove(handler);
			if(exit == true)
				cut_type = COPY_EXIT_HANDLER_USER_DEFINED;
			else
				cut_type = COPY_CONTINUE_HANDLER_USER_DEFINED;
		}
		Token::Remove(for_);
		Token::Remove(not_, found);
		Token::Remove(sqlexception);
		Token::Remove(sqlwarning);
		Token::Remove(user);
		Token *semi = (end != NULL) ? GetNextCharToken(';', L';') : NULL;
		Token::Remove(begin);
		Token::Remove(end, semi);
		Token *last = GetLastToken();
		Cut(COPY_SCOPE_PROC, cut_type, name, declare, last);
	}
	if(_spl_first_non_declare == NULL)
		_spl_last_declare = GetLastToken();
	return true;
}
bool SqlParser :: ParseDeclareHandler ( Token * declare , Token * type ) { if ( declare == NULL || type == NULL ) return false ; if ( Source ( SQL_DB2 , SQL_MYSQL , SQL_TERADATA ) == false ) return false ; STATS_DECL PL_STMS_STATS_V ( " " , declare ) ; bool continue_ = false ; bool exit = false ; bool undo = false ; if ( Token :: Compare ( type , " " , L" " , 8 ) == true ) continue_ = true ; else if ( Token :: Compare ( type , " " , L" " , 4 ) == true ) exit = true ; else if ( Token :: Compare ( type , " " , L" " , 4 ) == true ) undo = true ; if ( continue_ == false && exit == false && undo == false ) return false ; Token * handler = GetNextWordToken ( " " , L" " , 7 ) ; Token * for_ = GetNextWordToken ( " " , L" " , 3 ) ; Token * not_ = NULL ; Token * found = NULL ; Token * sqlexception = NULL ; Token * sqlwarning = NULL ; Token * user = NULL ; Token * sqlstate = NULL ; Token * value = NULL ; Token * sqlstate_value = NULL ; while ( true ) { Token * condition = GetNextToken ( ) ; if ( condition == NULL ) break ; if ( Token :: Compare ( condition , " " , L" " , 3 ) == true ) { not_ = condition ; found = GetNextWordToken ( " " , L" " , 5 ) ; } else if ( Token :: Compare ( condition , " " , L" " , 12 ) == true ) sqlexception = condition ; else if ( Token :: Compare ( condition , " " , L" " , 10 ) == true ) sqlwarning = condition ; else if ( Token :: Compare ( condition , " " , L" " , 8 ) == true ) { sqlstate = condition ; value = GetNextWordToken ( " " , L" " , 5 ) ; sqlstate_value = GetNextToken ( ) ; } else { user = condition ; break ; } Token * comma = GetNextCharToken ( ' ' , L' ' ) ; if ( comma == NULL ) break ; if ( _target == SQL_ORACLE ) Token :: Remove ( comma ) ; } Token * begin = GetNextWordToken ( " " , L" " , 5 ) ; Token * end = NULL ; bool frontier = ( begin != NULL ) ? true : false ; ParseBlock ( SQL_BLOCK_HANDLER , frontier , 0 , NULL ) ; if ( begin != NULL ) end = GetNextWordToken ( " " , L" " , 3 ) ; if ( _target == SQL_ORACLE ) { int cut_type = 0 ; Token * name = NULL ; if ( exit == true ) Token :: Change ( declare , " " , L" " , 4 ) ; else Token :: Remove ( declare ) ; if ( sqlexception != NULL ) { if ( exit == true ) { Token :: Change ( type , " " , L" " , 6 ) ; Token :: Change ( handler , " " , L" " , 4 ) ; cut_type = COPY_EXIT_HANDLER_SQLEXCEPTION ; } else { Token :: Remove ( type ) ; Token :: Remove ( handler ) ; cut_type = COPY_CONTINUE_HANDLER_SQLEXCEPTION ; } } else if ( not_ != NULL ) { if ( exit == true ) { Token :: Change ( type , " " , L" " , 13 ) ; Token :: Change ( handler , " " , L" " , 4 ) ; cut_type = COPY_EXIT_HANDLER_NOT_FOUND ; } else { Token :: Remove ( type ) ; Token :: Remove ( handler ) ; cut_type = COPY_CONTINUE_HANDLER_NOT_FOUND ; } } else if ( sqlstate != NULL ) { if ( exit == true ) cut_type = COPY_EXIT_HANDLER_FOR_SQLSTATE ; else cut_type = COPY_CONTINUE_HANDLER_FOR_SQLSTATE ; if ( _source == SQL_TERADATA ) { if ( Token :: Compare ( sqlstate_value , " " , L" " , 7 ) == true ) { Token :: Change ( sqlstate , " " , L" " , 22 ) ; Token :: Remove ( type ) ; Token :: Remove ( handler ) ; Token :: Remove ( value ) ; Token :: Remove ( sqlstate_value ) ; } else { Token :: Change ( type , " " , L" " , 12 ) ; Token :: Remove ( handler ) ; Comment ( sqlstate , sqlstate_value ) ; Token :: Remove ( value ) ; } } } else if ( user != NULL ) { name = user ; Token :: Remove ( type ) ; Token :: Remove ( handler ) ; if ( exit == true ) cut_type = COPY_EXIT_HANDLER_USER_DEFINED ; else cut_type = COPY_CONTINUE_HANDLER_USER_DEFINED ; } Token :: Remove ( for_ ) ; Token :: Remove ( not_ , found ) ; Token :: Remove ( sqlexception ) ; Token :: Remove ( sqlwarning ) ; Token :: Remove ( user ) ; Token * semi = ( end != NULL ) ? GetNextCharToken ( ' ' , L' ' ) : NULL ; Token :: Remove ( begin ) ; Token :: Remove ( end , semi ) ; Token * last = GetLastToken ( ) ; Cut ( COPY_SCOPE_PROC , cut_type , name , declare , last ) ; } if ( _spl_first_non_declare == NULL ) _spl_last_declare = GetLastToken ( ) ; return true ; }
DB2, MySQL, Teradata DECLARE type HANDLER
DB2 MySQL Teradata DECLARE type HANDLER
// Possible conflict with variable name // CONTINUE, EXIT, UNDO possible handler types // Not a handler // HANDLER keyword // FOR keyword // FOR SQLSTATE [VALUE] 'value' can be specified in Teradata // Multiple comma-separated conditions can be specified NOT FOUND, SQLEXCEPTION and SQLWARNING // NOT FOUND // SQLEXCEPTION // SQLWARNING // SQLSTATE in Teradata // VALUE is optional in Teradata // User-defined exception // Optional BEGIN END // Convert to EXCEPTION clause in Oracle // If SQLEXCEPTION is set it takes priority on other conditions // EXIT handler always transferred to OTHERS exception // CONTINUE handler implementation depends on the statement // EXIT handler always transferred to NO_DATA_FOUND exception // CONTINUE handler implementation depends on the statement // For SQLSTATE // Duplicate key in Teradata // Unknown SQLSTATE value // User-defined handler // END can be terminated with ; // Remove outer BEGIN END; as each block starts with THEN // Block will be transferred to EXCEPTION section or IF cur%NOTFOUND, SQL%ROWCOUNT condition // If there are no non-declare statements above, set last declare