SQLLEN *Length, SQLSMALLINT *Precision,
SQLSMALLINT *Scale, SQLSMALLINT *Nullable)
{
- MYLOG(0, "Entering\n");
- MYLOG(0, "Error not implemented\n");
- return SQL_ERROR;
+ RETCODE ret;
+
+ MYLOG(0, "Entering h=%p rec=%d name=%p blen=%d\n", DescriptorHandle, RecNumber, Name, BufferLength);
+ MYLOG(0, "str=%p type=%p sub=%p len=%p prec=%p scale=%p null=%p\n", StringLength, Type, SubType, Length, Precision, Scale, Nullable);
+ ret = PGAPI_GetDescRec(DescriptorHandle, RecNumber, Name, BufferLength,
+ StringLength, Type, SubType, Length, Precision,
+ Scale, Nullable);
+ return ret;
}
/* new function */
PTR Data, SQLLEN *StringLength,
SQLLEN *Indicator)
{
- MYLOG(0, "Entering\n");
- MYLOG(0, "Error not implemented\n");
- return SQL_ERROR;
+ RETCODE ret;
+
+ MYLOG(0, "Entering h=%p rec=%d type=%d sub=%d len=" FORMAT_LEN " prec=%d scale=%d data=%p\n", DescriptorHandle, RecNumber, Type, SubType, Length, Precision, Scale, Data);
+ MYLOG(0, "str=%p ind=%p\n", StringLength, Indicator);
+ ret = PGAPI_SetDescRec(DescriptorHandle, RecNumber, Type,
+ SubType, Length, Precision, Scale, Data,
+ StringLength, Indicator);
+ return ret;
}
#endif /* UNICODE_SUPPORTXX */
SQL_FUNC_ESET(pfExists, SQL_API_SQLFREEHANDLE); /* 1006 */
SQL_FUNC_ESET(pfExists, SQL_API_SQLGETCONNECTATTR); /* 1007 */
SQL_FUNC_ESET(pfExists, SQL_API_SQLGETDESCFIELD); /* 1008 */
- if (ci->drivers.lie)
- {
- SQL_FUNC_ESET(pfExists, SQL_API_SQLGETDESCREC); /* 1009 not implemented yet */
- }
+ SQL_FUNC_ESET(pfExists, SQL_API_SQLGETDESCREC); /* 1009 */
SQL_FUNC_ESET(pfExists, SQL_API_SQLGETDIAGFIELD); /* 1010 minimal implementation */
SQL_FUNC_ESET(pfExists, SQL_API_SQLGETDIAGREC); /* 1011 */
SQL_FUNC_ESET(pfExists, SQL_API_SQLGETENVATTR); /* 1012 */
SQL_FUNC_ESET(pfExists, SQL_API_SQLGETSTMTATTR); /* 1014 */
SQL_FUNC_ESET(pfExists, SQL_API_SQLSETCONNECTATTR); /* 1016 */
SQL_FUNC_ESET(pfExists, SQL_API_SQLSETDESCFIELD); /* 1017 */
- if (ci->drivers.lie)
- {
- SQL_FUNC_ESET(pfExists, SQL_API_SQLSETDESCREC); /* 1018 not implemented yet */
- }
+ SQL_FUNC_ESET(pfExists, SQL_API_SQLSETDESCREC); /* 1018 */
SQL_FUNC_ESET(pfExists, SQL_API_SQLSETENVATTR); /* 1019 */
SQL_FUNC_ESET(pfExists, SQL_API_SQLSETSTMTATTR); /* 1020 */
SQL_FUNC_ESET(pfExists, SQL_API_SQLFETCHSCROLL); /* 1021 */
SQLLEN *Length, SQLSMALLINT *Precision,
SQLSMALLINT *Scale, SQLSMALLINT *Nullable)
{
- MYLOG(0, "Entering\n");
- MYLOG(0, "Error not implemented\n");
- return SQL_ERROR;
+ RETCODE ret;
+ char *NameA = NULL;
+ SQLSMALLINT nlen;
+
+ MYLOG(0, "Entering h=%p rec=%d name=%p blen=%d\n", DescriptorHandle, RecNumber, Name, BufferLength);
+ MYLOG(0, "str=%p type=%p sub=%p len=%p prec=%p scale=%p null=%p\n", StringLength, Type, SubType, Length, Precision, Scale, Nullable);
+
+ if (BufferLength > 0)
+ NameA = malloc(BufferLength);
+
+ ret = PGAPI_GetDescRec(DescriptorHandle, RecNumber, (SQLCHAR *) NameA, BufferLength,
+ &nlen, Type, SubType, Length, Precision,
+ Scale, Nullable);
+ if (SQL_SUCCEEDED(ret))
+ {
+ if (NameA && nlen <= BufferLength)
+ {
+ SQLULEN ulen = utf8_to_ucs2_lf(NameA, nlen, FALSE, Name, BufferLength, TRUE);
+ if (ulen == (SQLULEN) -1)
+ nlen = (SQLSMALLINT) locale_to_sqlwchar((SQLWCHAR *) Name, NameA, BufferLength, FALSE);
+ else
+ nlen = (SQLSMALLINT) ulen;
+ if (nlen >= BufferLength)
+ ret = SQL_SUCCESS_WITH_INFO;
+ }
+ if (StringLength)
+ *StringLength = nlen;
+ }
+ if (NameA)
+ free(NameA);
+ return ret;
}
/* new function */
PTR Data, SQLLEN *StringLength,
SQLLEN *Indicator)
{
- MYLOG(0, "Entering\n");
- MYLOG(0, "Error not implemented\n");
- return SQL_ERROR;
+ RETCODE ret;
+ SQLLEN vallen;
+ char *uval = NULL;
+ BOOL val_alloced = FALSE;
+
+ MYLOG(0, "Entering h=%p rec=%d type=%d sub=%d len=" FORMAT_LEN " prec=%d scale=%d data=%p\n", DescriptorHandle, RecNumber, Type, SubType, Length, Precision, Scale, Data);
+ MYLOG(0, "str=%p ind=%p\n", StringLength, Indicator);
+
+ if (Length > 0 || SQL_NTS == Length)
+ {
+ uval = ucs2_to_utf8(Data, Length > 0 ? Length / WCLEN : Length, &vallen, FALSE);
+ val_alloced = TRUE;
+ }
+ if (!val_alloced)
+ {
+ uval = Data;
+ vallen = Length;
+ }
+ ret = PGAPI_SetDescRec(DescriptorHandle, RecNumber, Type,
+ SubType, Length, Precision, Scale, uval,
+ &vallen, Indicator);
+ if (val_alloced)
+ free(uval);
+ return ret;
}
switch (FieldIdentifier)
{
+ case SQL_DESC_TYPE:
+ bookmark->returntype = CAST_PTR(SQLSMALLINT, Value);
+ break;
+ case SQL_DESC_DATETIME_INTERVAL_CODE:
+ switch (bookmark->returntype)
+ {
+ case SQL_DATETIME:
+ case SQL_C_TYPE_DATE:
+ case SQL_C_TYPE_TIME:
+ case SQL_C_TYPE_TIMESTAMP:
+ switch ((LONG_PTR) Value)
+ {
+ case SQL_CODE_DATE:
+ bookmark->returntype = SQL_C_TYPE_DATE;
+ break;
+ case SQL_CODE_TIME:
+ bookmark->returntype = SQL_C_TYPE_TIME;
+ break;
+ case SQL_CODE_TIMESTAMP:
+ bookmark->returntype = SQL_C_TYPE_TIMESTAMP;
+ break;
+ }
+ break;
+ }
+ break;
case SQL_DESC_DATA_PTR:
bookmark->buffer = Value;
break;
case SQL_DESC_OCTET_LENGTH_PTR:
bookmark->used = Value;
break;
+ case SQL_DESC_OCTET_LENGTH:
+ bookmark->buflen = CAST_PTR(SQLLEN, Value);
+ break;
+ case SQL_DESC_PRECISION:
+ bookmark->precision = CAST_PTR(SQLSMALLINT, Value);
+ break;
+ case SQL_DESC_SCALE:
+ bookmark->scale = CAST_PTR(SQLSMALLINT, Value);
+ break;
default:
DC_set_error(desc, DESC_INVALID_COLUMN_NUMBER_ERROR, "invalid column number");
ret = SQL_ERROR;
case SQL_DESC_PARAMETER_TYPE:
ipdopts->parameters[para_idx].paramType = CAST_PTR(SQLSMALLINT, Value);
break;
+ case SQL_DESC_PRECISION:
+ switch (ipdopts->parameters[para_idx].SQLType)
+ {
+ case SQL_TYPE_DATE:
+ case SQL_TYPE_TIME:
+ case SQL_TYPE_TIMESTAMP:
+ case SQL_DATETIME:
+ ipdopts->parameters[para_idx].decimal_digits = CAST_PTR(SQLSMALLINT, Value);
+ break;
+ case SQL_NUMERIC:
+ ipdopts->parameters[para_idx].precision = CAST_PTR(SQLINTEGER, Value);
+ break;
+ }
+ break;
case SQL_DESC_SCALE:
ipdopts->parameters[para_idx].decimal_digits = CAST_PTR(SQLSMALLINT, Value);
break;
else
NULL_THE_NAME(ipdopts->parameters[para_idx].paramName);
break;
+ case SQL_DESC_OCTET_LENGTH:
+ break;
case SQL_DESC_ALLOC_TYPE: /* read-only */
case SQL_DESC_CASE_SENSITIVE: /* read-only */
case SQL_DESC_DATETIME_INTERVAL_PRECISION:
case SQL_DESC_LOCAL_TYPE_NAME: /* read-only */
case SQL_DESC_NULLABLE: /* read-only */
case SQL_DESC_NUM_PREC_RADIX:
- case SQL_DESC_OCTET_LENGTH:
- case SQL_DESC_PRECISION:
case SQL_DESC_ROWVER: /* read-only */
case SQL_DESC_TYPE_NAME: /* read-only */
case SQL_DESC_UNSIGNED: /* read-only */
}
switch (FieldIdentifier)
{
+ case SQL_DESC_ALLOC_TYPE:
case SQL_DESC_ARRAY_SIZE:
case SQL_DESC_ARRAY_STATUS_PTR:
case SQL_DESC_BIND_OFFSET_PTR:
case SQL_DESC_COUNT:
break;
default:
- if (RecNumber <= 0 || RecNumber > opts->allocated)
+ if (RecNumber <= 0)
{
DC_set_error(desc, DESC_INVALID_COLUMN_NUMBER_ERROR,
"invalid column number");
return SQL_ERROR;
}
+ /* RecNumber should be less than or equal to the number of descriptor records */
+ else if (RecNumber > opts->allocated)
+ return SQL_NO_DATA;
}
row_idx = RecNumber - 1;
switch (FieldIdentifier)
len = sizeof(SQLINTEGER);
switch (FieldIdentifier)
{
+ case SQL_DESC_ALLOC_TYPE:
case SQL_DESC_ARRAY_SIZE:
case SQL_DESC_ARRAY_STATUS_PTR:
case SQL_DESC_BIND_OFFSET_PTR:
case SQL_DESC_BIND_TYPE:
case SQL_DESC_COUNT:
break;
- default:if (RecNumber <= 0 || RecNumber > opts->allocated)
+ default:
+ if (RecNumber <= 0)
{
-MYLOG(DETAIL_LOG_LEVEL, "RecN=%d allocated=%d\n", RecNumber, opts->allocated);
+ MYLOG(DETAIL_LOG_LEVEL, "RecN=%d allocated=%d\n", RecNumber, opts->allocated);
DC_set_error(desc, DESC_BAD_PARAMETER_NUMBER_ERROR,
"bad parameter number");
return SQL_ERROR;
}
+ /* RecNumber should be less than or equal to the number of descriptor records */
+ else if (RecNumber > opts->allocated)
+ return SQL_NO_DATA;
}
para_idx = RecNumber - 1;
switch (FieldIdentifier)
StatementClass *stmt;
stmt = opts->stmt;
+ /* if statement is in the prepared or executed state but there is no open cursor, return SQL_NO_DATA */
+ if ((stmt->prepared >= PREPARED_PERMANENTLY || stmt->status == STMT_FINISHED) && NAME_IS_NULL(stmt->cursor_name))
+ return SQL_NO_DATA;
+ /* HY007: statement handle had not been prepared or executed */
+ if (SC_get_Curres(stmt) == NULL && stmt->prepared == NOT_YET_PREPARED)
+ {
+ DC_set_error(desc, DESC_STATEMENT_NOT_PREPARED,
+ "associated statement is not prepared");
+ return SQL_ERROR;
+ }
ret = PGAPI_ColAttributes(stmt, RecNumber,
FieldIdentifier, Value, (SQLSMALLINT) BufferLength,
&pcbL, &ival);
if (StringLength)
*StringLength = len;
+ /* 01004: String data, right-truncated */
+ if (ret == SQL_SUCCESS_WITH_INFO)
+ DC_set_error(desc, DESC_STRING_DATA_TRUNCATED, "string data truncated");
return ret;
}
switch (FieldIdentifier)
{
+ case SQL_DESC_ALLOC_TYPE:
case SQL_DESC_ARRAY_STATUS_PTR:
case SQL_DESC_ROWS_PROCESSED_PTR:
case SQL_DESC_COUNT:
break;
- default:if (RecNumber <= 0 || RecNumber > ipdopts->allocated)
+ default:
+ if (RecNumber <= 0)
{
-MYLOG(DETAIL_LOG_LEVEL, "RecN=%d allocated=%d\n", RecNumber, ipdopts->allocated);
+ MYLOG(DETAIL_LOG_LEVEL, "RecN=%d allocated=%d\n", RecNumber, ipdopts->allocated);
DC_set_error(desc, DESC_BAD_PARAMETER_NUMBER_ERROR,
"bad parameter number");
return SQL_ERROR;
}
+ /* RecNumber should be less than or equal to the number of descriptor records */
+ else if (RecNumber > ipdopts->allocated)
+ return SQL_NO_DATA;
}
para_idx = RecNumber - 1;
switch (FieldIdentifier)
case SQL_DATETIME:
ival = ipdopts->parameters[para_idx].decimal_digits;
break;
+ case SQL_NUMERIC:
+ ival = ipdopts->parameters[para_idx].precision;
+ break;
}
break;
case SQL_DESC_SCALE:
break;
}
break;
+ case SQL_DESC_OCTET_LENGTH:
+ break;
case SQL_DESC_ALLOC_TYPE: /* read-only */
rettype = SQL_IS_SMALLINT;
ival = SQL_DESC_ALLOC_AUTO;
break;
+ case SQL_DESC_NAME:
+ rettype = SQL_NTS;
+ if (NAME_IS_NULL(ipdopts->parameters[para_idx].paramName))
+ ptr = (char *) SAFE_NAME(ipdopts->parameters[para_idx].paramName);
+ else
+ ptr = GET_NAME(ipdopts->parameters[para_idx].paramName);
+ if (ptr)
+ {
+ len = (SQLINTEGER) strlen(ptr);
+ if (Value)
+ {
+ strncpy_null((char *) Value, ptr, BufferLength);
+ if (len >= BufferLength)
+ ret = SQL_SUCCESS_WITH_INFO;
+ }
+ }
+ break;
+ case SQL_DESC_NULLABLE: /* read-only */
+ rettype = SQL_IS_SMALLINT;
+ ival = SQL_NULLABLE;
+ break;
case SQL_DESC_CASE_SENSITIVE: /* read-only */
case SQL_DESC_DATETIME_INTERVAL_PRECISION:
case SQL_DESC_FIXED_PREC_SCALE: /* read-only */
case SQL_DESC_LENGTH:
case SQL_DESC_LOCAL_TYPE_NAME: /* read-only */
- case SQL_DESC_NAME:
- case SQL_DESC_NULLABLE: /* read-only */
case SQL_DESC_NUM_PREC_RADIX:
- case SQL_DESC_OCTET_LENGTH:
case SQL_DESC_ROWVER: /* read-only */
case SQL_DESC_TYPE_NAME: /* read-only */
case SQL_DESC_UNSIGNED: /* read-only */
len = sizeof(SQLPOINTER);
*((void **)Value) = ptr;
break;
+ case SQL_NTS:
+ break;
}
if (StringLength)
*StringLength = len;
+ /* 01004: String data, right-truncated */
+ if (ret == SQL_SUCCESS_WITH_INFO)
+ DC_set_error(desc, DESC_STRING_DATA_TRUNCATED, "string data truncated");
return ret;
}
return ret;
}
+/* new function */
+RETCODE SQL_API
+PGAPI_SetDescRec(SQLHDESC DescriptorHandle,
+ SQLSMALLINT RecNumber, SQLSMALLINT Type,
+ SQLSMALLINT SubType, SQLLEN Length,
+ SQLSMALLINT Precision, SQLSMALLINT Scale,
+ PTR Data, SQLLEN *StringLength, SQLLEN *Indicator)
+{
+ CSTR func = "PGAPI_SetDescRec";
+ RETCODE ret = SQL_SUCCESS;
+ DescriptorClass *desc = (DescriptorClass *) DescriptorHandle;
+
+ MYLOG(0, "entering h=%p(%d) rec=" FORMAT_SMALLI " type=" FORMAT_SMALLI " sub=" FORMAT_SMALLI " len=" FORMAT_LEN " prec=" FORMAT_SMALLI " scale=" FORMAT_SMALLI " data=%p\n",
+ DescriptorHandle, DC_get_desc_type(desc), RecNumber, Type, SubType, Length, Precision, Scale, Data);
+ MYLOG(0, "str=%p ind=%p\n", StringLength, Indicator);
+
+ /* Descriptor handle must not be an IRD handle */
+ if (DC_get_desc_type(desc) == SQL_ATTR_IMP_ROW_DESC)
+ {
+ DC_set_error(desc, DESC_INVALID_DESCRIPTOR_IDENTIFIER, "Invalid descriptor identifier");
+ DC_log_error(func, "", desc);
+ return SQL_ERROR;
+ }
+
+ /*
+ Set following descriptor fields:
+
+ - SQL_DESC_TYPE
+ - SQL_DESC_DATETIME_INTERVAL_CODE
+ - SQL_DESC_OCTET_LENGTH
+ - SQL_DESC_PRECISION
+ - SQL_DESC_SCALE
+ - SQL_DESC_DATA_PTR
+ - SQL_DESC_OCTET_LENGTH_PTR
+ - SQL_DESC_INDICATOR_PTR
+ */
+ ret = PGAPI_SetDescField(DescriptorHandle, RecNumber, SQL_DESC_TYPE, &Type, 0);
+ if (ret != SQL_SUCCESS) return ret;
+
+ /* If Type is SQL_DATETIME or SQL_INTERVAL, the value of SQL_DESC_DATETIME_INTERVAL_CODE is set to SubType. */
+ if (Type == SQL_DATETIME || Type == SQL_INTERVAL) {
+ ret = PGAPI_SetDescField(DescriptorHandle, RecNumber, SQL_DESC_DATETIME_INTERVAL_CODE, &SubType, 0);
+ if (ret != SQL_SUCCESS) return ret;
+ }
+
+ ret = PGAPI_SetDescField(DescriptorHandle, RecNumber, SQL_DESC_OCTET_LENGTH, &Length, 0);
+ if (ret != SQL_SUCCESS) return ret;
+
+ ret = PGAPI_SetDescField(DescriptorHandle, RecNumber, SQL_DESC_PRECISION, &Precision, 0);
+ if (ret != SQL_SUCCESS) return ret;
+
+ ret = PGAPI_SetDescField(DescriptorHandle, RecNumber, SQL_DESC_SCALE, &Scale, 0);
+ if (ret != SQL_SUCCESS) return ret;
+
+ /* SQL_DESC_DATA_PTR is only for ARD or APD */
+ if (DC_get_desc_type(desc) != SQL_ATTR_IMP_PARAM_DESC)
+ {
+ ret = PGAPI_SetDescField(DescriptorHandle, RecNumber, SQL_DESC_DATA_PTR, &Data, 0);
+ if (ret != SQL_SUCCESS) return ret;
+ }
+
+ /* SQL_DESC_OCTET_LENGTH_PTR is only for ARD or APD */
+ if (DC_get_desc_type(desc) != SQL_ATTR_IMP_PARAM_DESC)
+ {
+ ret = PGAPI_SetDescField(DescriptorHandle, RecNumber, SQL_DESC_OCTET_LENGTH_PTR, StringLength, 0);
+ if (ret != SQL_SUCCESS) return ret;
+ }
+
+ /* SQL_DESC_INDICATOR_PTR is only for ARD or APD */
+ if (DC_get_desc_type(desc) != SQL_ATTR_IMP_PARAM_DESC)
+ {
+ ret = PGAPI_SetDescField(DescriptorHandle, RecNumber, SQL_DESC_INDICATOR_PTR, Indicator, 0);
+ if (ret != SQL_SUCCESS) return ret;
+ }
+
+ return SQL_SUCCESS;
+}
+
+/* new function */
+RETCODE SQL_API
+PGAPI_GetDescRec(SQLHDESC DescriptorHandle,
+ SQLSMALLINT RecNumber, SQLCHAR *Name,
+ SQLSMALLINT BufferLength, SQLSMALLINT *StringLength,
+ SQLSMALLINT *Type, SQLSMALLINT *SubType,
+ SQLLEN *Length, SQLSMALLINT *Precision,
+ SQLSMALLINT *Scale, SQLSMALLINT *Nullable)
+{
+ RETCODE ret = SQL_SUCCESS;
+ DescriptorClass *desc = (DescriptorClass *) DescriptorHandle;
+ SQLSMALLINT strlen, typ, subtyp, prec, scal, null;
+ SQLLEN len;
+
+ MYLOG(0, "entering h=%p(%d) rec=" FORMAT_SMALLI " name=%p blen=" FORMAT_SMALLI "\n", DescriptorHandle, DC_get_desc_type(desc), RecNumber, Name, BufferLength);
+ MYLOG(0, "str=%p type=%p sub=%p len=%p prec=%p scale=%p null=%p\n", StringLength, Type, SubType, Length, Precision, Scale, Nullable);
+
+ /*
+ Get following descriptor fields:
+
+ - SQL_DESC_TYPE
+ - SQL_DESC_DATETIME_INTERVAL_CODE
+ - SQL_DESC_OCTET_LENGTH
+ - SQL_DESC_PRECISION
+ - SQL_DESC_SCALE
+ - SQL_DESC_NULLABLE
+ - SQL_DESC_NAME
+ */
+
+ if (Type != NULL)
+ {
+ ret = PGAPI_GetDescField(DescriptorHandle, RecNumber, SQL_DESC_TYPE, &typ, 0, NULL);
+ if (ret != SQL_SUCCESS) return ret;
+ *Type = typ;
+ }
+
+ if (SubType != NULL && (typ == SQL_DATETIME || typ == SQL_INTERVAL))
+ {
+ ret = PGAPI_GetDescField(DescriptorHandle, RecNumber, SQL_DESC_DATETIME_INTERVAL_CODE, &subtyp, 0, NULL);
+ if (ret != SQL_SUCCESS) return ret;
+ *SubType = subtyp;
+ }
+
+ if (Length != NULL)
+ {
+ ret = PGAPI_GetDescField(DescriptorHandle, RecNumber, SQL_DESC_OCTET_LENGTH, &len, 0, NULL);
+ if (ret != SQL_SUCCESS) return ret;
+ *Length = (SQLLEN) len;
+ }
+
+ if (Precision != NULL)
+ {
+ ret = PGAPI_GetDescField(DescriptorHandle, RecNumber, SQL_DESC_PRECISION, &prec, 0, NULL);
+ if (ret != SQL_SUCCESS) return ret;
+ *Precision = prec;
+ }
+
+ if (Scale != NULL)
+ {
+ ret = PGAPI_GetDescField(DescriptorHandle, RecNumber, SQL_DESC_SCALE, &scal, 0, NULL);
+ if (ret != SQL_SUCCESS) return ret;
+ *Scale = scal;
+ }
+
+ if (Nullable != NULL && (DC_get_desc_type(desc) == SQL_ATTR_IMP_ROW_DESC || DC_get_desc_type(desc) == SQL_ATTR_IMP_PARAM_DESC))
+ {
+ ret = PGAPI_GetDescField(DescriptorHandle, RecNumber, SQL_DESC_NULLABLE, &null, 0, NULL);
+ if (ret != SQL_SUCCESS) return ret;
+ *Nullable = null;
+ }
+
+ if (Name != NULL && (DC_get_desc_type(desc) == SQL_ATTR_IMP_ROW_DESC || DC_get_desc_type(desc) == SQL_ATTR_IMP_PARAM_DESC))
+ {
+ ret = PGAPI_GetDescField(DescriptorHandle, RecNumber, SQL_DESC_NAME, Name, BufferLength, (SQLINTEGER *) &strlen);
+ if (ret != SQL_SUCCESS) return ret;
+ if (StringLength != NULL)
+ *StringLength = strlen;
+ }
+
+ return SQL_SUCCESS;
+}
+
/* SQLSet(Param/Scroll/Stmt)Option -> SQLSetStmtAttr */
RETCODE SQL_API
PGAPI_SetStmtAttr(HSTMT StatementHandle,
ret = bulk_ope_callback(SQL_SUCCESS, &s);
}
return ret;
-}
+}
\ No newline at end of file
--- /dev/null
+#include <stdio.h>
+#include <stdlib.h>
+
+#include "common.h"
+
+int main(int argc, char **argv)
+{
+ SQLRETURN rc;
+ HSTMT hstmt = SQL_NULL_HSTMT;
+ SQLSMALLINT colcount;
+ SQLHDESC hDesc;
+ SQLCHAR name[64];
+ SQLSMALLINT nameLen = 64;
+ SQLSMALLINT type, subType;
+ SQLSMALLINT precision, scale, nullable;
+ SQLLEN length;
+
+ test_connect();
+
+ rc = SQLAllocHandle(SQL_HANDLE_STMT, conn, &hstmt);
+ if (!SQL_SUCCEEDED(rc))
+ {
+ print_diag("failed to allocate stmt handle", SQL_HANDLE_DBC, conn);
+ exit(1);
+ }
+
+ /* Prepare a test table */
+ rc = SQLExecDirect(hstmt, (SQLCHAR *) "CREATE TEMPORARY TABLE desctable (col1 int4 not null, col2 numeric(4,2), col3 varchar(10) not null, col4 bigint not null)", SQL_NTS);
+ CHECK_STMT_RESULT(rc, "SQLExecDirect failed while creating temp table", hstmt);
+
+ /* Prepare a statement */
+ rc = SQLPrepare(hstmt, (SQLCHAR *) "SELECT * FROM desctable", SQL_NTS);
+ CHECK_STMT_RESULT(rc, "SQLPrepare failed", hstmt);
+
+ /* Execute */
+ rc = SQLExecute(hstmt);
+ CHECK_STMT_RESULT(rc, "SQLExecute failed", hstmt);
+
+ rc = SQLNumResultCols(hstmt, &colcount);
+ CHECK_STMT_RESULT(rc, "SQLNumResultCols failed", hstmt);
+
+ /* Get the descriptor handle */
+ rc = SQLGetStmtAttr(hstmt, SQL_ATTR_IMP_ROW_DESC, &hDesc, 0, NULL);
+ CHECK_STMT_RESULT(rc, "SQLGetStmtAttr failed", hstmt);
+
+ for (int i = 1; i <= colcount; i++)
+ {
+ rc = SQLGetDescRec(hDesc, i, name, nameLen, NULL, &type, &subType, &length, &precision, &scale, &nullable);
+ if (!SQL_SUCCEEDED(rc))
+ {
+ print_diag("SQLGetDescRec failed", SQL_HANDLE_DESC, hDesc);
+ exit(1);
+ }
+
+ printf("\n-- Column %d --\n", i);
+ printf("SQL_DESC_NAME: %s\n", name);
+ printf("SQL_DESC_TYPE: %d\n", type);
+ printf("SQL_DESC_OCTET_LENGTH: %d\n", (int) length);
+ printf("SQL_DESC_PRECISION: %d\n", precision);
+ printf("SQL_DESC_SCALE: %d\n", scale);
+ printf("SQL_DESC_NULLABLE: %d\n", nullable);
+ }
+
+ rc = SQLFreeStmt(hstmt, SQL_CLOSE);
+ CHECK_STMT_RESULT(rc, "SQLFreeStmt failed", hstmt);
+
+ /* Clean up */
+ test_disconnect();
+
+ return 0;
+}