RETCODE SQL_API OPENSEARCHAPI_GetInfo()

in sql-odbc/src/sqlodbc/info.c [31:927]


RETCODE SQL_API OPENSEARCHAPI_GetInfo(HDBC hdbc, SQLUSMALLINT fInfoType,
                              PTR rgbInfoValue, SQLSMALLINT cbInfoValueMax,
                              SQLSMALLINT *pcbInfoValue) {
    CSTR func = "OPENSEARCHAPI_GetInfo";
    ConnectionClass *conn = (ConnectionClass *)hdbc;
    ConnInfo *ci;
    const char *p = NULL;
    char tmp[MAX_INFO_STRING];
    SQLULEN len = 0, value = 0;
    RETCODE ret = SQL_ERROR;
    char odbcver[16];

    MYLOG(OPENSEARCH_TRACE, "entering...fInfoType=%d\n", fInfoType);

    if (!conn) {
        CC_log_error(func, NULL_STRING, NULL);
        return SQL_INVALID_HANDLE;
    }

    ci = &(conn->connInfo);

    switch (fInfoType) {
        case SQL_ACCESSIBLE_PROCEDURES: /* ODBC 1.0 */
            p = "N";
            break;

        case SQL_ACCESSIBLE_TABLES: /* ODBC 1.0 */
            p = "N";
            break;

        case SQL_ACTIVE_CONNECTIONS: /* ODBC 1.0 */
            len = 2;
            value = 0;
            break;

        case SQL_ACTIVE_STATEMENTS: /* ODBC 1.0 */
            len = 2;
            value = 0;
            break;

        case SQL_ALTER_TABLE: /* ODBC 2.0 */
            len = 4;
            value = SQL_AT_ADD_COLUMN | SQL_AT_DROP_COLUMN
                    | SQL_AT_ADD_COLUMN_SINGLE | SQL_AT_ADD_CONSTRAINT
                    | SQL_AT_ADD_TABLE_CONSTRAINT
                    | SQL_AT_CONSTRAINT_INITIALLY_DEFERRED
                    | SQL_AT_CONSTRAINT_INITIALLY_IMMEDIATE
                    | SQL_AT_CONSTRAINT_DEFERRABLE
                    | SQL_AT_DROP_TABLE_CONSTRAINT_RESTRICT
                    | SQL_AT_DROP_TABLE_CONSTRAINT_CASCADE
                    | SQL_AT_DROP_COLUMN_RESTRICT | SQL_AT_DROP_COLUMN_CASCADE;
            break;

        case SQL_BOOKMARK_PERSISTENCE: /* ODBC 2.0 */
            /* very simple bookmark support */
            len = 4;
            value = SQL_BP_SCROLL | SQL_BP_DELETE | SQL_BP_UPDATE
                    | SQL_BP_TRANSACTION;
            break;

        case SQL_COLUMN_ALIAS: /* ODBC 2.0 */
            p = "Y";
            break;

        case SQL_CONCAT_NULL_BEHAVIOR: /* ODBC 1.0 */
            len = 2;
            value = SQL_CB_NULL;
            break;

        case SQL_CONVERT_GUID:
        case SQL_CONVERT_SMALLINT:
        case SQL_CONVERT_TINYINT:
        case SQL_CONVERT_VARCHAR:
        case SQL_CONVERT_DECIMAL:
        case SQL_CONVERT_FLOAT:
        case SQL_CONVERT_NUMERIC:
        case SQL_CONVERT_DATE:
        case SQL_CONVERT_TIME:
        case SQL_CONVERT_BINARY:
        case SQL_CONVERT_LONGVARBINARY:
        case SQL_CONVERT_VARBINARY: /* ODBC 1.0 */
        case SQL_CONVERT_CHAR:
        case SQL_CONVERT_LONGVARCHAR:
#ifdef UNICODE_SUPPORT
        case SQL_CONVERT_WCHAR:
        case SQL_CONVERT_WLONGVARCHAR:
#endif /* UNICODE_SUPPORT */
            len = sizeof(SQLUINTEGER);
            value = 0; /* CONVERT is unavailable */
            break;

        case SQL_CONVERT_INTEGER: /* ODBC 1.0 */
            len = sizeof(SQLUINTEGER);
            value = SQL_CVT_INTEGER | SQL_CVT_BIT | SQL_CVT_WVARCHAR | SQL_CVT_DOUBLE | SQL_CVT_BIGINT | SQL_CVT_REAL;
            break;

        case SQL_CONVERT_BIT: /* ODBC 1.0 */
            len = sizeof(SQLUINTEGER);
            value = SQL_CVT_BIT | SQL_CVT_INTEGER | SQL_CVT_WVARCHAR | SQL_CVT_DOUBLE | SQL_CVT_BIGINT | SQL_CVT_REAL;
            break;

        case SQL_CONVERT_WVARCHAR: /* ODBC 1.0 */
            len = sizeof(SQLUINTEGER);
            value = SQL_CVT_WVARCHAR | SQL_CVT_INTEGER | SQL_CVT_DOUBLE | SQL_CVT_BIGINT | SQL_CVT_REAL;
            break;

        case SQL_CONVERT_DOUBLE: /* ODBC 1.0 */
            len = sizeof(SQLUINTEGER);
            value = SQL_CVT_DOUBLE | SQL_CVT_INTEGER | SQL_CVT_BIT | SQL_CVT_WVARCHAR | SQL_CVT_BIGINT | SQL_CVT_REAL;
            break;

        case SQL_CONVERT_BIGINT: /* ODBC 1.0 */
            len = sizeof(SQLUINTEGER);
            value = SQL_CVT_BIGINT | SQL_CVT_INTEGER | SQL_CVT_BIT | SQL_CVT_WVARCHAR | SQL_CVT_DOUBLE | SQL_CVT_REAL;
            break;

        case SQL_CONVERT_REAL: /* ODBC 1.0 */
            len = sizeof(SQLUINTEGER);
            value = SQL_CVT_REAL | SQL_CVT_INTEGER | SQL_CVT_BIT | SQL_CVT_WVARCHAR | SQL_CVT_DOUBLE | SQL_CVT_BIGINT;
            break;

        case SQL_CONVERT_TIMESTAMP: /* ODBC 1.0 */
            len = sizeof(SQLUINTEGER);
            value = SQL_CVT_TIMESTAMP | SQL_CVT_WVARCHAR;
            break;

        case SQL_CONVERT_FUNCTIONS: /* ODBC 1.0 */
            len = sizeof(SQLUINTEGER);
            value = SQL_FN_CVT_CAST;
            MYLOG(OPENSEARCH_DEBUG, "CONVERT_FUNCTIONS=" FORMAT_ULEN "\n", value);
            break;

        case SQL_CORRELATION_NAME: /* ODBC 1.0 */

            /*
             * Saying no correlation name makes Query not work right.
             * value = SQL_CN_NONE;
             */
            len = 2;
            value = SQL_CN_ANY;
            break;

        case SQL_CURSOR_COMMIT_BEHAVIOR: /* ODBC 1.0 */
            len = 2;
            value = SQL_CB_CLOSE;
            break;

        case SQL_CURSOR_ROLLBACK_BEHAVIOR: /* ODBC 1.0 */
            len = 2;
            value = SQL_CB_PRESERVE;
            break;

        case SQL_DATA_SOURCE_NAME: /* ODBC 1.0 */
            p = CC_get_DSN(conn);
            break;

        case SQL_DATA_SOURCE_READ_ONLY: /* ODBC 1.0 */
            p = "Y";
            break;

        case SQL_DATABASE_NAME: /* Support for old ODBC 1.0 Apps */

            /*
             * Returning the database name causes problems in MS Query. It
             * generates query like: "SELECT DISTINCT a FROM byronnbad3
             * bad3"
             *
             * p = CC_get_database(conn);
             */
            p = CurrCatString(conn);
            break;

        case SQL_DBMS_NAME: /* ODBC 1.0 */
            p = "OpenSearch";
            break;

        case SQL_DBMS_VER: /* ODBC 1.0 */
            STRCPY_FIXED(tmp, conn->opensearch_version);
            p = tmp;
            break;

        case SQL_DEFAULT_TXN_ISOLATION: /* ODBC 1.0 */
            len = 4;
            if (0 == conn->default_isolation)
                conn->isolation = CC_get_isolation(conn);
            value = conn->default_isolation;
            break;

        case SQL_DRIVER_NAME: /* ODBC 1.0 */
            p = DRIVER_FILE_NAME;
            break;

        case SQL_DRIVER_ODBC_VER:
            SPRINTF_FIXED(odbcver, "%02x.%02x", ODBCVER / 256, ODBCVER % 256);
            /* p = DRIVER_ODBC_VER; */
            p = odbcver;
            break;

        case SQL_DRIVER_VER: /* ODBC 1.0 */
            p = OPENSEARCHDRIVERVERSION;
            break;

        case SQL_EXPRESSIONS_IN_ORDERBY: /* ODBC 1.0 */
            p = "Y";
            break;

        case SQL_FETCH_DIRECTION: /* ODBC 1.0 */
            len = 4;
            value = (SQL_FD_FETCH_NEXT | SQL_FD_FETCH_FIRST | SQL_FD_FETCH_LAST
                     | SQL_FD_FETCH_PRIOR | SQL_FD_FETCH_ABSOLUTE
                     | SQL_FD_FETCH_RELATIVE | SQL_FD_FETCH_BOOKMARK);
            break;

        case SQL_FILE_USAGE: /* ODBC 2.0 */
            len = 2;
            value = SQL_FILE_NOT_SUPPORTED;
            break;

        case SQL_GETDATA_EXTENSIONS: /* ODBC 2.0 */
            len = 4;
            value = (SQL_GD_ANY_COLUMN | SQL_GD_ANY_ORDER | SQL_GD_BOUND
                     | SQL_GD_BLOCK);
            break;

        case SQL_GROUP_BY: /* ODBC 2.0 */
            len = 2;
            value = SQL_GB_GROUP_BY_CONTAINS_SELECT;
            break;

        case SQL_IDENTIFIER_CASE: /* ODBC 1.0 */

            /*
             * are identifiers case-sensitive (yes, but only when quoted.
             * If not quoted, they default to lowercase)
             */
            len = 2;
            value = SQL_IC_LOWER;
            break;

        case SQL_IDENTIFIER_QUOTE_CHAR: /* ODBC 1.0 */
            /* the character used to quote "identifiers" */
            p = "`";
            break;

        case SQL_KEYWORDS: /* ODBC 2.0 */
            p = NULL_STRING;
            break;

        case SQL_LIKE_ESCAPE_CLAUSE: /* ODBC 2.0 */
            p = "Y";
            break;

        case SQL_LOCK_TYPES: /* ODBC 2.0 */
            len = 4;
            value = SQL_LCK_NO_CHANGE;
            break;

        case SQL_MAX_BINARY_LITERAL_LEN: /* ODBC 2.0 */
            len = 4;
            value = 0;
            break;

        case SQL_MAX_CHAR_LITERAL_LEN: /* ODBC 2.0 */
            len = 4;
            value = 0;
            break;

        case SQL_MAX_COLUMN_NAME_LEN: /* ODBC 1.0 */
            len = 2;
            value = CC_get_max_idlen(conn);
            if (0 == value)
                value = NAMEDATALEN_V73 - 1;
            break;

        case SQL_MAX_COLUMNS_IN_GROUP_BY: /* ODBC 2.0 */
            len = 2;
            value = 0;
            break;

        case SQL_MAX_COLUMNS_IN_INDEX: /* ODBC 2.0 */
            len = 2;
            value = 0;
            break;

        case SQL_MAX_COLUMNS_IN_ORDER_BY: /* ODBC 2.0 */
            len = 2;
            value = 0;
            break;

        case SQL_MAX_COLUMNS_IN_SELECT: /* ODBC 2.0 */
            len = 2;
            value = 0;
            break;

        case SQL_MAX_COLUMNS_IN_TABLE: /* ODBC 2.0 */
            len = 2;
            value = 0;
            break;

        case SQL_MAX_CURSOR_NAME_LEN: /* ODBC 1.0 */
            len = 2;
            value = MAX_CURSOR_LEN;
            break;

        case SQL_MAX_INDEX_SIZE: /* ODBC 2.0 */
            len = 4;
            value = 0;
            break;

        case SQL_MAX_OWNER_NAME_LEN: /* ODBC 1.0 */
            len = 2;
            value = 0;
            break;

        case SQL_MAX_PROCEDURE_NAME_LEN: /* ODBC 1.0 */
            len = 2;
            value = 0;
            break;

        case SQL_MAX_QUALIFIER_NAME_LEN: /* ODBC 1.0 */
            len = 2;
            value = 0;
            break;

        case SQL_MAX_ROW_SIZE: /* ODBC 2.0 */
            len = 4;
            /* No limit with tuptoaster in 7.1+ */
            value = 0;
            break;

        case SQL_MAX_STATEMENT_LEN: /* ODBC 2.0 */
            len = 4;
            value = 0;
            break;

        case SQL_MAX_TABLE_NAME_LEN: /* ODBC 1.0 */
            len = 2;
            if (OPENSEARCH_VERSION_GT(conn, 7.4))
                value = CC_get_max_idlen(conn);
#ifdef MAX_TABLE_LEN
            else
                value = MAX_TABLE_LEN;
#endif /* MAX_TABLE_LEN */
            if (0 == value)
                value = NAMEDATALEN_V73 - 1;
            break;

        case SQL_MAX_TABLES_IN_SELECT: /* ODBC 2.0 */
            len = 2;
            value = 0;
            break;

        case SQL_MAX_USER_NAME_LEN:
            len = 2;
            value = 0;
            break;

        case SQL_MULT_RESULT_SETS: /* ODBC 1.0 */
            /* Don't support multiple result sets but say yes anyway? */
            p = "Y";
            break;

        case SQL_MULTIPLE_ACTIVE_TXN: /* ODBC 1.0 */
            p = "Y";
            break;

        case SQL_NEED_LONG_DATA_LEN: /* ODBC 2.0 */

            /*
             * Don't need the length, SQLPutData can handle any size and
             * multiple calls
             */
            p = "N";
            break;

        case SQL_NON_NULLABLE_COLUMNS: /* ODBC 1.0 */
            len = 2;
            value = SQL_NNC_NON_NULL;
            break;

        case SQL_NULL_COLLATION: /* ODBC 2.0 */
            /* where are nulls sorted? */
            len = 2;
            value = SQL_NC_HIGH;
            break;

        case SQL_NUMERIC_FUNCTIONS: /* ODBC 1.0 */
            len = 4;
            value = SQL_FN_NUM_ABS | SQL_FN_NUM_ATAN | SQL_FN_NUM_ATAN2
                    | SQL_FN_NUM_COS | SQL_FN_NUM_COT | SQL_FN_NUM_DEGREES
                    | SQL_FN_NUM_FLOOR | SQL_FN_NUM_LOG | SQL_FN_NUM_LOG10
                    | SQL_FN_NUM_PI | SQL_FN_NUM_POWER | SQL_FN_NUM_RADIANS
                    | SQL_FN_NUM_ROUND | SQL_FN_NUM_SIGN | SQL_FN_NUM_SIN
                    | SQL_FN_NUM_SQRT | SQL_FN_NUM_TAN;
            break;

        case SQL_ODBC_API_CONFORMANCE: /* ODBC 1.0 */
            len = 2;
            value = SQL_OAC_LEVEL1;
            break;

        case SQL_ODBC_SAG_CLI_CONFORMANCE: /* ODBC 1.0 */
            len = 2;
            value = SQL_OSCC_NOT_COMPLIANT;
            break;

        case SQL_ODBC_SQL_CONFORMANCE: /* ODBC 1.0 */
            len = 2;
            value = SQL_OSC_CORE;
            break;

        case SQL_ODBC_SQL_OPT_IEF: /* ODBC 1.0 */
            p = "N";
            break;

        case SQL_OJ_CAPABILITIES: /* ODBC 2.01 */
            len = 4;
            value = SQL_OJ_LEFT | SQL_OJ_RIGHT | SQL_OJ_NOT_ORDERED
                    | SQL_OJ_ALL_COMPARISON_OPS;
            break;

        case SQL_ORDER_BY_COLUMNS_IN_SELECT: /* ODBC 2.0 */
            p = "Y";
            break;

        case SQL_OUTER_JOINS: /* ODBC 1.0 */
            p = "Y";
            break;

        case SQL_OWNER_TERM: /* ODBC 1.0 */
            p = "";
            break;

        case SQL_OWNER_USAGE: /* ODBC 2.0 */
            // OpenSearch does not support schemas.
            // This will disable showing an empty schema box in Tableau.
            len = 4;
            value = 0;
            break;

        case SQL_POS_OPERATIONS: /* ODBC 2.0 */
            len = 4;
            value = (SQL_POS_POSITION | SQL_POS_REFRESH);
            break;

        case SQL_POSITIONED_STATEMENTS: /* ODBC 2.0 */
            len = 4;
            value = 0;
            break;

        case SQL_PROCEDURE_TERM: /* ODBC 1.0 */
            p = "procedure";
            break;

        case SQL_PROCEDURES: /* ODBC 1.0 */
            p = "Y";
            break;

        case SQL_QUALIFIER_LOCATION: /* ODBC 2.0 */
            len = 2;
            value = 0;
            break;

        case SQL_QUALIFIER_NAME_SEPARATOR: /* ODBC 1.0 */
            p = "";
            break;

        case SQL_QUALIFIER_TERM: /* ODBC 1.0 */
            p = "";
            break;

        case SQL_QUALIFIER_USAGE: /* ODBC 2.0 */
            len = 4;
            value = 0;
            break;

        case SQL_QUOTED_IDENTIFIER_CASE: /* ODBC 2.0 */
            /* are "quoted" identifiers case-sensitive?  YES! */
            len = 2;
            value = SQL_IC_SENSITIVE;
            break;

        case SQL_ROW_UPDATES: /* ODBC 1.0 */

            /*
             * Driver doesn't support keyset-driven or mixed cursors, so
             * not much point in saying row updates are supported
             */
            p = "N";
            break;

        case SQL_SCROLL_CONCURRENCY: /* ODBC 1.0 */
            len = 4;
            value = SQL_SCCO_READ_ONLY;
            break;

        case SQL_SCROLL_OPTIONS: /* ODBC 1.0 */
            len = 4;
            value = SQL_SO_FORWARD_ONLY | SQL_SO_STATIC;
            break;

        case SQL_SEARCH_PATTERN_ESCAPE: /* ODBC 1.0 */
            p = "";
            break;

        case SQL_SERVER_NAME: /* ODBC 1.0 */
            p = CC_get_server(conn);
            break;

        case SQL_SPECIAL_CHARACTERS: /* ODBC 2.0 */
            p = "_";
            break;

        case SQL_STATIC_SENSITIVITY: /* ODBC 2.0 */
            len = 4;
            value = 0;
            break;

        case SQL_STRING_FUNCTIONS: /* ODBC 1.0 */
            len = 4;
            value = SQL_FN_STR_ASCII | SQL_FN_STR_LENGTH | SQL_FN_STR_LTRIM
                    | SQL_FN_STR_REPLACE | SQL_FN_STR_RTRIM
                    | SQL_FN_STR_SUBSTRING;
            break;

        case SQL_SUBQUERIES: /* ODBC 2.0 */
            len = 4;
            value = (SQL_SQ_QUANTIFIED | SQL_SQ_IN | SQL_SQ_EXISTS
                     | SQL_SQ_COMPARISON);
            break;

        case SQL_SYSTEM_FUNCTIONS: /* ODBC 1.0 */
            len = 4;
            value = SQL_FN_SYS_IFNULL;
            break;

        case SQL_TABLE_TERM: /* ODBC 1.0 */
            p = "table";
            break;

        case SQL_TIMEDATE_ADD_INTERVALS: /* ODBC 2.0 */
            len = 4;
            value = 0;
            break;

        case SQL_TIMEDATE_DIFF_INTERVALS: /* ODBC 2.0 */
            len = 4;
            value = 0;
            break;

        case SQL_TIMEDATE_FUNCTIONS: /* ODBC 1.0 */
            len = 4;
            value = SQL_FN_TD_CURDATE | SQL_FN_TD_DAYOFMONTH | SQL_FN_TD_MONTH
                    | SQL_FN_TD_MONTHNAME | SQL_FN_TD_NOW | SQL_FN_TD_YEAR;
            break;

        case SQL_TXN_CAPABLE: /* ODBC 1.0 */
            /*
             * OpenSearch does not support transactions.
             */
            len = 2;
            value = SQL_TC_NONE;
            break;

        case SQL_TXN_ISOLATION_OPTION: /* ODBC 1.0 */
            len = 4;
            value = SQL_TXN_READ_UNCOMMITTED | SQL_TXN_READ_COMMITTED
                    | SQL_TXN_REPEATABLE_READ | SQL_TXN_SERIALIZABLE;
            break;

        case SQL_UNION: /* ODBC 2.0 */
            len = 4;
            value = (SQL_U_UNION | SQL_U_UNION_ALL);
            break;

        case SQL_USER_NAME: /* ODBC 1.0 */
            p = CC_get_username(conn);
            break;

        /* Keys for ODBC 3.0 */
        case SQL_DYNAMIC_CURSOR_ATTRIBUTES1:
            len = 4;
            value = 0;
            break;
        case SQL_DYNAMIC_CURSOR_ATTRIBUTES2:
            len = 4;
            value = 0;
            break;
        case SQL_FORWARD_ONLY_CURSOR_ATTRIBUTES1:
            len = 4;
            value = SQL_CA1_NEXT; /* others aren't allowed in ODBC spec */
            break;
        case SQL_FORWARD_ONLY_CURSOR_ATTRIBUTES2:
            len = 4;
            value = SQL_CA2_READ_ONLY_CONCURRENCY | SQL_CA2_CRC_EXACT;
            break;
        case SQL_KEYSET_CURSOR_ATTRIBUTES1:
            len = 4;
            value = 0;
            break;
        case SQL_KEYSET_CURSOR_ATTRIBUTES2:
            len = 4;
            value = 0;
            break;

        case SQL_STATIC_CURSOR_ATTRIBUTES1:
            len = 4;
            value = SQL_CA1_NEXT | SQL_CA1_ABSOLUTE | SQL_CA1_RELATIVE
                    | SQL_CA1_BOOKMARK | SQL_CA1_LOCK_NO_CHANGE
                    | SQL_CA1_POS_POSITION | SQL_CA1_POS_REFRESH;
            break;
        case SQL_STATIC_CURSOR_ATTRIBUTES2:
            len = 4;
            value = SQL_CA2_READ_ONLY_CONCURRENCY | SQL_CA2_CRC_EXACT;
            break;

        case SQL_ODBC_INTERFACE_CONFORMANCE:
            len = 4;
            value = SQL_OIC_CORE;
            break;
        case SQL_ACTIVE_ENVIRONMENTS:
            len = 2;
            value = 0;
            break;
        case SQL_AGGREGATE_FUNCTIONS:
            len = 4;
            value = SQL_AF_ALL;
            break;
        case SQL_ALTER_DOMAIN:
            len = 4;
            value = 0;
            break;
        case SQL_ASYNC_MODE:
            len = 4;
            value = SQL_AM_NONE;
            break;
        case SQL_BATCH_ROW_COUNT:
            len = 4;
            value = SQL_BRC_EXPLICIT;
            break;
        case SQL_BATCH_SUPPORT:
            len = 4;
            value = SQL_BS_SELECT_EXPLICIT | SQL_BS_ROW_COUNT_EXPLICIT;
            break;
        case SQL_CATALOG_NAME:
            p = "N";
            break;
        case SQL_COLLATION_SEQ:
            p = "";
            break;
        case SQL_CREATE_ASSERTION:
            len = 4;
            value = 0;
            break;
        case SQL_CREATE_CHARACTER_SET:
            len = 4;
            value = 0;
            break;
        case SQL_CREATE_COLLATION:
            len = 4;
            value = 0;
            break;
        case SQL_CREATE_DOMAIN:
            len = 4;
            value = 0;
            break;
        case SQL_CREATE_SCHEMA:
            len = 4;
            value = SQL_CS_CREATE_SCHEMA | SQL_CS_AUTHORIZATION;
            break;
        case SQL_CREATE_TABLE:
            len = 4;
            value = SQL_CT_CREATE_TABLE | SQL_CT_COLUMN_CONSTRAINT
                    | SQL_CT_COLUMN_DEFAULT | SQL_CT_GLOBAL_TEMPORARY
                    | SQL_CT_TABLE_CONSTRAINT
                    | SQL_CT_CONSTRAINT_NAME_DEFINITION
                    | SQL_CT_CONSTRAINT_INITIALLY_DEFERRED
                    | SQL_CT_CONSTRAINT_INITIALLY_IMMEDIATE
                    | SQL_CT_CONSTRAINT_DEFERRABLE;
            break;
        case SQL_CREATE_TRANSLATION:
            len = 4;
            value = 0;
            break;
        case SQL_CREATE_VIEW:
            len = 4;
            value = SQL_CV_CREATE_VIEW;
            break;
        case SQL_DDL_INDEX:
            len = 4;
            value = SQL_DI_CREATE_INDEX | SQL_DI_DROP_INDEX;
            break;
        case SQL_DESCRIBE_PARAMETER:
            p = "N";
            break;
        case SQL_DROP_ASSERTION:
            len = 4;
            value = 0;
            break;
        case SQL_DROP_CHARACTER_SET:
            len = 4;
            value = 0;
            break;
        case SQL_DROP_COLLATION:
            len = 4;
            value = 0;
            break;
        case SQL_DROP_DOMAIN:
            len = 4;
            value = 0;
            break;
        case SQL_DROP_SCHEMA:
            len = 4;
            value = SQL_DS_DROP_SCHEMA | SQL_DS_RESTRICT | SQL_DS_CASCADE;
            break;
        case SQL_DROP_TABLE:
            len = 4;
            value = SQL_DT_DROP_TABLE;
            value |= (SQL_DT_RESTRICT | SQL_DT_CASCADE);
            break;
        case SQL_DROP_TRANSLATION:
            len = 4;
            value = 0;
            break;
        case SQL_DROP_VIEW:
            len = 4;
            value = SQL_DV_DROP_VIEW;
            value |= (SQL_DV_RESTRICT | SQL_DV_CASCADE);
            break;
        case SQL_INDEX_KEYWORDS:
            len = 4;
            value = SQL_IK_NONE;
            break;
        case SQL_INFO_SCHEMA_VIEWS:
            len = 4;
            value = 0;
            break;
        case SQL_INSERT_STATEMENT:
            len = 4;
            value = SQL_IS_INSERT_LITERALS | SQL_IS_INSERT_SEARCHED
                    | SQL_IS_SELECT_INTO;
            break;
        case SQL_MAX_IDENTIFIER_LEN:
            len = 2;
            value = CC_get_max_idlen(conn);
            if (0 == value)
                value = NAMEDATALEN_V73 - 1;
            break;
        case SQL_MAX_ROW_SIZE_INCLUDES_LONG:
            p = "Y";
            break;
        case SQL_PARAM_ARRAY_ROW_COUNTS:
            len = 4;
            value = SQL_PARC_BATCH;
            break;
        case SQL_PARAM_ARRAY_SELECTS:
            len = 4;
            value = SQL_PAS_BATCH;
            break;
        case SQL_SQL_CONFORMANCE:
            // SQL plugin currently does not support this level,
            // but Tableau requires at least Entry level reported for retrieving
            // row data
            len = 4;
            value = SQL_SC_SQL92_ENTRY;
            break;
        case SQL_SQL92_DATETIME_FUNCTIONS:
            len = 4;
            value = 0;
            break;
        case SQL_SQL92_FOREIGN_KEY_DELETE_RULE:
            len = 4;
            value = SQL_SFKD_CASCADE | SQL_SFKD_NO_ACTION | SQL_SFKD_SET_DEFAULT
                    | SQL_SFKD_SET_NULL;
            break;
        case SQL_SQL92_FOREIGN_KEY_UPDATE_RULE:
            len = 4;
            value = SQL_SFKU_CASCADE | SQL_SFKU_NO_ACTION | SQL_SFKU_SET_DEFAULT
                    | SQL_SFKU_SET_NULL;
            break;
        case SQL_SQL92_GRANT:
            len = 4;
            value = SQL_SG_DELETE_TABLE | SQL_SG_INSERT_TABLE
                    | SQL_SG_REFERENCES_TABLE | SQL_SG_SELECT_TABLE
                    | SQL_SG_UPDATE_TABLE;
            break;
        case SQL_SQL92_NUMERIC_VALUE_FUNCTIONS:
            len = 4;
            value = 0;
            break;
        case SQL_SQL92_PREDICATES:
            len = 4;
            value = SQL_SP_BETWEEN | SQL_SP_COMPARISON | SQL_SP_IN
                    | SQL_SP_ISNULL | SQL_SP_LIKE;
            break;
        case SQL_SQL92_RELATIONAL_JOIN_OPERATORS:
            len = 4;
            value = SQL_SRJO_CROSS_JOIN | SQL_SRJO_INNER_JOIN
                    | SQL_SRJO_LEFT_OUTER_JOIN | SQL_SRJO_RIGHT_OUTER_JOIN;
            break;
        case SQL_SQL92_REVOKE:
            len = 4;
            value = SQL_SR_DELETE_TABLE | SQL_SR_INSERT_TABLE
                    | SQL_SR_REFERENCES_TABLE | SQL_SR_SELECT_TABLE
                    | SQL_SR_UPDATE_TABLE;
            break;
        case SQL_SQL92_ROW_VALUE_CONSTRUCTOR:
            len = 4;
            value = SQL_SRVC_VALUE_EXPRESSION | SQL_SRVC_NULL;
            break;
        case SQL_SQL92_STRING_FUNCTIONS:
            len = 4;
            value = SQL_SSF_LOWER | SQL_SSF_UPPER;
            break;
        case SQL_SQL92_VALUE_EXPRESSIONS:
            len = 4;
            value = SQL_SVE_CASE | SQL_SVE_CAST;
            break;
#ifdef SQL_DTC_TRANSACTION_COST
        case SQL_DTC_TRANSACTION_COST:
#else
        case 1750:
#endif
            len = 4;
            break;
        case SQL_DATETIME_LITERALS:
        case SQL_DRIVER_HDESC:
        case SQL_MAX_ASYNC_CONCURRENT_STATEMENTS:
        case SQL_STANDARD_CLI_CONFORMANCE:
        case SQL_CONVERT_INTERVAL_DAY_TIME:
            len = 4;
            value = 0;
            break;
        case SQL_DM_VER:
        case SQL_XOPEN_CLI_YEAR:
            len = 0;
            value = 0;
            break;

        default:
            /* unrecognized key */
            CC_set_error(conn, CONN_NOT_IMPLEMENTED_ERROR,
                         "Unrecognized key passed to OPENSEARCHAPI_GetInfo.", NULL);
            goto cleanup;
    }

    ret = SQL_SUCCESS;

    MYLOG(OPENSEARCH_DEBUG, "p='%s', len=" FORMAT_ULEN ", value=" FORMAT_ULEN ", cbMax=%d\n",
          p ? p : "<NULL>", len, value, cbInfoValueMax);

    /*
     * NOTE, that if rgbInfoValue is NULL, then no warnings or errors
     * should result and just pcbInfoValue is returned, which indicates
     * what length would be required if a real buffer had been passed in.
     */
    if (p) {
        /* char/binary data */
        len = strlen(p);

        if (rgbInfoValue) {
#ifdef UNICODE_SUPPORT
            if (CC_is_in_unicode_driver(conn)) {
                len = utf8_to_ucs2(p, len, (SQLWCHAR *)rgbInfoValue,
                                   cbInfoValueMax / WCLEN);
                len *= WCLEN;
            } else
#endif /* UNICODE_SUPPORT */
                strncpy_null((char *)rgbInfoValue, p, (size_t)cbInfoValueMax);

            if (len >= (SQLULEN)cbInfoValueMax) {
                ret = SQL_SUCCESS_WITH_INFO;
                CC_set_error(conn, CONN_TRUNCATED,
                             "The buffer was too small for the InfoValue.",
                             func);
            }
        }
#ifdef UNICODE_SUPPORT
        else if (CC_is_in_unicode_driver(conn))
            len *= WCLEN;
#endif /* UNICODE_SUPPORT */
    } else {
        /* numeric data */
        if (rgbInfoValue) {
            if (len == sizeof(SQLSMALLINT))
                *((SQLUSMALLINT *)rgbInfoValue) = (SQLUSMALLINT)value;
            else if (len == sizeof(SQLINTEGER))
                *((SQLUINTEGER *)rgbInfoValue) = (SQLUINTEGER)value;
        }
    }

    if (pcbInfoValue)
        *pcbInfoValue = (SQLSMALLINT)len;
cleanup:

    return ret;
}