1) Add conversion from text to SQL_C_BINARY(bug report from Brad Wilson).
2) Change SQLColumns, SQLTables etc to initialize the statement handle
properly(bug report from Yutaka Tanida).
3) Improve the handling of mutex under *nix(bug report from Steve Wampler).
#define LEAVE_CONN_CS(x) LeaveCriticalSection(&((x)->cs))
#define DELETE_CONN_CS(x) DeleteCriticalSection(&((x)->cs))
#elif defined(POSIX_MULTITHREAD_SUPPORT)
-#define INIT_CONN_CS(x) pthread_mutex_init(&((x)->cs),0)
+#define INIT_CONN_CS(x) pthread_mutex_init(&((x)->cs), getMutexAttr())
#define ENTER_CONN_CS(x) pthread_mutex_lock(&((x)->cs))
#define LEAVE_CONN_CS(x) pthread_mutex_unlock(&((x)->cs))
#define DELETE_CONN_CS(x) pthread_mutex_destroy(&((x)->cs))
#endif /* ODBCINT64 */
case SQL_C_BINARY:
- if (PG_TYPE_UNKNOWN == field_type)
+ if (PG_TYPE_UNKNOWN == field_type ||
+ PG_TYPE_TEXT == field_type ||
+ PG_TYPE_VARCHAR == field_type ||
+ PG_TYPE_BPCHAR == field_type)
{
int len = SQL_NULL_DATA;
if (pcbValue)
*((SDWORD *) pcbValueBindRow) = len;
if (len > 0 && cbValueMax > 0)
+ {
memcpy(rgbValueBindRow, neut_str, len < cbValueMax ? len : cbValueMax);
+ if (cbValueMax >= len + 1)
+ rgbValueBindRow[len] = '\0';
+ }
if (cbValueMax >= len)
return COPY_OK;
else
* should work.
*/
if (globals.socket_buffersize <= 0)
+ {
+ initialize_global_cs();
getCommonDefaults(DBMS_NAME, ODBCINST_INI, NULL);
+ }
*phenv = (HENV) EN_Constructor();
if (!*phenv)
mylog("%s: entering...\n", func);
- if (!stmt)
- {
- SC_log_error(func, "", NULL);
- return SQL_INVALID_HANDLE;
- }
-
- SC_initialize_stmts(stmt, TRUE);
+ if (result = SC_initialize_ifclosed(stmt, func), SQL_SUCCESS != result)
+ return result;
/*
* keep a copy of the un-parametrized statement, in case they try to
mylog("**** %s: hstmt=%u, statement='%s'\n", func, hstmt, stmt->statement);
- stmt->prepare = FALSE;
- SC_set_prepared(stmt, FALSE);
-
/*
* If an SQLPrepare was performed prior to this, but was left in the
* premature state because an error occurred prior to SQLExecute then
/* Int4 type; */
Int4 pgType;
Int2 sqlType;
+ RETCODE result;
mylog("%s: entering...fSqlType = %d\n", func, fSqlType);
- if (!stmt)
- {
- SC_log_error(func, "", NULL);
- return SQL_INVALID_HANDLE;
- }
+ if (result = SC_initialize_ifclosed(stmt, func), SQL_SUCCESS != result)
+ return result;
stmt->manual_result = TRUE;
if (res = QR_Constructor(), !res)
mylog("%s: entering...stmt=%u scnm=%x len=%d\n", func, stmt, szTableOwner, cbTableOwner);
- if (!stmt)
- {
- SC_log_error(func, "", NULL);
- return SQL_INVALID_HANDLE;
- }
+ if (result = SC_initialize_ifclosed(stmt, func), SQL_SUCCESS != result)
+ return result;
stmt->manual_result = TRUE;
stmt->errormsg_created = TRUE;
mylog("%s: entering...stmt=%u scnm=%x len=%d\n", func, stmt, szTableOwner, cbTableOwner);
- if (!stmt)
- {
- SC_log_error(func, "", NULL);
- return SQL_INVALID_HANDLE;
- }
+ if (result = SC_initialize_ifclosed(stmt, func), SQL_SUCCESS != result)
+ return result;
stmt->manual_result = TRUE;
stmt->errormsg_created = TRUE;
mylog("%s: entering...stmt=%u scnm=%x len=%d colType=%d\n", func, stmt, szTableOwner, cbTableOwner, fColType);
- if (!stmt)
- {
- SC_log_error(func, "", NULL);
- return SQL_INVALID_HANDLE;
- }
+ if (result = SC_initialize_ifclosed(stmt, func), SQL_SUCCESS != result)
+ return result;
conn = SC_get_conn(stmt);
ci = &(conn->connInfo);
#ifdef UNICODE_SUPPORT
mylog("%s: entering...stmt=%u scnm=%x len=%d\n", func, stmt, szTableOwner, cbTableOwner);
- if (!stmt)
- {
- SC_log_error(func, "", NULL);
- return SQL_INVALID_HANDLE;
- }
+ if (result = SC_initialize_ifclosed(stmt, func), SQL_SUCCESS != result)
+ return result;
stmt->manual_result = TRUE;
stmt->errormsg_created = TRUE;
{
CSTR func = "PGAPI_ColumnPrivileges";
StatementClass *stmt = (StatementClass *) hstmt;
+ RETCODE result;
mylog("%s: entering...\n", func);
/* Neither Access or Borland care about this. */
+ if (result = SC_initialize_ifclosed(stmt, func), SQL_SUCCESS != result)
+ return result;
SC_set_error(stmt, STMT_NOT_IMPLEMENTED_ERROR, "not implemented");
SC_log_error(func, "Function not implemented", stmt);
return SQL_ERROR;
mylog("%s: entering...stmt=%u scnm=%x len=%d\n", func, stmt, szTableOwner, cbTableOwner);
- if (!stmt)
- {
- SC_log_error(func, "", NULL);
- return SQL_INVALID_HANDLE;
- }
+ if (result = SC_initialize_ifclosed(stmt, func), SQL_SUCCESS != result)
+ return result;
stmt->manual_result = TRUE;
stmt->errormsg_created = TRUE;
mylog("%s: entering...stmt=%u\n", func, stmt);
- if (!stmt)
- {
- SC_log_error(func, "", NULL);
- return SQL_INVALID_HANDLE;
- }
+ if (result = SC_initialize_ifclosed(stmt, func), SQL_SUCCESS != result)
+ return result;
stmt->manual_result = TRUE;
stmt->errormsg_created = TRUE;
char *schema_name, *procname, *params;
QResultClass *res, *tres;
Int4 tcount, paramcount, i, j, pgtype;
+ RETCODE result;
const char *likeeq = "like";
mylog("%s: entering...\n", func);
SC_log_error(func, "Function not implemented", stmt);
return SQL_ERROR;
}
- if (!SC_recycle_statement(stmt))
- return SQL_ERROR;
+ if (result = SC_initialize_ifclosed(stmt, func), SQL_SUCCESS != result)
+ return result;
if (conn->schema_support)
{
strcpy(proc_query, "select proname, proretset, prorettype, "
ConnectionClass *conn = SC_get_conn(stmt);
char proc_query[INFO_INQUIRY_LEN];
QResultClass *res;
+ RETCODE result;
const char *likeeq = "like";
mylog("%s: entering... scnm=%x len=%d\n", func, szProcOwner, cbProcOwner);
SC_log_error(func, "Function not implemented", stmt);
return SQL_ERROR;
}
- if (!SC_recycle_statement(stmt))
- return SQL_ERROR;
+ if (result = SC_initialize_ifclosed(stmt, func), SQL_SUCCESS != result)
+ return result;
/*
* The following seems the simplest implementation
BOOL grpauth, sys, su;
char (*useracl)[ACLMAX], *acl, *user, *delim, *auth;
char *reln, *owner, *priv, *schnm = NULL;
+ RETCODE result;
const char *likeeq = "like";
mylog("%s: entering... scnm=%x len-%d\n", func, szTableOwner, cbTableOwner);
- if (!SC_recycle_statement(stmt))
- return SQL_ERROR;
+ if (result = SC_initialize_ifclosed(stmt, func), SQL_SUCCESS != result)
+ return result;
/*
* a statement is actually executed, so we'll have to do this
RETCODE SQL_API SQLDummyOrdinal(void);
-#ifdef WIN32
-HINSTANCE NEAR s_hModule; /* Saved module handle. */
#if defined(WIN_MULTITHREAD_SUPPORT)
extern CRITICAL_SECTION qlog_cs, mylog_cs, conns_cs;
#elif defined(POSIX_MULTITHREAD_SUPPORT)
extern pthread_mutex_t qlog_cs, mylog_cs, conns_cs;
+static pthread_mutexattr_t recur_attr;
+const pthread_mutexattr_t* getMutexAttr(void)
+{
+ static int init = 1;
+
+ if (init)
+ {
+ if (0 != pthread_mutexattr_init(&recur_attr))
+ return NULL;
+ if (0 != pthread_mutexattr_settype(&recur_attr, PTHREAD_MUTEX_RECURSIVE_NP))
+ return NULL;
+ }
+ init = 0;
+
+ return &recur_attr;
+}
#endif /* WIN_MULTITHREAD_SUPPORT */
+int initialize_global_cs(void)
+{
+ static int init = 1;
+
+ if (!init)
+ return 0;
+ init = 0;
+#ifdef POSIX_MULTITHREAD_SUPPORT
+ getMutexAttr();
+#endif /* POSIX_MULTITHREAD_SUPPORT */
+ INIT_QLOG_CS;
+ INIT_MYLOG_CS;
+ INIT_CONNS_CS;
+
+ return 0;
+}
+
+static void finalize_global_cs(void)
+{
+ DELETE_CONNS_CS;
+ DELETE_QLOG_CS;
+ DELETE_MYLOG_CS;
+}
+
+#ifdef WIN32
+HINSTANCE NEAR s_hModule; /* Saved module handle. */
/* This is where the Driver Manager attaches to this Driver */
BOOL WINAPI
DllMain(HANDLE hInst, ULONG ul_reason_for_call, LPVOID lpReserved)
return FALSE;
}
- INIT_QLOG_CS;
- INIT_MYLOG_CS;
- INIT_CONNS_CS;
+ initialize_global_cs();
getCommonDefaults(DBMS_NAME, ODBCINST_INI, NULL);
break;
break;
case DLL_PROCESS_DETACH:
- DELETE_CONNS_CS;
- DELETE_QLOG_CS;
- DELETE_MYLOG_CS;
+ finalize_global_cs();
WSACleanup();
return TRUE;
__attribute__((constructor))
init(void)
{
+ initialize_global_cs();
getCommonDefaults(DBMS_NAME, ODBCINST_INI, NULL);
return TRUE;
}
BOOL
_init(void)
{
+ initialize_global_cs();
getCommonDefaults(DBMS_NAME, ODBCINST_INI, NULL);
return TRUE;
}
BOOL
_fini(void)
{
+ finalize_global_cs();
return TRUE;
}
#endif /* not __GNUC__ */
*
* Comments: See "notice.txt" for copyright and license information.
*
- * $Id: psqlodbc.h,v 1.79 2003/10/25 04:19:22 hinoue Exp $
+ * $Id: psqlodbc.h,v 1.80 2003/11/10 07:10:07 hinoue Exp $
*
*/
#include "misc.h"
+int initialize_global_cs(void);
+#ifdef POSIX_MULTITHTREAD_SUPPORT
+const pthread_mutexattr_t *getMutexAttr(void);
+#endif /* POSIX_MULTITHTREAD_SUPPORT */
#ifdef UNICODE_SUPPORT
UInt4 ucs2strlen(const SQLWCHAR *ucs2str);
char *ucs2_to_utf8(const SQLWCHAR *ucs2str, Int4 ilen, UInt4 *olen, BOOL tolower);
UInt4 utf8_to_ucs2_lf(const char * utf8str, Int4 ilen, BOOL lfconv, SQLWCHAR *ucs2str, UInt4 buflen);
#define utf8_to_ucs2(utf8str, ilen, ucs2str, buflen) utf8_to_ucs2_lf(utf8str, ilen, FALSE, ucs2str, buflen)
#endif /* UNICODE_SUPPORT */
+
/*#define _MEMORY_DEBUG_ */
#ifdef _MEMORY_DEBUG_
-void *debug_alloc(size_t);
-void *debug_realloc(void *, size_t);
-char *debug_strdup(const char *);
+void *debug_alloc(size_t);
+void *debug_realloc(void *, size_t);
+char *debug_strdup(const char *);
void debug_free(void *);
void debug_memory_check(void);
SC_clear_error(stmt);
parse_ok = FALSE;
- if (ci->drivers.parse && stmt->statement_type == STMT_TYPE_SELECT)
+ if (!stmt->manual_result && ci->drivers.parse && stmt->statement_type == STMT_TYPE_SELECT)
{
if (stmt->parse_status == STMT_PARSE_NONE)
{
icol--; /* use zero based column numbers */
parse_ok = FALSE;
- if (ci->drivers.parse && stmt->statement_type == STMT_TYPE_SELECT)
+ if (!stmt->manual_result && ci->drivers.parse && stmt->statement_type == STMT_TYPE_SELECT)
{
if (stmt->parse_status == STMT_PARSE_NONE)
{
unknown_sizes = UNKNOWNS_AS_MAX;
parse_ok = FALSE;
- if (ci->drivers.parse && stmt->statement_type == STMT_TYPE_SELECT)
+ if (!stmt->manual_result && ci->drivers.parse && stmt->statement_type == STMT_TYPE_SELECT)
{
if (stmt->parse_status == STMT_PARSE_NONE)
{
}
/* Free the parsed field information */
- DC_Destructor(SC_get_ARDi(self));
- DC_Destructor(SC_get_APDi(self));
- DC_Destructor(SC_get_IRDi(self));
- DC_Destructor(SC_get_IPDi(self));
+ DC_Destructor((DescriptorClass *) SC_get_ARDi(self));
+ DC_Destructor((DescriptorClass *) SC_get_APDi(self));
+ DC_Destructor((DescriptorClass *) SC_get_IRDi(self));
+ DC_Destructor((DescriptorClass *) SC_get_IPDi(self));
if (self->__error_message)
free(self->__error_message);
free(self->execute_statement);
self->execute_statement = NULL;
}
+ self->prepare = 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)
+{
+ QResultClass *res;
+
+ if (res = SC_get_Curres(self), NULL != res)
+ {
+ if (res->backend_tuples)
+ return TRUE;
+ }
+
+ return FALSE;
+}
+
+RETCODE
+SC_initialize_ifclosed(StatementClass *self, const char *func)
+{
+ 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 SQL_SUCCESS;
+}
+
/*
* Called from SQLPrepare if STMT_PREMATURE, or
* from SQLExecute if STMT_FINISHED, or
self->ntab = 0;
}
/* Free the parsed field information */
- DC_Destructor(SC_get_IRD(self));
+ DC_Destructor((DescriptorClass *) SC_get_IRD(self));
self->parse_status = STMT_PARSE_NONE;
self->updatable = FALSE;
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);
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.0202"
-#define POSTGRES_RESOURCE_VERSION "07.03.0202\0"
-#define PG_DRVFILE_VERSION 7,3,2,02
+#define POSTGRESDRIVERVERSION "07.03.0203"
+#define POSTGRES_RESOURCE_VERSION "07.03.0203\0"
+#define PG_DRVFILE_VERSION 7,3,2,03
#endif