示例#1
0
Token* SqlParser::GetNextNumberToken(Token *prev)
{
	if(prev == NULL)
		return NULL;

	return GetNextNumberToken();
}
示例#2
0
// 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;
}
示例#3
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;
}
示例#4
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;
}