blob: d145e5231d0420ed92c1dcba7e2d74c43288f281 [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.
*/
#ifdef _WIN32
# include <windows.h>
#endif
#include <sql.h>
#include <sqlext.h>
#include <cstdio>
#include <vector>
#include <string>
#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 "odbc_test_suite.h"
using namespace ignite;
using namespace ignite::cache;
using namespace ignite::cache::query;
using namespace ignite::common;
using namespace ignite_test;
using namespace boost::unit_test;
using ignite::impl::binary::BinaryUtils;
/**
* Test setup fixture.
*/
struct CursorBindingTestSuiteFixture : public odbc::OdbcTestSuite
{
static Ignite StartAdditionalNode(const char* name)
{
return StartPlatformNode("queries-test.xml", name);
}
/**
* Constructor.
*/
CursorBindingTestSuiteFixture() :
testCache(0)
{
grid = StartAdditionalNode("NodeMain");
testCache = grid.GetCache<int64_t, TestType>("cache");
}
/**
* Destructor.
*/
virtual ~CursorBindingTestSuiteFixture()
{
// No-op.
}
/** Node started during the test. */
Ignite grid;
/** Test cache instance. */
Cache<int64_t, TestType> testCache;
};
BOOST_FIXTURE_TEST_SUITE(CursorBindingTestSuite, CursorBindingTestSuiteFixture)
#define CHECK_TEST_VALUES(idx, testIdx) \
do { \
BOOST_TEST_CONTEXT("Test idx: " << testIdx) \
{ \
BOOST_CHECK(RowStatus[idx] == SQL_ROW_SUCCESS || RowStatus[idx] == SQL_ROW_SUCCESS_WITH_INFO); \
\
BOOST_CHECK(i8FieldsInd[idx] != SQL_NULL_DATA); \
BOOST_CHECK(i16FieldsInd[idx] != SQL_NULL_DATA); \
BOOST_CHECK(i32FieldsInd[idx] != SQL_NULL_DATA); \
BOOST_CHECK(strFieldsLen[idx] != SQL_NULL_DATA); \
BOOST_CHECK(floatFields[idx] != SQL_NULL_DATA); \
BOOST_CHECK(doubleFieldsInd[idx] != SQL_NULL_DATA); \
BOOST_CHECK(boolFieldsInd[idx] != SQL_NULL_DATA); \
BOOST_CHECK(dateFieldsInd[idx] != SQL_NULL_DATA); \
BOOST_CHECK(timeFieldsInd[idx] != SQL_NULL_DATA); \
BOOST_CHECK(timestampFieldsInd[idx] != SQL_NULL_DATA); \
BOOST_CHECK(i8ArrayFieldsLen[idx] != SQL_NULL_DATA); \
\
int8_t i8Field = static_cast<int8_t>(i8Fields[idx]); \
int16_t i16Field = static_cast<int16_t>(i16Fields[idx]); \
int32_t i32Field = static_cast<int32_t>(i32Fields[idx]); \
std::string strField(reinterpret_cast<char*>(&strFields[idx][0]), \
static_cast<size_t>(strFieldsLen[idx])); \
float floatField = static_cast<float>(floatFields[idx]); \
double doubleField = static_cast<double>(doubleFields[idx]); \
bool boolField = boolFields[idx] != 0; \
\
CheckTestI8Value(testIdx, i8Field); \
CheckTestI16Value(testIdx, i16Field); \
CheckTestI32Value(testIdx, i32Field); \
CheckTestStringValue(testIdx, strField); \
CheckTestFloatValue(testIdx, floatField); \
CheckTestDoubleValue(testIdx, doubleField); \
CheckTestBoolValue(testIdx, boolField); \
CheckTestDateValue(testIdx, dateFields[idx]); \
CheckTestTimeValue(testIdx, timeFields[idx]); \
CheckTestTimestampValue(testIdx, timestampFields[idx]); \
CheckTestI8ArrayValue(testIdx, reinterpret_cast<int8_t*>(i8ArrayFields[idx]), \
static_cast<SQLLEN>(i8ArrayFieldsLen[idx])); \
} \
} while (false)
BOOST_AUTO_TEST_CASE(TestCursorBindingColumnWise)
{
enum { ROWS_COUNT = 15 };
enum { ROW_ARRAY_SIZE = 10 };
enum { BUFFER_SIZE = 1024 };
StartAdditionalNode("Node2");
Connect("DRIVER={Apache Ignite};ADDRESS=127.0.0.1:11110;SCHEMA=cache;PAGE_SIZE=8");
// Preloading data.
InsertTestBatch(0, ROWS_COUNT, ROWS_COUNT);
// Setting attributes.
SQLUSMALLINT RowStatus[ROW_ARRAY_SIZE];
SQLUINTEGER NumRowsFetched;
SQLRETURN ret;
ret = SQLSetStmtAttr(stmt, SQL_ATTR_ROW_BIND_TYPE, SQL_BIND_BY_COLUMN, 0);
ODBC_THROW_ON_ERROR(ret, SQL_HANDLE_STMT, stmt);
ret = SQLSetStmtAttr(stmt, SQL_ATTR_ROW_ARRAY_SIZE, reinterpret_cast<SQLPOINTER*>(ROW_ARRAY_SIZE), 0);
ODBC_THROW_ON_ERROR(ret, SQL_HANDLE_STMT, stmt);
ret = SQLSetStmtAttr(stmt, SQL_ATTR_ROW_STATUS_PTR, RowStatus, 0);
ODBC_THROW_ON_ERROR(ret, SQL_HANDLE_STMT, stmt);
ret = SQLSetStmtAttr(stmt, SQL_ATTR_ROWS_FETCHED_PTR, &NumRowsFetched, 0);
ODBC_THROW_ON_ERROR(ret, SQL_HANDLE_STMT, stmt);
// Binding collumns.
SQLSCHAR i8Fields[ROW_ARRAY_SIZE] = {0};
SQLLEN i8FieldsInd[ROW_ARRAY_SIZE];
SQLSMALLINT i16Fields[ROW_ARRAY_SIZE] = {0};
SQLLEN i16FieldsInd[ROW_ARRAY_SIZE];
SQLINTEGER i32Fields[ROW_ARRAY_SIZE] = {0};
SQLLEN i32FieldsInd[ROW_ARRAY_SIZE];
SQLCHAR strFields[ROW_ARRAY_SIZE][BUFFER_SIZE];
SQLLEN strFieldsLen[ROW_ARRAY_SIZE];
SQLREAL floatFields[ROW_ARRAY_SIZE];
SQLLEN floatFieldsInd[ROW_ARRAY_SIZE];
SQLDOUBLE doubleFields[ROW_ARRAY_SIZE];
SQLLEN doubleFieldsInd[ROW_ARRAY_SIZE];
SQLCHAR boolFields[ROW_ARRAY_SIZE];
SQLLEN boolFieldsInd[ROW_ARRAY_SIZE];
SQL_DATE_STRUCT dateFields[ROW_ARRAY_SIZE];
SQLLEN dateFieldsInd[ROW_ARRAY_SIZE];
SQL_TIME_STRUCT timeFields[ROW_ARRAY_SIZE];
SQLLEN timeFieldsInd[ROW_ARRAY_SIZE];
SQL_TIMESTAMP_STRUCT timestampFields[ROW_ARRAY_SIZE];
SQLLEN timestampFieldsInd[ROW_ARRAY_SIZE];
SQLCHAR i8ArrayFields[ROW_ARRAY_SIZE][BUFFER_SIZE];
SQLLEN i8ArrayFieldsLen[ROW_ARRAY_SIZE];
ret = SQLBindCol(stmt, 1, SQL_C_STINYINT, i8Fields, 0, i8FieldsInd);
ODBC_THROW_ON_ERROR(ret, SQL_HANDLE_STMT, stmt);
ret = SQLBindCol(stmt, 2, SQL_C_SSHORT, i16Fields, 0, i16FieldsInd);
ODBC_THROW_ON_ERROR(ret, SQL_HANDLE_STMT, stmt);
ret = SQLBindCol(stmt, 3, SQL_C_LONG, i32Fields, 0, i32FieldsInd);
ODBC_THROW_ON_ERROR(ret, SQL_HANDLE_STMT, stmt);
ret = SQLBindCol(stmt, 4, SQL_C_CHAR, strFields, BUFFER_SIZE, strFieldsLen);
ODBC_THROW_ON_ERROR(ret, SQL_HANDLE_STMT, stmt);
ret = SQLBindCol(stmt, 5, SQL_C_FLOAT, floatFields, 0, floatFieldsInd);
ODBC_THROW_ON_ERROR(ret, SQL_HANDLE_STMT, stmt);
ret = SQLBindCol(stmt, 6, SQL_C_DOUBLE, doubleFields, 0, doubleFieldsInd);
ODBC_THROW_ON_ERROR(ret, SQL_HANDLE_STMT, stmt);
ret = SQLBindCol(stmt, 7, SQL_C_BIT, boolFields, 0, boolFieldsInd);
ODBC_THROW_ON_ERROR(ret, SQL_HANDLE_STMT, stmt);
ret = SQLBindCol(stmt, 8, SQL_C_TYPE_DATE, dateFields, 0, dateFieldsInd);
ODBC_THROW_ON_ERROR(ret, SQL_HANDLE_STMT, stmt);
ret = SQLBindCol(stmt, 9, SQL_C_TYPE_TIME, timeFields, 0, timeFieldsInd);
ODBC_THROW_ON_ERROR(ret, SQL_HANDLE_STMT, stmt);
ret = SQLBindCol(stmt, 10, SQL_C_TYPE_TIMESTAMP, timestampFields, 0, timestampFieldsInd);
ODBC_THROW_ON_ERROR(ret, SQL_HANDLE_STMT, stmt);
ret = SQLBindCol(stmt, 11, SQL_C_BINARY, i8ArrayFields, BUFFER_SIZE, i8ArrayFieldsLen);
ODBC_THROW_ON_ERROR(ret, SQL_HANDLE_STMT, stmt);
SQLCHAR sql[] = "SELECT "
"i8Field, i16Field, i32Field, strField, floatField, doubleField, "
"boolField, dateField, timeField, timestampField, i8ArrayField "
"FROM TestType "
"ORDER BY _key";
// Execute a statement to retrieve rows from the Orders table.
ret = SQLExecDirect(stmt, sql, SQL_NTS);
ODBC_THROW_ON_ERROR(ret, SQL_HANDLE_STMT, stmt);
ret = SQLFetchScroll(stmt, SQL_FETCH_NEXT, 0);
ODBC_THROW_ON_ERROR(ret, SQL_HANDLE_STMT, stmt);
BOOST_CHECK_EQUAL(NumRowsFetched, (SQLUINTEGER)ROW_ARRAY_SIZE);
for (int64_t i = 0; i < NumRowsFetched; i++)
{
CHECK_TEST_VALUES(i, static_cast<int>(i));
}
ret = SQLFetch(stmt);
ODBC_THROW_ON_ERROR(ret, SQL_HANDLE_STMT, stmt);
BOOST_CHECK_EQUAL(NumRowsFetched, ROWS_COUNT - ROW_ARRAY_SIZE);
for (int64_t i = 0; i < NumRowsFetched; i++)
{
int64_t testIdx = i + ROW_ARRAY_SIZE;
CHECK_TEST_VALUES(i, static_cast<int>(testIdx));
}
for (int64_t i = NumRowsFetched; i < ROW_ARRAY_SIZE; i++)
{
BOOST_TEST_INFO("Checking row status for row: " << i);
BOOST_CHECK(RowStatus[i] == SQL_ROW_NOROW);
}
ret = SQLFetchScroll(stmt, SQL_FETCH_NEXT, 0);
BOOST_CHECK_EQUAL(ret, SQL_NO_DATA);
// Close the cursor.
ret = SQLCloseCursor(stmt);
ODBC_THROW_ON_ERROR(ret, SQL_HANDLE_STMT, stmt);
}
BOOST_AUTO_TEST_CASE(TestCursorBindingRowWise)
{
Connect("DRIVER={Apache Ignite};ADDRESS=127.0.0.1:11110;SCHEMA=cache;PAGE_SIZE=8");
SQLRETURN ret = SQLSetStmtAttr(stmt, SQL_ATTR_ROW_BIND_TYPE, reinterpret_cast<SQLPOINTER*>(42), 0);
BOOST_CHECK_EQUAL(ret, SQL_ERROR);
CheckSQLStatementDiagnosticError("HYC00");
}
BOOST_AUTO_TEST_SUITE_END()