blob: ac2e24df8a07b2fea27541f75d7e4f244c406da7 [file] [log] [blame]
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#ifndef _MSC_VER
# define BOOST_TEST_DYN_LINK
#endif
#include <boost/test/unit_test.hpp>
#include <string>
#include <ignite/ignite.h>
#include <ignite/ignition.h>
#include <ignite/odbc/odbc_error.h>
#include <ignite/odbc/sql/sql_lexer.h>
#include <ignite/odbc/sql/sql_parser.h>
#include <ignite/odbc/sql/sql_utils.h>
#include <ignite/odbc/sql/sql_set_streaming_command.h>
#include "test_utils.h"
using namespace ignite;
using namespace ignite_test;
using namespace boost::unit_test;
void CheckNextToken(odbc::SqlLexer& lexer, odbc::TokenType::Type tokenType, const std::string& expected)
{
BOOST_REQUIRE(!lexer.IsEod());
odbc::OdbcExpected<bool> hasNext = lexer.Shift();
if (!hasNext.IsOk())
BOOST_FAIL(hasNext.GetError().GetErrorMessage());
BOOST_CHECK(*hasNext);
const odbc::SqlToken& token = lexer.GetCurrentToken();
BOOST_REQUIRE(token.GetValue());
BOOST_CHECK_GT(token.GetSize(), 0);
BOOST_CHECK_EQUAL(token.GetType(), tokenType);
BOOST_CHECK_EQUAL(token.ToString(), expected);
}
void CheckSetStreamingCommand(
odbc::SqlParser& parser,
bool enabled,
bool allowOverwrite,
int32_t batchSize,
int32_t bufferSizePerNode,
int32_t parallelOperationsPerNode,
int64_t flushFrequency,
bool ordered)
{
std::auto_ptr<odbc::SqlCommand> cmd = parser.GetNextCommand();
BOOST_REQUIRE(cmd.get() != 0);
BOOST_REQUIRE_EQUAL(cmd->GetType(), odbc::SqlCommandType::SET_STREAMING);
odbc::SqlSetStreamingCommand& cmd0 = static_cast<odbc::SqlSetStreamingCommand&>(*cmd);
BOOST_CHECK_EQUAL(cmd0.IsEnabled(), enabled);
BOOST_CHECK_EQUAL(cmd0.IsAllowOverwrite(), allowOverwrite);
BOOST_CHECK_EQUAL(cmd0.GetBatchSize(), batchSize);
BOOST_CHECK_EQUAL(cmd0.GetBufferSizePerNode(), bufferSizePerNode);
BOOST_CHECK_EQUAL(cmd0.GetParallelOperationsPerNode(), parallelOperationsPerNode);
BOOST_CHECK_EQUAL(cmd0.GetFlushFrequency(), flushFrequency);
BOOST_CHECK_EQUAL(cmd0.IsOrdered(), ordered);
}
void CheckSingleSetStreamingCommand(
const std::string& sql,
bool enabled,
bool allowOverwrite,
int32_t batchSize,
int32_t bufferSizePerNode,
int32_t parallelOperationsPerNode,
int64_t flushFrequency,
bool ordered)
{
BOOST_CHECK(odbc::sql_utils::IsInternalCommand(sql));
odbc::SqlParser parser(sql);
CheckSetStreamingCommand(parser, enabled, allowOverwrite, batchSize, bufferSizePerNode,
parallelOperationsPerNode, flushFrequency, ordered);
std::auto_ptr<odbc::SqlCommand> cmd = parser.GetNextCommand();
BOOST_CHECK(cmd.get() == 0);
}
void CheckUnexpectedTokenError(const std::string& sql, const std::string& token, const std::string& expected = "additional parameter of SET STREAMING command or semicolon")
{
odbc::SqlParser parser(sql);
try
{
parser.GetNextCommand();
BOOST_FAIL("Exception expected.");
}
catch (const odbc::OdbcError& err)
{
std::string expErr = "Unexpected token: '" + token + "'";
if (!expected.empty())
expErr += ", " + expected + " expected.";
BOOST_CHECK_EQUAL(err.GetStatus(), odbc::SqlState::S42000_SYNTAX_ERROR_OR_ACCESS_VIOLATION);
BOOST_CHECK_EQUAL(err.GetErrorMessage(), expErr);
}
}
void CheckUnexpectedEndOfStatement(const std::string& sql, const std::string& expected)
{
odbc::SqlParser parser(sql);
try
{
parser.GetNextCommand();
BOOST_FAIL("Exception expected.");
}
catch (const odbc::OdbcError& err)
{
std::string expErr = "Unexpected end of statement: " + expected + " expected.";
BOOST_CHECK_EQUAL(err.GetStatus(), odbc::SqlState::S42000_SYNTAX_ERROR_OR_ACCESS_VIOLATION);
BOOST_CHECK_EQUAL(err.GetErrorMessage(), expErr);
}
}
BOOST_AUTO_TEST_SUITE(SqlParsingTestSuite)
BOOST_AUTO_TEST_CASE(LexerTokens)
{
std::string sql(
"word "
"otherword "
"and "
"another "
"\"quoted\" "
"\"quoted with \"\"qoutes\"\" inside \" "
"'string' "
"'string with \"quotes\"' "
" \n \r \t "
"'string with ''string quotes'' inside' "
"some.val "
"three,vals,here "
"\"Lorem;,.\";'Ipsum,;.--' "
"(something) "
"-- comment "
"still comment \n"
"-5 end");
odbc::SqlLexer lexer(sql);
CheckNextToken(lexer, odbc::TokenType::WORD, "word");
CheckNextToken(lexer, odbc::TokenType::WORD, "otherword");
CheckNextToken(lexer, odbc::TokenType::WORD, "and");
CheckNextToken(lexer, odbc::TokenType::WORD, "another");
CheckNextToken(lexer, odbc::TokenType::QUOTED, "\"quoted\"");
CheckNextToken(lexer, odbc::TokenType::QUOTED, "\"quoted with \"\"qoutes\"\" inside \"");
CheckNextToken(lexer, odbc::TokenType::STRING, "'string'");
CheckNextToken(lexer, odbc::TokenType::STRING, "'string with \"quotes\"'");
CheckNextToken(lexer, odbc::TokenType::STRING, "'string with ''string quotes'' inside'");
CheckNextToken(lexer, odbc::TokenType::WORD, "some");
CheckNextToken(lexer, odbc::TokenType::DOT, ".");
CheckNextToken(lexer, odbc::TokenType::WORD, "val");
CheckNextToken(lexer, odbc::TokenType::WORD, "three");
CheckNextToken(lexer, odbc::TokenType::COMMA, ",");
CheckNextToken(lexer, odbc::TokenType::WORD, "vals");
CheckNextToken(lexer, odbc::TokenType::COMMA, ",");
CheckNextToken(lexer, odbc::TokenType::WORD, "here");
CheckNextToken(lexer, odbc::TokenType::QUOTED, "\"Lorem;,.\"");
CheckNextToken(lexer, odbc::TokenType::SEMICOLON, ";");
CheckNextToken(lexer, odbc::TokenType::STRING, "'Ipsum,;.--'");
CheckNextToken(lexer, odbc::TokenType::PARENTHESIS_LEFT, "(");
CheckNextToken(lexer, odbc::TokenType::WORD, "something");
CheckNextToken(lexer, odbc::TokenType::PARENTHESIS_RIGHT, ")");
CheckNextToken(lexer, odbc::TokenType::MINUS, "-");
CheckNextToken(lexer, odbc::TokenType::WORD, "5");
CheckNextToken(lexer, odbc::TokenType::WORD, "end");
BOOST_REQUIRE(lexer.IsEod());
odbc::OdbcExpected<bool> hasNext = lexer.Shift();
if (!hasNext.IsOk())
BOOST_FAIL(hasNext.GetError().GetErrorMessage());
BOOST_CHECK(!*hasNext);
}
BOOST_AUTO_TEST_CASE(ParserSetStreamingOff)
{
CheckSingleSetStreamingCommand("set streaming off", false, false, 2048, 0, 0, 0, false);
CheckSingleSetStreamingCommand("set streaming 0", false, false, 2048, 0, 0, 0, false);
}
BOOST_AUTO_TEST_CASE(ParserSetStreamingOffMixedCase)
{
CheckSingleSetStreamingCommand("SET Streaming OfF", false, false, 2048, 0, 0, 0, false);
}
BOOST_AUTO_TEST_CASE(ParserSetStreamingOn)
{
CheckSingleSetStreamingCommand("set streaming on", true, false, 2048, 0, 0, 0, false);
CheckSingleSetStreamingCommand("set streaming 1", true, false, 2048, 0, 0, 0, false);
}
BOOST_AUTO_TEST_CASE(ParserSetStreamingOnAllowOverwriteOn)
{
CheckSingleSetStreamingCommand("set streaming on allow_overwrite on", true, true, 2048, 0, 0, 0, false);
CheckSingleSetStreamingCommand("set streaming on allow_overwrite 1", true, true, 2048, 0, 0, 0, false);
}
BOOST_AUTO_TEST_CASE(ParserSetStreamingOnAllowOverwriteOff)
{
CheckSingleSetStreamingCommand("set streaming on allow_overwrite off", true, false, 2048, 0, 0, 0, false);
CheckSingleSetStreamingCommand("set streaming on allow_overwrite 0", true, false, 2048, 0, 0, 0, false);
}
BOOST_AUTO_TEST_CASE(ParserSetStreamingOnPageSize512)
{
CheckSingleSetStreamingCommand("set streaming on batch_size 512", true, false, 512, 0, 0, 0, false);
}
BOOST_AUTO_TEST_CASE(ParserSetStreamingOnPerNodeBufferSize500)
{
CheckSingleSetStreamingCommand("set streaming on per_node_buffer_size 500", true, false, 2048, 500, 0, 0, false);
}
BOOST_AUTO_TEST_CASE(ParserSetStreamingOnPerNodeParallelOperations4)
{
CheckSingleSetStreamingCommand("set streaming on per_node_parallel_operations 4", true, false, 2048, 0, 4, 0, false);
}
BOOST_AUTO_TEST_CASE(ParserSetStreamingOnFlushFrequency100)
{
CheckSingleSetStreamingCommand("set streaming on flush_frequency 100", true, false, 2048, 0, 0, 100, false);
}
BOOST_AUTO_TEST_CASE(ParserSetStreamingOnOrdered)
{
CheckSingleSetStreamingCommand("set streaming on ordered", true, false, 2048, 0, 0, 0, true);
}
BOOST_AUTO_TEST_CASE(ParserSetStreamingOnAll)
{
CheckSingleSetStreamingCommand(
"set streaming 1 "
"allow_overwrite on "
"batch_size 512 "
"per_node_buffer_size 500 "
"per_node_parallel_operations 4 "
"flush_frequency 100 "
"ordered",
true, true, 512, 500, 4, 100, true);
}
BOOST_AUTO_TEST_CASE(ParserSetStreamingOnAllDisorder)
{
CheckSingleSetStreamingCommand(
"set streaming 1 "
"batch_size 512 "
"allow_overwrite on "
"ordered "
"per_node_buffer_size 500 "
"flush_frequency 100 "
"per_node_parallel_operations 4 ",
true, true, 512, 500, 4, 100, true);
}
BOOST_AUTO_TEST_CASE(ParserSetStreamingOnAllBackward)
{
CheckSingleSetStreamingCommand(
"set streaming 1 "
"ordered "
"flush_frequency 100 "
"per_node_parallel_operations 4 "
"per_node_buffer_size 500 "
"batch_size 512 "
"allow_overwrite on ",
true, true, 512, 500, 4, 100, true);
}
BOOST_AUTO_TEST_CASE(ParserSetStreamingOnOff)
{
std::string sql("set streaming 1; set streaming off");
odbc::SqlParser parser(sql);
CheckSetStreamingCommand(parser, true, false, 2048, 0, 0, 0, false);
CheckSetStreamingCommand(parser, false, false, 2048, 0, 0, 0, false);
std::auto_ptr<odbc::SqlCommand> cmd = parser.GetNextCommand();
BOOST_CHECK(cmd.get() == 0);
}
BOOST_AUTO_TEST_CASE(ParserSetStreamingOnUnexpectedTokenError)
{
CheckUnexpectedTokenError("set streaming 1 ololo", "ololo");
CheckUnexpectedTokenError("set streaming 1 ordered lorem_ipsum", "lorem_ipsum");
CheckUnexpectedTokenError("set streaming ON lorem_ipsum ordered", "lorem_ipsum");
CheckUnexpectedTokenError("set streaming some", "some", "ON, OFF, 1 or 0");
CheckUnexpectedTokenError("some", "some", "");
}
BOOST_AUTO_TEST_CASE(ParserSetStreamingOffUnexpectedTokenError)
{
CheckUnexpectedTokenError("set streaming 0 ololo", "ololo");
CheckUnexpectedTokenError("set streaming 0 ordered", "ordered", "no parameters with STREAMING OFF command");
CheckUnexpectedTokenError("set streaming OFF lorem_ipsum ordered", "lorem_ipsum");
}
BOOST_AUTO_TEST_CASE(ParserInternalCommand)
{
BOOST_CHECK(odbc::sql_utils::IsInternalCommand("set streaming 1"));
BOOST_CHECK(odbc::sql_utils::IsInternalCommand("set streaming 0"));
BOOST_CHECK(odbc::sql_utils::IsInternalCommand("set streaming on"));
BOOST_CHECK(odbc::sql_utils::IsInternalCommand("set streaming off"));
BOOST_CHECK(odbc::sql_utils::IsInternalCommand("SET STREAMING 1"));
BOOST_CHECK(odbc::sql_utils::IsInternalCommand("SET STREAMING 0"));
BOOST_CHECK(odbc::sql_utils::IsInternalCommand("SET STREAMING ON"));
BOOST_CHECK(odbc::sql_utils::IsInternalCommand("SET STREAMING OFF"));
BOOST_CHECK(odbc::sql_utils::IsInternalCommand("Set Streaming 1"));
BOOST_CHECK(odbc::sql_utils::IsInternalCommand("Set Streaming 0"));
BOOST_CHECK(odbc::sql_utils::IsInternalCommand("Set Streaming On"));
BOOST_CHECK(odbc::sql_utils::IsInternalCommand("Set Streaming Off"));
BOOST_CHECK(odbc::sql_utils::IsInternalCommand(";SET STREAMING 1"));
BOOST_CHECK(odbc::sql_utils::IsInternalCommand(";;SET STREAMING 0"));
BOOST_CHECK(odbc::sql_utils::IsInternalCommand(";;;SET STREAMING ON"));
BOOST_CHECK(odbc::sql_utils::IsInternalCommand(";;;;SET STREAMING OFF"));
BOOST_CHECK(odbc::sql_utils::IsInternalCommand("set streaming"));
BOOST_CHECK(odbc::sql_utils::IsInternalCommand("set streaming blah"));
}
BOOST_AUTO_TEST_CASE(ParserNonInternalCommand)
{
BOOST_CHECK(!odbc::sql_utils::IsInternalCommand(""));
BOOST_CHECK(!odbc::sql_utils::IsInternalCommand("Blah"));
BOOST_CHECK(!odbc::sql_utils::IsInternalCommand("0"));
BOOST_CHECK(!odbc::sql_utils::IsInternalCommand(";"));
BOOST_CHECK(!odbc::sql_utils::IsInternalCommand("Lorem ipsum"));
BOOST_CHECK(!odbc::sql_utils::IsInternalCommand("set some"));
}
BOOST_AUTO_TEST_SUITE_END()