Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 12 additions & 1 deletion info.c
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@

#include <string.h>
#include <stdio.h>
#include <limits.h>

#ifndef WIN32
#include <ctype.h>
Expand Down Expand Up @@ -1246,6 +1247,7 @@ MYLOG(DETAIL_LOG_LEVEL, "%d sqltype=%d -> pgtype=%d\n", ci->bytea_as_longvarbina
if (fSqlType == SQL_ALL_TYPES || fSqlType == sqlType)
{
int pgtcount = 1, aunq_match = -1, cnt;
Int4 column_size;

/*if (SQL_INTEGER == sqlType || SQL_TINYINT == sqlType)*/
if (SQL_INTEGER == sqlType)
Expand Down Expand Up @@ -1290,7 +1292,16 @@ MYLOG(DETAIL_LOG_LEVEL, "serial in\n");
set_tuplefield_null(&tuple[GETTYPE_LOCAL_TYPE_NAME]);

/* These values can be NULL */
set_nullfield_int4(&tuple[GETTYPE_COLUMN_SIZE], PGTYPE_COLUMN_SIZE(conn, pgType));
column_size = PGTYPE_COLUMN_SIZE(conn, pgType);
/*
* COLUMN_SIZE is the maximum column size, so SQL_NO_TOTAL
* (a length/indicator value) is not valid here; applications
* such as MSDASQL bind it as SQL_C_ULONG, where -4 fails
* with 22003. Report the largest representable size.
*/
if (SQL_NO_TOTAL == column_size)
column_size = INT_MAX;
set_nullfield_int4(&tuple[GETTYPE_COLUMN_SIZE], column_size);
set_nullfield_string(&tuple[GETTYPE_LITERAL_PREFIX], pgtype_literal_prefix(conn, pgType));
set_nullfield_string(&tuple[GETTYPE_LITERAL_SUFFIX], pgtype_literal_suffix(conn, pgType));
set_nullfield_string(&tuple[GETTYPE_CREATE_PARAMS], pgtype_create_params(conn, pgType));
Expand Down
3 changes: 3 additions & 0 deletions test/expected/typeinfo-column-size.out
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
connected
bytea: COLUMN_SIZE=2147483647
disconnecting
54 changes: 54 additions & 0 deletions test/src/typeinfo-column-size-test.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
/*
* Test that every SQLGetTypeInfo(SQL_ALL_TYPES) row can be fetched with
* COLUMN_SIZE bound as SQL_C_ULONG and no indicator, the way MSDASQL binds
* it. bytea used to report SQL_NO_TOTAL (-4) there, which fails the 22003
* range check for unsigned C types. (issue #215)
*/
#include <stdio.h>
#include <stdlib.h>

#include "common.h"

int
main(int argc, char **argv)
{
SQLRETURN rc;
HSTMT hstmt = SQL_NULL_HSTMT;
SQLCHAR type_name[64];
SQLSMALLINT data_type;
SQLUINTEGER column_size;

test_connect_ext("ByteaAsLongVarBinary=1");

rc = SQLAllocHandle(SQL_HANDLE_STMT, conn, &hstmt);
CHECK_CONN_RESULT(rc, "SQLAllocHandle failed", conn);

rc = SQLGetTypeInfo(hstmt, SQL_ALL_TYPES);
CHECK_STMT_RESULT(rc, "SQLGetTypeInfo failed", hstmt);

rc = SQLBindCol(hstmt, 1, SQL_C_CHAR, type_name, sizeof(type_name), NULL);
CHECK_STMT_RESULT(rc, "SQLBindCol failed", hstmt);
rc = SQLBindCol(hstmt, 2, SQL_C_SSHORT, &data_type, sizeof(data_type), NULL);
CHECK_STMT_RESULT(rc, "SQLBindCol failed", hstmt);
rc = SQLBindCol(hstmt, 3, SQL_C_ULONG, &column_size, sizeof(column_size), NULL);
CHECK_STMT_RESULT(rc, "SQLBindCol failed", hstmt);

while ((rc = SQLFetch(hstmt)) != SQL_NO_DATA)
{
if (!SQL_SUCCEEDED(rc))
{
print_diag("SQLFetch failed", SQL_HANDLE_STMT, hstmt);
break;
}
if (data_type == SQL_LONGVARBINARY)
printf("%s: COLUMN_SIZE=%lu\n", (char *) type_name,
(unsigned long) column_size);
}

rc = SQLFreeStmt(hstmt, SQL_CLOSE);
CHECK_STMT_RESULT(rc, "SQLFreeStmt failed", hstmt);

test_disconnect();

return 0;
}
1 change: 1 addition & 0 deletions test/tests
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,7 @@ TESTBINS = exe/connect-test \
exe/primarykeys-include-test \
exe/interval-overflow-test \
exe/int-overflow-test \
exe/typeinfo-column-size-test \
exe/conn-settings-test \
exe/percent-decode-test \
exe/connstring-escape-test \
Expand Down
Loading