blob: 652d8a4802320d2e3e556fc3d315f1c5ae72d5f4 [file]
/*
* 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 "ignite/common/detail/config.h"
#include "odbc_suite.h"
#include <gtest/gtest.h>
#include <vector>
// Using NULLs as specified by ODBC
#ifdef __JETBRAINS_IDE__
# pragma ide diagnostic ignored "modernize-use-nullptr"
#endif // __JETBRAINS_IDE__
using namespace ignite;
/**
* Test suite.
*/
class api_robustness_test : public odbc_suite {
public:
static void SetUpTestSuite() {
odbc_connection conn;
conn.odbc_connect(get_basic_connection_string());
auto table_avail = conn.wait_for_table(TABLE_NAME_ALL_COLUMNS_SQL, std::chrono::seconds(10));
if (!table_avail) {
FAIL() << "Table '" + TABLE_NAME_ALL_COLUMNS_SQL + "' is not available";
}
}
};
std::vector<SQLSMALLINT> unsupported_c_types = {SQL_C_INTERVAL_YEAR, SQL_C_INTERVAL_MONTH, SQL_C_INTERVAL_DAY,
SQL_C_INTERVAL_HOUR, SQL_C_INTERVAL_MINUTE, SQL_C_INTERVAL_SECOND, SQL_C_INTERVAL_YEAR_TO_MONTH,
SQL_C_INTERVAL_DAY_TO_HOUR, SQL_C_INTERVAL_DAY_TO_MINUTE, SQL_C_INTERVAL_DAY_TO_SECOND,
SQL_C_INTERVAL_HOUR_TO_MINUTE, SQL_C_INTERVAL_HOUR_TO_SECOND, SQL_C_INTERVAL_MINUTE_TO_SECOND};
std::vector<SQLSMALLINT> unsupported_sql_types = {SQL_WVARCHAR, SQL_WLONGVARCHAR, SQL_REAL, SQL_NUMERIC,
SQL_INTERVAL_MONTH, SQL_INTERVAL_YEAR, SQL_INTERVAL_YEAR_TO_MONTH, SQL_INTERVAL_DAY, SQL_INTERVAL_HOUR,
SQL_INTERVAL_MINUTE, SQL_INTERVAL_SECOND, SQL_INTERVAL_DAY_TO_HOUR, SQL_INTERVAL_DAY_TO_MINUTE,
SQL_INTERVAL_DAY_TO_SECOND, SQL_INTERVAL_HOUR_TO_MINUTE, SQL_INTERVAL_HOUR_TO_SECOND,
SQL_INTERVAL_MINUTE_TO_SECOND};
TEST_F(api_robustness_test, sql_driver_connect) {
// There are no checks because we do not really care what is the result of these
// calls as long as they do not cause segmentation fault.
prepare_environment();
auto connect_str = to_sqlchar(get_basic_connection_string());
SQLCHAR out_str[ODBC_BUFFER_SIZE]{};
SQLSMALLINT out_str_len{};
// Normal connect.
SQLRETURN ret = SQLDriverConnect(m_conn, NULL, connect_str.data(), SQLSMALLINT(connect_str.size()), out_str,
sizeof(out_str), &out_str_len, SQL_DRIVER_COMPLETE);
ODBC_FAIL_ON_ERROR(ret, SQL_HANDLE_DBC, m_conn);
SQLDisconnect(m_conn);
// Null out string resulting length.
SQLDriverConnect(m_conn, NULL, connect_str.data(), SQLSMALLINT(connect_str.size()), out_str, sizeof(out_str), 0,
SQL_DRIVER_COMPLETE);
SQLDisconnect(m_conn);
// Null out string buffer length.
SQLDriverConnect(m_conn, NULL, connect_str.data(), SQLSMALLINT(connect_str.size()), out_str, 0, &out_str_len,
SQL_DRIVER_COMPLETE);
SQLDisconnect(m_conn);
// Null output string.
SQLDriverConnect(m_conn, NULL, connect_str.data(), SQLSMALLINT(connect_str.size()), 0, sizeof(out_str),
&out_str_len, SQL_DRIVER_COMPLETE);
SQLDisconnect(m_conn);
// Null all.
SQLDriverConnect(m_conn, NULL, connect_str.data(), SQLSMALLINT(connect_str.size()), 0, 0, 0, SQL_DRIVER_COMPLETE);
SQLDisconnect(m_conn);
}
TEST_F(api_robustness_test, sql_get_info) {
// There are no checks because we do not really care what is the result of these
// calls as long as they do not cause segmentation fault.
odbc_connect(get_basic_connection_string());
SQLCHAR buffer[ODBC_BUFFER_SIZE];
SQLSMALLINT resLen = 0;
// Everything is ok.
SQLRETURN ret = SQLGetInfo(m_conn, SQL_DRIVER_NAME, buffer, ODBC_BUFFER_SIZE, &resLen);
ODBC_FAIL_ON_ERROR(ret, SQL_HANDLE_DBC, m_conn);
// The Resulting length is null.
SQLGetInfo(m_conn, SQL_DRIVER_NAME, buffer, ODBC_BUFFER_SIZE, 0);
// Buffer length is null.
SQLGetInfo(m_conn, SQL_DRIVER_NAME, buffer, 0, &resLen);
// Buffer is null.
SQLGetInfo(m_conn, SQL_DRIVER_NAME, 0, ODBC_BUFFER_SIZE, &resLen);
// Unknown info.
SQLGetInfo(m_conn, -1, buffer, ODBC_BUFFER_SIZE, &resLen);
// All nulls.
SQLGetInfo(m_conn, SQL_DRIVER_NAME, 0, 0, 0);
}
TEST_F(api_robustness_test, sql_connect_failed_dsn) {
// Tests that SQLConnect using DSN doesn't fail with link error (especially on linux).
prepare_environment();
SQLCHAR dsn_conn_str[] = "DSN=IGNITE_TEST";
SQLRETURN ret = SQLConnect(m_conn, dsn_conn_str, sizeof(dsn_conn_str), 0, 0, 0, 0);
EXPECT_FALSE(SQL_SUCCEEDED(ret));
EXPECT_EQ(get_odbc_error_state(SQL_HANDLE_DBC, m_conn), "IM002");
}
TEST_F(api_robustness_test, sql_prepare) {
// There are no checks because we do not really care what is the result of these
// calls as long as they do not cause segmentation fault.
odbc_connect(get_basic_connection_string());
SQLCHAR sql[] = "select str from TBL_ALL_COLUMNS_SQL";
// Everything is ok.
SQLRETURN ret = SQLPrepare(m_statement, sql, sizeof(sql));
ODBC_FAIL_ON_ERROR(ret, SQL_HANDLE_STMT, m_statement);
SQLCloseCursor(m_statement);
// Value length is null.
SQLPrepare(m_statement, sql, 0);
SQLCloseCursor(m_statement);
// Value is null.
SQLPrepare(m_statement, 0, sizeof(sql));
SQLCloseCursor(m_statement);
// All nulls.
SQLPrepare(m_statement, 0, 0);
SQLCloseCursor(m_statement);
}
TEST_F(api_robustness_test, sql_exec_direct) {
// There are no checks because we do not really care what is the result of these
// calls as long as they do not cause segmentation fault.
odbc_connect(get_basic_connection_string());
SQLCHAR sql[] = "select str from TBL_ALL_COLUMNS_SQL";
// Everything is ok.
SQLRETURN ret = SQLExecDirect(m_statement, sql, sizeof(sql) - 1);
ODBC_FAIL_ON_ERROR(ret, SQL_HANDLE_STMT, m_statement);
SQLCloseCursor(m_statement);
// Value length is null.
SQLExecDirect(m_statement, sql, 0);
SQLCloseCursor(m_statement);
// Value is null.
SQLExecDirect(m_statement, 0, SQL_NTS);
SQLCloseCursor(m_statement);
// All nulls.
SQLExecDirect(m_statement, 0, 0);
SQLCloseCursor(m_statement);
}
TEST_F(api_robustness_test, sql_tables) {
// There are no checks because we do not really care about the result of these
// calls as long as they do not cause segmentation fault.
odbc_connect(get_basic_connection_string());
SQLCHAR catalog_name[] = "";
SQLCHAR schema_name[] = "";
SQLCHAR table_name[] = "";
SQLCHAR table_type[] = "";
// Everything is ok.
SQLRETURN ret = SQLTables(m_statement, catalog_name, sizeof(catalog_name), schema_name, sizeof(schema_name),
table_name, sizeof(table_name), table_type, sizeof(table_type));
UNUSED_VALUE ret;
ODBC_FAIL_ON_ERROR(ret, SQL_HANDLE_STMT, m_statement);
// Sizes are nulls.
SQLTables(m_conn, catalog_name, 0, schema_name, 0, table_name, 0, table_type, 0);
// Values are nulls.
SQLTables(m_conn, 0, sizeof(catalog_name), 0, sizeof(schema_name), 0, sizeof(table_name), 0, sizeof(table_type));
// All nulls.
SQLTables(m_conn, 0, 0, 0, 0, 0, 0, 0, 0);
}
TEST_F(api_robustness_test, sql_columns) {
// There are no checks because we do not really care what is the result of these
// calls as long as they do not cause segmentation fault.
odbc_connect(get_basic_connection_string());
SQLCHAR catalog_name[] = "";
SQLCHAR schema_name[] = "";
SQLCHAR table_name[] = "";
SQLCHAR columnName[] = "";
// Everything is ok.
SQLRETURN ret = SQLColumns(m_statement, catalog_name, sizeof(catalog_name), schema_name, sizeof(schema_name),
table_name, sizeof(table_name), columnName, sizeof(columnName));
ODBC_FAIL_ON_ERROR(ret, SQL_HANDLE_STMT, m_statement);
// Sizes are nulls.
SQLColumns(m_conn, catalog_name, 0, schema_name, 0, table_name, 0, columnName, 0);
// Values are nulls.
SQLColumns(m_conn, 0, sizeof(catalog_name), 0, sizeof(schema_name), 0, sizeof(table_name), 0, sizeof(columnName));
// All nulls.
SQLColumns(m_conn, 0, 0, 0, 0, 0, 0, 0, 0);
}
TEST_F(api_robustness_test, sql_bind_col) {
// There are no checks because we do not really care what is the result of these
// calls as long as they do not cause segmentation fault.
odbc_connect(get_basic_connection_string());
SQLINTEGER ind1;
SQLLEN len1 = 0;
// Everything is ok.
SQLRETURN ret = SQLBindCol(m_statement, 1, SQL_C_SLONG, &ind1, sizeof(ind1), &len1);
ODBC_FAIL_ON_ERROR(ret, SQL_HANDLE_STMT, m_statement);
// Unsupported data types
for (short c_type : unsupported_c_types) {
ret = SQLBindCol(m_statement, 1, c_type, &ind1, sizeof(ind1), &len1);
ASSERT_EQ(ret, SQL_ERROR);
EXPECT_EQ(get_statement_error_state(), "HY003");
}
// Size is negative.
ret = SQLBindCol(m_statement, 1, SQL_C_SLONG, &ind1, -1, &len1);
ASSERT_EQ(ret, SQL_ERROR);
EXPECT_EQ(get_statement_error_state(), "HY090");
// Size is null.
SQLBindCol(m_statement, 1, SQL_C_SLONG, &ind1, 0, &len1);
// Res size is null.
SQLBindCol(m_statement, 2, SQL_C_SLONG, &ind1, sizeof(ind1), 0);
// Value is null.
SQLBindCol(m_statement, 3, SQL_C_SLONG, 0, sizeof(ind1), &len1);
// All nulls.
SQLBindCol(m_statement, 4, SQL_C_SLONG, 0, 0, 0);
}
TEST_F(api_robustness_test, sql_bind_parameter) {
// There are no checks because we do not really care what is the result of these
// calls as long as they do not cause segmentation fault.
odbc_connect(get_basic_connection_string());
SQLINTEGER ind1;
SQLLEN len1 = 0;
// Everything is ok.
SQLRETURN ret = SQLBindParameter(
m_statement, 1, SQL_PARAM_INPUT, SQL_C_SLONG, SQL_INTEGER, 100, 100, &ind1, sizeof(ind1), &len1);
ODBC_FAIL_ON_ERROR(ret, SQL_HANDLE_STMT, m_statement);
// Unsupported parameter type: output
SQLBindParameter(m_statement, 2, SQL_PARAM_OUTPUT, SQL_C_SLONG, SQL_INTEGER, 100, 100, &ind1, sizeof(ind1), &len1);
EXPECT_EQ(get_statement_error_state(), "HY105");
// Unsupported parameter type: input/output
SQLBindParameter(
m_statement, 2, SQL_PARAM_INPUT_OUTPUT, SQL_C_SLONG, SQL_INTEGER, 100, 100, &ind1, sizeof(ind1), &len1);
EXPECT_EQ(get_statement_error_state(), "HY105");
// Unsupported data types
for (short sql_type : unsupported_sql_types) {
ret = SQLBindParameter(
m_statement, 2, SQL_PARAM_INPUT, SQL_C_SLONG, sql_type, 100, 100, &ind1, sizeof(ind1), &len1);
ASSERT_EQ(ret, SQL_ERROR);
EXPECT_EQ(get_statement_error_state(), "HYC00");
}
// Size is null.
SQLBindParameter(m_statement, 2, SQL_PARAM_INPUT, SQL_C_SLONG, SQL_INTEGER, 100, 100, &ind1, 0, &len1);
// Res size is null.
SQLBindParameter(m_statement, 3, SQL_PARAM_INPUT, SQL_C_SLONG, SQL_INTEGER, 100, 100, &ind1, sizeof(ind1), 0);
// Value is null.
SQLBindParameter(m_statement, 4, SQL_PARAM_INPUT, SQL_C_SLONG, SQL_INTEGER, 100, 100, 0, sizeof(ind1), &len1);
// All nulls.
SQLBindParameter(m_statement, 5, SQL_PARAM_INPUT, SQL_C_SLONG, SQL_INTEGER, 100, 100, 0, 0, 0);
}
TEST_F(api_robustness_test, sql_native_sql) {
// There are no checks because we do not really care what is the result of these
// calls as long as they do not cause segmentation fault.
odbc_connect(get_basic_connection_string());
SQLCHAR sql[] = "select str from TBL_ALL_COLUMNS_SQL";
SQLCHAR buffer[ODBC_BUFFER_SIZE];
SQLINTEGER resLen = 0;
// Everything is ok.
SQLRETURN ret = SQLNativeSql(m_conn, sql, sizeof(sql) - 1, buffer, sizeof(buffer), &resLen);
ODBC_FAIL_ON_ERROR(ret, SQL_HANDLE_STMT, m_statement);
// Value size is null.
SQLNativeSql(m_conn, sql, 0, buffer, sizeof(buffer), &resLen);
// Buffer size is null.
SQLNativeSql(m_conn, sql, sizeof(sql) - 1, buffer, 0, &resLen);
// Res size is null.
SQLNativeSql(m_conn, sql, sizeof(sql) - 1, buffer, sizeof(buffer), 0);
// Value is null.
SQLNativeSql(m_conn, sql, 0, buffer, sizeof(buffer), &resLen);
// Buffer is null.
SQLNativeSql(m_conn, sql, sizeof(sql) - 1, 0, sizeof(buffer), &resLen);
// All nulls.
SQLNativeSql(m_conn, sql, 0, 0, 0, 0);
}
TEST_F(api_robustness_test, sql_col_attribute) {
// There are no checks because we do not really care what is the result of these
// calls as long as they do not cause segmentation fault.
odbc_connect(get_basic_connection_string());
SQLCHAR sql[] = "select str from TBL_ALL_COLUMNS_SQL";
SQLRETURN ret = SQLExecDirect(m_statement, sql, sizeof(sql) - 1);
ODBC_FAIL_ON_ERROR(ret, SQL_HANDLE_STMT, m_statement);
SQLCHAR buffer[ODBC_BUFFER_SIZE];
SQLSMALLINT resLen = 0;
SQLLEN numericAttr = 0;
// Everything is ok. Character attribute.
ret = SQLColAttribute(m_statement, 1, SQL_COLUMN_TABLE_NAME, buffer, sizeof(buffer), &resLen, &numericAttr);
ODBC_FAIL_ON_ERROR(ret, SQL_HANDLE_STMT, m_statement);
// Everything is ok. Numeric attribute.
ret = SQLColAttribute(m_statement, 1, SQL_DESC_COUNT, buffer, sizeof(buffer), &resLen, &numericAttr);
ODBC_FAIL_ON_ERROR(ret, SQL_HANDLE_STMT, m_statement);
SQLColAttribute(m_statement, 1, SQL_COLUMN_TABLE_NAME, buffer, sizeof(buffer), &resLen, 0);
SQLColAttribute(m_statement, 1, SQL_COLUMN_TABLE_NAME, buffer, sizeof(buffer), 0, &numericAttr);
SQLColAttribute(m_statement, 1, SQL_COLUMN_TABLE_NAME, buffer, 0, &resLen, &numericAttr);
SQLColAttribute(m_statement, 1, SQL_COLUMN_TABLE_NAME, 0, sizeof(buffer), &resLen, &numericAttr);
SQLColAttribute(m_statement, 1, SQL_COLUMN_TABLE_NAME, 0, 0, 0, 0);
SQLColAttribute(m_statement, 1, SQL_DESC_COUNT, buffer, sizeof(buffer), &resLen, 0);
SQLColAttribute(m_statement, 1, SQL_DESC_COUNT, buffer, sizeof(buffer), 0, &numericAttr);
SQLColAttribute(m_statement, 1, SQL_DESC_COUNT, buffer, 0, &resLen, &numericAttr);
SQLColAttribute(m_statement, 1, SQL_DESC_COUNT, 0, sizeof(buffer), &resLen, &numericAttr);
SQLColAttribute(m_statement, 1, SQL_DESC_COUNT, 0, 0, 0, 0);
}
TEST_F(api_robustness_test, sql_describe_col) {
// There are no checks because we do not really care what is the result of these
// calls as long as they do not cause segmentation fault.
odbc_connect(get_basic_connection_string());
SQLCHAR sql[] = "select str from TBL_ALL_COLUMNS_SQL";
SQLRETURN ret = SQLExecDirect(m_statement, sql, sizeof(sql) - 1);
ODBC_FAIL_ON_ERROR(ret, SQL_HANDLE_STMT, m_statement);
SQLCHAR columnName[ODBC_BUFFER_SIZE];
SQLSMALLINT columnNameLen = 0;
SQLSMALLINT dataType = 0;
SQLULEN columnSize = 0;
SQLSMALLINT decimalDigits = 0;
SQLSMALLINT nullable = 0;
// Everything is ok.
ret = SQLDescribeCol(m_statement, 1, columnName, sizeof(columnName), &columnNameLen, &dataType, &columnSize,
&decimalDigits, &nullable);
ODBC_FAIL_ON_ERROR(ret, SQL_HANDLE_STMT, m_statement);
SQLDescribeCol(
m_statement, 1, 0, sizeof(columnName), &columnNameLen, &dataType, &columnSize, &decimalDigits, &nullable);
SQLDescribeCol(m_statement, 1, columnName, 0, &columnNameLen, &dataType, &columnSize, &decimalDigits, &nullable);
SQLDescribeCol(
m_statement, 1, columnName, sizeof(columnName), 0, &dataType, &columnSize, &decimalDigits, &nullable);
SQLDescribeCol(
m_statement, 1, columnName, sizeof(columnName), &columnNameLen, 0, &columnSize, &decimalDigits, &nullable);
SQLDescribeCol(
m_statement, 1, columnName, sizeof(columnName), &columnNameLen, &dataType, 0, &decimalDigits, &nullable);
SQLDescribeCol(
m_statement, 1, columnName, sizeof(columnName), &columnNameLen, &dataType, &columnSize, 0, &nullable);
SQLDescribeCol(
m_statement, 1, columnName, sizeof(columnName), &columnNameLen, &dataType, &columnSize, &decimalDigits, 0);
SQLDescribeCol(m_statement, 1, 0, 0, 0, 0, 0, 0, 0);
}
TEST_F(api_robustness_test, sql_row_count) {
// There are no checks because we do not really care what is the result of these
// calls as long as they do not cause segmentation fault.
odbc_connect(get_basic_connection_string());
SQLCHAR sql[] = "select str from TBL_ALL_COLUMNS_SQL";
SQLRETURN ret = SQLExecDirect(m_statement, sql, SQL_NTS);
ODBC_FAIL_ON_ERROR(ret, SQL_HANDLE_STMT, m_statement);
SQLLEN rows = 0;
// Everything is ok.
ret = SQLRowCount(m_statement, &rows);
ODBC_FAIL_ON_ERROR(ret, SQL_HANDLE_STMT, m_statement);
SQLRowCount(m_statement, 0);
}
TEST_F(api_robustness_test, sql_foreign_keys) {
// There are no checks because we do not really care what is the result of these
// calls as long as they do not cause segmentation fault.
odbc_connect(get_basic_connection_string());
SQLCHAR catalog_name[] = "";
SQLCHAR schema_name[] = "cache";
SQLCHAR table_name[] = "TestType";
// Everything is ok.
SQLRETURN ret = SQLForeignKeys(m_statement, catalog_name, sizeof(catalog_name), schema_name, sizeof(schema_name),
table_name, sizeof(table_name), catalog_name, sizeof(catalog_name), schema_name, sizeof(schema_name),
table_name, sizeof(table_name));
ODBC_FAIL_ON_ERROR(ret, SQL_HANDLE_STMT, m_statement);
SQLCloseCursor(m_statement);
SQLForeignKeys(m_statement, 0, sizeof(catalog_name), schema_name, sizeof(schema_name), table_name,
sizeof(table_name), catalog_name, sizeof(catalog_name), schema_name, sizeof(schema_name), table_name,
sizeof(table_name));
SQLCloseCursor(m_statement);
SQLForeignKeys(m_statement, catalog_name, 0, schema_name, sizeof(schema_name), table_name, sizeof(table_name),
catalog_name, sizeof(catalog_name), schema_name, sizeof(schema_name), table_name, sizeof(table_name));
SQLCloseCursor(m_statement);
SQLForeignKeys(m_statement, catalog_name, sizeof(catalog_name), 0, sizeof(schema_name), table_name,
sizeof(table_name), catalog_name, sizeof(catalog_name), schema_name, sizeof(schema_name), table_name,
sizeof(table_name));
SQLCloseCursor(m_statement);
SQLForeignKeys(m_statement, catalog_name, sizeof(catalog_name), schema_name, 0, table_name, sizeof(table_name),
catalog_name, sizeof(catalog_name), schema_name, sizeof(schema_name), table_name, sizeof(table_name));
SQLCloseCursor(m_statement);
SQLForeignKeys(m_statement, catalog_name, sizeof(catalog_name), schema_name, sizeof(schema_name), 0,
sizeof(table_name), catalog_name, sizeof(catalog_name), schema_name, sizeof(schema_name), table_name,
sizeof(table_name));
SQLCloseCursor(m_statement);
SQLForeignKeys(m_statement, catalog_name, sizeof(catalog_name), schema_name, sizeof(schema_name), table_name, 0,
catalog_name, sizeof(catalog_name), schema_name, sizeof(schema_name), table_name, sizeof(table_name));
SQLCloseCursor(m_statement);
SQLForeignKeys(m_statement, catalog_name, sizeof(catalog_name), schema_name, sizeof(schema_name), table_name,
sizeof(table_name), 0, sizeof(catalog_name), schema_name, sizeof(schema_name), table_name, sizeof(table_name));
SQLCloseCursor(m_statement);
SQLForeignKeys(m_statement, catalog_name, sizeof(catalog_name), schema_name, sizeof(schema_name), table_name,
sizeof(table_name), catalog_name, 0, schema_name, sizeof(schema_name), table_name, sizeof(table_name));
SQLCloseCursor(m_statement);
SQLForeignKeys(m_statement, catalog_name, sizeof(catalog_name), schema_name, sizeof(schema_name), table_name,
sizeof(table_name), catalog_name, sizeof(catalog_name), 0, sizeof(schema_name), table_name, sizeof(table_name));
SQLCloseCursor(m_statement);
SQLForeignKeys(m_statement, catalog_name, sizeof(catalog_name), schema_name, sizeof(schema_name), table_name,
sizeof(table_name), catalog_name, sizeof(catalog_name), schema_name, 0, table_name, sizeof(table_name));
SQLCloseCursor(m_statement);
SQLForeignKeys(m_statement, catalog_name, sizeof(catalog_name), schema_name, sizeof(schema_name), table_name,
sizeof(table_name), catalog_name, sizeof(catalog_name), schema_name, sizeof(schema_name), 0,
sizeof(table_name));
SQLCloseCursor(m_statement);
SQLForeignKeys(m_statement, catalog_name, sizeof(catalog_name), schema_name, sizeof(schema_name), table_name,
sizeof(table_name), catalog_name, sizeof(catalog_name), schema_name, sizeof(schema_name), table_name, 0);
SQLCloseCursor(m_statement);
SQLForeignKeys(m_statement, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0);
SQLCloseCursor(m_statement);
}
TEST_F(api_robustness_test, sql_get_stmt_attr) {
// There are no checks because we do not really care what is the result of these
// calls as long as they do not cause segmentation fault.
odbc_connect(get_basic_connection_string());
SQLCHAR buffer[ODBC_BUFFER_SIZE];
SQLINTEGER resLen = 0;
// Everything is ok.
SQLRETURN ret = SQLGetStmtAttr(m_statement, SQL_ATTR_ROW_ARRAY_SIZE, buffer, sizeof(buffer), &resLen);
ODBC_FAIL_ON_ERROR(ret, SQL_HANDLE_STMT, m_statement);
SQLGetStmtAttr(m_statement, SQL_ATTR_ROW_ARRAY_SIZE, 0, sizeof(buffer), &resLen);
SQLGetStmtAttr(m_statement, SQL_ATTR_ROW_ARRAY_SIZE, buffer, 0, &resLen);
SQLGetStmtAttr(m_statement, SQL_ATTR_ROW_ARRAY_SIZE, buffer, sizeof(buffer), 0);
SQLGetStmtAttr(m_statement, SQL_ATTR_ROW_ARRAY_SIZE, 0, 0, 0);
}
TEST_F(api_robustness_test, sql_set_stmt_attr) {
// There are no checks because we do not really care what is the result of these
// calls as long as they do not cause segmentation fault.
odbc_connect(get_basic_connection_string());
SQLULEN val = 1;
// Everything is ok.
SQLRETURN ret =
SQLSetStmtAttr(m_statement, SQL_ATTR_ROW_ARRAY_SIZE, reinterpret_cast<SQLPOINTER>(val), sizeof(val));
ODBC_FAIL_ON_ERROR(ret, SQL_HANDLE_STMT, m_statement);
SQLSetStmtAttr(m_statement, SQL_ATTR_ROW_ARRAY_SIZE, 0, sizeof(val));
SQLSetStmtAttr(m_statement, SQL_ATTR_ROW_ARRAY_SIZE, reinterpret_cast<SQLPOINTER>(val), 0);
SQLSetStmtAttr(m_statement, SQL_ATTR_ROW_ARRAY_SIZE, 0, 0);
}
TEST_F(api_robustness_test, sql_primary_keys) {
// There are no checks because we do not really care what is the result of these
// calls as long as they do not cause segmentation fault.
odbc_connect(get_basic_connection_string());
SQLCHAR catalog_name[] = "";
SQLCHAR schema_name[] = "cache";
SQLCHAR table_name[] = "TestType";
// Everything is ok.
SQLRETURN ret = SQLPrimaryKeys(m_statement, catalog_name, sizeof(catalog_name), schema_name, sizeof(schema_name),
table_name, sizeof(table_name));
ODBC_FAIL_ON_ERROR(ret, SQL_HANDLE_STMT, m_statement);
SQLPrimaryKeys(
m_statement, 0, sizeof(catalog_name), schema_name, sizeof(schema_name), table_name, sizeof(table_name));
SQLPrimaryKeys(m_statement, catalog_name, 0, schema_name, sizeof(schema_name), table_name, sizeof(table_name));
SQLPrimaryKeys(
m_statement, catalog_name, sizeof(catalog_name), 0, sizeof(schema_name), table_name, sizeof(table_name));
SQLPrimaryKeys(m_statement, catalog_name, sizeof(catalog_name), schema_name, 0, table_name, sizeof(table_name));
SQLPrimaryKeys(
m_statement, catalog_name, sizeof(catalog_name), schema_name, sizeof(schema_name), 0, sizeof(table_name));
SQLPrimaryKeys(m_statement, catalog_name, sizeof(catalog_name), schema_name, sizeof(schema_name), table_name, 0);
SQLPrimaryKeys(m_statement, 0, 0, 0, 0, 0, 0);
}
TEST_F(api_robustness_test, sql_num_params) {
// There are no checks because we do not really care what is the result of these
// calls as long as they do not cause segmentation fault.
odbc_connect(get_basic_connection_string());
SQLCHAR sql[] = "select str from TBL_ALL_COLUMNS_SQL";
// Everything is ok.
SQLRETURN ret = SQLPrepare(m_statement, sql, sizeof(sql));
ODBC_FAIL_ON_ERROR(ret, SQL_HANDLE_STMT, m_statement);
SQLSMALLINT params;
// Everything is ok.
ret = SQLNumParams(m_statement, &params);
ODBC_FAIL_ON_ERROR(ret, SQL_HANDLE_STMT, m_statement);
SQLNumParams(m_statement, 0);
}
TEST_F(api_robustness_test, sql_num_params_escaped) {
// There are no checks because we do not really care what is the result of these
// calls as long as they do not cause segmentation fault.
odbc_connect(get_basic_connection_string());
SQLCHAR sql[] = "SELECT {fn NOW()}";
// Everything is ok.
SQLRETURN ret = SQLPrepare(m_statement, sql, sizeof(sql));
ODBC_FAIL_ON_ERROR(ret, SQL_HANDLE_STMT, m_statement);
SQLSMALLINT params;
// Everything is ok.
ret = SQLNumParams(m_statement, &params);
ODBC_FAIL_ON_ERROR(ret, SQL_HANDLE_STMT, m_statement);
SQLNumParams(m_statement, 0);
}
TEST_F(api_robustness_test, sql_get_diag_field) {
// There are no checks because we do not really care what is the result of these
// calls as long as they do not cause segmentation fault.
odbc_connect(get_basic_connection_string());
// Should fail.
SQLRETURN ret = SQLGetTypeInfo(m_statement, SQL_INTERVAL_MONTH);
ASSERT_EQ(ret, SQL_ERROR);
SQLCHAR buffer[ODBC_BUFFER_SIZE];
SQLSMALLINT resLen = 0;
// Everything is ok
ret = SQLGetDiagField(SQL_HANDLE_STMT, m_statement, 1, SQL_DIAG_MESSAGE_TEXT, buffer, sizeof(buffer), &resLen);
ASSERT_EQ(ret, SQL_SUCCESS);
SQLGetDiagField(SQL_HANDLE_STMT, m_statement, 1, SQL_DIAG_MESSAGE_TEXT, 0, sizeof(buffer), &resLen);
SQLGetDiagField(SQL_HANDLE_STMT, m_statement, 1, SQL_DIAG_MESSAGE_TEXT, buffer, 0, &resLen);
SQLGetDiagField(SQL_HANDLE_STMT, m_statement, 1, SQL_DIAG_MESSAGE_TEXT, buffer, sizeof(buffer), 0);
SQLGetDiagField(SQL_HANDLE_STMT, m_statement, 1, SQL_DIAG_MESSAGE_TEXT, 0, 0, 0);
}
TEST_F(api_robustness_test, sql_get_diag_rec) {
odbc_connect(get_basic_connection_string());
SQLCHAR state[ODBC_BUFFER_SIZE];
SQLINTEGER nativeError = 0;
SQLCHAR message[ODBC_BUFFER_SIZE];
SQLSMALLINT messageLen = 0;
// Generating error.
SQLRETURN ret = SQLGetTypeInfo(m_statement, SQL_INTERVAL_MONTH);
ASSERT_EQ(ret, SQL_ERROR);
// Everything is ok.
ret = SQLGetDiagRec(SQL_HANDLE_STMT, m_statement, 1, state, &nativeError, message, sizeof(message), &messageLen);
ASSERT_EQ(ret, SQL_SUCCESS);
// Should return error.
ret = SQLGetDiagRec(SQL_HANDLE_STMT, m_statement, 1, state, &nativeError, message, -1, &messageLen);
ASSERT_EQ(ret, SQL_ERROR);
// Should return message length.
ret = SQLGetDiagRec(SQL_HANDLE_STMT, m_statement, 1, state, &nativeError, message, 1, &messageLen);
ASSERT_EQ(ret, SQL_SUCCESS_WITH_INFO);
// There are no checks because we do not really care what is the result of these
// calls as long as they do not cause segmentation fault.
SQLGetDiagRec(SQL_HANDLE_STMT, m_statement, 1, 0, &nativeError, message, sizeof(message), &messageLen);
SQLGetDiagRec(SQL_HANDLE_STMT, m_statement, 1, state, 0, message, sizeof(message), &messageLen);
SQLGetDiagRec(SQL_HANDLE_STMT, m_statement, 1, state, &nativeError, 0, sizeof(message), &messageLen);
SQLGetDiagRec(SQL_HANDLE_STMT, m_statement, 1, state, &nativeError, message, 0, &messageLen);
SQLGetDiagRec(SQL_HANDLE_STMT, m_statement, 1, state, &nativeError, message, sizeof(message), 0);
SQLGetDiagRec(SQL_HANDLE_STMT, m_statement, 1, 0, 0, 0, 0, 0);
}
TEST_F(api_robustness_test, sql_get_env_attr) {
// There are no checks because we do not really care what is the result of these
// calls as long as they do not cause segmentation fault.
odbc_connect(get_basic_connection_string());
SQLCHAR buffer[ODBC_BUFFER_SIZE];
SQLINTEGER resLen = 0;
// Everything is ok.
SQLRETURN ret = SQLGetEnvAttr(m_env, SQL_ATTR_ODBC_VERSION, buffer, sizeof(buffer), &resLen);
ODBC_FAIL_ON_ERROR(ret, SQL_HANDLE_ENV, m_env);
SQLGetEnvAttr(m_env, SQL_ATTR_ODBC_VERSION, 0, sizeof(buffer), &resLen);
SQLGetEnvAttr(m_env, SQL_ATTR_ODBC_VERSION, buffer, 0, &resLen);
SQLGetEnvAttr(m_env, SQL_ATTR_ODBC_VERSION, buffer, sizeof(buffer), 0);
SQLGetEnvAttr(m_env, SQL_ATTR_ODBC_VERSION, 0, 0, 0);
}
TEST_F(api_robustness_test, sql_special_columns) {
// There are no checks because we do not really care what is the result of these
// calls as long as they do not cause segmentation fault.
odbc_connect(get_basic_connection_string());
SQLCHAR catalog_name[] = "";
SQLCHAR schema_name[] = "cache";
SQLCHAR table_name[] = "TestType";
// Everything is ok.
SQLRETURN ret = SQLSpecialColumns(m_statement, SQL_BEST_ROWID, catalog_name, sizeof(catalog_name), schema_name,
sizeof(schema_name), table_name, sizeof(table_name), SQL_SCOPE_CURROW, SQL_NO_NULLS);
ODBC_FAIL_ON_ERROR(ret, SQL_HANDLE_STMT, m_statement);
SQLCloseCursor(m_statement);
SQLSpecialColumns(m_statement, SQL_BEST_ROWID, 0, sizeof(catalog_name), schema_name, sizeof(schema_name),
table_name, sizeof(table_name), SQL_SCOPE_CURROW, SQL_NO_NULLS);
SQLCloseCursor(m_statement);
SQLSpecialColumns(m_statement, SQL_BEST_ROWID, catalog_name, 0, schema_name, sizeof(schema_name), table_name,
sizeof(table_name), SQL_SCOPE_CURROW, SQL_NO_NULLS);
SQLCloseCursor(m_statement);
SQLSpecialColumns(m_statement, SQL_BEST_ROWID, catalog_name, sizeof(catalog_name), 0, sizeof(schema_name),
table_name, sizeof(table_name), SQL_SCOPE_CURROW, SQL_NO_NULLS);
SQLCloseCursor(m_statement);
SQLSpecialColumns(m_statement, SQL_BEST_ROWID, catalog_name, sizeof(catalog_name), schema_name, 0, table_name,
sizeof(table_name), SQL_SCOPE_CURROW, SQL_NO_NULLS);
SQLCloseCursor(m_statement);
SQLSpecialColumns(m_statement, SQL_BEST_ROWID, catalog_name, sizeof(catalog_name), schema_name, sizeof(schema_name),
0, sizeof(table_name), SQL_SCOPE_CURROW, SQL_NO_NULLS);
SQLCloseCursor(m_statement);
SQLSpecialColumns(m_statement, SQL_BEST_ROWID, catalog_name, sizeof(catalog_name), schema_name, sizeof(schema_name),
table_name, 0, SQL_SCOPE_CURROW, SQL_NO_NULLS);
SQLCloseCursor(m_statement);
SQLSpecialColumns(m_statement, SQL_BEST_ROWID, 0, 0, 0, 0, 0, 0, SQL_SCOPE_CURROW, SQL_NO_NULLS);
SQLCloseCursor(m_statement);
}
TEST_F(api_robustness_test, sql_error) {
// There are no checks because we do not really care what is the result of these
// calls as long as they do not cause segmentation fault.
odbc_connect(get_basic_connection_string());
SQLCHAR state[6] = {0};
SQLINTEGER nativeCode = 0;
SQLCHAR message[ODBC_BUFFER_SIZE] = {0};
SQLSMALLINT messageLen = 0;
// Everything is ok.
SQLRETURN ret = SQLError(m_env, 0, 0, state, &nativeCode, message, sizeof(message), &messageLen);
if (ret != SQL_SUCCESS && ret != SQL_NO_DATA)
FAIL() << "Unexpected error";
ret = SQLError(0, m_conn, 0, state, &nativeCode, message, sizeof(message), &messageLen);
if (ret != SQL_SUCCESS && ret != SQL_NO_DATA)
FAIL() << "Unexpected error";
ret = SQLError(0, 0, m_statement, state, &nativeCode, message, sizeof(message), &messageLen);
if (ret != SQL_SUCCESS && ret != SQL_NO_DATA)
FAIL() << "Unexpected error";
SQLError(0, 0, 0, state, &nativeCode, message, sizeof(message), &messageLen);
SQLError(0, 0, m_statement, 0, &nativeCode, message, sizeof(message), &messageLen);
SQLError(0, 0, m_statement, state, 0, message, sizeof(message), &messageLen);
SQLError(0, 0, m_statement, state, &nativeCode, 0, sizeof(message), &messageLen);
SQLError(0, 0, m_statement, state, &nativeCode, message, 0, &messageLen);
SQLError(0, 0, m_statement, state, &nativeCode, message, sizeof(message), 0);
SQLError(0, 0, m_statement, 0, 0, 0, 0, 0);
SQLError(0, 0, 0, 0, 0, 0, 0, 0);
}
TEST_F(api_robustness_test, sql_diagnostic_records) {
odbc_connect(get_basic_connection_string());
SQLHANDLE hnd;
SQLRETURN ret = SQLAllocHandle(SQL_HANDLE_DESC, m_conn, &hnd);
ASSERT_EQ(ret, SQL_ERROR);
EXPECT_EQ(get_connection_error_state(), "IM001");
ret = SQLFreeStmt(m_statement, 4);
ASSERT_EQ(ret, SQL_ERROR);
EXPECT_EQ(get_statement_error_state(), "HY092");
}
TEST_F(api_robustness_test, many_fds) {
enum { FDS_NUM = 2000 };
std::FILE *fds[FDS_NUM];
for (auto &fd : fds)
fd = tmpfile();
odbc_connect(get_basic_connection_string());
for (auto fd : fds) {
if (fd)
fclose(fd);
}
}
TEST_F(api_robustness_test, reusing_connection_with_args) {
odbc_connect(get_basic_connection_string());
std::vector<std::int64_t> mem;
// Allocating a bunch of memory so the new page is allocated
mem.resize(1024 * 1024);
SQLRETURN ret = SQLBindParameter(m_statement, 1, SQL_PARAM_INPUT, SQL_C_SBIGINT, SQL_BIGINT, 0, 0, &mem.back(), 8, &mem.back());
if (!SQL_SUCCEEDED(ret))
FAIL() << get_odbc_error_message(SQL_HANDLE_STMT, m_statement);
SQLCHAR firstReq[] = "SELECT ?";
ret = SQLExecDirect(m_statement, firstReq, SQL_NTS);
if (!SQL_SUCCEEDED(ret))
FAIL() << get_odbc_error_message(SQL_HANDLE_STMT, m_statement);
// Un-binding parameter.
ret = SQLFreeStmt(m_statement, SQL_RESET_PARAMS);
if (!SQL_SUCCEEDED(ret))
FAIL() << get_odbc_error_message(SQL_HANDLE_STMT, m_statement);
// De-allocation happens here
mem = std::vector<std::int64_t>();
mem.reserve(1);
SQLCHAR secondReq[] = "SELECT 1";
SQLExecDirect(m_statement, secondReq, SQL_NTS);
}