IGNITE-3749: ODBC: Added support for numeric scalar functions. This closes #981.
Project: http://git-wip-us.apache.org/repos/asf/ignite/repo Commit: http://git-wip-us.apache.org/repos/asf/ignite/commit/5a3b3e2c Tree: http://git-wip-us.apache.org/repos/asf/ignite/tree/5a3b3e2c Diff: http://git-wip-us.apache.org/repos/asf/ignite/diff/5a3b3e2c Branch: refs/heads/master Commit: 5a3b3e2c6ecb5d6c96513b79f21828526b4a98a0 Parents: d6449ff Author: isapego <[email protected]> Authored: Thu Aug 25 12:35:07 2016 +0300 Committer: vozerov-gridgain <[email protected]> Committed: Thu Aug 25 12:35:07 2016 +0300 ---------------------------------------------------------------------- modules/platforms/cpp/odbc-test/Makefile.am | 2 + .../platforms/cpp/odbc-test/include/Makefile.am | 3 +- .../include/sql_function_test_suite_fixture.h | 138 +++++++++ .../cpp/odbc-test/project/vs/odbc-test.vcxproj | 3 + .../project/vs/odbc-test.vcxproj.filters | 9 + .../src/sql_function_test_suite_fixture.cpp | 188 +++++++++++ .../src/sql_numeric_functions_test.cpp | 309 +++++++++++++++++++ .../odbc-test/src/sql_string_functions_test.cpp | 228 +------------- .../cpp/odbc/src/config/connection_info.cpp | 7 +- 9 files changed, 659 insertions(+), 228 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/ignite/blob/5a3b3e2c/modules/platforms/cpp/odbc-test/Makefile.am ---------------------------------------------------------------------- diff --git a/modules/platforms/cpp/odbc-test/Makefile.am b/modules/platforms/cpp/odbc-test/Makefile.am index cc84a7f..62bdec3 100644 --- a/modules/platforms/cpp/odbc-test/Makefile.am +++ b/modules/platforms/cpp/odbc-test/Makefile.am @@ -62,7 +62,9 @@ ignite_odbc_tests_SOURCES = \ src/utility_test.cpp \ src/queries_test.cpp \ src/test_utils.cpp \ + src/sql_function_test_suite_fixture.cpp \ src/sql_string_functions_test.cpp \ + src/sql_numeric_functions_test.cpp \ ../odbc/src/cursor.cpp \ ../odbc/src/config/connection_info.cpp \ ../odbc/src/app/application_data_buffer.cpp \ http://git-wip-us.apache.org/repos/asf/ignite/blob/5a3b3e2c/modules/platforms/cpp/odbc-test/include/Makefile.am ---------------------------------------------------------------------- diff --git a/modules/platforms/cpp/odbc-test/include/Makefile.am b/modules/platforms/cpp/odbc-test/include/Makefile.am index 7b17102..baca1b7 100644 --- a/modules/platforms/cpp/odbc-test/include/Makefile.am +++ b/modules/platforms/cpp/odbc-test/include/Makefile.am @@ -20,5 +20,6 @@ ACLOCAL_AMFLAGS =-I m4 noinst_HEADERS = \ teamcity/teamcity_messages.h \ test_type.h \ - test_utils.h + test_utils.h \ + sql_function_test_suite_fixture.h http://git-wip-us.apache.org/repos/asf/ignite/blob/5a3b3e2c/modules/platforms/cpp/odbc-test/include/sql_function_test_suite_fixture.h ---------------------------------------------------------------------- diff --git a/modules/platforms/cpp/odbc-test/include/sql_function_test_suite_fixture.h b/modules/platforms/cpp/odbc-test/include/sql_function_test_suite_fixture.h new file mode 100644 index 0000000..c09c1ae --- /dev/null +++ b/modules/platforms/cpp/odbc-test/include/sql_function_test_suite_fixture.h @@ -0,0 +1,138 @@ +/* + * 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 _IGNITE_ODBC_TEST_SQL_FUNCTION_TEST_FIXTURE +#define _IGNITE_ODBC_TEST_SQL_FUNCTION_TEST_FIXTURE + +#ifdef _WIN32 +# include <windows.h> +#endif + +#include <sql.h> +#include <sqlext.h> + +#include <string> + +#ifndef _MSC_VER +# define BOOST_TEST_DYN_LINK +#endif + +#include <boost/test/unit_test.hpp> + +#include "ignite/ignite.h" +#include "ignite/ignition.h" + +#include "test_type.h" + +namespace ignite +{ + /** + * Test setup fixture. + */ + struct SqlFunctionTestSuiteFixture + { + /** + * Constructor. + */ + SqlFunctionTestSuiteFixture(); + + /** + * Destructor. + */ + ~SqlFunctionTestSuiteFixture(); + + /** + * Run query returning single result and stores it to buffer. + * + * @param request SQL request. + * @param type Result type. + * @param column Result buffer. + * @param bufSize Result buffer size. + * @param resSize Size of received value. + */ + void CheckSingleResult0(const char* request, SQLSMALLINT type, + void* column, SQLLEN bufSize, SQLLEN* resSize) const; + + /** + * Run query returning single result and check it to be equal to expected. + * + * @param request SQL request. + * @param expected Expected result. + */ + template<typename T> + void CheckSingleResult(const char* request, const T& expected) + { + BOOST_FAIL("Function is not defined for the type."); + } + + /** + * Run query returning single result and check it to be equal to expected. + * + * @param request SQL request. + * @param expected Expected result. + * @param type Result type. + */ + template<typename T> + void CheckSingleResultNum0(const char* request, const T& expected, SQLSMALLINT type) + { + T res = 0; + + CheckSingleResult0(request, type, &res, 0, 0); + + BOOST_CHECK_EQUAL(res, expected); + } + + + /** Node started during the test. */ + Ignite grid; + + /** Test cache instance. */ + cache::Cache<int64_t, TestType> testCache; + + /** ODBC Environment. */ + SQLHENV env; + + /** ODBC Connect. */ + SQLHDBC dbc; + + /** ODBC Statement. */ + SQLHSTMT stmt; + }; + + template<> + void SqlFunctionTestSuiteFixture::CheckSingleResult<std::string>(const char* request, const std::string& expected); + + template<> + void SqlFunctionTestSuiteFixture::CheckSingleResult<int64_t>(const char* request, const int64_t& expected); + + template<> + void SqlFunctionTestSuiteFixture::CheckSingleResult<int32_t>(const char* request, const int32_t& expected); + + template<> + void SqlFunctionTestSuiteFixture::CheckSingleResult<int16_t>(const char* request, const int16_t& expected); + + template<> + void SqlFunctionTestSuiteFixture::CheckSingleResult<int8_t>(const char* request, const int8_t& expected); + + template<> + void SqlFunctionTestSuiteFixture::CheckSingleResult<float>(const char* request, const float& expected); + + template<> + void SqlFunctionTestSuiteFixture::CheckSingleResult<double>(const char* request, const double& expected); +} + +#endif //_IGNITE_ODBC_TEST_SQL_FUNCTION_TEST_FIXTURE http://git-wip-us.apache.org/repos/asf/ignite/blob/5a3b3e2c/modules/platforms/cpp/odbc-test/project/vs/odbc-test.vcxproj ---------------------------------------------------------------------- diff --git a/modules/platforms/cpp/odbc-test/project/vs/odbc-test.vcxproj b/modules/platforms/cpp/odbc-test/project/vs/odbc-test.vcxproj index 619b4b2..a83ed6b 100644 --- a/modules/platforms/cpp/odbc-test/project/vs/odbc-test.vcxproj +++ b/modules/platforms/cpp/odbc-test/project/vs/odbc-test.vcxproj @@ -168,6 +168,8 @@ <ClCompile Include="..\..\src\queries_test.cpp" /> <ClCompile Include="..\..\src\parser_test.cpp" /> <ClCompile Include="..\..\src\row_test.cpp" /> + <ClCompile Include="..\..\src\sql_function_test_suite_fixture.cpp" /> + <ClCompile Include="..\..\src\sql_numeric_functions_test.cpp" /> <ClCompile Include="..\..\src\sql_string_functions_test.cpp" /> <ClCompile Include="..\..\src\teamcity\teamcity_boost.cpp" /> <ClCompile Include="..\..\src\teamcity\teamcity_messages.cpp" /> @@ -175,6 +177,7 @@ <ClCompile Include="..\..\src\utility_test.cpp" /> </ItemGroup> <ItemGroup> + <ClInclude Include="..\..\include\sql_function_test_suite_fixture.h" /> <ClInclude Include="..\..\include\teamcity\teamcity_messages.h" /> <ClInclude Include="..\..\include\test_type.h" /> <ClInclude Include="..\..\include\test_utils.h" /> http://git-wip-us.apache.org/repos/asf/ignite/blob/5a3b3e2c/modules/platforms/cpp/odbc-test/project/vs/odbc-test.vcxproj.filters ---------------------------------------------------------------------- diff --git a/modules/platforms/cpp/odbc-test/project/vs/odbc-test.vcxproj.filters b/modules/platforms/cpp/odbc-test/project/vs/odbc-test.vcxproj.filters index 1871149..f993ed9 100644 --- a/modules/platforms/cpp/odbc-test/project/vs/odbc-test.vcxproj.filters +++ b/modules/platforms/cpp/odbc-test/project/vs/odbc-test.vcxproj.filters @@ -82,6 +82,12 @@ <ClCompile Include="..\..\src\test_utils.cpp"> <Filter>Code</Filter> </ClCompile> + <ClCompile Include="..\..\src\sql_numeric_functions_test.cpp"> + <Filter>Code</Filter> + </ClCompile> + <ClCompile Include="..\..\src\sql_function_test_suite_fixture.cpp"> + <Filter>Code</Filter> + </ClCompile> </ItemGroup> <ItemGroup> <ClInclude Include="..\..\include\test_type.h"> @@ -93,6 +99,9 @@ <ClInclude Include="..\..\include\test_utils.h"> <Filter>Code</Filter> </ClInclude> + <ClInclude Include="..\..\include\sql_function_test_suite_fixture.h"> + <Filter>Code</Filter> + </ClInclude> </ItemGroup> <ItemGroup> <None Include="..\..\config\queries-test.xml"> http://git-wip-us.apache.org/repos/asf/ignite/blob/5a3b3e2c/modules/platforms/cpp/odbc-test/src/sql_function_test_suite_fixture.cpp ---------------------------------------------------------------------- diff --git a/modules/platforms/cpp/odbc-test/src/sql_function_test_suite_fixture.cpp b/modules/platforms/cpp/odbc-test/src/sql_function_test_suite_fixture.cpp new file mode 100644 index 0000000..2398393 --- /dev/null +++ b/modules/platforms/cpp/odbc-test/src/sql_function_test_suite_fixture.cpp @@ -0,0 +1,188 @@ +/* + * 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. + */ + +#include "sql_function_test_suite_fixture.h" + +#include "test_utils.h" + +namespace ignite +{ + SqlFunctionTestSuiteFixture::SqlFunctionTestSuiteFixture(): + testCache(0), + env(NULL), + dbc(NULL), + stmt(NULL) + { + IgniteConfiguration cfg; + + cfg.jvmOpts.push_back("-Xdebug"); + cfg.jvmOpts.push_back("-Xnoagent"); + cfg.jvmOpts.push_back("-Djava.compiler=NONE"); + cfg.jvmOpts.push_back("-agentlib:jdwp=transport=dt_socket,server=y,suspend=n,address=5005"); + cfg.jvmOpts.push_back("-XX:+HeapDumpOnOutOfMemoryError"); + +#ifdef IGNITE_TESTS_32 + cfg.jvmInitMem = 256; + cfg.jvmMaxMem = 768; +#else + cfg.jvmInitMem = 1024; + cfg.jvmMaxMem = 4096; +#endif + + char* cfgPath = getenv("IGNITE_NATIVE_TEST_ODBC_CONFIG_PATH"); + + BOOST_REQUIRE(cfgPath != 0) ; + + cfg.springCfgPath.assign(cfgPath).append("/queries-test.xml"); + + IgniteError err; + + grid = Ignition::Start(cfg, &err); + + if (err.GetCode() != IgniteError::IGNITE_SUCCESS) + BOOST_FAIL(err.GetText()) ; + + testCache = grid.GetCache<int64_t, TestType>("cache"); + + // Allocate an environment handle + SQLAllocHandle(SQL_HANDLE_ENV, SQL_NULL_HANDLE, &env); + + BOOST_REQUIRE(env != NULL) ; + + // We want ODBC 3 support + SQLSetEnvAttr(env, SQL_ATTR_ODBC_VERSION, reinterpret_cast<void*>(SQL_OV_ODBC3), 0); + + // Allocate a connection handle + SQLAllocHandle(SQL_HANDLE_DBC, env, &dbc); + + BOOST_REQUIRE(dbc != NULL) ; + + // Connect string + SQLCHAR connectStr[] = "DRIVER={Apache Ignite};SERVER=localhost;PORT=10800;CACHE=cache"; + + SQLCHAR outstr[ODBC_BUFFER_SIZE]; + SQLSMALLINT outstrlen; + + // Connecting to ODBC server. + SQLRETURN ret = SQLDriverConnect(dbc, NULL, connectStr, static_cast<SQLSMALLINT>(sizeof(connectStr)), + outstr, sizeof(outstr), &outstrlen, SQL_DRIVER_COMPLETE); + + if (!SQL_SUCCEEDED(ret)) + { + Ignition::Stop(grid.GetName(), true); + + BOOST_FAIL(GetOdbcErrorMessage(SQL_HANDLE_DBC, dbc)) ; + } + + // Allocate a statement handle + SQLAllocHandle(SQL_HANDLE_STMT, dbc, &stmt); + + BOOST_REQUIRE(stmt != NULL) ; + } + + SqlFunctionTestSuiteFixture::~SqlFunctionTestSuiteFixture() + { + // Releasing statement handle. + SQLFreeHandle(SQL_HANDLE_STMT, stmt); + + // Disconneting from the server. + SQLDisconnect(dbc); + + // Releasing allocated handles. + SQLFreeHandle(SQL_HANDLE_DBC, dbc); + SQLFreeHandle(SQL_HANDLE_ENV, env); + + ignite::Ignition::Stop(grid.GetName(), true); + } + + void SqlFunctionTestSuiteFixture::CheckSingleResult0(const char* request, + SQLSMALLINT type, void* column, SQLLEN bufSize, SQLLEN* resSize) const + { + SQLRETURN ret; + + ret = SQLBindCol(stmt, 1, type, column, bufSize, resSize); + + if (!SQL_SUCCEEDED(ret)) + BOOST_FAIL(GetOdbcErrorMessage(SQL_HANDLE_STMT, stmt)) ; + + ret = SQLExecDirect(stmt, reinterpret_cast<SQLCHAR*>(const_cast<char*>(request)), SQL_NTS); + if (!SQL_SUCCEEDED(ret)) + BOOST_FAIL(GetOdbcErrorMessage(SQL_HANDLE_STMT, stmt)) ; + + ret = SQLFetch(stmt); + if (!SQL_SUCCEEDED(ret)) + BOOST_FAIL(GetOdbcErrorMessage(SQL_HANDLE_STMT, stmt)) ; + + ret = SQLFetch(stmt); + BOOST_CHECK(ret == SQL_NO_DATA) ; + } + + template<> + void SqlFunctionTestSuiteFixture::CheckSingleResult<std::string>(const char* request, const std::string& expected) + { + SQLCHAR res[ODBC_BUFFER_SIZE] = { 0 }; + SQLLEN resLen = 0; + + CheckSingleResult0(request, SQL_C_CHAR, res, ODBC_BUFFER_SIZE, &resLen); + + BOOST_CHECK_EQUAL(std::string(reinterpret_cast<char*>(res), static_cast<size_t>(resLen)), expected); + } + + template<> + void SqlFunctionTestSuiteFixture::CheckSingleResult<int64_t>(const char* request, const int64_t& expected) + { + CheckSingleResultNum0<int64_t>(request, expected, SQL_C_SBIGINT); + } + + template<> + void SqlFunctionTestSuiteFixture::CheckSingleResult<int32_t>(const char* request, const int32_t& expected) + { + CheckSingleResultNum0<int32_t>(request, expected, SQL_C_SLONG); + } + + template<> + void SqlFunctionTestSuiteFixture::CheckSingleResult<int16_t>(const char* request, const int16_t& expected) + { + CheckSingleResultNum0<int16_t>(request, expected, SQL_C_SSHORT); + } + + template<> + void SqlFunctionTestSuiteFixture::CheckSingleResult<int8_t>(const char* request, const int8_t& expected) + { + CheckSingleResultNum0<int8_t>(request, expected, SQL_C_STINYINT); + } + + template<> + void SqlFunctionTestSuiteFixture::CheckSingleResult<float>(const char* request, const float& expected) + { + SQLFLOAT res = 0; + + CheckSingleResult0(request, SQL_C_FLOAT, &res, 0, 0); + + BOOST_CHECK_CLOSE(static_cast<float>(res), expected, 1E-6f); + } + + template<> + void SqlFunctionTestSuiteFixture::CheckSingleResult<double>(const char* request, const double& expected) + { + SQLDOUBLE res = 0; + + CheckSingleResult0(request, SQL_C_DOUBLE, &res, 0, 0); + + BOOST_CHECK_CLOSE(static_cast<double>(res), expected, 1E-6); + } +} http://git-wip-us.apache.org/repos/asf/ignite/blob/5a3b3e2c/modules/platforms/cpp/odbc-test/src/sql_numeric_functions_test.cpp ---------------------------------------------------------------------- diff --git a/modules/platforms/cpp/odbc-test/src/sql_numeric_functions_test.cpp b/modules/platforms/cpp/odbc-test/src/sql_numeric_functions_test.cpp new file mode 100644 index 0000000..80ffd83 --- /dev/null +++ b/modules/platforms/cpp/odbc-test/src/sql_numeric_functions_test.cpp @@ -0,0 +1,309 @@ +/* + * 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. + */ + +#define _USE_MATH_DEFINES + +#ifdef _WIN32 +# include <windows.h> +#endif + +#include <sql.h> +#include <sqlext.h> + +#include <cmath> + +#include <vector> +#include <string> + +#ifndef _MSC_VER +# define BOOST_TEST_DYN_LINK +#endif + +#include <boost/test/unit_test.hpp> + +#include "ignite/ignite.h" +#include "ignite/ignition.h" +#include "ignite/impl/binary/binary_utils.h" + +#include "test_type.h" +#include "test_utils.h" +#include "sql_function_test_suite_fixture.h" + +using namespace ignite; +using namespace ignite::cache; +using namespace ignite::cache::query; +using namespace ignite::common; + +using namespace boost::unit_test; + +using ignite::impl::binary::BinaryUtils; + +BOOST_FIXTURE_TEST_SUITE(SqlNumericFunctionTestSuite, ignite::SqlFunctionTestSuiteFixture) + +BOOST_AUTO_TEST_CASE(TestNumericFunctionAbs) +{ + TestType in; + + in.i32Field = -42; + + testCache.Put(1, in); + + CheckSingleResult<int32_t>("SELECT {fn ABS(i32Field)} FROM TestType", std::abs(in.i32Field)); +} + +BOOST_AUTO_TEST_CASE(TestNumericFunctionAcos) +{ + TestType in; + + in.doubleField = 0.32; + + testCache.Put(1, in); + + CheckSingleResult<double>("SELECT {fn ACOS(doubleField)} FROM TestType", std::acos(in.doubleField)); +} + +BOOST_AUTO_TEST_CASE(TestNumericFunctionAsin) +{ + TestType in; + + in.doubleField = 0.12; + + testCache.Put(1, in); + + CheckSingleResult<double>("SELECT {fn ASIN(doubleField)} FROM TestType", std::asin(in.doubleField)); +} + +BOOST_AUTO_TEST_CASE(TestNumericFunctionAtan) +{ + TestType in; + + in.doubleField = 0.14; + + testCache.Put(1, in); + + CheckSingleResult<double>("SELECT {fn ATAN(doubleField)} FROM TestType", std::atan(in.doubleField)); +} + +BOOST_AUTO_TEST_CASE(TestNumericFunctionAtan2) +{ + TestType in; + + in.doubleField = 0.24; + + testCache.Put(1, in); + + CheckSingleResult<double>("SELECT {fn ATAN2(doubleField, 0.2)} FROM TestType", std::atan2(in.doubleField, 0.2)); +} + +BOOST_AUTO_TEST_CASE(TestNumericFunctionCeiling) +{ + TestType in; + + in.doubleField = 7.31; + + testCache.Put(1, in); + + CheckSingleResult<double>("SELECT {fn CEILING(doubleField)} FROM TestType", std::ceil(in.doubleField)); +} + +BOOST_AUTO_TEST_CASE(TestNumericFunctionCos) +{ + TestType in; + + in.doubleField = 2.31; + + testCache.Put(1, in); + + CheckSingleResult<double>("SELECT {fn COS(doubleField)} FROM TestType", std::cos(in.doubleField)); +} + +BOOST_AUTO_TEST_CASE(TestNumericFunctionCot) +{ + TestType in; + + in.doubleField = 2.31; + + testCache.Put(1, in); + + CheckSingleResult<double>("SELECT {fn COT(doubleField)} FROM TestType", 1 / std::tan(in.doubleField)); +} + +BOOST_AUTO_TEST_CASE(TestNumericFunctionDegrees) +{ + TestType in; + + in.doubleField = 2.31; + + testCache.Put(1, in); + + CheckSingleResult<double>("SELECT {fn DEGREES(doubleField)} FROM TestType", in.doubleField * M_1_PI * 180); +} + +BOOST_AUTO_TEST_CASE(TestNumericFunctionExp) +{ + TestType in; + + in.doubleField = 1.23; + + testCache.Put(1, in); + + CheckSingleResult<double>("SELECT {fn EXP(doubleField)} FROM TestType", std::exp(in.doubleField)); +} + +BOOST_AUTO_TEST_CASE(TestNumericFunctionFloor) +{ + TestType in; + + in.doubleField = 5.29; + + testCache.Put(1, in); + + CheckSingleResult<double>("SELECT {fn FLOOR(doubleField)} FROM TestType", std::floor(in.doubleField)); +} + +BOOST_AUTO_TEST_CASE(TestNumericFunctionLog) +{ + TestType in; + + in.doubleField = 15.3; + + testCache.Put(1, in); + + CheckSingleResult<double>("SELECT {fn LOG(doubleField)} FROM TestType", std::log(in.doubleField)); +} + +BOOST_AUTO_TEST_CASE(TestNumericFunctionLog10) +{ + TestType in; + + in.doubleField = 15.3; + + testCache.Put(1, in); + + CheckSingleResult<double>("SELECT {fn LOG10(doubleField)} FROM TestType", std::log10(in.doubleField)); +} + +BOOST_AUTO_TEST_CASE(TestNumericFunctionMod) +{ + TestType in; + + in.i64Field = 26; + + testCache.Put(1, in); + + CheckSingleResult<int64_t>("SELECT {fn MOD(i64Field, 3)} FROM TestType", in.i64Field % 3); +} + +BOOST_AUTO_TEST_CASE(TestNumericFunctionPi) +{ + CheckSingleResult<double>("SELECT {fn PI()}", M_PI); +} + +BOOST_AUTO_TEST_CASE(TestNumericFunctionPower) +{ + TestType in; + + in.doubleField = 1.81; + + testCache.Put(1, in); + + CheckSingleResult<double>("SELECT {fn POWER(doubleField, 2.5)} FROM TestType", std::pow(in.doubleField, 2.5)); +} + +BOOST_AUTO_TEST_CASE(TestNumericFunctionRadians) +{ + TestType in; + + in.doubleField = 161; + + testCache.Put(1, in); + + CheckSingleResult<double>("SELECT {fn RADIANS(doubleField)} FROM TestType", in.doubleField * M_PI / 180.0); +} + +BOOST_AUTO_TEST_CASE(TestNumericFunctionRand) +{ + CheckSingleResult<double>("SELECT {fn RAND()} * 0", 0); +} + +BOOST_AUTO_TEST_CASE(TestNumericFunctionRound) +{ + TestType in; + + in.doubleField = 5.29; + + testCache.Put(1, in); + + CheckSingleResult<double>("SELECT {fn ROUND(doubleField)} FROM TestType", std::floor(in.doubleField)); +} + +BOOST_AUTO_TEST_CASE(TestNumericFunctionSign) +{ + TestType in; + + in.doubleField = -1.39; + + testCache.Put(1, in); + + CheckSingleResult<double>("SELECT {fn SIGN(doubleField)} FROM TestType", in.doubleField < 0 ? -1 : in.doubleField == 0 ? 0 : 1); +} + +BOOST_AUTO_TEST_CASE(TestNumericFunctionSin) +{ + TestType in; + + in.doubleField = 1.01; + + testCache.Put(1, in); + + CheckSingleResult<double>("SELECT {fn SIN(doubleField)} FROM TestType", std::sin(in.doubleField)); +} + +BOOST_AUTO_TEST_CASE(TestNumericFunctionSqrt) +{ + TestType in; + + in.doubleField = 2.56; + + testCache.Put(1, in); + + CheckSingleResult<double>("SELECT {fn SQRT(doubleField)} FROM TestType", std::sqrt(in.doubleField)); +} + +BOOST_AUTO_TEST_CASE(TestNumericFunctionTan) +{ + TestType in; + + in.doubleField = 0.56; + + testCache.Put(1, in); + + CheckSingleResult<double>("SELECT {fn TAN(doubleField)} FROM TestType", std::tan(in.doubleField)); +} + +BOOST_AUTO_TEST_CASE(TestNumericFunctionTruncate) +{ + TestType in; + + in.doubleField = 4.17133; + + testCache.Put(1, in); + + CheckSingleResult<double>("SELECT {fn TRUNCATE(doubleField, 3)} FROM TestType", 4.171); +} + +BOOST_AUTO_TEST_SUITE_END() http://git-wip-us.apache.org/repos/asf/ignite/blob/5a3b3e2c/modules/platforms/cpp/odbc-test/src/sql_string_functions_test.cpp ---------------------------------------------------------------------- diff --git a/modules/platforms/cpp/odbc-test/src/sql_string_functions_test.cpp b/modules/platforms/cpp/odbc-test/src/sql_string_functions_test.cpp index e84aba6..d22bb83 100644 --- a/modules/platforms/cpp/odbc-test/src/sql_string_functions_test.cpp +++ b/modules/platforms/cpp/odbc-test/src/sql_string_functions_test.cpp @@ -15,8 +15,6 @@ * limitations under the License. */ -#define _USE_MATH_DEFINES - #ifdef _WIN32 # include <windows.h> #endif @@ -24,8 +22,6 @@ #include <sql.h> #include <sqlext.h> -#include <cmath> - #include <vector> #include <string> @@ -41,6 +37,7 @@ #include "test_type.h" #include "test_utils.h" +#include "sql_function_test_suite_fixture.h" using namespace ignite; using namespace ignite::cache; @@ -51,228 +48,7 @@ using namespace boost::unit_test; using ignite::impl::binary::BinaryUtils; -/** - * Test setup fixture. - */ -struct SqlStringFunctionTestSuiteFixture -{ - /** - * Constructor. - */ - SqlStringFunctionTestSuiteFixture() : - testCache(0), - env(NULL), - dbc(NULL), - stmt(NULL) - { - IgniteConfiguration cfg; - - cfg.jvmOpts.push_back("-Xdebug"); - cfg.jvmOpts.push_back("-Xnoagent"); - cfg.jvmOpts.push_back("-Djava.compiler=NONE"); - cfg.jvmOpts.push_back("-agentlib:jdwp=transport=dt_socket,server=y,suspend=n,address=5005"); - cfg.jvmOpts.push_back("-XX:+HeapDumpOnOutOfMemoryError"); - -#ifdef IGNITE_TESTS_32 - cfg.jvmInitMem = 256; - cfg.jvmMaxMem = 768; -#else - cfg.jvmInitMem = 1024; - cfg.jvmMaxMem = 4096; -#endif - - char* cfgPath = getenv("IGNITE_NATIVE_TEST_ODBC_CONFIG_PATH"); - - BOOST_REQUIRE(cfgPath != 0); - - cfg.springCfgPath.assign(cfgPath).append("/queries-test.xml"); - - IgniteError err; - - grid = Ignition::Start(cfg, &err); - - if (err.GetCode() != IgniteError::IGNITE_SUCCESS) - BOOST_FAIL(err.GetText()); - - testCache = grid.GetCache<int64_t, TestType>("cache"); - - // Allocate an environment handle - SQLAllocHandle(SQL_HANDLE_ENV, SQL_NULL_HANDLE, &env); - - BOOST_REQUIRE(env != NULL); - - // We want ODBC 3 support - SQLSetEnvAttr(env, SQL_ATTR_ODBC_VERSION, reinterpret_cast<void*>(SQL_OV_ODBC3), 0); - - // Allocate a connection handle - SQLAllocHandle(SQL_HANDLE_DBC, env, &dbc); - - BOOST_REQUIRE(dbc != NULL); - - // Connect string - SQLCHAR connectStr[] = "DRIVER={Apache Ignite};SERVER=localhost;PORT=10800;CACHE=cache"; - - SQLCHAR outstr[ODBC_BUFFER_SIZE]; - SQLSMALLINT outstrlen; - - // Connecting to ODBC server. - SQLRETURN ret = SQLDriverConnect(dbc, NULL, connectStr, static_cast<SQLSMALLINT>(sizeof(connectStr)), - outstr, sizeof(outstr), &outstrlen, SQL_DRIVER_COMPLETE); - - if (!SQL_SUCCEEDED(ret)) - { - Ignition::Stop(grid.GetName(), true); - - BOOST_FAIL(GetOdbcErrorMessage(SQL_HANDLE_DBC, dbc)); - } - - // Allocate a statement handle - SQLAllocHandle(SQL_HANDLE_STMT, dbc, &stmt); - - BOOST_REQUIRE(stmt != NULL); - } - - /** - * Destructor. - */ - ~SqlStringFunctionTestSuiteFixture() - { - // Releasing statement handle. - SQLFreeHandle(SQL_HANDLE_STMT, stmt); - - // Disconneting from the server. - SQLDisconnect(dbc); - - // Releasing allocated handles. - SQLFreeHandle(SQL_HANDLE_DBC, dbc); - SQLFreeHandle(SQL_HANDLE_ENV, env); - - Ignition::Stop(grid.GetName(), true); - } - - void CheckSingleResult0(const char* request, SQLSMALLINT type, void* column, SQLLEN bufSize, SQLLEN* resSize) - { - SQLRETURN ret; - - ret = SQLBindCol(stmt, 1, type, column, bufSize, resSize); - - if (!SQL_SUCCEEDED(ret)) - BOOST_FAIL(GetOdbcErrorMessage(SQL_HANDLE_STMT, stmt)); - - ret = SQLExecDirect(stmt, reinterpret_cast<SQLCHAR*>(const_cast<char*>(request)), SQL_NTS); - if (!SQL_SUCCEEDED(ret)) - BOOST_FAIL(GetOdbcErrorMessage(SQL_HANDLE_STMT, stmt)); - - ret = SQLFetch(stmt); - if (!SQL_SUCCEEDED(ret)) - BOOST_FAIL(GetOdbcErrorMessage(SQL_HANDLE_STMT, stmt)); - - ret = SQLFetch(stmt); - BOOST_CHECK(ret == SQL_NO_DATA); - } - - /** - * Run query returning single result and check it to be equal to expected. - * - * @param request SQL request. - * @param expected Expected result. - */ - template<typename T> - void CheckSingleResult(const char* request, const T& expected) - { - BOOST_FAIL("Function is not defined for the type."); - } - - /** - * Run query returning single result and check it to be equal to expected. - * - * @param request SQL request. - * @param expected Expected result. - * @param type Result type. - */ - template<typename T> - void CheckSingleResultNum0(const char* request, const T& expected, SQLSMALLINT type) - { - T res = 0; - - CheckSingleResult0(request, type, &res, 0, 0); - - BOOST_CHECK_EQUAL(res, expected); - } - - - /** Node started during the test. */ - Ignite grid; - - /** Test cache instance. */ - Cache<int64_t, TestType> testCache; - - /** ODBC Environment. */ - SQLHENV env; - - /** ODBC Connect. */ - SQLHDBC dbc; - - /** ODBC Statement. */ - SQLHSTMT stmt; -}; - -template<> -void SqlStringFunctionTestSuiteFixture::CheckSingleResult<std::string>(const char* request, const std::string& expected) -{ - SQLCHAR res[ODBC_BUFFER_SIZE] = { 0 }; - SQLLEN resLen = 0; - - CheckSingleResult0(request, SQL_C_CHAR, res, ODBC_BUFFER_SIZE, &resLen); - - BOOST_CHECK_EQUAL(std::string(reinterpret_cast<char*>(res), static_cast<size_t>(resLen)), expected); -} - -template<> -void SqlStringFunctionTestSuiteFixture::CheckSingleResult<int64_t>(const char* request, const int64_t& expected) -{ - CheckSingleResultNum0<int64_t>(request, expected, SQL_C_SBIGINT); -} - -template<> -void SqlStringFunctionTestSuiteFixture::CheckSingleResult<int32_t>(const char* request, const int32_t& expected) -{ - CheckSingleResultNum0<int32_t>(request, expected, SQL_C_SLONG); -} - -template<> -void SqlStringFunctionTestSuiteFixture::CheckSingleResult<int16_t>(const char* request, const int16_t& expected) -{ - CheckSingleResultNum0<int16_t>(request, expected, SQL_C_SSHORT); -} - -template<> -void SqlStringFunctionTestSuiteFixture::CheckSingleResult<int8_t>(const char* request, const int8_t& expected) -{ - CheckSingleResultNum0<int8_t>(request, expected, SQL_C_STINYINT); -} - -template<> -void SqlStringFunctionTestSuiteFixture::CheckSingleResult<float>(const char* request, const float& expected) -{ - SQLFLOAT res = 0; - - CheckSingleResult0(request, SQL_C_FLOAT, &res, 0, 0); - - BOOST_CHECK_CLOSE(static_cast<float>(res), expected, 1E-6f); -} - -template<> -void SqlStringFunctionTestSuiteFixture::CheckSingleResult<double>(const char* request, const double& expected) -{ - SQLDOUBLE res = 0; - - CheckSingleResult0(request, SQL_C_DOUBLE, &res, 0, 0); - - BOOST_CHECK_CLOSE(static_cast<double>(res), expected, 1E-6); -} - -BOOST_FIXTURE_TEST_SUITE(SqlStringFunctionTestSuite, SqlStringFunctionTestSuiteFixture) +BOOST_FIXTURE_TEST_SUITE(SqlStringFunctionTestSuite, ignite::SqlFunctionTestSuiteFixture) BOOST_AUTO_TEST_CASE(TestStringFunctionAscii) { http://git-wip-us.apache.org/repos/asf/ignite/blob/5a3b3e2c/modules/platforms/cpp/odbc/src/config/connection_info.cpp ---------------------------------------------------------------------- diff --git a/modules/platforms/cpp/odbc/src/config/connection_info.cpp b/modules/platforms/cpp/odbc/src/config/connection_info.cpp index f9a3f96..1fed7c5 100644 --- a/modules/platforms/cpp/odbc/src/config/connection_info.cpp +++ b/modules/platforms/cpp/odbc/src/config/connection_info.cpp @@ -233,7 +233,12 @@ namespace ignite #ifdef SQL_NUMERIC_FUNCTIONS // Bitmask enumerating the scalar numeric functions supported by // the driver and associated data source. - intParams[SQL_NUMERIC_FUNCTIONS] = SQL_FN_NUM_ABS; + intParams[SQL_NUMERIC_FUNCTIONS] = SQL_FN_NUM_ABS | SQL_FN_NUM_ACOS | SQL_FN_NUM_ASIN | + SQL_FN_NUM_ATAN | SQL_FN_NUM_ATAN2 | SQL_FN_NUM_CEILING | SQL_FN_NUM_COS | SQL_FN_NUM_COT | + SQL_FN_NUM_EXP | SQL_FN_NUM_FLOOR | SQL_FN_NUM_LOG | SQL_FN_NUM_MOD | SQL_FN_NUM_SIGN | + SQL_FN_NUM_SIN | SQL_FN_NUM_SQRT | SQL_FN_NUM_TAN | SQL_FN_NUM_PI | SQL_FN_NUM_RAND | + SQL_FN_NUM_DEGREES | SQL_FN_NUM_LOG10 | SQL_FN_NUM_POWER | SQL_FN_NUM_RADIANS | SQL_FN_NUM_ROUND | + SQL_FN_NUM_TRUNCATE; #endif // SQL_NUMERIC_FUNCTIONS #ifdef SQL_STRING_FUNCTIONS
