AM_CONDITIONAL(with_unixodbc, [test $with_unixodbc = yes])
AM_CONDITIONAL(with_iodbc, [test $with_iodbc = yes])
-AC_CHECK_FUNCS(strtoll)
+AC_CHECK_FUNCS(strtoul strtoll)
AC_CHECK_LIB(socket, socket)
# to implement the thread-safe driver
AC_CHECK_TYPES(uint8)
PGAC_VAR_INT_TIMEZONE
+AC_C_CONST
+AC_TYPE_SIZE_T
+AC_STRUCT_TM
+
AC_CONFIG_FILES([Makefile])
AC_OUTPUT
rv->client_encoding = NULL;
rv->server_encoding = NULL;
rv->current_schema = NULL;
-
+ rv->num_discardp = 0;
+ rv->discardp = NULL;
/* Initialize statement options to defaults */
/* Statements under this conn will inherit these options */
/* Free cached table info */
if (self->col_info)
{
- int i;
-
for (i = 0; i < self->ntables; i++)
{
if (self->col_info[i]->result) /* Free the SQLColumns result structure */
self->col_info = NULL;
}
self->ntables = 0;
+ if (self->num_discardp > 0 && self->discardp)
+ {
+ for (i = 0; i < self->num_discardp; i++)
+ free(self->discardp[i]);
+ self->num_discardp = 0;
+ }
+ if (self->discardp)
+ {
+ free(self->discardp);
+ self->discardp = NULL;
+ }
+
mylog("exit CC_Cleanup\n");
return TRUE;
}
mylog("sending an empty query...\n");
res = CC_send_query(self, " ", NULL, CLEAR_RESULT_ON_ABORT);
- if (res == NULL || QR_get_status(res) != PGRES_EMPTY_QUERY)
+ if (res == NULL ||
+ (QR_get_status(res) != PGRES_EMPTY_QUERY &&
+ QR_command_nonfatal(res)))
{
mylog("got no result from the empty query. (probably database does not exist)\n");
CC_set_error(self, CONNECTION_NO_SUCH_DATABASE, "The database does not exist on the server\nor user authentication failed.");
{
int i;
+ if (stmt->status == STMT_EXECUTING)
+ return FALSE;
for (i = 0; i < self->num_stmts; i++)
{
- if (self->stmts[i] == stmt && stmt->status != STMT_EXECUTING)
+ if (self->stmts[i] == stmt)
{
self->stmts[i] = NULL;
return TRUE;
}
conn->result_uncommitted = 0;
CC_clear_cursors(conn, TRUE);
+ CC_discard_marked_plans(conn);
}
void CC_on_abort(ConnectionClass *conn, UDWORD opt)
{
+ BOOL set_no_trans = FALSE;
+
+ if (0 != (opt & CONN_DEAD))
+ opt |= NO_TRANS;
if (CC_is_in_trans(conn))
{
#ifdef DRIVER_CURSOR_IMPLEMENT
{
CC_set_no_trans(conn);
CC_set_no_manual_trans(conn);
+ set_no_trans = TRUE;
}
}
+ CC_clear_cursors(conn, TRUE);
if (0 != (opt & CONN_DEAD))
{
conn->status = CONN_DOWN;
conn->sock = NULL;
}
}
+ else if (set_no_trans)
+ CC_discard_marked_plans(conn);
conn->result_uncommitted = 0;
- CC_clear_cursors(conn, TRUE);
}
/*
int maxlen,
empty_reqs;
BOOL msg_truncated,
- ReadyToReturn,
+ ReadyToReturn = FALSE,
query_completed = FALSE,
before_64 = PG_VERSION_LT(self, 6.4),
aborted = FALSE,
used_passed_result_object = FALSE;
UDWORD abort_opt;
- int entered;
+ int func_cs_count = 0;
/* ERROR_MSG_LENGTH is suffcient */
char msgbuffer[ERROR_MSG_LENGTH + 1];
return NULL;
}
- ENTER_INNER_CONN_CS(self, entered);
+#define return DONT_CALL_RETURN_FROM_HERE???
+ ENTER_INNER_CONN_CS(self, func_cs_count);
SOCK_put_char(sock, 'Q');
if (SOCK_get_errcode(sock) != 0)
{
CC_set_error(self, CONNECTION_COULD_NOT_SEND, "Could not send Query to backend");
CC_on_abort(self, NO_TRANS | CONN_DEAD);
- RETURN_AFTER_LEAVE_CS(entered, self, NULL);
+ goto cleanup;
}
if (issue_begin)
{
CC_set_error(self, CONNECTION_COULD_NOT_SEND, "Could not send Query to backend");
CC_on_abort(self, NO_TRANS | CONN_DEAD);
- RETURN_AFTER_LEAVE_CS(entered, self, NULL);
+ goto cleanup;
}
mylog("send_query: done sending query\n");
- ReadyToReturn = FALSE;
empty_reqs = 0;
for (wq = query; isspace((UCHAR) *wq); wq++)
;
if (!cmdres)
{
CC_set_error(self, CONNECTION_COULD_NOT_RECEIVE, "Could not create result info in send_query.");
- RETURN_AFTER_LEAVE_CS(entered, self, NULL);
+ goto cleanup;
}
}
res = cmdres;
abort_opt = NO_TRANS | CONN_DEAD;
}
else
+ {
CC_set_errornumber(self, CONNECTION_SERVER_REPORTED_WARNING);
+ if (CC_is_in_trans(self))
+ CC_set_in_error_trans(self);
+ }
CC_on_abort(self, abort_opt);
QR_set_status(res, PGRES_FATAL_ERROR);
QR_set_message(res, msgbuffer);
}
}
+cleanup:
+ CLEANUP_FUNC_CONN_CS(func_cs_count, self);
/*
* Break before being ready to return.
*/
}
}
}
- RETURN_AFTER_LEAVE_CS(entered, self, retres);
+#undef return
+ return retres;
}
case 'E':
SOCK_get_string(sock, msgbuffer, ERROR_MSG_LENGTH);
CC_set_errormsg(self, msgbuffer);
+ if (CC_is_in_trans(self))
+ CC_set_in_error_trans(self);
CC_on_abort(self, 0);
mylog("send_function(V): 'E' - %s\n", CC_get_errormsg(self));
return ret;
}
+
+int CC_mark_a_plan_to_discard(ConnectionClass *conn, const char *plan)
+{
+ int cnt = conn->num_discardp + 1;
+ char *pname;
+
+ CC_REALLOC_return_with_error(conn->discardp, char *,
+ (cnt * sizeof(char *)), conn, "Couldn't alloc discardp.", -1)
+ CC_MALLOC_return_with_error(pname, char, (strlen(plan) + 1),
+ conn, "Couldn't alloc discardp mem.", -1)
+ strcpy(pname, plan);
+ conn->discardp[conn->num_discardp++] = pname;
+ return 1;
+}
+int CC_discard_marked_plans(ConnectionClass *conn)
+{
+ int i, cnt;
+ QResultClass *res;
+ char cmd[32];
+
+ if ((cnt = conn->num_discardp) <= 0)
+ return 0;
+ for (i = cnt - 1; i >= 0; i--)
+ {
+ sprintf(cmd, "DEALLOCATE \"%s\"", conn->discardp[i]);
+ res = CC_send_query(conn, cmd, NULL, CLEAR_RESULT_ON_ABORT);
+ if (res)
+ {
+ QR_Destructor(res);
+ free(conn->discardp[i]);
+ conn->num_discardp--;
+ }
+ else
+ return -1;
+ }
+ return 1;
+}
#define CONN_IN_AUTOCOMMIT 1L
#define CONN_IN_TRANSACTION (1L<<1)
#define CONN_IN_MANUAL_TRANSACTION (1L<<2)
+#define CONN_IN_ERROR_BEFORE_IDLE (1L<<3)
/* AutoCommit functions */
#define CC_set_autocommit_off(x) (x->transact_status &= ~CONN_IN_AUTOCOMMIT)
/* Transaction in/not functions */
#define CC_set_in_trans(x) (x->transact_status |= CONN_IN_TRANSACTION)
-#define CC_set_no_trans(x) (x->transact_status &= ~CONN_IN_TRANSACTION)
+#define CC_set_no_trans(x) (x->transact_status &= ~(CONN_IN_TRANSACTION | CONN_IN_ERROR_BEFORE_IDLE))
#define CC_is_in_trans(x) (x->transact_status & CONN_IN_TRANSACTION)
/* Manual transaction in/not functions */
#define CC_set_no_manual_trans(x) (x->transact_status &= ~CONN_IN_MANUAL_TRANSACTION)
#define CC_is_in_manual_trans(x) (x->transact_status & CONN_IN_MANUAL_TRANSACTION)
+/* Error waiting for ROLLBACK */
+#define CC_set_in_error_trans(x) (x->transact_status |= CONN_IN_ERROR_BEFORE_IDLE)
+#define CC_set_no_error_trans(x) (x->transact_status &= ~CONN_IN_ERROR_BEFORE_IDLE)
+#define CC_is_in_error_trans(x) (x->transact_status & CONN_IN_ERROR_BEFORE_IDLE)
+
#define CC_get_errornumber(x) (x->__error_number)
#define CC_get_errormsg(x) (x->__error_message)
#define CC_set_errornumber(x, n) (x->__error_number = n)
+#define CC_MALLOC_return_with_error(t, tp, s, x, m, ret) \
+ { \
+ if (t = malloc(s), NULL == t) \
+ { \
+ CC_set_error(x, CONN_NO_MEMORY_ERROR, m); \
+ return ret; \
+ } \
+ }
+#define CC_REALLOC_return_with_error(t, tp, s, x, m, ret) \
+ { \
+ if (t = (tp *) realloc(t, s), NULL == t) \
+ { \
+ CC_set_error(x, CONN_NO_MEMORY_ERROR, m); \
+ return ret; \
+ } \
+ }
+
/* For Multi-thread */
#if defined(WIN_MULTITHREAD_SUPPORT)
#define INIT_CONN_CS(x) InitializeCriticalSection(&((x)->cs))
#define ENTER_CONN_CS(x) EnterCriticalSection(&((x)->cs))
#define ENTER_INNER_CONN_CS(x, entered) \
- { EnterCriticalSection(&((x)->cs)); entered = 1; }
+ { EnterCriticalSection(&((x)->cs)); entered++; }
#define LEAVE_CONN_CS(x) LeaveCriticalSection(&((x)->cs))
#define DELETE_CONN_CS(x) DeleteCriticalSection(&((x)->cs))
#elif defined(POSIX_THREADMUTEX_SUPPORT)
if (getMutexAttr()) \
{ \
if (pthread_mutex_lock(&((x)->cs)) == 0) \
- entered = 1; \
+ entered++; \
else \
- entered = -1; \
+ -1; \
} \
else \
- entered = 0; \
+ 0; \
}
#define LEAVE_CONN_CS(x) pthread_mutex_unlock(&((x)->cs))
#define DELETE_CONN_CS(x) pthread_mutex_destroy(&((x)->cs))
#else
#define INIT_CONN_CS(x)
#define ENTER_CONN_CS(x)
-#define ENTER_INNER_CONN_CS(x, entered) {entered = 0;}
+#define ENTER_INNER_CONN_CS(x, entered) (0)
#define LEAVE_CONN_CS(x)
#define DELETE_CONN_CS(x)
#endif /* WIN_MULTITHREAD_SUPPORT */
#define LEAVE_INNER_CONN_CS(entered, conn) \
- { if (entered > 0) LEAVE_CONN_CS(conn); }
-#define RETURN_AFTER_LEAVE_CS(entered, conn, ret) \
- { if (entered > 0) LEAVE_CONN_CS(conn); return ret; }
+ { \
+ if (entered > 0) \
+ { \
+ LEAVE_CONN_CS(conn); \
+ entered--; \
+ } \
+ }
+#define CLEANUP_FUNC_CONN_CS(entered, conn) \
+ while (entered > 0) \
+ { \
+ LEAVE_CONN_CS(conn); \
+ entered--; \
+ }
/* Authentication types */
#define AUTH_REQ_OK 0
int be_key; /* auth code needed to send cancel */
UInt4 isolation;
char *current_schema;
+ int num_discardp;
+ char **discardp;
#if (ODBCVER >= 0x0300)
int num_descs;
DescriptorClass **descs;
void CC_on_abort(ConnectionClass *conn, UDWORD opt);
void ProcessRollback(ConnectionClass *conn, BOOL undo);
const char *CC_get_current_schema(ConnectionClass *conn);
+int CC_mark_a_plan_to_discard(ConnectionClass *conn, const char *plannm);
+int CC_discard_marked_plans(ConnectionClass *conn);
/* CC_send_query options */
#define CLEAR_RESULT_ON_ABORT 1L
*/
+/*
+ * Macros for unsigned long handling.
+ */
+#ifdef WIN32
+#define ATOI32U atol
+#elif defined(HAVE_STRTOUL)
+#define ATOI32U(val) strtoul(val, NULL, 10)
+#else /* HAVE_STRTOUL */
+#define ATOI32U atol
+#endif /* WIN32 */
+
/*
* Macros for BIGINT handling.
*/
*ptr;
int scnt,
i;
-#if defined(WIN32) || defined(HAVE_INT_TIMEZONE)
+#ifdef TIMEZONE_GLOBAL
long timediff;
#endif
BOOL withZone = *bZone;
*zone = 0;
st->fr = 0;
st->infinity = 0;
- if ((scnt = sscanf(str, "%4d-%2d-%2d %2d:%2d:%2d%s", &st->y, &st->m, &st->d, &st->hh, &st->mm, &st->ss, rest)) < 6)
+ rest[0] = '\0';
+ if ((scnt = sscanf(str, "%4d-%2d-%2d %2d:%2d:%2d%32s", &st->y, &st->m, &st->d, &st->hh, &st->mm, &st->ss, rest)) < 6)
return FALSE;
else if (scnt == 6)
return TRUE;
}
if (!withZone || !*bZone || st->y < 1970)
return TRUE;
-#if defined(WIN32) || defined(HAVE_INT_TIMEZONE)
+#ifdef TIMEZONE_GLOBAL
if (!tzname[0] || !tzname[0][0])
{
*bZone = FALSE;
*bZone = TRUE;
}
}
-#endif /* WIN32 */
+#endif /* TIMEZONE_GLOBAL */
return TRUE;
}
}
}
zonestr[0] = '\0';
-#if defined(WIN32) || defined(HAVE_INT_TIMEZONE)
+#ifdef TIMEZONE_GLOBAL
if (bZone && tzname[0] && tzname[0][0] && st->y >= 1970)
{
long zoneint;
else
sprintf(zonestr, "+%02d", -(int) zoneint / 3600);
}
-#endif /* WIN32 */
+#endif /* TIMEZONE_GLOBAL */
sprintf(str, "%.4d-%.2d-%.2d %.2d:%.2d:%.2d%s%s", st->y, st->m, st->d, st->hh, st->mm, st->ss, precstr, zonestr);
return TRUE;
}
if (cbValueMax > 0)
{
- copy_len = (len >= cbValueMax) ? cbValueMax - 1 : len;
+ BOOL already_copied = FALSE;
+ copy_len = (len >= cbValueMax) ? cbValueMax - 1 : len;
+#ifdef WIN_UNICODE_SUPPORT
+ if (fCType == SQL_C_WCHAR)
+ {
+ copy_len /= 2;
+ copy_len *= 2;
+ }
+#endif /* WIN_UNICODE_SUPPORT */
#ifdef HAVE_LOCALE_H
switch (field_type)
{
char *new_string;
int i, j;
- new_string = malloc( cbValueMax );
+ new_string = malloc(cbValueMax);
lc = localeconv();
for (i = 0, j = 0; ptr[i]; i++)
if (ptr[i] == '.')
new_string[j] = '\0';
strncpy_null(rgbValueBindRow, new_string, copy_len + 1);
free(new_string);
+ already_copied = TRUE;
break;
}
- default:
- /* Copy the data */
- strncpy_null(rgbValueBindRow, ptr, copy_len + 1);
- }
-#else /* HAVE_LOCALE_H */
- /* Copy the data */
- memcpy(rgbValueBindRow, ptr, copy_len);
- rgbValueBindRow[copy_len] = '\0';
+ }
#endif /* HAVE_LOCALE_H */
+ if (!already_copied)
+ {
+ /* Copy the data */
+ memcpy(rgbValueBindRow, ptr, copy_len);
+ rgbValueBindRow[copy_len] = '\0';
+ }
+#ifdef WIN_UNICODE_SUPPORT
+ if (fCType == SQL_C_WCHAR)
+ rgbValueBindRow[copy_len + 1] = '\0';
+#endif /* WIN_UNICODE_SUPPORT */
/* Adjust data_left for next time */
if (stmt->current_col >= 0)
case SQL_C_ULONG:
len = 4;
if (bind_size > 0)
- *((UDWORD *) rgbValueBindRow) = atol(neut_str);
+ *((UDWORD *) rgbValueBindRow) = ATOI32U(neut_str);
else
- *((UDWORD *) rgbValue + bind_row) = atol(neut_str);
+ *((UDWORD *) rgbValue + bind_row) = ATOI32U(neut_str);
break;
#if (ODBCVER >= 0x0300) && defined(ODBCINT64)
/* The following is for SQL_C_VARBOOKMARK */
else if (PG_TYPE_INT4 == field_type)
{
- UInt4 ival = atol(neut_str);
+ UInt4 ival = ATOI32U(neut_str);
inolog("SQL_C_VARBOOKMARK value=%d\n", ival);
if (pcbValue)
new_statement = qb->query_statement;
qb->flags = FLGB_BUILDING_PREPARE_STATEMENT;
- sprintf(new_statement, "PREPARE _PLAN%0x", stmt);
+ sprintf(new_statement, "PREPARE \"_PLAN%0x\"", stmt);
qb->npos = strlen(new_statement);
if (SQL_SUCCESS != PGAPI_NumParams(stmt, &marker_count))
{
CVT_APPEND_CHAR(qb, ';');
/* build the execute statement */
exe_statement = malloc(30 + 2 * marker_count);
- sprintf(exe_statement, "EXECUTE _PLAN%0x", stmt);
+ sprintf(exe_statement, "EXECUTE \"_PLAN%0x\"", stmt);
if (marker_count > 0)
{
elen = strlen(exe_statement);
newlen = 0;
if (0 == ns->sign)
chrform[newlen++] = '-';
- for (i = len - 1; i >= ns->scale; i--)
+ if (i = len - 1, i < ns->scale)
+ i = ns->scale;
+ for (; i >= ns->scale; i--)
chrform[newlen++] = calv[i] + '0';
if (ns->scale > 0)
{
}
}
- oid = atoi(value);
+ oid = ATOI32U(value);
stmt->lobj_fd = lo_open(conn, oid, INV_READ);
if (stmt->lobj_fd < 0)
{
flag |= BIT_PROTOCOL_64;
else if (strncmp(ci->protocol, PG63, strlen(PG63)) == 0)
flag |= BIT_PROTOCOL_63;
+ else if (strncmp(ci->protocol, "7.4", 3) == 0)
+ flag |= (BIT_PROTOCOL_63 | BIT_PROTOCOL_64);
switch (ci->drivers.unknown_sizes)
{
case UNKNOWNS_AS_DONTKNOW:
mylog("%s: entering...\n", func);
- if (result = SC_initialize_ifclosed(stmt, func), SQL_SUCCESS != result)
+ if (result = SC_initialize_and_recycle(stmt), SQL_SUCCESS != result)
return result;
/*
mylog("%s: entering...fSqlType = %d\n", func, fSqlType);
- if (result = SC_initialize_ifclosed(stmt, func), SQL_SUCCESS != result)
+ if (result = SC_initialize_and_recycle(stmt), SQL_SUCCESS != result)
return result;
stmt->manual_result = TRUE;
for (cnt = 0; cnt < pgtcount; cnt ++)
{
- row = (TupleNode *) malloc(sizeof(TupleNode) + (result_cols - 1) * sizeof(TupleField));
+ SC_MALLOC_return_with_error(row, TupleNode, (sizeof(TupleNode) + (result_cols - 1) * sizeof(TupleField)),
+ stmt, "Couldn't alloc row", SQL_ERROR)
/* These values can't be NULL */
if (1 == cnt)
set_nullfield_int2(&row->tuple[9], pgtype_unsigned(stmt, pgType));
set_nullfield_int2(&row->tuple[11], pgtype_auto_increment(stmt, pgType));
}
- set_nullfield_int2(&row->tuple[13], pgtype_scale(stmt, pgType, PG_STATIC));
- set_nullfield_int2(&row->tuple[14], pgtype_scale(stmt, pgType, PG_STATIC));
+ set_nullfield_int2(&row->tuple[13], pgtype_min_decimal_digits(stmt, pgType));
+ set_nullfield_int2(&row->tuple[14], pgtype_max_decimal_digits(stmt, pgType));
#if (ODBCVER >=0x0300)
set_nullfield_int2(&row->tuple[15], pgtype_to_sqldesctype(stmt, pgType, PG_STATIC));
set_nullfield_int2(&row->tuple[16], pgtype_to_datetime_sub(stmt, pgType));
QResultClass *res;
TupleNode *row;
HSTMT htbl_stmt;
- RETCODE result;
+ RETCODE ret = SQL_ERROR, result;
char *tableType;
char tables_query[INFO_INQUIRY_LEN];
char table_name[MAX_INFO_STRING],
mylog("%s: entering...stmt=%u scnm=%x len=%d\n", func, stmt, szTableOwner, cbTableOwner);
- if (result = SC_initialize_ifclosed(stmt, func), SQL_SUCCESS != result)
+ if (result = SC_initialize_and_recycle(stmt), SQL_SUCCESS != result)
return result;
stmt->manual_result = TRUE;
{
/* view is represented by its relkind since 7.1 */
strcpy(tables_query, "select relname, nspname, relkind"
- " from pg_catalog.pg_class, pg_catalog.pg_namespace");
+ " from pg_catalog.pg_class c, pg_catalog.pg_namespace n");
strcat(tables_query, " where relkind in ('r', 'v')");
}
else if (PG_VERSION_GE(conn, 7.1))
{
/* view is represented by its relkind since 7.1 */
strcpy(tables_query, "select relname, usename, relkind"
- " from pg_class, pg_user");
+ " from pg_class c, pg_user u");
strcat(tables_query, " where relkind in ('r', 'v')");
}
else
{
- strcpy(tables_query, "select relname, usename, relhasrules from pg_class, pg_user");
+ strcpy(tables_query, "select relname, usename, relhasrules from pg_class c, pg_user u");
strcat(tables_query, " where relkind = 'r'");
}
if (conn->schema_support)
+ {
schema_strcat1(tables_query, " and nspname %s '%.*s'", likeeq, szTableOwner, cbTableOwner, szTableName, cbTableName, conn);
+ strcat(tables_query, " and pg_catalog.pg_table_is_visible(c.oid)");
+ }
else
my_strcat1(tables_query, " and usename %s '%.*s'", likeeq, szTableOwner, cbTableOwner);
my_strcat1(tables_query, " and relname %s '%.*s'", likeeq, szTableName, cbTableName);
strcat(tables_query, " and relname !~ '^xinv[0-9]+'");
if (conn->schema_support)
- strcat(tables_query, " and pg_namespace.oid = relnamespace order by nspname, relname");
+ strcat(tables_query, " and n.oid = relnamespace order by nspname, relname");
else
strcat(tables_query, " and usesysid = relowner order by relname");
if ((result != SQL_SUCCESS) && (result != SQL_SUCCESS_WITH_INFO))
{
SC_full_error_copy(stmt, htbl_stmt);
- SC_log_error(func, "", stmt);
- PGAPI_FreeStmt(htbl_stmt, SQL_DROP);
- return SQL_ERROR;
+ goto cleanup;
}
#ifdef UNICODE_SUPPORT
if ((result != SQL_SUCCESS) && (result != SQL_SUCCESS_WITH_INFO))
{
SC_error_copy(stmt, tbl_stmt);
- SC_log_error(func, "", stmt);
- PGAPI_FreeStmt(htbl_stmt, SQL_DROP);
- return SQL_ERROR;
+ goto cleanup;
}
result = PGAPI_BindCol(htbl_stmt, 2, internal_asis_type,
if ((result != SQL_SUCCESS) && (result != SQL_SUCCESS_WITH_INFO))
{
SC_error_copy(stmt, tbl_stmt);
- SC_log_error(func, "", stmt);
- PGAPI_FreeStmt(htbl_stmt, SQL_DROP);
- return SQL_ERROR;
+ goto cleanup;
}
result = PGAPI_BindCol(htbl_stmt, 3, internal_asis_type,
relkind_or_hasrules, MAX_INFO_STRING, NULL);
if ((result != SQL_SUCCESS) && (result != SQL_SUCCESS_WITH_INFO))
{
SC_error_copy(stmt, tbl_stmt);
- SC_log_error(func, "", stmt);
- PGAPI_FreeStmt(htbl_stmt, SQL_DROP);
- return SQL_ERROR;
+ goto cleanup;
}
if (res = QR_Constructor(), !res)
{
SC_set_error(stmt, STMT_NO_MEMORY_ERROR, "Couldn't allocate memory for PGAPI_Tables result.");
- SC_log_error(func, "", stmt);
- PGAPI_FreeStmt(htbl_stmt, SQL_DROP);
- return SQL_ERROR;
+ goto cleanup;
}
SC_set_Result(stmt, res);
(view && show_views) ||
(regular_table && show_regular_tables))
{
- row = (TupleNode *) malloc(sizeof(TupleNode) + (5 - 1) *sizeof(TupleField));
+ SC_MALLOC_return_with_error(row, TupleNode, (sizeof(TupleNode) + (5 - 1) * sizeof(TupleField)), stmt, "Couldn't alloc row", SQL_ERROR)
/*set_tuplefield_string(&row->tuple[0], "");*/
set_tuplefield_null(&row->tuple[0]);
if (result != SQL_NO_DATA_FOUND)
{
SC_full_error_copy(stmt, htbl_stmt);
- SC_log_error(func, "", stmt);
- PGAPI_FreeStmt(htbl_stmt, SQL_DROP);
- return SQL_ERROR;
+ goto cleanup;
}
+ ret = SQL_SUCCESS;
+cleanup:
/*
* also, things need to think that this statement is finished so the
* results can be retrieved.
*/
stmt->status = STMT_FINISHED;
+ if (SQL_ERROR == ret)
+ SC_log_error(func, "", stmt);
/* set up the current tuple pointer for SQLFetch */
stmt->currTuple = -1;
stmt->rowset_start = -1;
SC_set_current_col(stmt, -1);
- PGAPI_FreeStmt(htbl_stmt, SQL_DROP);
- mylog("%s: EXIT, stmt=%u\n", func, stmt);
- return SQL_SUCCESS;
+ if (htbl_stmt)
+ PGAPI_FreeStmt(htbl_stmt, SQL_DROP);
+
+ mylog("%s: EXIT, stmt=%u, ret=%d\n", func, stmt, ret);
+ return ret;
}
table_name[MAX_INFO_STRING],
field_name[MAX_INFO_STRING],
field_type_name[MAX_INFO_STRING];
- Int2 field_number, sqltype,
+ Int2 field_number, sqltype, concise_type,
reserved_cols,
result_cols,
decimal_digits;
mod_length,
column_size,
ordinal;
- char useStaticPrecision;
+ char useStaticPrecision, useStaticScale;
char not_null[MAX_INFO_STRING],
relhasrules[MAX_INFO_STRING], relkind[8];
BOOL relisaview;
mylog("%s: entering...stmt=%u scnm=%x len=%d\n", func, stmt, szTableOwner, cbTableOwner);
- if (result = SC_initialize_ifclosed(stmt, func), SQL_SUCCESS != result)
+ if (result = SC_initialize_and_recycle(stmt), SQL_SUCCESS != result)
return result;
stmt->manual_result = TRUE;
{
/* For OID fields */
the_type = PG_TYPE_OID;
- row = (TupleNode *) malloc(sizeof(TupleNode) +
- (result_cols - 1) *sizeof(TupleField));
+ SC_MALLOC_return_with_error(row, TupleNode,
+ (sizeof(TupleNode) + (result_cols - 1) * sizeof(TupleField)),
+ stmt, "Couldn't alloc row", SQL_ERROR)
set_tuplefield_string(&row->tuple[0], "");
/* see note in SQLTables() */
while ((result == SQL_SUCCESS) || (result == SQL_SUCCESS_WITH_INFO))
{
- row = (TupleNode *) malloc(sizeof(TupleNode) +
- (result_cols - 1) *sizeof(TupleField));
-
+ SC_MALLOC_return_with_error(row, TupleNode,
+ (sizeof(TupleNode) + (result_cols - 1) * sizeof(TupleField)),
+ stmt, "Couldn't alloc row", SQL_ERROR)
sqltype = SQL_TYPE_NULL; /* unspecified */
set_tuplefield_string(&row->tuple[0], "");
set_tuplefield_string(&row->tuple[1], "");
set_tuplefield_string(&row->tuple[2], table_name);
set_tuplefield_string(&row->tuple[3], field_name);
- sqltype = pgtype_to_concise_type(stmt, field_type, -1);
- set_tuplefield_int2(&row->tuple[4], sqltype);
set_tuplefield_string(&row->tuple[5], field_type_name);
table_name, field_name, field_type, field_type_name);
useStaticPrecision = TRUE;
+ useStaticScale = TRUE;
if (field_type == PG_TYPE_NUMERIC)
{
if (mod_length >= 0)
{
useStaticPrecision = FALSE;
+ useStaticScale = FALSE;
column_size = (mod_length >> 16) & 0xffff;
decimal_digits = mod_length & 0xffff;
set_tuplefield_int4(&row->tuple[reserved_cols], column_size + 2); /* sign+dec.point */
}
}
+ else if ((field_type == PG_TYPE_DATETIME) ||
+ (field_type == PG_TYPE_TIMESTAMP_NO_TMZONE))
+ {
+ if (PG_VERSION_GE(conn, 7.2))
+ {
+ useStaticScale = FALSE;
+
+ set_nullfield_int2(&row->tuple[8], (Int2) mod_length);
+ }
+ }
if ((field_type == PG_TYPE_VARCHAR) ||
(field_type == PG_TYPE_BPCHAR))
set_tuplefield_int4(&row->tuple[6], mod_length);
set_tuplefield_int4(&row->tuple[7], mod_length);
- set_nullfield_int2(&row->tuple[8], pgtype_decimal_digits(stmt, field_type, PG_STATIC));
- set_tuplefield_int2(&row->tuple[13], sqltype);
#if (ODBCVER >= 0x0300)
set_tuplefield_int4(&row->tuple[15], pgtype_transfer_octet_length(stmt, field_type, PG_STATIC, PG_STATIC));
#endif /* ODBCVER */
set_tuplefield_int4(&row->tuple[6], pgtype_column_size(stmt, field_type, PG_STATIC, PG_STATIC));
set_tuplefield_int4(&row->tuple[7], pgtype_buffer_length(stmt, field_type, PG_STATIC, PG_STATIC));
- set_nullfield_int2(&row->tuple[8], pgtype_decimal_digits(stmt, field_type, PG_STATIC));
#if (ODBCVER >= 0x0300)
set_tuplefield_null(&row->tuple[15]);
#endif /* ODBCVER */
set_tuplefield_int4(&row->tuple[reserved_cols], pgtype_display_size(stmt, field_type, PG_STATIC, PG_STATIC));
}
+ if (useStaticScale)
+ {
+ set_nullfield_int2(&row->tuple[8], pgtype_decimal_digits(stmt, field_type, PG_STATIC));
+ }
if (SQL_TYPE_NULL == sqltype)
{
sqltype = pgtype_to_concise_type(stmt, field_type, PG_STATIC);
- set_tuplefield_int2(&row->tuple[13], pgtype_to_sqldesctype(stmt, field_type, PG_STATIC));
+ concise_type = pgtype_to_sqldesctype(stmt, field_type, PG_STATIC);
}
+ else
+ concise_type = sqltype;
set_tuplefield_int2(&row->tuple[4], sqltype);
set_nullfield_int2(&row->tuple[9], pgtype_radix(stmt, field_type));
set_tuplefield_string(&row->tuple[11], "");
#if (ODBCVER >= 0x0300)
set_tuplefield_null(&row->tuple[12]);
+ set_tuplefield_int2(&row->tuple[13], concise_type);
set_nullfield_int2(&row->tuple[14], pgtype_to_datetime_sub(stmt, field_type));
set_tuplefield_int4(&row->tuple[16], ordinal);
set_tuplefield_null(&row->tuple[17]);
/* For Row Versioning fields */
the_type = PG_TYPE_INT4;
- row = (TupleNode *) malloc(sizeof(TupleNode) +
- (result_cols - 1) *sizeof(TupleField));
+ SC_MALLOC_return_with_error(row, TupleNode, (sizeof(TupleNode) + (result_cols - 1) * sizeof(TupleField)),
+ stmt, "Couldn't alloc row", SQL_ERROR)
set_tuplefield_string(&row->tuple[0], "");
if (conn->schema_support)
mylog("%s: entering...stmt=%u scnm=%x len=%d colType=%d\n", func, stmt, szTableOwner, cbTableOwner, fColType);
- if (result = SC_initialize_ifclosed(stmt, func), SQL_SUCCESS != result)
+ if (result = SC_initialize_and_recycle(stmt), SQL_SUCCESS != result)
return result;
conn = SC_get_conn(stmt);
ci = &(conn->connInfo);
{
Int2 the_type = PG_TYPE_TID;
- row = (TupleNode *) malloc(sizeof(TupleNode) + (8 - 1) *sizeof(TupleField));
+ SC_MALLOC_return_with_error(row, TupleNode, (sizeof(TupleNode) + (8 - 1) * sizeof(TupleField)),
+ stmt, "Couldn't alloc row", SQL_ERROR)
set_tuplefield_null(&row->tuple[0]);
set_tuplefield_string(&row->tuple[1], "ctid");
{
if (relhasoids[0] != '1')
return SQL_NO_DATA_FOUND;
- row = (TupleNode *) malloc(sizeof(TupleNode) + (8 - 1) *sizeof(TupleField));
+ SC_MALLOC_return_with_error(row, TupleNode, (sizeof(TupleNode) + (8 - 1) *sizeof(TupleField)),
+ stmt, "Couldn't alloc row", SQL_ERROR)
set_tuplefield_int2(&row->tuple[0], SQL_SCOPE_SESSION);
set_tuplefield_string(&row->tuple[1], "oid");
if (atoi(ci->row_versioning))
{
- row = (TupleNode *) malloc(sizeof(TupleNode) + (8 - 1) *sizeof(TupleField));
+ SC_MALLOC_return_with_error(row, TupleNode,
+ (sizeof(TupleNode) + (8 - 1) * sizeof(TupleField)),
+ stmt, "Couldn't alloc row", SQL_ERROR)
set_tuplefield_null(&row->tuple[0]);
set_tuplefield_string(&row->tuple[1], "xmin");
ConnectionClass *conn;
QResultClass *res;
char index_query[INFO_INQUIRY_LEN];
- HSTMT hindx_stmt;
- RETCODE result;
- char *table_name;
+ HSTMT hcol_stmt = NULL, hindx_stmt = NULL;
+ RETCODE ret = SQL_ERROR, result;
+ char *table_name = NULL;
char index_name[MAX_INFO_STRING];
short fields_vector[INDEX_KEYS_STORAGE_COUNT];
char isunique[10],
fields_vector_len;
TupleNode *row;
int i;
- HSTMT hcol_stmt;
StatementClass *col_stmt,
*indx_stmt;
char column_name[MAX_INFO_STRING],
table_qualifier[MAX_INFO_STRING],
relhasrules[10], relkind[8];
- char **column_names = 0;
+ char **column_names = NULL;
SQLINTEGER column_name_len;
int total_columns = 0;
- char error = TRUE;
ConnInfo *ci;
char buf[256];
SWORD internal_asis_type = SQL_C_CHAR;
mylog("%s: entering...stmt=%u scnm=%x len=%d\n", func, stmt, szTableOwner, cbTableOwner);
- if (result = SC_initialize_ifclosed(stmt, func), SQL_SUCCESS != result)
+ if (result = SC_initialize_and_recycle(stmt), SQL_SUCCESS != result)
return result;
stmt->manual_result = TRUE;
if ((result != SQL_SUCCESS) && (result != SQL_SUCCESS_WITH_INFO))
{
SC_set_error(stmt, STMT_NO_MEMORY_ERROR, "PGAPI_AllocStmt failed in PGAPI_Statistics for columns.");
- goto SEEYA;
+ goto cleanup;
}
col_stmt = (StatementClass *) hcol_stmt;
if ((result != SQL_SUCCESS) && (result != SQL_SUCCESS_WITH_INFO))
{
SC_error_copy(stmt, col_stmt);
- PGAPI_FreeStmt(hcol_stmt, SQL_DROP);
- goto SEEYA;
+ goto cleanup;
}
result = PGAPI_BindCol(hcol_stmt, 4, internal_asis_type,
column_name, sizeof(column_name), &column_name_len);
if ((result != SQL_SUCCESS) && (result != SQL_SUCCESS_WITH_INFO))
{
SC_error_copy(stmt, col_stmt);
- PGAPI_FreeStmt(hcol_stmt, SQL_DROP);
- goto SEEYA;
+ goto cleanup;
}
column_names =
(char **) realloc(column_names,
total_columns * sizeof(char *));
- column_names[total_columns - 1] =
- (char *) malloc(strlen(column_name) + 1);
+ SC_MALLOC_return_with_error(column_names[total_columns - 1],
+ char, (strlen(column_name) + 1), stmt,
+ "Couldn't alloc column_name", SQL_ERROR)
strcpy(column_names[total_columns - 1], column_name);
mylog("%s: column_name = '%s'\n", func, column_name);
result = PGAPI_Fetch(hcol_stmt);
}
- if (result != SQL_NO_DATA_FOUND || total_columns == 0)
+ PGAPI_FreeStmt(hcol_stmt, SQL_DROP);
+ hcol_stmt = NULL;
+ if (result != SQL_NO_DATA_FOUND)
{
- SC_full_error_copy(stmt, col_stmt); /* "Couldn't get column
- * names in
- * SQLStatistics."; */
- PGAPI_FreeStmt(hcol_stmt, SQL_DROP);
- goto SEEYA;
-
+ SC_full_error_copy(stmt, col_stmt);
+ goto cleanup;
+ }
+ if (total_columns == 0)
+ {
+ /* Couldn't get column names in SQLStatistics.; */
+ ret = SQL_SUCCESS;
+ goto cleanup;
}
-
- PGAPI_FreeStmt(hcol_stmt, SQL_DROP);
/* get a list of indexes on this table */
result = PGAPI_AllocStmt(stmt->hdbc, &hindx_stmt);
if ((result != SQL_SUCCESS) && (result != SQL_SUCCESS_WITH_INFO))
{
SC_set_error(stmt, STMT_NO_MEMORY_ERROR, "PGAPI_AllocStmt failed in SQLStatistics for indices.");
- goto SEEYA;
+ goto cleanup;
}
indx_stmt = (StatementClass *) hindx_stmt;
* SQLStatistics.";
*/
SC_full_error_copy(stmt, indx_stmt);
- PGAPI_FreeStmt(hindx_stmt, SQL_DROP);
- goto SEEYA;
+ goto cleanup;
}
/* bind the index name column */
{
SC_error_copy(stmt, indx_stmt); /* "Couldn't bind column
* in SQLStatistics."; */
- PGAPI_FreeStmt(hindx_stmt, SQL_DROP);
- goto SEEYA;
+ goto cleanup;
}
/* bind the vector column */
{
SC_error_copy(stmt, indx_stmt); /* "Couldn't bind column
* in SQLStatistics."; */
- PGAPI_FreeStmt(hindx_stmt, SQL_DROP);
- goto SEEYA;
+ goto cleanup;
}
/* bind the "is unique" column */
{
SC_error_copy(stmt, indx_stmt); /* "Couldn't bind column
* in SQLStatistics."; */
- PGAPI_FreeStmt(hindx_stmt, SQL_DROP);
- goto SEEYA;
+ goto cleanup;
}
/* bind the "is clustered" column */
{
SC_error_copy(stmt, indx_stmt); /* "Couldn't bind column *
* in SQLStatistics."; */
- PGAPI_FreeStmt(hindx_stmt, SQL_DROP);
- goto SEEYA;
+ goto cleanup;
}
{
SC_error_copy(stmt, indx_stmt); /* "Couldn't bind column *
* in SQLStatistics."; */
- PGAPI_FreeStmt(hindx_stmt, SQL_DROP);
- goto SEEYA;
+ goto cleanup;
}
if ((result != SQL_SUCCESS) && (result != SQL_SUCCESS_WITH_INFO))
{
SC_error_copy(stmt, indx_stmt);
- PGAPI_FreeStmt(hindx_stmt, SQL_DROP);
- goto SEEYA;
+ goto cleanup;
}
relhasrules[0] = '0';
{
/* "SQLFetch failed in SQLStatistics."; */
SC_full_error_copy(stmt, indx_stmt);
- PGAPI_FreeStmt(hindx_stmt, SQL_DROP);
- goto SEEYA;
+ goto cleanup;
}
- PGAPI_FreeStmt(hindx_stmt, SQL_DROP);
-
/*
* also, things need to think that this statement is finished so the
* results can be retrieved.
*/
stmt->status = STMT_FINISHED;
- /* set up the current tuple pointer for SQLFetch */
- stmt->currTuple = -1;
- stmt->rowset_start = -1;
- SC_set_current_col(stmt, -1);
+ ret = SQL_SUCCESS;
- error = FALSE;
+cleanup:
+ /*
+ * also, things need to think that this statement is finished so the
+ * results can be retrieved.
+ */
+ stmt->status = STMT_FINISHED;
-SEEYA:
+ if (SQL_ERROR == ret)
+ SC_log_error(func, "", stmt);
+ if (hcol_stmt)
+ PGAPI_FreeStmt(hcol_stmt, SQL_DROP);
+ if (hindx_stmt)
+ PGAPI_FreeStmt(hindx_stmt, SQL_DROP);
/* These things should be freed on any error ALSO! */
- free(table_name);
- for (i = 0; i < total_columns; i++)
- free(column_names[i]);
- free(column_names);
-
- mylog("%s: EXIT, %s, stmt=%u\n", func, error ? "error" : "success", stmt);
+ if (table_name)
+ free(table_name);
+ if (column_names)
+ {
+ for (i = 0; i < total_columns; i++)
+ free(column_names[i]);
+ free(column_names);
+ }
- if (error)
+ if (SQL_SUCCESS == ret)
{
- SC_log_error(func, "", stmt);
- return SQL_ERROR;
+ /* set up the current tuple pointer for SQLFetch */
+ stmt->currTuple = -1;
+ stmt->rowset_start = -1;
+ SC_set_current_col(stmt, -1);
}
- else
- return SQL_SUCCESS;
+ mylog("%s: EXIT, stmt=%u, ret=%d\n", func, stmt, ret);
+
+ return ret;
}
/* Neither Access or Borland care about this. */
- if (result = SC_initialize_ifclosed(stmt, func), SQL_SUCCESS != result)
+ if (result = SC_initialize_and_recycle(stmt), SQL_SUCCESS != result)
return result;
SC_set_error(stmt, STMT_NOT_IMPLEMENTED_ERROR, "not implemented");
SC_log_error(func, "Function not implemented", stmt);
QResultClass *res;
ConnectionClass *conn;
TupleNode *row;
- RETCODE result;
+ RETCODE ret = SQL_ERROR, result;
int seq = 0;
- HSTMT htbl_stmt;
+ HSTMT htbl_stmt = NULL;
StatementClass *tbl_stmt;
char tables_query[INFO_INQUIRY_LEN];
char attname[MAX_INFO_STRING];
mylog("%s: entering...stmt=%u scnm=%x len=%d\n", func, stmt, szTableOwner, cbTableOwner);
- if (result = SC_initialize_ifclosed(stmt, func), SQL_SUCCESS != result)
+ if (result = SC_initialize_and_recycle(stmt), SQL_SUCCESS != result)
return result;
stmt->manual_result = TRUE;
stmt->errormsg_created = TRUE;
if (pktab[0] == '\0')
{
SC_set_error(stmt, STMT_INTERNAL_ERROR, "No Table specified to PGAPI_PrimaryKeys.");
- SC_log_error(func, "", stmt);
- PGAPI_FreeStmt(htbl_stmt, SQL_DROP);
- return SQL_ERROR;
+ goto cleanup;
}
pkscm[0] = '\0';
if (conn->schema_support)
if ((result != SQL_SUCCESS) && (result != SQL_SUCCESS_WITH_INFO))
{
SC_error_copy(stmt, tbl_stmt);
- SC_log_error(func, "", stmt);
- PGAPI_FreeStmt(htbl_stmt, SQL_DROP);
- return SQL_ERROR;
+ goto cleanup;
}
if (PG_VERSION_LE(conn, 6.4))
if ((result != SQL_SUCCESS) && (result != SQL_SUCCESS_WITH_INFO))
{
SC_full_error_copy(stmt, tbl_stmt);
- SC_log_error(func, "", stmt);
- PGAPI_FreeStmt(htbl_stmt, SQL_DROP);
- return SQL_ERROR;
+ goto cleanup;
}
result = PGAPI_Fetch(htbl_stmt);
if (result != SQL_NO_DATA_FOUND)
{
SC_full_error_copy(stmt, htbl_stmt);
- SC_log_error(func, "", stmt);
- PGAPI_FreeStmt(htbl_stmt, SQL_DROP);
- return SQL_ERROR;
+ goto cleanup;
}
+ ret = SQL_SUCCESS;
- PGAPI_FreeStmt(htbl_stmt, SQL_DROP);
-
-
+cleanup:
/*
* also, things need to think that this statement is finished so the
* results can be retrieved.
*/
stmt->status = STMT_FINISHED;
+ if (SQL_ERROR == ret)
+ SC_log_error(func, "", stmt);
+ if (htbl_stmt)
+ PGAPI_FreeStmt(htbl_stmt, SQL_DROP);
+
/* set up the current tuple pointer for SQLFetch */
stmt->currTuple = -1;
stmt->rowset_start = -1;
SC_set_current_col(stmt, -1);
- mylog("%s: EXIT, stmt=%u\n", func, stmt);
- return SQL_SUCCESS;
+ mylog("%s: EXIT, stmt=%u, ret=%d\n", func, stmt, ret);
+ return ret;
}
StatementClass *stmt = (StatementClass *) hstmt;
QResultClass *res;
TupleNode *row;
- HSTMT htbl_stmt,
- hpkey_stmt;
+ HSTMT htbl_stmt = NULL, hpkey_stmt = NULL;
StatementClass *tbl_stmt;
- RETCODE result,
- keyresult;
+ RETCODE ret = SQL_ERROR, result, keyresult;
char tables_query[INFO_INQUIRY_LEN];
char trig_deferrable[2];
char trig_initdeferred[2];
mylog("%s: entering...stmt=%u\n", func, stmt);
- if (result = SC_initialize_ifclosed(stmt, func), SQL_SUCCESS != result)
+ if (result = SC_initialize_and_recycle(stmt), SQL_SUCCESS != result)
return result;
stmt->manual_result = TRUE;
if ((result != SQL_SUCCESS) && (result != SQL_SUCCESS_WITH_INFO))
{
SC_full_error_copy(stmt, tbl_stmt);
- SC_log_error(func, "", stmt);
- PGAPI_FreeStmt(htbl_stmt, SQL_DROP);
- return SQL_ERROR;
+ goto cleanup;
}
result = PGAPI_BindCol(htbl_stmt, 1, SQL_C_BINARY,
if ((result != SQL_SUCCESS) && (result != SQL_SUCCESS_WITH_INFO))
{
SC_error_copy(stmt, tbl_stmt);
- SC_log_error(func, "", stmt);
- PGAPI_FreeStmt(htbl_stmt, SQL_DROP);
- return SQL_ERROR;
+ goto cleanup;
}
result = PGAPI_BindCol(htbl_stmt, 2, SQL_C_SHORT,
if ((result != SQL_SUCCESS) && (result != SQL_SUCCESS_WITH_INFO))
{
SC_error_copy(stmt, tbl_stmt);
- SC_log_error(func, "", stmt);
- PGAPI_FreeStmt(htbl_stmt, SQL_DROP);
- return SQL_ERROR;
+ goto cleanup;
}
result = PGAPI_BindCol(htbl_stmt, 3, internal_asis_type,
if ((result != SQL_SUCCESS) && (result != SQL_SUCCESS_WITH_INFO))
{
SC_error_copy(stmt, tbl_stmt);
- SC_log_error(func, "", stmt);
- PGAPI_FreeStmt(htbl_stmt, SQL_DROP);
- return SQL_ERROR;
+ goto cleanup;
}
result = PGAPI_BindCol(htbl_stmt, 4, internal_asis_type,
if ((result != SQL_SUCCESS) && (result != SQL_SUCCESS_WITH_INFO))
{
SC_error_copy(stmt, tbl_stmt);
- SC_log_error(func, "", stmt);
- PGAPI_FreeStmt(htbl_stmt, SQL_DROP);
- return SQL_ERROR;
+ goto cleanup;
}
result = PGAPI_BindCol(htbl_stmt, 5, internal_asis_type,
if ((result != SQL_SUCCESS) && (result != SQL_SUCCESS_WITH_INFO))
{
SC_error_copy(stmt, tbl_stmt);
- SC_log_error(func, "", stmt);
- PGAPI_FreeStmt(htbl_stmt, SQL_DROP);
- return SQL_ERROR;
+ goto cleanup;
}
result = PGAPI_BindCol(htbl_stmt, 6, internal_asis_type,
if ((result != SQL_SUCCESS) && (result != SQL_SUCCESS_WITH_INFO))
{
SC_error_copy(stmt, tbl_stmt);
- SC_log_error(func, "", stmt);
- PGAPI_FreeStmt(htbl_stmt, SQL_DROP);
- return SQL_ERROR;
+ goto cleanup;
}
result = PGAPI_BindCol(htbl_stmt, 7, SQL_C_ULONG,
if ((result != SQL_SUCCESS) && (result != SQL_SUCCESS_WITH_INFO))
{
SC_error_copy(stmt, tbl_stmt);
- SC_log_error(func, "", stmt);
- PGAPI_FreeStmt(htbl_stmt, SQL_DROP);
- return SQL_ERROR;
+ goto cleanup;
}
result = PGAPI_BindCol(htbl_stmt, 8, SQL_C_ULONG,
&relid2, sizeof(relid2), NULL);
if ((result != SQL_SUCCESS) && (result != SQL_SUCCESS_WITH_INFO))
{
SC_error_copy(stmt, tbl_stmt);
- SC_log_error(func, "", stmt);
- PGAPI_FreeStmt(htbl_stmt, SQL_DROP);
- return SQL_ERROR;
+ goto cleanup;
}
result = PGAPI_BindCol(htbl_stmt, 9, internal_asis_type,
pk_table_fetched, TABLE_NAME_STORAGE_LEN, NULL);
if ((result != SQL_SUCCESS) && (result != SQL_SUCCESS_WITH_INFO))
{
SC_error_copy(stmt, tbl_stmt);
- SC_log_error(func, "", stmt);
- PGAPI_FreeStmt(htbl_stmt, SQL_DROP);
- return SQL_ERROR;
+ goto cleanup;
}
if (conn->schema_support)
if ((result != SQL_SUCCESS) && (result != SQL_SUCCESS_WITH_INFO))
{
SC_error_copy(stmt, tbl_stmt);
- SC_log_error(func, "", stmt);
- PGAPI_FreeStmt(htbl_stmt, SQL_DROP);
- return SQL_ERROR;
+ goto cleanup;
}
}
result = PGAPI_Fetch(htbl_stmt);
if (result == SQL_NO_DATA_FOUND)
- return SQL_SUCCESS;
+ {
+ ret = SQL_SUCCESS;
+ goto cleanup;
+ }
if (result != SQL_SUCCESS)
{
SC_full_error_copy(stmt, tbl_stmt);
- SC_log_error(func, "", stmt);
- PGAPI_FreeStmt(htbl_stmt, SQL_DROP);
- return SQL_ERROR;
+ goto cleanup;
}
keyresult = PGAPI_AllocStmt(stmt->hdbc, &hpkey_stmt);
if ((keyresult != SQL_SUCCESS) && (keyresult != SQL_SUCCESS_WITH_INFO))
{
SC_set_error(stmt, STMT_NO_MEMORY_ERROR, "Couldn't allocate statement for PGAPI_ForeignKeys (pkeys) result.");
- SC_log_error(func, "", stmt);
- return SQL_ERROR;
+ goto cleanup;
}
keyresult = PGAPI_BindCol(hpkey_stmt, 4, internal_asis_type,
if (keyresult != SQL_SUCCESS)
{
SC_set_error(stmt, STMT_NO_MEMORY_ERROR, "Couldn't bindcol for primary keys for PGAPI_ForeignKeys result.");
- SC_log_error(func, "", stmt);
- PGAPI_FreeStmt(hpkey_stmt, SQL_DROP);
- return SQL_ERROR;
+ goto cleanup;
}
while (result == SQL_SUCCESS)
if (keyresult != SQL_SUCCESS)
{
SC_set_error(stmt, STMT_NO_MEMORY_ERROR, "Couldn't get primary keys for PGAPI_ForeignKeys result.");
- SC_log_error(func, "", stmt);
- PGAPI_FreeStmt(hpkey_stmt, SQL_DROP);
- return SQL_ERROR;
+ goto cleanup;
}
result = PGAPI_Fetch(htbl_stmt);
}
PGAPI_FreeStmt(hpkey_stmt, SQL_DROP);
+ hpkey_stmt = NULL;
}
/*
if ((result != SQL_SUCCESS) && (result != SQL_SUCCESS_WITH_INFO))
{
SC_error_copy(stmt, tbl_stmt);
- SC_log_error(func, "", stmt);
- PGAPI_FreeStmt(htbl_stmt, SQL_DROP);
- return SQL_ERROR;
+ goto cleanup;
}
result = PGAPI_BindCol(htbl_stmt, 1, SQL_C_BINARY,
if ((result != SQL_SUCCESS) && (result != SQL_SUCCESS_WITH_INFO))
{
SC_error_copy(stmt, tbl_stmt);
- SC_log_error(func, "", stmt);
- PGAPI_FreeStmt(htbl_stmt, SQL_DROP);
- return SQL_ERROR;
+ goto cleanup;
}
result = PGAPI_BindCol(htbl_stmt, 2, SQL_C_SHORT,
if ((result != SQL_SUCCESS) && (result != SQL_SUCCESS_WITH_INFO))
{
SC_error_copy(stmt, tbl_stmt);
- SC_log_error(func, "", stmt);
- PGAPI_FreeStmt(htbl_stmt, SQL_DROP);
- return SQL_ERROR;
+ goto cleanup;
}
result = PGAPI_BindCol(htbl_stmt, 3, internal_asis_type,
if ((result != SQL_SUCCESS) && (result != SQL_SUCCESS_WITH_INFO))
{
SC_error_copy(stmt, tbl_stmt);
- SC_log_error(func, "", stmt);
- PGAPI_FreeStmt(htbl_stmt, SQL_DROP);
- return SQL_ERROR;
+ goto cleanup;
}
result = PGAPI_BindCol(htbl_stmt, 4, internal_asis_type,
if ((result != SQL_SUCCESS) && (result != SQL_SUCCESS_WITH_INFO))
{
SC_error_copy(stmt, tbl_stmt);
- SC_log_error(func, "", stmt);
- PGAPI_FreeStmt(htbl_stmt, SQL_DROP);
- return SQL_ERROR;
+ goto cleanup;
}
result = PGAPI_BindCol(htbl_stmt, 5, internal_asis_type,
if ((result != SQL_SUCCESS) && (result != SQL_SUCCESS_WITH_INFO))
{
SC_error_copy(stmt, tbl_stmt);
- SC_log_error(func, "", stmt);
- PGAPI_FreeStmt(htbl_stmt, SQL_DROP);
- return SQL_ERROR;
+ goto cleanup;
}
result = PGAPI_BindCol(htbl_stmt, 6, internal_asis_type,
if ((result != SQL_SUCCESS) && (result != SQL_SUCCESS_WITH_INFO))
{
SC_error_copy(stmt, tbl_stmt);
- SC_log_error(func, "", stmt);
- PGAPI_FreeStmt(htbl_stmt, SQL_DROP);
- return SQL_ERROR;
+ goto cleanup;
}
result = PGAPI_BindCol(htbl_stmt, 7, SQL_C_ULONG,
if ((result != SQL_SUCCESS) && (result != SQL_SUCCESS_WITH_INFO))
{
SC_error_copy(stmt, tbl_stmt);
- SC_log_error(func, "", stmt);
- PGAPI_FreeStmt(htbl_stmt, SQL_DROP);
- return SQL_ERROR;
+ goto cleanup;
}
result = PGAPI_BindCol(htbl_stmt, 8, SQL_C_ULONG,
&relid2, sizeof(relid2), NULL);
if ((result != SQL_SUCCESS) && (result != SQL_SUCCESS_WITH_INFO))
{
SC_error_copy(stmt, tbl_stmt);
- SC_log_error(func, "", stmt);
- PGAPI_FreeStmt(htbl_stmt, SQL_DROP);
- return SQL_ERROR;
+ goto cleanup;
}
result = PGAPI_BindCol(htbl_stmt, 9, internal_asis_type,
fk_table_fetched, TABLE_NAME_STORAGE_LEN, NULL);
if ((result != SQL_SUCCESS) && (result != SQL_SUCCESS_WITH_INFO))
{
SC_error_copy(stmt, tbl_stmt);
- SC_log_error(func, "", stmt);
- PGAPI_FreeStmt(htbl_stmt, SQL_DROP);
- return SQL_ERROR;
+ goto cleanup;
}
if (conn->schema_support)
if ((result != SQL_SUCCESS) && (result != SQL_SUCCESS_WITH_INFO))
{
SC_error_copy(stmt, tbl_stmt);
- SC_log_error(func, "", stmt);
- PGAPI_FreeStmt(htbl_stmt, SQL_DROP);
- return SQL_ERROR;
+ goto cleanup;
}
}
result = PGAPI_Fetch(htbl_stmt);
if (result == SQL_NO_DATA_FOUND)
- return SQL_SUCCESS;
+ {
+ ret = SQL_SUCCESS;
+ goto cleanup;
+ }
if (result != SQL_SUCCESS)
{
SC_full_error_copy(stmt, tbl_stmt);
- SC_log_error(func, "", stmt);
- PGAPI_FreeStmt(htbl_stmt, SQL_DROP);
- return SQL_ERROR;
+ goto cleanup;
}
while (result == SQL_SUCCESS)
else
{
SC_set_error(stmt, STMT_INTERNAL_ERROR, "No tables specified to PGAPI_ForeignKeys.");
- SC_log_error(func, "", stmt);
- PGAPI_FreeStmt(htbl_stmt, SQL_DROP);
- return SQL_ERROR;
+ goto cleanup;
}
+ ret = SQL_SUCCESS;
+cleanup:
+ /*
+ * also, things need to think that this statement is finished so the
+ * results can be retrieved.
+ */
+ stmt->status = STMT_FINISHED;
+
+ if (SQL_ERROR == ret)
+ SC_log_error(func, "", stmt);
if (pkey_alloced)
free(pkey_text);
if (fkey_alloced)
free(fkey_text);
- PGAPI_FreeStmt(htbl_stmt, SQL_DROP);
+ if (htbl_stmt)
+ PGAPI_FreeStmt(htbl_stmt, SQL_DROP);
+ if (hpkey_stmt)
+ PGAPI_FreeStmt(hpkey_stmt, SQL_DROP);
- mylog("PGAPI_ForeignKeys(): EXIT, stmt=%u\n", stmt);
- return SQL_SUCCESS;
+ /* set up the current tuple pointer for SQLFetch */
+ stmt->currTuple = -1;
+ stmt->rowset_start = -1;
+ SC_set_current_col(stmt, -1);
+
+ mylog("%s(): EXIT, stmt=%u, ret=%d\n", func, stmt, ret);
+ return ret;
}
SC_log_error(func, "Function not implemented", stmt);
return SQL_ERROR;
}
- if (result = SC_initialize_ifclosed(stmt, func), SQL_SUCCESS != result)
+ if (result = SC_initialize_and_recycle(stmt), SQL_SUCCESS != result)
return result;
if (conn->schema_support)
{
SC_log_error(func, "Function not implemented", stmt);
return SQL_ERROR;
}
- if (result = SC_initialize_ifclosed(stmt, func), SQL_SUCCESS != result)
+ if (result = SC_initialize_and_recycle(stmt), SQL_SUCCESS != result)
return result;
/*
const char *likeeq = "like";
mylog("%s: entering... scnm=%x len-%d\n", func, szTableOwner, cbTableOwner);
- if (result = SC_initialize_ifclosed(stmt, func), SQL_SUCCESS != result)
+ if (result = SC_initialize_and_recycle(stmt), SQL_SUCCESS != result)
return result;
/*
SQLCHAR *TableName, SQLSMALLINT NameLength3,
SQLCHAR *ColumnName, SQLSMALLINT NameLength4)
{
+ CSTR func = "SQLColumns";
RETCODE ret;
StatementClass *stmt = (StatementClass *) StatementHandle;
SQLCHAR *ctName = CatalogName, *scName = SchemaName,
*tbName = TableName, *clName = ColumnName;
- mylog("[SQLColumns]");
+ mylog("[%s]", func);
ENTER_STMT_CS(stmt);
SC_clear_error(stmt);
- ret = PGAPI_Columns(StatementHandle, ctName, NameLength1,
+ if (SC_opencheck(stmt, func))
+ ret = SQL_ERROR;
+ else
+ ret = PGAPI_Columns(StatementHandle, ctName, NameLength1,
scName, NameLength2, tbName, NameLength3,
clName, NameLength4, 0);
if (SQL_SUCCESS == ret && 0 == QR_get_num_total_tuples(SC_get_Result(stmt)))
SQLExecDirect(HSTMT StatementHandle,
SQLCHAR *StatementText, SQLINTEGER TextLength)
{
+ CSTR func = "SQLExecDirect";
RETCODE ret;
StatementClass *stmt = (StatementClass *) StatementHandle;
- mylog("[SQLExecDirect]");
+ mylog("[%s]", func);
ENTER_STMT_CS(stmt);
SC_clear_error(stmt);
- ret = PGAPI_ExecDirect(StatementHandle, StatementText, TextLength, 0);
+ if (SC_opencheck(stmt, func))
+ ret = SQL_ERROR;
+ else
+ ret = PGAPI_ExecDirect(StatementHandle, StatementText, TextLength, 0);
LEAVE_STMT_CS(stmt);
return ret;
}
SQLGetTypeInfo(HSTMT StatementHandle,
SQLSMALLINT DataType)
{
+ CSTR func = "SQLGetTypeInfo";
RETCODE ret;
StatementClass *stmt = (StatementClass *) StatementHandle;
- mylog("[SQLGetTypeInfo]");
+ mylog("[%s]", func);
ENTER_STMT_CS(stmt);
SC_clear_error(stmt);
- ret = PGAPI_GetTypeInfo(StatementHandle, DataType);
+ if (SC_opencheck(stmt, func))
+ ret = SQL_ERROR;
+ else
+ ret = PGAPI_GetTypeInfo(StatementHandle, DataType);
LEAVE_STMT_CS(stmt);
return ret;
}
SQLSMALLINT NameLength3, SQLUSMALLINT Scope,
SQLUSMALLINT Nullable)
{
+ CSTR func = "SQLSpecialColumns";
RETCODE ret;
StatementClass *stmt = (StatementClass *) StatementHandle;
SQLCHAR *ctName = CatalogName, *scName = SchemaName, *tbName = TableName;
- mylog("[SQLSpecialColumns]");
+ mylog("[%s]", func);
ENTER_STMT_CS(stmt);
SC_clear_error(stmt);
- ret = PGAPI_SpecialColumns(StatementHandle, IdentifierType, ctName,
+ if (SC_opencheck(stmt, func))
+ ret = SQL_ERROR;
+ else
+ ret = PGAPI_SpecialColumns(StatementHandle, IdentifierType, ctName,
NameLength1, scName, NameLength2, tbName, NameLength3,
Scope, Nullable);
if (SQL_SUCCESS == ret && 0 == QR_get_num_total_tuples(SC_get_Result(stmt)))
SQLCHAR *TableName, SQLSMALLINT NameLength3,
SQLUSMALLINT Unique, SQLUSMALLINT Reserved)
{
+ CSTR func = "SQLStatistics";
RETCODE ret;
StatementClass *stmt = (StatementClass *) StatementHandle;
SQLCHAR *ctName = CatalogName, *scName = SchemaName, *tbName = TableName;
- mylog("[SQLStatistics]");
+ mylog("[%s]", func);
ENTER_STMT_CS(stmt);
SC_clear_error(stmt);
- ret = PGAPI_Statistics(StatementHandle, ctName, NameLength1,
+ if (SC_opencheck(stmt, func))
+ ret = SQL_ERROR;
+ else
+ ret = PGAPI_Statistics(StatementHandle, ctName, NameLength1,
scName, NameLength2, tbName, NameLength3,
Unique, Reserved);
if (SQL_SUCCESS == ret && 0 == QR_get_num_total_tuples(SC_get_Result(stmt)))
SQLCHAR *TableName, SQLSMALLINT NameLength3,
SQLCHAR *TableType, SQLSMALLINT NameLength4)
{
+ CSTR func = "SQLTables";
RETCODE ret;
StatementClass *stmt = (StatementClass *) StatementHandle;
SQLCHAR *ctName = CatalogName, *scName = SchemaName, *tbName = TableName;
- mylog("[SQLTables]");
+ mylog("[%s]", func);
ENTER_STMT_CS(stmt);
SC_clear_error(stmt);
- ret = PGAPI_Tables(StatementHandle, ctName, NameLength1,
+ if (SC_opencheck(stmt, func))
+ ret = SQL_ERROR;
+ else
+ ret = PGAPI_Tables(StatementHandle, ctName, NameLength1,
scName, NameLength2, tbName, NameLength3,
TableType, NameLength4);
if (SQL_SUCCESS == ret && 0 == QR_get_num_total_tuples(SC_get_Result(stmt)))
SQLCHAR *szColumnName,
SQLSMALLINT cbColumnName)
{
+ CSTR func = "SQLColumnPrivileges";
RETCODE ret;
StatementClass *stmt = (StatementClass *) hstmt;
SQLCHAR *ctName = szCatalogName, *scName = szSchemaName,
*tbName = szTableName, *clName = szColumnName;
- mylog("[SQLColumnPrivileges]");
+ mylog("[%s]", func);
ENTER_STMT_CS(stmt);
SC_clear_error(stmt);
- ret = PGAPI_ColumnPrivileges(hstmt, ctName, cbCatalogName,
+ if (SC_opencheck(stmt, func))
+ ret = SQL_ERROR;
+ else
+ ret = PGAPI_ColumnPrivileges(hstmt, ctName, cbCatalogName,
scName, cbSchemaName, tbName, cbTableName,
clName, cbColumnName);
if (SQL_SUCCESS == ret && 0 == QR_get_num_total_tuples(SC_get_Result(stmt)))
SQLCHAR *szFkTableName,
SQLSMALLINT cbFkTableName)
{
+ CSTR func = "SQLForeignKeys";
RETCODE ret;
StatementClass *stmt = (StatementClass *) hstmt;
SQLCHAR *pkctName = szPkCatalogName, *pkscName = szPkSchemaName,
*pktbName = szPkTableName, *fkctName = szFkCatalogName,
*fkscName = szFkSchemaName, *fktbName = szFkTableName;
- mylog("[SQLForeignKeys]");
+ mylog("[%s]", func);
ENTER_STMT_CS(stmt);
SC_clear_error(stmt);
- ret = PGAPI_ForeignKeys(hstmt, pkctName, cbPkCatalogName,
+ if (SC_opencheck(stmt, func))
+ ret = SQL_ERROR;
+ else
+ ret = PGAPI_ForeignKeys(hstmt, pkctName, cbPkCatalogName,
pkscName, cbPkSchemaName, pktbName, cbPkTableName,
fkctName, cbFkCatalogName, fkscName, cbFkSchemaName,
fktbName, cbFkTableName);
SQLCHAR *szTableName,
SQLSMALLINT cbTableName)
{
+ CSTR func = "SQLPrimaryKeys";
RETCODE ret;
StatementClass *stmt = (StatementClass *) hstmt;
SQLCHAR *ctName = szCatalogName, *scName = szSchemaName,
*tbName = szTableName;
- mylog("[SQLPrimaryKeys]");
+ mylog("[%s]", func);
ENTER_STMT_CS(stmt);
SC_clear_error(stmt);
- ret = PGAPI_PrimaryKeys(hstmt, ctName, cbCatalogName,
+ if (SC_opencheck(stmt, func))
+ ret = SQL_ERROR;
+ else
+ ret = PGAPI_PrimaryKeys(hstmt, ctName, cbCatalogName,
scName, cbSchemaName, tbName, cbTableName);
if (SQL_SUCCESS == ret && 0 == QR_get_num_total_tuples(SC_get_Result(stmt)))
{
SQLCHAR *szColumnName,
SQLSMALLINT cbColumnName)
{
+ CSTR func = "SQLProcedureColumns";
RETCODE ret;
StatementClass *stmt = (StatementClass *) hstmt;
SQLCHAR *ctName = szCatalogName, *scName = szSchemaName,
*prName = szProcName, *clName = szColumnName;
- mylog("[SQLProcedureColumns]");
+ mylog("[%s]", func);
ENTER_STMT_CS(stmt);
SC_clear_error(stmt);
- ret = PGAPI_ProcedureColumns(hstmt, ctName, cbCatalogName,
+ if (SC_opencheck(stmt, func))
+ ret = SQL_ERROR;
+ else
+ ret = PGAPI_ProcedureColumns(hstmt, ctName, cbCatalogName,
scName, cbSchemaName, prName, cbProcName,
clName, cbColumnName);
if (SQL_SUCCESS == ret && 0 == QR_get_num_total_tuples(SC_get_Result(stmt)))
SQLCHAR *szProcName,
SQLSMALLINT cbProcName)
{
+ CSTR func = "SQLProcedures";
RETCODE ret;
StatementClass *stmt = (StatementClass *) hstmt;
SQLCHAR *ctName = szCatalogName, *scName = szSchemaName,
*prName = szProcName;
- mylog("[SQLProcedures]");
+ mylog("[%s]", func);
ENTER_STMT_CS(stmt);
SC_clear_error(stmt);
- ret = PGAPI_Procedures(hstmt, ctName, cbCatalogName,
+ if (SC_opencheck(stmt, func))
+ ret = SQL_ERROR;
+ else
+ ret = PGAPI_Procedures(hstmt, ctName, cbCatalogName,
scName, cbSchemaName, prName, cbProcName);
if (SQL_SUCCESS == ret && 0 == QR_get_num_total_tuples(SC_get_Result(stmt)))
{
SQLCHAR *szTableName,
SQLSMALLINT cbTableName)
{
+ CSTR func = "SQLTablePrivileges";
RETCODE ret;
StatementClass *stmt = (StatementClass *) hstmt;
SQLCHAR *ctName = szCatalogName, *scName = szSchemaName,
*tbName = szTableName;
- mylog("[SQLTablePrivileges]");
+ mylog("[%s]", func);
ENTER_STMT_CS(stmt);
SC_clear_error(stmt);
- ret = PGAPI_TablePrivileges(hstmt, ctName, cbCatalogName,
+ if (SC_opencheck(stmt, func))
+ ret = SQL_ERROR;
+ else
+ ret = PGAPI_TablePrivileges(hstmt, ctName, cbCatalogName,
scName, cbSchemaName, tbName, cbTableName, 0);
if (SQL_SUCCESS == ret && 0 == QR_get_num_total_tuples(SC_get_Result(stmt)))
{
SQLSMALLINT *rgbL, blen, bMax;
char *rgbD = NULL;
- mylog("[[SQLGetDiagField]] Handle=(%u,%x) Rec=%d Id=%d\n", fHandleType,
+ mylog("[[SQLGetDiagFieldW]] Handle=(%u,%x) Rec=%d Id=%d\n", fHandleType,
handle, iRecord, fDiagField);
switch (fDiagField)
{
conn->stmtOptions.use_bookmarks = vParam;
break;
- case 1227:
- case 1228:
+ case 1204: /* SQL_COPT_SS_PRESERVE_CURSORS ? */
+ case 1227: /* SQL_SOPT_SS_HIDDEN_COLUMNS ? */
+ case 1228: /* SQL_SOPT_SS_NOBROWSETABLE ? */
if (stmt)
{
SC_set_error(stmt, STMT_OPTION_NOT_FOR_THE_DRIVER, "The option may be for MS SQL Server(Set)");
return -1;
}
+static Int2
+getTimestampMaxDecimalDigits(StatementClass *stmt, Int4 type)
+{
+ ConnectionClass *conn = SC_get_conn(stmt);
+
+ if (PG_VERSION_LT(conn, 7.2))
+ return 0;
+ return 6;
+}
+
static Int2
getTimestampDecimalDigits(StatementClass *stmt, Int4 type, int col)
{
return -1;
}
+/*
+ * corrsponds to "min_scale" in ODBC 2.x.
+ */
+Int2
+pgtype_min_decimal_digits(StatementClass *stmt, Int4 type)
+{
+ switch (type)
+ {
+ case PG_TYPE_INT2:
+ case PG_TYPE_OID:
+ case PG_TYPE_XID:
+ case PG_TYPE_INT4:
+ case PG_TYPE_INT8:
+ case PG_TYPE_FLOAT4:
+ case PG_TYPE_FLOAT8:
+ case PG_TYPE_MONEY:
+ case PG_TYPE_BOOL:
+ case PG_TYPE_ABSTIME:
+ case PG_TYPE_TIMESTAMP:
+ case PG_TYPE_DATETIME:
+ case PG_TYPE_TIMESTAMP_NO_TMZONE:
+ case PG_TYPE_NUMERIC:
+ return 0;
+ default:
+ return -1;
+ }
+}
+
+/*
+ * corrsponds to "max_scale" in ODBC 2.x.
+ */
+Int2
+pgtype_max_decimal_digits(StatementClass *stmt, Int4 type)
+{
+ switch (type)
+ {
+ case PG_TYPE_INT2:
+ case PG_TYPE_OID:
+ case PG_TYPE_XID:
+ case PG_TYPE_INT4:
+ case PG_TYPE_INT8:
+ case PG_TYPE_FLOAT4:
+ case PG_TYPE_FLOAT8:
+ case PG_TYPE_MONEY:
+ case PG_TYPE_BOOL:
+ case PG_TYPE_ABSTIME:
+ case PG_TYPE_TIMESTAMP:
+ return 0;
+ case PG_TYPE_DATETIME:
+ case PG_TYPE_TIMESTAMP_NO_TMZONE:
+ return getTimestampMaxDecimalDigits(stmt, type);
+ case PG_TYPE_NUMERIC:
+ return 38;
+ default:
+ return -1;
+ }
+}
+
/*
* corrsponds to "scale" in ODBC 2.x.
*/
Int4 pgtype_transfer_octet_length(StatementClass *stmt, Int4 type, int col, int handle_unknown_size_as);
Int2 pgtype_decimal_digits(StatementClass *stmt, Int4 type, int col); /* corresponds to "scale" in ODBC 2.x */
+Int2 pgtype_min_decimal_digits(StatementClass *stmt, Int4 type); /* corresponds to "min_scale" in ODBC 2.x */
+Int2 pgtype_max_decimal_digits(StatementClass *stmt, Int4 type); /* corresponds to "max_scale" in ODBC 2.x */
Int2 pgtype_scale(StatementClass *stmt, Int4 type, int col); /* ODBC 3.x " */
Int2 pgtype_radix(StatementClass *stmt, Int4 type);
Int2 pgtype_nullable(StatementClass *stmt, Int4 type);
void
QR_Destructor(QResultClass *self)
{
+ ConnectionClass *conn = self->conn;
+
if (!self) return;
mylog("QResult: in DESTRUCTOR\n");
* If conn is defined, then we may have used "backend_tuples", so in
* case we need to, free it up. Also, close the cursor.
*/
- if (self->conn && self->conn->sock && CC_is_in_trans(self->conn))
+ if (conn && conn->sock && CC_is_in_trans(conn))
{
if (!QR_close(self)) /* close the cursor if there is one */
{
void
QR_free_memory(QResultClass *self)
{
- register int lf,
- row;
- register TupleField *tuple = self->backend_tuples;
- int num_backend_rows = self->num_backend_rows;
- int num_fields = self->num_fields;
+ int lf, row;
+ TupleField *tuple = self->backend_tuples;
+ int num_backend_rows = self->num_backend_rows;
+ int num_fields = self->num_fields;
mylog("QResult: free memory in, fcount=%d\n", num_backend_rows);
}
if (self->keyset)
{
+ ConnectionClass *conn = self->conn;
+
free(self->keyset);
self->keyset = NULL;
self->count_keyset_allocated = 0;
- if (self->reload_count > 0 && self->conn)
+ if (self->reload_count > 0 && conn && conn->sock)
{
- QResultClass *res;
- char cmd[64];
+ char plannm[32];
+
+ sprintf(plannm, "_KEYSET_%x", self);
+ if (CC_is_in_error_trans(conn))
+ {
+ CC_mark_a_plan_to_discard(conn, plannm);
+ }
+ else
+ {
+ QResultClass *res;
+ char cmd[64];
- sprintf(cmd, "DEALLOCATE \"_KEYSET_%x\"", self);
- res = CC_send_query(self->conn, cmd, NULL, CLEAR_RESULT_ON_ABORT);
- if (res)
- QR_Destructor(res);
+ sprintf(cmd, "DEALLOCATE \"%s\"", plannm);
+ res = CC_send_query(conn, cmd, NULL, CLEAR_RESULT_ON_ABORT);
+ if (res)
+ QR_Destructor(res);
+ }
}
self->reload_count = 0;
}
self->count_backend_allocated = self->count_keyset_allocated = 0;
if (self->num_fields > 0)
{
- self->backend_tuples = (TupleField *) malloc(self->num_fields * sizeof(TupleField) * tuple_size);
- if (!self->backend_tuples)
- {
- self->status = PGRES_FATAL_ERROR;
- QR_set_message(self, "Could not get memory for tuple cache.");
- return FALSE;
- }
+ QR_MALLOC_return_with_error(self->backend_tuples,
+ TupleField,
+ (self->num_fields * sizeof(TupleField) * tuple_size),
+ self, PGRES_FATAL_ERROR,
+ "Could not get memory for tuple cache.",
+ FALSE)
self->count_backend_allocated = tuple_size;
}
if (self->haskeyset)
QR_close(QResultClass *self)
{
QResultClass *res;
+ ConnectionClass *conn = self->conn;
+ int ret = TRUE;
- if (self->conn && self->cursor && self->conn->connInfo.drivers.use_declarefetch)
+ if (conn && self->cursor && conn->connInfo.drivers.use_declarefetch)
{
- char buf[64];
+ if (!CC_is_in_error_trans(conn))
+ {
+ char buf[64];
- sprintf(buf, "close %s", self->cursor);
- mylog("QResult: closing cursor: '%s'\n", buf);
+ sprintf(buf, "close %s", self->cursor);
+ mylog("QResult: closing cursor: '%s'\n", buf);
- res = CC_send_query(self->conn, buf, NULL, CLEAR_RESULT_ON_ABORT);
+ res = CC_send_query(conn, buf, NULL, CLEAR_RESULT_ON_ABORT);
+ if (NULL == res)
+ {
+ QR_set_status(self, PGRES_FATAL_ERROR);
+ QR_set_message(self, "Error closing cursor.");
+ ret = FALSE;
+ }
+ QR_Destructor(res);
+ }
self->inTuples = FALSE;
self->currTuple = -1;
free(self->cursor);
self->cursor = NULL;
-
- if (res == NULL)
- {
- self->status = PGRES_FATAL_ERROR;
- QR_set_message(self, "Error closing cursor.");
- return FALSE;
- }
- QR_Destructor(res);
+ if (!ret)
+ return ret;
/* End the transaction if there are no cursors left on this conn */
if (CC_is_in_autocommit(self->conn) && CC_cursor_count(self->conn) == 0)
{
self->status = PGRES_FATAL_ERROR;
QR_set_message(self, "Error ending transaction.");
- return FALSE;
+ ret = FALSE;
}
}
}
- return TRUE;
+ return ret;
}
self->count_backend_allocated = 0;
if (self->num_fields > 0)
{
- self->backend_tuples = (TupleField *) realloc(self->backend_tuples,
- self->num_fields * sizeof(TupleField) * self->cache_size);
- if (!self->backend_tuples)
- {
- self->status = PGRES_FATAL_ERROR;
- QR_set_message(self, "Out of memory while reading tuples.");
- return FALSE;
- }
+ QR_REALLOC_return_with_error(self->backend_tuples, TupleField,
+ (self->num_fields * sizeof(TupleField) * self->cache_size),
+ self, "Out of memory while reading tuples.", FALSE)
self->count_backend_allocated = self->cache_size;
}
}
if (self->haskeyset && (!self->keyset || self->cache_size > self->count_keyset_allocated))
{
self->count_keyset_allocated = 0;
- self->keyset = (KeySet *) realloc(self->keyset, sizeof(KeySet) * self->cache_size);
+ QR_REALLOC_return_with_error(self->keyset, KeySet,
+ (sizeof(KeySet) * self->cache_size),
+ self, "Out of memory while reading tuples.", FALSE)
self->count_keyset_allocated = self->cache_size;
}
sprintf(fetch, "fetch %d in %s", fetch_size, self->cursor);
mylog("REALLOC: old_count = %d, size = %d\n", tuple_size, self->num_fields * sizeof(TupleField) * tuple_size);
tuple_size *= 2;
- self->backend_tuples = (TupleField *) realloc(self->backend_tuples,
- tuple_size * self->num_fields * sizeof(TupleField));
- if (!self->backend_tuples)
- {
- self->status = PGRES_FATAL_ERROR;
- QR_set_message(self, "Out of memory while reading tuples.");
- return FALSE;
- }
+ QR_REALLOC_return_with_error(self->backend_tuples, TupleField,
+ (tuple_size * self->num_fields * sizeof(TupleField)),
+ self, "Out of memory while reading tuples.", FALSE)
self->count_backend_allocated = tuple_size;
}
if (self->haskeyset &&
{
int tuple_size = self->count_keyset_allocated;
tuple_size *= 2;
- self->keyset = (KeySet *) realloc(self->keyset, sizeof(KeySet) * tuple_size);
+ QR_REALLOC_return_with_error(self->keyset, KeySet,
+ (sizeof(KeySet) * tuple_size),
+ self, "Out of memory while reading tuples.", FALSE)
self->count_keyset_allocated = tuple_size;
}
}
if (field_lf >= effective_cols)
buffer = tidoidbuf;
else
- buffer = (char *) malloc(len + 1);
+ QR_MALLOC_return_with_error(buffer, char,
+ (len + 1), self,
+ PGRES_FATAL_ERROR,
+ "Couldn't allocate buffer",
+ FALSE);
SOCK_get_n_char(sock, buffer, len);
buffer[len] = '\0';
#define QR_set_field_info(self, field_num, name, adtid, adtsize) (CI_set_field_info(self->fields, field_num, name, adtid, adtsize, -1))
/* status macros */
-#define QR_command_successful(self) ( !(self->status == PGRES_BAD_RESPONSE || self->status == PGRES_NONFATAL_ERROR || self->status == PGRES_FATAL_ERROR))
+#define QR_command_successful(self) ( !(self->status == PGRES_BAD_RESPONSE || self->status == PGRES_NONFATAL_ERROR || self->status == PGRES_FATAL_ERROR))
#define QR_command_maybe_successful(self) ( !(self->status == PGRES_BAD_RESPONSE || self->status == PGRES_FATAL_ERROR))
-#define QR_command_nonfatal(self) ( self->status == PGRES_NONFATAL_ERROR)
-#define QR_end_tuples(self) ( self->status == PGRES_END_TUPLES)
+#define QR_command_nonfatal(self) ( self->status == PGRES_NONFATAL_ERROR)
+#define QR_end_tuples(self) ( self->status == PGRES_END_TUPLES)
#define QR_set_status(self, condition) ( self->status = condition )
#define QR_set_aborted(self, aborted_) ( self->aborted = aborted_)
#define QR_set_haskeyset(self) (self->haskeyset = TRUE)
#define QR_aborted(self) (!self || self->aborted)
+#define QR_MALLOC_return_with_error(t, tp, s, self, n, m, r) \
+ { \
+ if (t = (tp *) malloc(s), NULL == t) \
+ { \
+ QR_set_status(self, n); \
+ QR_set_message(self, m); \
+ return r; \
+ } \
+ }
+#define QR_REALLOC_return_with_error(t, tp, s, self, m, r) \
+ { \
+ if (t = (tp *) realloc(t, s), NULL == t) \
+ { \
+ QR_set_status(self, PGRES_FATAL_ERROR); \
+ QR_set_message(self, m); \
+ return r; \
+ } \
+ }
+#define QR_MALLOC_exit_if_error(t, tp, s, self, n, m) \
+ { \
+ if (t = (tp *) malloc(s), NULL == t) \
+ { \
+ self->status = n; \
+ QR_set_message(self, m); \
+ goto MALLOC_exit; \
+ } \
+ }
+
/* Core Functions */
QResultClass *QR_Constructor(void);
void QR_Destructor(QResultClass *self);
value = (fi && !fi->name[0] && !fi->alias[0]) ? SQL_UNNAMED : SQL_NAMED;
break;
#endif /* ODBCVER */
- case 1212:
+ case 1212: /* SQL_CA_SS_COLUMN_KEY ? */
SC_set_error(stmt, STMT_OPTION_NOT_FOR_THE_DRIVER, "this request may be for MS SQL Server");
return SQL_ERROR;
default:
len = strlen(stmt->load_statement);
if (tidval)
- {
len += 100;
- selstr = malloc(len);
+ else if ((flag & USE_INSERTED_TID) != 0)
+ len += 50;
+ else
+ len += 20;
+ SC_MALLOC_return_with_error(selstr, char, len, stmt,
+ "Couldn't alloc selstr", NULL)
+ if (tidval)
+ {
if (latest)
{
if (stmt->ti[0]->schema[0])
sprintf(selstr, "%s where ctid = '%s' and oid = %u", stmt->load_statement, tidval, oid);
}
else if ((flag & USE_INSERTED_TID) != 0)
- {
- len += 50;
- selstr = malloc(len);
sprintf(selstr, "%s where ctid = currtid(0, '(,)') and oid = %u", stmt->load_statement, oid);
- }
else
- {
- len += 20;
- selstr = malloc(len);
sprintf(selstr, "%s where oid = %u", stmt->load_statement, oid);
- }
mylog("selstr=%s\n", selstr);
qres = CC_send_query(SC_get_conn(stmt), selstr, NULL, CLEAR_RESULT_ON_ABORT);
return ret;
}
-static const int ahead_fetch_count = 32;
+static const int pre_fetch_count = 32;
static int LoadFromKeyset(StatementClass *stmt, QResultClass * res, int rows_per_fetch, int limitrow)
{
ConnectionClass *conn = SC_get_conn(stmt);
int j;
QResultClass *qres;
- if (rows_per_fetch >= ahead_fetch_count * 2)
- keys_per_fetch = ahead_fetch_count;
+ if (rows_per_fetch >= pre_fetch_count * 2)
+ keys_per_fetch = pre_fetch_count;
else
keys_per_fetch = rows_per_fetch;
lodlen = strlen(stmt->load_statement);
3 + 4 * keys_per_fetch + 1
+ 1 + 2 + lodlen + 20 +
4 * keys_per_fetch + 1;
- qval = malloc(allen);
+ SC_MALLOC_return_with_error(qval, char, allen,
+ stmt, "Couldn't alloc qval", -1)
sprintf(qval, "PREPARE \"%s\"", planname);
sval = strchr(qval, '\0');
for (j = 0; j < keys_per_fetch; j++)
strcpy(sval, ")");
qres = CC_send_query(conn, qval, NULL, CLEAR_RESULT_ON_ABORT);
if (qres)
+ {
res->reload_count = keys_per_fetch;
+ QR_Destructor(qres);
+ }
else
{
SC_set_error(stmt, STMT_EXEC_ERROR, "Prepare for Data Load Error");
}
}
allen = 25 + 23 * keys_per_fetch;
- qval = realloc(qval, allen);
}
else
{
- keys_per_fetch = ahead_fetch_count;
+ keys_per_fetch = pre_fetch_count;
lodlen = strlen(stmt->load_statement);
allen = lodlen + 20 + 23 * keys_per_fetch;
- qval = malloc(allen);
}
+ SC_REALLOC_return_with_error(qval, char, allen,
+ stmt, "Couldn't alloc qval", -1)
}
if (res->reload_count > 0)
{
}
if (create_from_scratch)
{
- rows_per_fetch = ((ahead_fetch_count - 1) / res->rowset_size + 1) * res->rowset_size;
+ rows_per_fetch = ((pre_fetch_count - 1) / res->rowset_size + 1) * res->rowset_size;
limitrow = RowIdx2GIdx(rows_per_fetch, stmt);
}
else
#ifdef HAVE_UNIX_SOCKETS
{
un = (struct sockaddr_un *) malloc(sizeof(struct sockaddr_un));
+ if (!un)
+ {
+ self->errornumber = SOCKET_COULD_NOT_CREATE_SOCKET;
+ self->errormsg = "coulnd't allocate memory for un.";
+ return 0;
+ }
un->sun_family = family = AF_UNIX;
/* passing NULL means that this only suports the pg default "/tmp" */
UNIXSOCK_PATH(un, port, ((char *) NULL));
if (!prepared)
{
ConnectionClass *conn = SC_get_conn(stmt);
- if (CONN_CONNECTED == conn->status)
+
+ if (conn && CONN_CONNECTED == conn->status)
{
- QResultClass *res;
- char dealloc_stmt[128];
+ char plannm[32];
+
+ sprintf(plannm, "_PLAN%0x", stmt);
+ if (CC_is_in_error_trans(conn))
+ {
+ CC_mark_a_plan_to_discard(conn, plannm);
+ }
+ else
+ {
+ QResultClass *res;
+ char dealloc_stmt[128];
- sprintf(dealloc_stmt, "DEALLOCATE _PLAN%0x", stmt);
- res = CC_send_query(conn, dealloc_stmt, NULL, 0);
- if (res)
- QR_Destructor(res);
+ sprintf(dealloc_stmt, "DEALLOCATE \"%s\"", plannm);
+ res = CC_send_query(conn, dealloc_stmt, NULL, 0);
+ if (res)
+ QR_Destructor(res);
+ }
}
}
stmt->prepared = prepared;
self->execute_statement = NULL;
}
self->prepare = FALSE;
- SC_set_prepared(self,FALSE);
+ SC_set_prepared(self, FALSE);
self->statement_type = STMT_TYPE_UNKNOWN;
}
if (self->stmt_with_params)
return 0;
}
-BOOL SC_is_open(const StatementClass *self)
+BOOL SC_opencheck(StatementClass *self, const char *func)
{
QResultClass *res;
+ if (self->status == STMT_EXECUTING)
+ {
+ SC_set_error(self, STMT_SEQUENCE_ERROR, "Statement is currently executing a transaction.");
+ return TRUE;
+ }
if (res = SC_get_Curres(self), NULL != res)
{
if (res->backend_tuples)
+ {
+ SC_set_error(self, STMT_SEQUENCE_ERROR, "The cursor is open.");
+ SC_log_error(func, "", self);
return TRUE;
+ }
}
return FALSE;
}
RETCODE
-SC_initialize_ifclosed(StatementClass *self, const char *func)
+SC_initialize_and_recycle(StatementClass *self)
{
- if (!self)
- {
- SC_log_error(func, "", NULL);
- return SQL_INVALID_HANDLE;
- }
- if (self->status == STMT_EXECUTING)
- {
- SC_set_error(self, STMT_SEQUENCE_ERROR, "Statement is currently executing a transaction.");
- return FALSE;
- }
- if (SC_is_open(self))
- {
- SC_set_error(self, STMT_INVALID_CURSOR_STATE_ERROR, "The cursor is open");
- SC_log_error(func, "", self);
- return SQL_ERROR;
- }
SC_initialize_stmts(self, TRUE);
if (!SC_recycle_statement(self))
return SQL_ERROR;
return result;
}
+#define return DONT_CALL_RETURN_FROM_HERE???
RETCODE
SC_execute(StatementClass *self)
ConnInfo *ci;
UDWORD qflag = 0;
BOOL auto_begin = FALSE, is_in_trans;
- int entered;
+ int func_cs_count = 0;
conn = SC_get_conn(self);
* 2) we are in autocommit off state and the statement isn't of type
* OTHER.
*/
- ENTER_INNER_CONN_CS(conn, entered);
+ ENTER_INNER_CONN_CS(conn, func_cs_count);
if (CONN_EXECUTING == conn->status)
{
SC_set_error(self, STMT_SEQUENCE_ERROR, "Connection is already in use.");
- SC_log_error(func, "", self);
mylog("%s: problem with connection\n", func);
- RETURN_AFTER_LEAVE_CS(entered, conn, SQL_ERROR);
+ goto cleanup;
}
is_in_trans = CC_is_in_trans(conn);
if (!self->internal && !is_in_trans &&
else if (!CC_begin(conn))
{
SC_set_error(self, STMT_EXEC_ERROR, "Could not begin a transaction");
- SC_log_error(func, "", self);
- RETURN_AFTER_LEAVE_CS(entered, conn, SQL_ERROR);
+ goto cleanup;
}
}
if (CONN_DOWN != conn->status)
conn->status = oldstatus;
self->status = STMT_FINISHED;
- LEAVE_INNER_CONN_CS(entered, conn);
+ LEAVE_INNER_CONN_CS(func_cs_count, conn);
/* Check the status of the result */
if (res)
{
QR_Destructor(res);
SC_set_error(self, STMT_NO_MEMORY_ERROR,"Could not get enough free memory to store the binding information");
- SC_log_error(func, "", self);
- return SQL_ERROR;
+ goto cleanup;
}
}
}
SC_set_error(self, STMT_EXEC_ERROR, "SC_fetch to get a Procedure return failed.");
}
}
+#undef return
+cleanup:
+ CLEANUP_FUNC_CONN_CS(func_cs_count, conn);
if (SC_get_errornumber(self) == STMT_OK)
return SQL_SUCCESS;
else if (SC_get_errornumber(self) == STMT_INFO_ONLY)
{
if (stmt->num_callbacks >= stmt->allocated_callbacks)
{
- stmt->callbacks = (NeedDataCallback *) realloc(stmt->callbacks,
+ SC_REALLOC_return_with_error(stmt->callbacks, NeedDataCallback,
sizeof(NeedDataCallback) * (stmt->allocated_callbacks +
- CALLBACK_ALLOC_ONCE));
+ CALLBACK_ALLOC_ONCE), stmt,
+ "Couldn't alloc callbacks", -1)
stmt->allocated_callbacks += CALLBACK_ALLOC_ONCE;
}
stmt->callbacks[stmt->num_callbacks].func = func;
#define SC_is_lower_case(a, b) (b->connInfo.lower_case_identifier)
#endif /* ODBCVER */
+#define SC_MALLOC_return_with_error(t, tp, s, a, m, r) \
+ { \
+ if (t = (tp *) malloc(s), NULL == t) \
+ { \
+ SC_set_error(a, STMT_NO_MEMORY_ERROR, m); \
+ return r; \
+ } \
+ }
+#define SC_REALLOC_return_with_error(t, tp, s, a, m, r) \
+ { \
+ if (t = (tp *) realloc(t, s), NULL == t) \
+ { \
+ SC_set_error(a, STMT_NO_MEMORY_ERROR, m); \
+ return r; \
+ } \
+ }
+
/* options for SC_free_params() */
#define STMT_FREE_PARAMS_ALL 0
#define STMT_FREE_PARAMS_DATA_AT_EXEC_ONLY 1
StatementClass *SC_Constructor(void);
void InitializeStatementOptions(StatementOptions *opt);
char SC_Destructor(StatementClass *self);
-BOOL SC_is_open(const StatementClass *self);
-RETCODE SC_initialize_ifclosed(StatementClass *self, const char *func);
+BOOL SC_opencheck(StatementClass *self, const char *func);
+RETCODE SC_initialize_and_recycle(StatementClass *self);
int statement_type(const char *statement);
char parse_statement(StatementClass *stmt);
void SC_pre_execute(StatementClass *self);
#ifndef __VERSION_H__
#define __VERSION_H__
-#define POSTGRESDRIVERVERSION "07.03.0205"
-#define POSTGRES_RESOURCE_VERSION "07.03.0205\0"
-#define PG_DRVFILE_VERSION 7,3,2,05
+#define POSTGRESDRIVERVERSION "07.03.0207"
+#define POSTGRES_RESOURCE_VERSION "07.03.0207\0"
+#define PG_DRVFILE_VERSION 7,3,2,07
#endif
const UCHAR *str;
/*mylog("utf8_to_ucs2 ilen=%d bufcount=%d", ilen, bufcount);*/
- if (!utf8str || !ilen)
+ if (!utf8str)
return 0;
/*mylog(" string=%s\n", utf8str);*/
if (!bufcount)
str += 2;
}
}
- if (ocount && ocount < bufcount && ucs2str)
+ if (ocount < bufcount && ucs2str)
ucs2str[ocount] = 0;
/*mylog(" ocount=%d\n", ocount);*/
return ocount;