mirror of
https://github.com/postgres/postgres.git
synced 2025-07-28 23:42:10 +03:00
Mini Update #2 -- final fixes for buffer lengths, null buffers, truncation
This commit is contained in:
@ -65,6 +65,8 @@ typedef enum {
|
|||||||
#define CONN_OPTION_VALUE_CHANGED 213
|
#define CONN_OPTION_VALUE_CHANGED 213
|
||||||
#define CONN_VALUE_OUT_OF_RANGE 214
|
#define CONN_VALUE_OUT_OF_RANGE 214
|
||||||
|
|
||||||
|
#define CONN_TRUNCATED 215
|
||||||
|
|
||||||
/* Conn_status defines */
|
/* Conn_status defines */
|
||||||
#define CONN_IN_AUTOCOMMIT 0x01
|
#define CONN_IN_AUTOCOMMIT 0x01
|
||||||
#define CONN_IN_TRANSACTION 0x02
|
#define CONN_IN_TRANSACTION 0x02
|
||||||
|
@ -79,12 +79,14 @@ static char *func = "SQLDriverConnect";
|
|||||||
ConnectionClass *conn = (ConnectionClass *) hdbc;
|
ConnectionClass *conn = (ConnectionClass *) hdbc;
|
||||||
ConnInfo *ci;
|
ConnInfo *ci;
|
||||||
#ifdef WIN32
|
#ifdef WIN32
|
||||||
RETCODE dialog_result;
|
RETCODE dialog_result, result;
|
||||||
#endif
|
#endif
|
||||||
char connStrIn[MAX_CONNECT_STRING];
|
char connStrIn[MAX_CONNECT_STRING];
|
||||||
char connStrOut[MAX_CONNECT_STRING];
|
char connStrOut[MAX_CONNECT_STRING];
|
||||||
int retval;
|
int retval;
|
||||||
char password_required = FALSE;
|
char password_required = FALSE;
|
||||||
|
int len = 0;
|
||||||
|
|
||||||
|
|
||||||
mylog("%s: entering...\n", func);
|
mylog("%s: entering...\n", func);
|
||||||
|
|
||||||
@ -166,22 +168,6 @@ dialog:
|
|||||||
return SQL_NO_DATA_FOUND;
|
return SQL_NO_DATA_FOUND;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(szConnStrOut) {
|
|
||||||
|
|
||||||
/* Return the completed string to the caller.
|
|
||||||
Only construct the connect string if a dialog was put up,
|
|
||||||
otherwise, just copy the connection input string to the output.
|
|
||||||
*/
|
|
||||||
makeConnectString(connStrOut, ci);
|
|
||||||
|
|
||||||
if(pcbConnStrOut) {
|
|
||||||
*pcbConnStrOut = strlen(connStrOut);
|
|
||||||
}
|
|
||||||
strncpy_null(szConnStrOut, connStrOut, cbConnStrOutMax);
|
|
||||||
}
|
|
||||||
|
|
||||||
mylog("szConnStrOut = '%s'\n", szConnStrOut);
|
|
||||||
qlog("conn=%u, SQLDriverConnect(out)='%s'\n", conn, szConnStrOut);
|
|
||||||
|
|
||||||
// do the actual connect
|
// do the actual connect
|
||||||
retval = CC_connect(conn, password_required);
|
retval = CC_connect(conn, password_required);
|
||||||
@ -205,8 +191,41 @@ dialog:
|
|||||||
return SQL_ERROR;
|
return SQL_ERROR;
|
||||||
}
|
}
|
||||||
|
|
||||||
mylog("SQLDRiverConnect: returning success\n");
|
/*********************************************/
|
||||||
return SQL_SUCCESS;
|
/* Create the Output Connection String */
|
||||||
|
/*********************************************/
|
||||||
|
result = SQL_SUCCESS;
|
||||||
|
|
||||||
|
makeConnectString(connStrOut, ci);
|
||||||
|
len = strlen(connStrOut);
|
||||||
|
|
||||||
|
if(szConnStrOut) {
|
||||||
|
|
||||||
|
/* Return the completed string to the caller. The correct method is to
|
||||||
|
only construct the connect string if a dialog was put up, otherwise,
|
||||||
|
it should just copy the connection input string to the output.
|
||||||
|
However, it seems ok to just always construct an output string. There
|
||||||
|
are possible bad side effects on working applications (Access) by
|
||||||
|
implementing the correct behavior, anyway.
|
||||||
|
*/
|
||||||
|
strncpy_null(szConnStrOut, connStrOut, cbConnStrOutMax);
|
||||||
|
|
||||||
|
if (len >= cbConnStrOutMax) {
|
||||||
|
result = SQL_SUCCESS_WITH_INFO;
|
||||||
|
conn->errornumber = CONN_TRUNCATED;
|
||||||
|
conn->errormsg = "The buffer was too small for the result.";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if(pcbConnStrOut)
|
||||||
|
*pcbConnStrOut = len;
|
||||||
|
|
||||||
|
mylog("szConnStrOut = '%s'\n", szConnStrOut);
|
||||||
|
qlog("conn=%u, SQLDriverConnect(out)='%s'\n", conn, szConnStrOut);
|
||||||
|
|
||||||
|
|
||||||
|
mylog("SQLDRiverConnect: returning %d\n", result);
|
||||||
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef WIN32
|
#ifdef WIN32
|
||||||
|
@ -242,6 +242,7 @@ int status;
|
|||||||
strcpy(szSqlState, "01S02");
|
strcpy(szSqlState, "01S02");
|
||||||
break;
|
break;
|
||||||
case STMT_TRUNCATED:
|
case STMT_TRUNCATED:
|
||||||
|
case CONN_TRUNCATED:
|
||||||
strcpy(szSqlState, "01004");
|
strcpy(szSqlState, "01004");
|
||||||
// data truncated
|
// data truncated
|
||||||
break;
|
break;
|
||||||
|
@ -431,7 +431,8 @@ FARPROC addr;
|
|||||||
// - - - - - - - - -
|
// - - - - - - - - -
|
||||||
|
|
||||||
// Returns the SQL string as modified by the driver.
|
// Returns the SQL string as modified by the driver.
|
||||||
|
// Currently, just copy the input string without modification
|
||||||
|
// observing buffer limits and truncation.
|
||||||
RETCODE SQL_API SQLNativeSql(
|
RETCODE SQL_API SQLNativeSql(
|
||||||
HDBC hdbc,
|
HDBC hdbc,
|
||||||
UCHAR FAR *szSqlStrIn,
|
UCHAR FAR *szSqlStrIn,
|
||||||
@ -441,12 +442,40 @@ RETCODE SQL_API SQLNativeSql(
|
|||||||
SDWORD FAR *pcbSqlStr)
|
SDWORD FAR *pcbSqlStr)
|
||||||
{
|
{
|
||||||
static char *func="SQLNativeSql";
|
static char *func="SQLNativeSql";
|
||||||
|
int len = 0;
|
||||||
|
char *ptr;
|
||||||
|
ConnectionClass *conn = (ConnectionClass *) hdbc;
|
||||||
|
RETCODE result;
|
||||||
|
|
||||||
mylog( "%s: entering...\n", func);
|
mylog( "%s: entering...cbSqlStrIn=%d\n", func, cbSqlStrIn);
|
||||||
|
|
||||||
strncpy_null(szSqlStr, szSqlStrIn, cbSqlStrMax);
|
ptr = (cbSqlStrIn == 0) ? "" : make_string(szSqlStrIn, cbSqlStrIn, NULL);
|
||||||
|
if ( ! ptr) {
|
||||||
|
conn->errornumber = CONN_NO_MEMORY_ERROR;
|
||||||
|
conn->errormsg = "No memory available to store native sql string";
|
||||||
|
CC_log_error(func, "", conn);
|
||||||
|
return SQL_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
return SQL_SUCCESS;
|
result = SQL_SUCCESS;
|
||||||
|
len = strlen(ptr);
|
||||||
|
|
||||||
|
if (szSqlStr) {
|
||||||
|
strncpy_null(szSqlStr, ptr, cbSqlStrMax);
|
||||||
|
|
||||||
|
if (len >= cbSqlStrMax) {
|
||||||
|
result = SQL_SUCCESS_WITH_INFO;
|
||||||
|
conn->errornumber = STMT_TRUNCATED;
|
||||||
|
conn->errormsg = "The buffer was too small for the result.";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (pcbSqlStr)
|
||||||
|
*pcbSqlStr = len;
|
||||||
|
|
||||||
|
free(ptr);
|
||||||
|
|
||||||
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
// - - - - - - - - -
|
// - - - - - - - - -
|
||||||
|
@ -175,13 +175,16 @@ RETCODE SQL_API SQLDescribeCol(
|
|||||||
static char *func="SQLDescribeCol";
|
static char *func="SQLDescribeCol";
|
||||||
/* gets all the information about a specific column */
|
/* gets all the information about a specific column */
|
||||||
StatementClass *stmt = (StatementClass *) hstmt;
|
StatementClass *stmt = (StatementClass *) hstmt;
|
||||||
QResultClass *result;
|
QResultClass *res;
|
||||||
char *col_name = NULL;
|
char *col_name = NULL;
|
||||||
Int4 fieldtype = 0;
|
Int4 fieldtype = 0;
|
||||||
int precision = 0;
|
int precision = 0;
|
||||||
ConnInfo *ci;
|
ConnInfo *ci;
|
||||||
char parse_ok;
|
char parse_ok;
|
||||||
char buf[255];
|
char buf[255];
|
||||||
|
int len = 0;
|
||||||
|
RETCODE result;
|
||||||
|
|
||||||
|
|
||||||
mylog("%s: entering...\n", func);
|
mylog("%s: entering...\n", func);
|
||||||
|
|
||||||
@ -239,10 +242,10 @@ char buf[255];
|
|||||||
if ( ! parse_ok) {
|
if ( ! parse_ok) {
|
||||||
SC_pre_execute(stmt);
|
SC_pre_execute(stmt);
|
||||||
|
|
||||||
result = SC_get_Result(stmt);
|
res = SC_get_Result(stmt);
|
||||||
|
|
||||||
mylog("**** SQLDescribeCol: result = %u, stmt->status = %d, !finished=%d, !premature=%d\n", result, stmt->status, stmt->status != STMT_FINISHED, stmt->status != STMT_PREMATURE);
|
mylog("**** SQLDescribeCol: res = %u, stmt->status = %d, !finished=%d, !premature=%d\n", res, stmt->status, stmt->status != STMT_FINISHED, stmt->status != STMT_PREMATURE);
|
||||||
if ( (NULL == result) || ((stmt->status != STMT_FINISHED) && (stmt->status != STMT_PREMATURE))) {
|
if ( (NULL == res) || ((stmt->status != STMT_FINISHED) && (stmt->status != STMT_PREMATURE))) {
|
||||||
/* no query has been executed on this statement */
|
/* no query has been executed on this statement */
|
||||||
stmt->errornumber = STMT_SEQUENCE_ERROR;
|
stmt->errornumber = STMT_SEQUENCE_ERROR;
|
||||||
stmt->errormsg = "No query has been assigned to this statement.";
|
stmt->errormsg = "No query has been assigned to this statement.";
|
||||||
@ -250,16 +253,16 @@ char buf[255];
|
|||||||
return SQL_ERROR;
|
return SQL_ERROR;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (icol >= QR_NumResultCols(result)) {
|
if (icol >= QR_NumResultCols(res)) {
|
||||||
stmt->errornumber = STMT_INVALID_COLUMN_NUMBER_ERROR;
|
stmt->errornumber = STMT_INVALID_COLUMN_NUMBER_ERROR;
|
||||||
stmt->errormsg = "Invalid column number in DescribeCol.";
|
stmt->errormsg = "Invalid column number in DescribeCol.";
|
||||||
sprintf(buf, "Col#=%d, #Cols=%d", icol, QR_NumResultCols(result));
|
sprintf(buf, "Col#=%d, #Cols=%d", icol, QR_NumResultCols(res));
|
||||||
SC_log_error(func, buf, stmt);
|
SC_log_error(func, buf, stmt);
|
||||||
return SQL_ERROR;
|
return SQL_ERROR;
|
||||||
}
|
}
|
||||||
|
|
||||||
col_name = QR_get_fieldname(result, icol);
|
col_name = QR_get_fieldname(res, icol);
|
||||||
fieldtype = QR_get_field_type(result, icol);
|
fieldtype = QR_get_field_type(res, icol);
|
||||||
|
|
||||||
precision = pgtype_precision(stmt, fieldtype, icol, globals.unknown_sizes); // atoi(ci->unknown_sizes)
|
precision = pgtype_precision(stmt, fieldtype, icol, globals.unknown_sizes); // atoi(ci->unknown_sizes)
|
||||||
}
|
}
|
||||||
@ -268,28 +271,40 @@ char buf[255];
|
|||||||
mylog("describeCol: col %d fieldtype = %d\n", icol, fieldtype);
|
mylog("describeCol: col %d fieldtype = %d\n", icol, fieldtype);
|
||||||
mylog("describeCol: col %d precision = %d\n", icol, precision);
|
mylog("describeCol: col %d precision = %d\n", icol, precision);
|
||||||
|
|
||||||
if (cbColNameMax >= 1) {
|
|
||||||
if (pcbColName) {
|
result = SQL_SUCCESS;
|
||||||
if (col_name)
|
|
||||||
*pcbColName = strlen(col_name);
|
/************************/
|
||||||
else
|
/* COLUMN NAME */
|
||||||
*pcbColName = 0;
|
/************************/
|
||||||
}
|
len = strlen(col_name);
|
||||||
if (szColName) {
|
|
||||||
if (col_name)
|
if (pcbColName)
|
||||||
strncpy_null(szColName, col_name, cbColNameMax);
|
*pcbColName = len;
|
||||||
else
|
|
||||||
szColName[0] = '\0';
|
if (szColName) {
|
||||||
}
|
strncpy_null(szColName, col_name, cbColNameMax);
|
||||||
|
|
||||||
|
if (len >= cbColNameMax) {
|
||||||
|
result = SQL_SUCCESS_WITH_INFO;
|
||||||
|
stmt->errornumber = STMT_TRUNCATED;
|
||||||
|
stmt->errormsg = "The buffer was too small for the result.";
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/************************/
|
||||||
|
/* SQL TYPE */
|
||||||
|
/************************/
|
||||||
if (pfSqlType) {
|
if (pfSqlType) {
|
||||||
*pfSqlType = pgtype_to_sqltype(stmt, fieldtype);
|
*pfSqlType = pgtype_to_sqltype(stmt, fieldtype);
|
||||||
|
|
||||||
mylog("describeCol: col %d *pfSqlType = %d\n", icol, *pfSqlType);
|
mylog("describeCol: col %d *pfSqlType = %d\n", icol, *pfSqlType);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/************************/
|
||||||
|
/* PRECISION */
|
||||||
|
/************************/
|
||||||
if (pcbColDef) {
|
if (pcbColDef) {
|
||||||
|
|
||||||
if ( precision < 0)
|
if ( precision < 0)
|
||||||
@ -300,6 +315,9 @@ char buf[255];
|
|||||||
mylog("describeCol: col %d *pcbColDef = %d\n", icol, *pcbColDef);
|
mylog("describeCol: col %d *pcbColDef = %d\n", icol, *pcbColDef);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/************************/
|
||||||
|
/* SCALE */
|
||||||
|
/************************/
|
||||||
if (pibScale) {
|
if (pibScale) {
|
||||||
Int2 scale;
|
Int2 scale;
|
||||||
scale = pgtype_scale(stmt, fieldtype);
|
scale = pgtype_scale(stmt, fieldtype);
|
||||||
@ -309,16 +327,16 @@ char buf[255];
|
|||||||
mylog("describeCol: col %d *pibScale = %d\n", icol, *pibScale);
|
mylog("describeCol: col %d *pibScale = %d\n", icol, *pibScale);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/************************/
|
||||||
|
/* NULLABILITY */
|
||||||
|
/************************/
|
||||||
if (pfNullable) {
|
if (pfNullable) {
|
||||||
if (parse_ok)
|
*pfNullable = (parse_ok) ? stmt->fi[icol]->nullable : pgtype_nullable(stmt, fieldtype);
|
||||||
*pfNullable = stmt->fi[icol]->nullable;
|
|
||||||
else
|
|
||||||
*pfNullable = pgtype_nullable(stmt, fieldtype);
|
|
||||||
|
|
||||||
mylog("describeCol: col %d *pfNullable = %d\n", icol, *pfNullable);
|
mylog("describeCol: col %d *pfNullable = %d\n", icol, *pfNullable);
|
||||||
}
|
}
|
||||||
|
|
||||||
return SQL_SUCCESS;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Returns result column descriptor information for a result set.
|
// Returns result column descriptor information for a result set.
|
||||||
@ -334,12 +352,14 @@ RETCODE SQL_API SQLColAttributes(
|
|||||||
{
|
{
|
||||||
static char *func = "SQLColAttributes";
|
static char *func = "SQLColAttributes";
|
||||||
StatementClass *stmt = (StatementClass *) hstmt;
|
StatementClass *stmt = (StatementClass *) hstmt;
|
||||||
char *value;
|
|
||||||
Int4 field_type = 0;
|
Int4 field_type = 0;
|
||||||
ConnInfo *ci;
|
ConnInfo *ci;
|
||||||
int unknown_sizes;
|
int unknown_sizes;
|
||||||
int cols = 0;
|
int cols = 0;
|
||||||
char parse_ok;
|
char parse_ok;
|
||||||
|
RETCODE result;
|
||||||
|
char *p = NULL;
|
||||||
|
int len = 0, value = 0;
|
||||||
|
|
||||||
mylog("%s: entering...\n", func);
|
mylog("%s: entering...\n", func);
|
||||||
|
|
||||||
@ -434,17 +454,14 @@ char parse_ok;
|
|||||||
|
|
||||||
switch(fDescType) {
|
switch(fDescType) {
|
||||||
case SQL_COLUMN_AUTO_INCREMENT:
|
case SQL_COLUMN_AUTO_INCREMENT:
|
||||||
if (pfDesc) {
|
value = pgtype_auto_increment(stmt, field_type);
|
||||||
*pfDesc = pgtype_auto_increment(stmt, field_type);
|
if (value == -1) /* non-numeric becomes FALSE (ODBC Doc) */
|
||||||
if (*pfDesc == -1) /* non-numeric becomes FALSE (ODBC Doc) */
|
value = FALSE;
|
||||||
*pfDesc = FALSE;
|
|
||||||
|
|
||||||
}
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case SQL_COLUMN_CASE_SENSITIVE:
|
case SQL_COLUMN_CASE_SENSITIVE:
|
||||||
if (pfDesc)
|
value = pgtype_case_sensitive(stmt, field_type);
|
||||||
*pfDesc = pgtype_case_sensitive(stmt, field_type);
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
/* This special case is handled above.
|
/* This special case is handled above.
|
||||||
@ -453,151 +470,127 @@ char parse_ok;
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
case SQL_COLUMN_DISPLAY_SIZE:
|
case SQL_COLUMN_DISPLAY_SIZE:
|
||||||
if (pfDesc) {
|
value = (parse_ok) ? stmt->fi[icol]->display_size : pgtype_display_size(stmt, field_type, icol, unknown_sizes);
|
||||||
if (parse_ok)
|
|
||||||
*pfDesc = stmt->fi[icol]->display_size;
|
|
||||||
else
|
|
||||||
*pfDesc = pgtype_display_size(stmt, field_type, icol, unknown_sizes);
|
|
||||||
}
|
|
||||||
|
|
||||||
mylog("SQLColAttributes: col %d, display_size= %d\n", icol, *pfDesc);
|
mylog("SQLColAttributes: col %d, display_size= %d\n", icol, value);
|
||||||
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case SQL_COLUMN_LABEL:
|
case SQL_COLUMN_LABEL:
|
||||||
if (parse_ok && stmt->fi[icol]->alias[0] != '\0') {
|
if (parse_ok && stmt->fi[icol]->alias[0] != '\0') {
|
||||||
strncpy_null((char *)rgbDesc, stmt->fi[icol]->alias, cbDescMax);
|
p = stmt->fi[icol]->alias;
|
||||||
if (pcbDesc)
|
|
||||||
*pcbDesc = strlen(stmt->fi[icol]->alias);
|
|
||||||
|
|
||||||
|
mylog("SQLColAttr: COLUMN_LABEL = '%s'\n", p);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
mylog("SQLColAttr: COLUMN_LABEL = '%s'\n", rgbDesc);
|
} // otherwise same as column name -- FALL THROUGH!!!
|
||||||
} // otherwise same as column name
|
|
||||||
|
|
||||||
case SQL_COLUMN_NAME:
|
case SQL_COLUMN_NAME:
|
||||||
|
|
||||||
if (parse_ok)
|
p = (parse_ok) ? stmt->fi[icol]->name : QR_get_fieldname(stmt->result, icol);
|
||||||
value = stmt->fi[icol]->name;
|
|
||||||
else
|
|
||||||
value = QR_get_fieldname(stmt->result, icol);
|
|
||||||
|
|
||||||
strncpy_null((char *)rgbDesc, value, cbDescMax);
|
mylog("SQLColAttr: COLUMN_NAME = '%s'\n", p);
|
||||||
|
|
||||||
if (pcbDesc)
|
|
||||||
*pcbDesc = strlen(value);
|
|
||||||
|
|
||||||
mylog("SQLColAttr: COLUMN_NAME = '%s'\n", rgbDesc);
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case SQL_COLUMN_LENGTH:
|
case SQL_COLUMN_LENGTH:
|
||||||
if (pfDesc) {
|
value = (parse_ok) ? stmt->fi[icol]->length : pgtype_length(stmt, field_type, icol, unknown_sizes);
|
||||||
if (parse_ok)
|
|
||||||
*pfDesc = stmt->fi[icol]->length;
|
mylog("SQLColAttributes: col %d, length = %d\n", icol, value);
|
||||||
else
|
|
||||||
*pfDesc = pgtype_length(stmt, field_type, icol, unknown_sizes);
|
|
||||||
}
|
|
||||||
mylog("SQLColAttributes: col %d, length = %d\n", icol, *pfDesc);
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case SQL_COLUMN_MONEY:
|
case SQL_COLUMN_MONEY:
|
||||||
if (pfDesc)
|
value = pgtype_money(stmt, field_type);
|
||||||
*pfDesc = pgtype_money(stmt, field_type);
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case SQL_COLUMN_NULLABLE:
|
case SQL_COLUMN_NULLABLE:
|
||||||
if (pfDesc) {
|
value = (parse_ok) ? stmt->fi[icol]->nullable : pgtype_nullable(stmt, field_type);
|
||||||
if (parse_ok)
|
|
||||||
*pfDesc = stmt->fi[icol]->nullable;
|
|
||||||
else
|
|
||||||
*pfDesc = pgtype_nullable(stmt, field_type);
|
|
||||||
}
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case SQL_COLUMN_OWNER_NAME:
|
case SQL_COLUMN_OWNER_NAME:
|
||||||
strncpy_null((char *)rgbDesc, "", cbDescMax);
|
p = "";
|
||||||
if (pcbDesc)
|
|
||||||
*pcbDesc = 0;
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case SQL_COLUMN_PRECISION:
|
case SQL_COLUMN_PRECISION:
|
||||||
if (pfDesc) {
|
value = (parse_ok) ? stmt->fi[icol]->precision : pgtype_precision(stmt, field_type, icol, unknown_sizes);
|
||||||
if (parse_ok)
|
|
||||||
*pfDesc = stmt->fi[icol]->precision;
|
mylog("SQLColAttributes: col %d, precision = %d\n", icol, value);
|
||||||
else
|
|
||||||
*pfDesc = pgtype_precision(stmt, field_type, icol, unknown_sizes);
|
|
||||||
}
|
|
||||||
mylog("SQLColAttributes: col %d, precision = %d\n", icol, *pfDesc);
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case SQL_COLUMN_QUALIFIER_NAME:
|
case SQL_COLUMN_QUALIFIER_NAME:
|
||||||
strncpy_null((char *)rgbDesc, "", cbDescMax);
|
p = "";
|
||||||
if (pcbDesc)
|
|
||||||
*pcbDesc = 0;
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case SQL_COLUMN_SCALE:
|
case SQL_COLUMN_SCALE:
|
||||||
if (pfDesc)
|
value = pgtype_scale(stmt, field_type);
|
||||||
*pfDesc = pgtype_scale(stmt, field_type);
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case SQL_COLUMN_SEARCHABLE:
|
case SQL_COLUMN_SEARCHABLE:
|
||||||
if (pfDesc)
|
value = pgtype_searchable(stmt, field_type);
|
||||||
*pfDesc = pgtype_searchable(stmt, field_type);
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case SQL_COLUMN_TABLE_NAME:
|
case SQL_COLUMN_TABLE_NAME:
|
||||||
if (parse_ok && stmt->fi[icol]->ti) {
|
|
||||||
strncpy_null((char *)rgbDesc, stmt->fi[icol]->ti->name, cbDescMax);
|
|
||||||
if (pcbDesc)
|
|
||||||
*pcbDesc = strlen(stmt->fi[icol]->ti->name);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
strncpy_null((char *)rgbDesc, "", cbDescMax);
|
|
||||||
if (pcbDesc)
|
|
||||||
*pcbDesc = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
mylog("SQLColAttr: TABLE_NAME = '%s'\n", rgbDesc);
|
p = (parse_ok && stmt->fi[icol]->ti) ? stmt->fi[icol]->ti->name : "";
|
||||||
|
|
||||||
|
mylog("SQLColAttr: TABLE_NAME = '%s'\n", p);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case SQL_COLUMN_TYPE:
|
case SQL_COLUMN_TYPE:
|
||||||
if (pfDesc) {
|
value = pgtype_to_sqltype(stmt, field_type);
|
||||||
*pfDesc = pgtype_to_sqltype(stmt, field_type);
|
|
||||||
}
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case SQL_COLUMN_TYPE_NAME:
|
case SQL_COLUMN_TYPE_NAME:
|
||||||
value = pgtype_to_name(stmt, field_type);
|
p = pgtype_to_name(stmt, field_type);
|
||||||
strncpy_null((char *)rgbDesc, value, cbDescMax);
|
|
||||||
if (pcbDesc)
|
|
||||||
*pcbDesc = strlen(value);
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case SQL_COLUMN_UNSIGNED:
|
case SQL_COLUMN_UNSIGNED:
|
||||||
if (pfDesc) {
|
value = pgtype_unsigned(stmt, field_type);
|
||||||
*pfDesc = pgtype_unsigned(stmt, field_type);
|
if(value == -1) /* non-numeric becomes TRUE (ODBC Doc) */
|
||||||
if(*pfDesc == -1) /* non-numeric becomes TRUE (ODBC Doc) */
|
value = TRUE;
|
||||||
*pfDesc = TRUE;
|
|
||||||
}
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case SQL_COLUMN_UPDATABLE:
|
case SQL_COLUMN_UPDATABLE:
|
||||||
if (pfDesc) {
|
/* Neither Access or Borland care about this.
|
||||||
/* Neither Access or Borland care about this.
|
|
||||||
|
|
||||||
if (field_type == PG_TYPE_OID)
|
if (field_type == PG_TYPE_OID)
|
||||||
*pfDesc = SQL_ATTR_READONLY;
|
*pfDesc = SQL_ATTR_READONLY;
|
||||||
else
|
else
|
||||||
*/
|
*/
|
||||||
|
|
||||||
*pfDesc = SQL_ATTR_WRITE;
|
value = SQL_ATTR_WRITE;
|
||||||
mylog("SQLColAttr: UPDATEABLE = %d\n", *pfDesc);
|
|
||||||
}
|
mylog("SQLColAttr: UPDATEABLE = %d\n", value);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
return SQL_SUCCESS;
|
result = SQL_SUCCESS;
|
||||||
|
|
||||||
|
if (p) { /* char/binary data */
|
||||||
|
len = strlen(p);
|
||||||
|
|
||||||
|
if (rgbDesc) {
|
||||||
|
strncpy_null((char *)rgbDesc, p, (size_t)cbDescMax);
|
||||||
|
|
||||||
|
if (len >= cbDescMax) {
|
||||||
|
result = SQL_SUCCESS_WITH_INFO;
|
||||||
|
stmt->errornumber = STMT_TRUNCATED;
|
||||||
|
stmt->errormsg = "The buffer was too small for the result.";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (pcbDesc)
|
||||||
|
*pcbDesc = len;
|
||||||
|
}
|
||||||
|
else { /* numeric data */
|
||||||
|
|
||||||
|
if (pfDesc)
|
||||||
|
*pfDesc = value;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Returns result data for a single column in the current row.
|
// Returns result data for a single column in the current row.
|
||||||
@ -1162,14 +1155,15 @@ mylog("SQLSetCursorName: hstmt=%u, szCursor=%u, cbCursorMax=%d\n", hstmt, szCurs
|
|||||||
}
|
}
|
||||||
|
|
||||||
len = (cbCursor == SQL_NTS) ? strlen(szCursor) : cbCursor;
|
len = (cbCursor == SQL_NTS) ? strlen(szCursor) : cbCursor;
|
||||||
mylog("cursor len = %d\n", len);
|
|
||||||
if (len <= 0 || len > sizeof(stmt->cursor_name) - 1) {
|
if (len <= 0 || len > sizeof(stmt->cursor_name) - 1) {
|
||||||
stmt->errornumber = STMT_INVALID_CURSOR_NAME;
|
stmt->errornumber = STMT_INVALID_CURSOR_NAME;
|
||||||
stmt->errormsg = "Invalid Cursor Name";
|
stmt->errormsg = "Invalid Cursor Name";
|
||||||
SC_log_error(func, "", stmt);
|
SC_log_error(func, "", stmt);
|
||||||
return SQL_ERROR;
|
return SQL_ERROR;
|
||||||
}
|
}
|
||||||
strncpy_null(stmt->cursor_name, szCursor, cbCursor);
|
|
||||||
|
strncpy_null(stmt->cursor_name, szCursor, len+1);
|
||||||
return SQL_SUCCESS;
|
return SQL_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1183,6 +1177,8 @@ RETCODE SQL_API SQLGetCursorName(
|
|||||||
{
|
{
|
||||||
static char *func="SQLGetCursorName";
|
static char *func="SQLGetCursorName";
|
||||||
StatementClass *stmt = (StatementClass *) hstmt;
|
StatementClass *stmt = (StatementClass *) hstmt;
|
||||||
|
int len = 0;
|
||||||
|
RETCODE result;
|
||||||
|
|
||||||
mylog("SQLGetCursorName: hstmt=%u, szCursor=%u, cbCursorMax=%d, pcbCursor=%u\n", hstmt, szCursor, cbCursorMax, pcbCursor);
|
mylog("SQLGetCursorName: hstmt=%u, szCursor=%u, cbCursorMax=%d, pcbCursor=%u\n", hstmt, szCursor, cbCursorMax, pcbCursor);
|
||||||
|
|
||||||
@ -1191,7 +1187,6 @@ mylog("SQLGetCursorName: hstmt=%u, szCursor=%u, cbCursorMax=%d, pcbCursor=%u\n",
|
|||||||
return SQL_INVALID_HANDLE;
|
return SQL_INVALID_HANDLE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
if ( stmt->cursor_name[0] == '\0') {
|
if ( stmt->cursor_name[0] == '\0') {
|
||||||
stmt->errornumber = STMT_NO_CURSOR_NAME;
|
stmt->errornumber = STMT_NO_CURSOR_NAME;
|
||||||
stmt->errormsg = "No Cursor name available";
|
stmt->errormsg = "No Cursor name available";
|
||||||
@ -1199,12 +1194,23 @@ mylog("SQLGetCursorName: hstmt=%u, szCursor=%u, cbCursorMax=%d, pcbCursor=%u\n",
|
|||||||
return SQL_ERROR;
|
return SQL_ERROR;
|
||||||
}
|
}
|
||||||
|
|
||||||
strncpy_null(szCursor, stmt->cursor_name, cbCursorMax);
|
result = SQL_SUCCESS;
|
||||||
|
len = strlen(stmt->cursor_name);
|
||||||
|
|
||||||
|
if (szCursor) {
|
||||||
|
strncpy_null(szCursor, stmt->cursor_name, cbCursorMax);
|
||||||
|
|
||||||
|
if (len >= cbCursorMax) {
|
||||||
|
result = SQL_SUCCESS_WITH_INFO;
|
||||||
|
stmt->errornumber = STMT_TRUNCATED;
|
||||||
|
stmt->errormsg = "The buffer was too small for the result.";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (pcbCursor)
|
if (pcbCursor)
|
||||||
*pcbCursor = strlen(szCursor);
|
*pcbCursor = len;
|
||||||
|
|
||||||
return SQL_SUCCESS;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user