2) Reduce time() calls for the performance.
3) Improve the handling of per Driver resource.
4) #define HAVE_STRTOLL
etc.
AC_MSG_ERROR([ODBC driver cannot be built for both unixODBC and iODBC])
fi
+#
+# Default odbc version number (--with-odbcver), default 0x0250
+#
+AC_MSG_CHECKING([for ODBC version number])
+PGAC_ARG_REQ(with, odbcver, [ --with-odbcver=VERSION change default ODBC version number
+ [0x0250]],
+ [AC_DEFINE_UNQUOTED(ODBCVER, ${withval},
+ [Define to ODBC version (--with-odbcver)])])
+AC_MSG_RESULT([$with_odbcver])
+
AM_CONDITIONAL(with_unixodbc, [test $with_unixodbc = yes])
AM_CONDITIONAL(with_iodbc, [test $with_iodbc = yes])
+AC_CHECK_FUNCS(strtoll)
+
# to implement the thread-safe driver
PGAC_ARG_BOOL(enable, pthreads, no,
[ --enable-pthreads build pthread implementation if possible],
AC_CHECK_LIB(c_r, gethostbyname)
AC_CHECK_LIB(nsl, gethostbyname_r, [],
[AC_CHECK_FUNCS(getipnodebyname gethostbyname_r, break)])
- if test "$ac_cv_func_gethostbyname_r" = yes || test "$ac_cv_lib_nsl_gethostbyname_r" = yes; then
+ if test x"$ac_cv_func_gethostbyname_r" = xyes || test x"$ac_cv_lib_nsl_gethostbyname_r" = xyes; then
AC_TRY_COMPILE([#include <netdb.h>],
[ gethostbyname_r((char *) 0, (struct hostent *) 0, (char *) 0, 0, (int *) 0);],
[AC_DEFINE(PGS_REENTRANT_API_1, 1, [Define if you have 5 parameter gethostbyname_r])],
/* fill in any defaults */
getDSNdefaults(ci);
- qlog("conn = %u, %s(DSN='%s', UID='%s', PWD='%s')\n", conn, func, ci->dsn, ci->username, ci->password);
+ qlog("conn = %u, %s(DSN='%s', UID='%s', PWD='%s')\n", conn, func, ci->dsn, ci->username, ci->password ? "xxxxx" : "");
if (CC_connect(conn, AUTH_REQ_OK, NULL) <= 0)
{
return 0;
}
- mylog("CC_connect(): DSN = '%s', server = '%s', port = '%s', database = '%s', username = '%s', password='%s'\n", ci->dsn, ci->server, ci->port, ci->database, ci->username, ci->password);
+ mylog("CC_connect(): DSN = '%s', server = '%s', port = '%s', database = '%s', username = '%s', password='%s'\n", ci->dsn, ci->server, ci->port, ci->database, ci->username, ci->password ? "xxxxx" : "");
another_version_retry:
static unsigned int conv_from_hex(const unsigned char *s);
static char *conv_to_octal(unsigned char val, char *octal);
static int pg_bin2hex(UCHAR *src, UCHAR *dst, int length);
-static int pg_hex2bin(UCHAR *src, UCHAR *dst, int length);
/*---------
* A Guide for date/time/timestamp conversions
#define ATOI64U _atoi64
#define FORMATI64 "%I64d"
#define FORMATI64U "%I64u"
-#else
+#elif defined(HAVE_STRTOLL)
#define ATOI64(val) strtoll(val, NULL, 10)
#define ATOI64U(val) strtoull(val, NULL, 10)
#define FORMATI64 "%lld"
#define FORMATI64U "%llu"
+#else /* HAVE_STRTOLL */
#endif /* WIN32 */
#endif /* ODBCINT64 */
ARDFields *opts = SC_get_ARD(stmt);
Int4 len = 0,
copy_len = 0;
- SIMPLE_TIME st;
- time_t t = time(NULL);
+ SIMPLE_TIME std_time;
+ time_t stmt_t = SC_get_time(stmt);
struct tm *tim;
#ifdef HAVE_LOCALTIME_R
struct tm tm;
}
- memset(&st, 0, sizeof(SIMPLE_TIME));
+ memset(&std_time, 0, sizeof(SIMPLE_TIME));
/* Initialize current date */
#ifdef HAVE_LOCALTIME_R
- tim = localtime_r(&t, &tm);
+ tim = localtime_r(&stmt_t, &tm);
#else
- tim = localtime(&t);
+ tim = localtime(&stmt_t);
#endif /* HAVE_LOCALTIME_R */
- st.m = tim->tm_mon + 1;
- st.d = tim->tm_mday;
- st.y = tim->tm_year + 1900;
+ std_time.m = tim->tm_mon + 1;
+ std_time.d = tim->tm_mday;
+ std_time.y = tim->tm_year + 1900;
mylog("copy_and_convert: field_type = %d, fctype = %d, value = '%s', cbValueMax=%d\n", field_type, fCType, (value == NULL) ? "<NULL>" : value, cbValueMax);
* PG_TYPE_CHAR,VARCHAR $$$
*/
case PG_TYPE_DATE:
- sscanf(value, "%4d-%2d-%2d", &st.y, &st.m, &st.d);
+ sscanf(value, "%4d-%2d-%2d", &std_time.y, &std_time.m, &std_time.d);
break;
case PG_TYPE_TIME:
- sscanf(value, "%2d:%2d:%2d", &st.hh, &st.mm, &st.ss);
+ sscanf(value, "%2d:%2d:%2d", &std_time.hh, &std_time.mm, &std_time.ss);
break;
case PG_TYPE_ABSTIME:
case PG_TYPE_DATETIME:
case PG_TYPE_TIMESTAMP_NO_TMZONE:
case PG_TYPE_TIMESTAMP:
- st.fr = 0;
- st.infinity = 0;
+ std_time.fr = 0;
+ std_time.infinity = 0;
if (strnicmp(value, "infinity", 8) == 0)
{
- st.infinity = 1;
- st.m = 12;
- st.d = 31;
- st.y = 9999;
- st.hh = 23;
- st.mm = 59;
- st.ss = 59;
+ std_time.infinity = 1;
+ std_time.m = 12;
+ std_time.d = 31;
+ std_time.y = 9999;
+ std_time.hh = 23;
+ std_time.mm = 59;
+ std_time.ss = 59;
}
if (strnicmp(value, "-infinity", 9) == 0)
{
- st.infinity = -1;
- st.m = 0;
- st.d = 0;
- st.y = 0;
- st.hh = 0;
- st.mm = 0;
- st.ss = 0;
+ std_time.infinity = -1;
+ std_time.m = 0;
+ std_time.d = 0;
+ std_time.y = 0;
+ std_time.hh = 0;
+ std_time.mm = 0;
+ std_time.ss = 0;
}
if (strnicmp(value, "invalid", 7) != 0)
{
int zone;
/*
- * sscanf(value, "%4d-%2d-%2d %2d:%2d:%2d", &st.y, &st.m,
- * &st.d, &st.hh, &st.mm, &st.ss);
+ * sscanf(value, "%4d-%2d-%2d %2d:%2d:%2d", &std_time.y, &std_time.m,
+ * &std_time.d, &std_time.hh, &std_time.mm, &std_time.ss);
*/
bZone = FALSE; /* time zone stuff is unreliable */
- timestamp2stime(value, &st, &bZone, &zone);
+ timestamp2stime(value, &std_time, &bZone, &zone);
+inolog("2stime fr=%d\n", std_time.fr);
}
else
{
* The timestamp is invalid so set something conspicuous,
* like the epoch
*/
- t = 0;
+ time_t t = 0;
#ifdef HAVE_LOCALTIME_R
tim = localtime_r(&t, &tm);
#else
tim = localtime(&t);
#endif /* HAVE_LOCALTIME_R */
- st.m = tim->tm_mon + 1;
- st.d = tim->tm_mday;
- st.y = tim->tm_year + 1900;
- st.hh = tim->tm_hour;
- st.mm = tim->tm_min;
- st.ss = tim->tm_sec;
+ std_time.m = tim->tm_mon + 1;
+ std_time.d = tim->tm_mday;
+ std_time.y = tim->tm_year + 1900;
+ std_time.hh = tim->tm_hour;
+ std_time.mm = tim->tm_min;
+ std_time.ss = tim->tm_sec;
}
break;
case PG_TYPE_DATE:
len = 10;
if (cbValueMax > len)
- sprintf(rgbValueBindRow, "%.4d-%.2d-%.2d", st.y, st.m, st.d);
+ sprintf(rgbValueBindRow, "%.4d-%.2d-%.2d", std_time.y, std_time.m, std_time.d);
break;
case PG_TYPE_TIME:
len = 8;
if (cbValueMax > len)
- sprintf(rgbValueBindRow, "%.2d:%.2d:%.2d", st.hh, st.mm, st.ss);
+ sprintf(rgbValueBindRow, "%.2d:%.2d:%.2d", std_time.hh, std_time.mm, std_time.ss);
break;
case PG_TYPE_ABSTIME:
len = 19;
if (cbValueMax > len)
sprintf(rgbValueBindRow, "%.4d-%.2d-%.2d %.2d:%.2d:%.2d",
- st.y, st.m, st.d, st.hh, st.mm, st.ss);
+ std_time.y, std_time.m, std_time.d, std_time.hh, std_time.mm, std_time.ss);
break;
case PG_TYPE_BOOL:
ds = (DATE_STRUCT *) ((char *) rgbValue + (bind_row * bind_size));
else
ds = (DATE_STRUCT *) rgbValue + bind_row;
- ds->year = st.y;
- ds->month = st.m;
- ds->day = st.d;
+ ds->year = std_time.y;
+ ds->month = std_time.m;
+ ds->day = std_time.d;
}
break;
ts = (TIME_STRUCT *) ((char *) rgbValue + (bind_row * bind_size));
else
ts = (TIME_STRUCT *) rgbValue + bind_row;
- ts->hour = st.hh;
- ts->minute = st.mm;
- ts->second = st.ss;
+ ts->hour = std_time.hh;
+ ts->minute = std_time.mm;
+ ts->second = std_time.ss;
}
break;
ts = (TIMESTAMP_STRUCT *) ((char *) rgbValue + (bind_row * bind_size));
else
ts = (TIMESTAMP_STRUCT *) rgbValue + bind_row;
- ts->year = st.y;
- ts->month = st.m;
- ts->day = st.d;
- ts->hour = st.hh;
- ts->minute = st.mm;
- ts->second = st.ss;
- ts->fraction = st.fr;
+ ts->year = std_time.y;
+ ts->month = std_time.m;
+ ts->day = std_time.d;
+ ts->hour = std_time.hh;
+ ts->minute = std_time.mm;
+ ts->second = std_time.ss;
+ ts->fraction = std_time.fr;
}
break;
#endif /* ODBCINT64 */
case SQL_C_BINARY:
- if (PG_TYPE_BYTEA != field_type)
+ if (PG_TYPE_UNKNOWN == field_type)
+ {
+ if (pcbValue)
+ *(SDWORD *) ((char *) pcbValue + pcbValueOffset) = SQL_NULL_DATA;
+ return COPY_OK;
+ }
+ else if (PG_TYPE_BYTEA != field_type)
{
mylog("couldn't convert the type %d to SQL_C_BINARY\n", field_type);
return COPY_UNSUPPORTED_TYPE;
param_string[0] = '\0';
cbuf[0] = '\0';
memset(&st, 0, sizeof(st));
- t = time(NULL);
+ t = SC_get_time(qb->stmt);
#ifdef HAVE_LOCALTIME_R
tim = localtime_r(&t, &tm);
#else
return length;
}
-static int
-pg_hex2bin(UCHAR *src, UCHAR *dst, int length)
+int
+pg_hex2bin(const UCHAR *src, UCHAR *dst, int length)
{
- UCHAR chr,
- *src_wk,
- *dst_wk;
+ UCHAR chr;
+ const UCHAR *src_wk;
+ UCHAR *dst_wk;
int i, val;
BOOL HByte = TRUE;
int convert_pgbinary_to_char(const char *value, char *rgbValue, int cbValueMax);
int convert_from_pgbinary(const unsigned char *value, unsigned char *rgbValue, int cbValueMax);
int convert_to_pgbinary(const unsigned char *in, char *out, int len);
+int pg_hex2bin(const UCHAR *in, UCHAR *out, int len);
void encode(const char *in, char *out);
void decode(const char *in, char *out);
int convert_lo(StatementClass *stmt, const void *value, Int2 fCType, PTR rgbValue,
else if (stricmp(attribute, "CX") == 0)
unfoldCXAttribute(ci, value);
- mylog("copyAttributes: DSN='%s',server='%s',dbase='%s',user='%s',passwd='%s',port='%s',onlyread='%s',protocol='%s',conn_settings='%s',disallow_premature=%d)\n", ci->dsn, ci->server, ci->database, ci->username, ci->password, ci->port, ci->onlyread, ci->protocol, ci->conn_settings, ci->disallow_premature);
+ mylog("copyAttributes: DSN='%s',server='%s',dbase='%s',user='%s',passwd='%s',port='%s',onlyread='%s',protocol='%s',conn_settings='%s',disallow_premature=%d)\n", ci->dsn, ci->server, ci->database, ci->username, ci->password ? "xxxxx" : "", ci->port, ci->onlyread, ci->protocol, ci->conn_settings, ci->disallow_premature);
}
void
while (*(DSN + strlen(DSN) - 1) == ' ')
*(DSN + strlen(DSN) - 1) = '\0';
+ if (ci->driver[0] == '\0' || overwrite)
+ {
+ SQLGetPrivateProfileString(ODBC_DATASOURCES, DSN, "", ci->driver, sizeof(ci->driver), ODBC_INI);
+ if (ci->driver[0] && stricmp(ci->driver, DBMS_NAME))
+ getCommonDefaults(ci->driver, ODBCINST_INI, ci);
+ }
+
/* Proceed with getting info for the given DSN. */
if (ci->desc[0] == '\0' || overwrite)
ci->port,
ci->database,
ci->username,
- ci->password);
+ ci->password ? "xxxxx" : "");
qlog(" onlyread='%s',protocol='%s',showoid='%s',fakeoidindex='%s',showsystable='%s'\n",
ci->onlyread,
ci->protocol,
* to the ODBCINST.INI portion of the registry
*/
void
-writeDriverCommoninfo(const ConnInfo *ci)
+writeDriverCommoninfo(const char *fileName, const char *sectionName,
+ const GLOBAL_VALUES *comval)
{
- const char *sectionName;
- const char *fileName;
- const GLOBAL_VALUES *comval;
char tmp[128];
- if (ci)
- if (ci->dsn && ci->dsn[0])
- {
- mylog("DSN=%s updating\n", ci->dsn);
- comval = &(ci->drivers);
- sectionName = ci->dsn;
- fileName = ODBC_INI;
- }
- else
- {
- mylog("ci but dsn==NULL\n");
- return;
- }
- else
- {
- mylog("drivers updating\n");
- comval = &globals;
+ if (ODBCINST_INI == fileName && NULL == sectionName)
sectionName = DBMS_NAME;
- fileName = ODBCINST_INI;
- }
+
sprintf(tmp, "%d", comval->fetch_max);
SQLWritePrivateProfileString(sectionName,
INI_FETCH, tmp, fileName);
/*
* Never update the onlyread from this module.
*/
- if (!ci)
+ if (ODBCINST_INI == fileName)
{
sprintf(tmp, "%d", comval->onlyread);
SQLWritePrivateProfileString(sectionName, INI_READONLY, tmp,
#define ODBCINST_INI "ODBCINST.INI"
#endif
+#define ODBC_DATASOURCES "ODBC Data Sources"
#if (ODBCVER >= 0x0300)
#ifdef UNICODE_SUPPORT
#endif /* WIN32 */
void updateGlobals(void);
-void writeDriverCommoninfo(const ConnInfo *ci);
+void writeDriverCommoninfo(const char *fileName, const char *sectionName,
+ const GLOBAL_VALUES *);
void writeDSNinfo(const ConnInfo *ci);
void getDSNdefaults(ConnInfo *ci);
void getDSNinfo(ConnInfo *ci, char overwrite);
extern HINSTANCE NEAR s_hModule;
static int driver_optionsDraw(HWND, const ConnInfo *, int src, BOOL enable);
-static int driver_options_update(HWND hdlg, ConnInfo *ci, BOOL);
+static int driver_options_update(HWND hdlg, ConnInfo *ci, const char *);
void
SetDlgStuff(HWND hdlg, const ConnInfo *ci)
* If driver attribute NOT present, then set the datasource name and
* description
*/
- if (ci->driver[0] == '\0')
- {
+ /**if (ci->driver[0] == '\0')
+ {**/
SetDlgItemText(hdlg, IDC_DSNAME, ci->dsn);
SetDlgItemText(hdlg, IDC_DESC, ci->desc);
- }
+ /**}**/
SetDlgItemText(hdlg, IDC_DATABASE, ci->database);
SetDlgItemText(hdlg, IDC_SERVER, ci->server);
}
static int
-driver_options_update(HWND hdlg, ConnInfo *ci, BOOL updateProfile)
+driver_options_update(HWND hdlg, ConnInfo *ci, const char *updateDriver)
{
GLOBAL_VALUES *comval;
if (!ci)
GetDlgItemText(hdlg, DRV_CONNSETTINGS, comval->conn_settings, sizeof(comval->conn_settings));
- if (updateProfile)
- writeDriverCommoninfo(ci);
+ if (updateDriver)
+ writeDriverCommoninfo(ODBCINST_INI, updateDriver, comval);
/* fall through */
return 0;
case IDOK:
ci = (ConnInfo *) GetWindowLong(hdlg, DWL_USER);
driver_options_update(hdlg, NULL,
- ci && ci->dsn && ci->dsn[0]);
+ ci ? ci->driver : NULL);
case IDCANCEL:
EndDialog(hdlg, GET_WM_COMMAND_ID(wParam, lParam) == IDOK);
case IDOK:
globals.commlog = IsDlgButtonChecked(hdlg, DRV_COMMLOG);
globals.debug = IsDlgButtonChecked(hdlg, DRV_DEBUG);
- writeDriverCommoninfo(NULL);
+ writeDriverCommoninfo(ODBCINST_INI, NULL, &globals);
case IDCANCEL:
EndDialog(hdlg, GET_WM_COMMAND_ID(wParam, lParam) == IDOK);
switch (GET_WM_COMMAND_ID(wParam, lParam))
{
case IDOK:
- driver_options_update(hdlg, ci, FALSE);
+ driver_options_update(hdlg, ci, NULL);
case IDCANCEL:
EndDialog(hdlg, GET_WM_COMMAND_ID(wParam, lParam) == IDOK);
return TRUE;
case IDAPPLY:
- driver_options_update(hdlg, ci, FALSE);
+ driver_options_update(hdlg, ci, NULL);
SendMessage(GetWindow(hdlg, GW_OWNER), WM_COMMAND, wParam, lParam);
break;
break;
case IDNEXTPAGE:
- driver_options_update(hdlg, ci, FALSE);
+ driver_options_update(hdlg, ci, NULL);
EndDialog(hdlg, FALSE);
DialogBoxParam(s_hModule,
#include "dlg_specific.h"
+static char * hide_password(const char *str)
+{
+ char *outstr, *pwdp;
+
+ outstr = strdup(str);
+ if (pwdp = strstr(outstr, "PWD="), !pwdp)
+ pwdp = strstr(outstr, "pwd=");
+ if (pwdp)
+ {
+ char *p;
+
+ for (p=pwdp + 4; *p && *p != ';'; p++)
+ *p = 'x';
+ }
+ return outstr;
+}
+
/* prototypes */
void dconn_get_connect_attributes(const UCHAR FAR * connect_string, ConnInfo *ci);
static void dconn_get_common_attributes(const UCHAR FAR * connect_string, ConnInfo *ci);
make_string(szConnStrIn, cbConnStrIn, connStrIn);
+#ifdef FORCE_PASSWORD_DISPLAY
mylog("**** PGAPI_DriverConnect: fDriverCompletion=%d, connStrIn='%s'\n", fDriverCompletion, connStrIn);
qlog("conn=%u, PGAPI_DriverConnect( in)='%s', fDriverCompletion=%d\n", conn, connStrIn, fDriverCompletion);
+#else
+ if (get_qlog() || get_mylog())
+ {
+ char *hide_str = hide_password(connStrIn);
+
+ mylog("**** PGAPI_DriverConnect: fDriverCompletion=%d, connStrIn='%s'\n", fDriverCompletion, hide_str);
+ qlog("conn=%u, PGAPI_DriverConnect( in)='%s', fDriverCompletion=%d\n", conn, hide_str, fDriverCompletion);
+ free(hide_str);
+ }
+#endif /* FORCE_PASSWORD_DISPLAY */
ci = &(conn->connInfo);
if (pcbConnStrOut)
*pcbConnStrOut = len;
+#ifdef FORCE_PASSWORD_DISPLAY
mylog("szConnStrOut = '%s' len=%d,%d\n", szConnStrOut, len, cbConnStrOutMax);
qlog("conn=%u, PGAPI_DriverConnect(out)='%s'\n", conn, szConnStrOut);
+#else
+ if (get_qlog() || get_mylog())
+ {
+ char *hide_str = hide_password(szConnStrOut);
+
+ mylog("szConnStrOut = '%s' len=%d,%d\n", hide_str, len, cbConnStrOutMax);
+ qlog("conn=%u, PGAPI_DriverConnect(out)='%s'\n", conn, hide_str);
+ free(hide_str);
+ }
+#endif /* FORCE_PASSWORD_DISPLAY */
mylog("PGAPI_DriverConnect: returning %d\n", result);
our_connect_string = strdup(connect_string);
strtok_arg = our_connect_string;
+#ifdef FORCE_PASSWORD_DISPLAY
mylog("our_connect_string = '%s'\n", our_connect_string);
+#else
+ if (get_mylog())
+ {
+ char *hide_str = hide_password(our_connect_string);
+
+ mylog("our_connect_string = '%s'\n", hide_str);
+ free(hide_str);
+ }
+#endif /* FORCE_PASSWORD_DISPLAY */
while (1)
{
attribute = pair; /* ex. DSN */
value = equals + 1; /* ex. 'CEO co1' */
- mylog("attribute = '%s', value = '%s'\n", attribute, value);
+#ifndef FORCE_PASSWORD_DISPLAY
+ if (stricmp(attribute, INI_PASSWORD) == 0 ||
+ stricmp(attribute, "pwd") == 0)
+ mylog("attribute = '%s', value = 'xxxxx'\n", attribute);
+ else
+#endif /* FORCE_PASSWORD_DISPLAY */
+ mylog("attribute = '%s', value = '%s'\n", attribute, value);
if (!attribute || !value)
continue;
our_connect_string = strdup(connect_string);
strtok_arg = our_connect_string;
+#ifdef FORCE_PASSWORD_DISPLAY
mylog("our_connect_string = '%s'\n", our_connect_string);
+#else
+ if (get_mylog())
+ {
+ char *hide_str = hide_password(our_connect_string);
+
+ mylog("our_connect_string = '%s'\n", hide_str);
+ free(hide_str);
+ }
+#endif /* FORCE_PASSWORD_DISPLAY */
while (1)
{
attribute = pair; /* ex. DSN */
value = equals + 1; /* ex. 'CEO co1' */
- mylog("attribute = '%s', value = '%s'\n", attribute, value);
+#ifndef FORCE_PASSWORD_DISPLAY
+ if (stricmp(attribute, INI_PASSWORD) == 0 ||
+ stricmp(attribute, "pwd") == 0)
+ mylog("attribute = '%s', value = 'xxxxx'\n", attribute);
+ else
+#endif /* FORCE_PASSWORD_DISPLAY */
+ mylog("attribute = '%s', value = '%s'\n", attribute, value);
if (!attribute || !value)
continue;
retval;
ParameterInfoClass *current_param;
ParameterImplClass *current_iparam;
- char *buffer;
+ char *buffer, *putbuf, *allocbuf = NULL;
+ Int2 ctype;
+ SDWORD putlen;
+ BOOL lenset = FALSE;
mylog("%s: entering...\n", func);
current_param = &(apdopts->parameters[stmt->current_exec_param]);
ipdopts = SC_get_IPD(stmt);
current_iparam = &(ipdopts->parameters[stmt->current_exec_param]);
+ ctype = current_param->CType;
conn = SC_get_conn(stmt);
+ if (ctype == SQL_C_DEFAULT)
+ ctype = sqltype_to_default_ctype(conn, current_iparam->SQLType);
+ if (SQL_NTS == cbValue)
+ {
+#ifdef UNICODE_SUPPORT
+ if (SQL_C_WCHAR == ctype)
+ {
+ putlen = 2 * ucs2strlen((SQLWCHAR *) rgbValue);
+ lenset = TRUE;
+ }
+ else
+#endif /* UNICODE_SUPPORT */
+ if (SQL_C_CHAR == ctype)
+ {
+ putlen = strlen(rgbValue);
+ lenset = TRUE;
+ }
+ }
+ if (!lenset)
+ {
+ if (cbValue < 0)
+ putlen = cbValue;
+ else
+#ifdef UNICODE_SUPPORT
+ if (ctype == SQL_C_CHAR || ctype == SQL_C_BINARY || ctype == SQL_C_WCHAR)
+#else
+ if (ctype == SQL_C_CHAR || ctype == SQL_C_BINARY)
+#endif /* UNICODE_SUPPORT */
+ putlen = cbValue;
+ else
+ putlen = ctype_length(ctype);
+ }
+ putbuf = rgbValue;
+ if (current_iparam->PGType == conn->lobj_type && SQL_C_CHAR == ctype)
+ {
+ allocbuf = malloc(putlen / 2 + 1);
+ if (allocbuf)
+ {
+ pg_hex2bin(rgbValue, allocbuf, putlen);
+ putbuf = allocbuf;
+ putlen /= 2;
+ }
+ }
+
if (!stmt->put_data)
{ /* first call */
mylog("PGAPI_PutData: (1) cbValue = %d\n", cbValue);
return SQL_ERROR;
}
- *current_param->EXEC_used = cbValue;
+ *current_param->EXEC_used = putlen;
if (cbValue == SQL_NULL_DATA)
return SQL_SUCCESS;
return SQL_ERROR;
}
- retval = lo_write(stmt->hdbc, stmt->lobj_fd, rgbValue, cbValue);
- mylog("lo_write: cbValue=%d, wrote %d bytes\n", cbValue, retval);
+ retval = lo_write(stmt->hdbc, stmt->lobj_fd, putbuf, putlen);
+ mylog("lo_write: cbValue=%d, wrote %d bytes\n", putlen, retval);
}
else
{
- Int2 ctype = current_param->CType;
- if (ctype == SQL_C_DEFAULT)
- ctype = sqltype_to_default_ctype(conn, current_iparam->SQLType);
-
-#ifdef UNICODE_SUPPORT
- if (SQL_NTS == cbValue && SQL_C_WCHAR == ctype)
- cbValue = 2 * ucs2strlen((SQLWCHAR *) rgbValue);
-#endif /* UNICODE_SUPPORT */
- /* for handling fields */
- if (cbValue == SQL_NTS)
- {
- current_param->EXEC_buffer = strdup(rgbValue);
- if (!current_param->EXEC_buffer)
- {
- SC_set_error(stmt, STMT_NO_MEMORY_ERROR, "Out of memory in PGAPI_PutData (2)");
- SC_log_error(func, "", stmt);
- return SQL_ERROR;
- }
- }
- else
+ current_param->EXEC_buffer = malloc(putlen + 1);
+ if (!current_param->EXEC_buffer)
{
-#ifdef UNICODE_SUPPORT
- if (ctype == SQL_C_CHAR || ctype == SQL_C_BINARY || ctype == SQL_C_WCHAR)
-#else
- if (ctype == SQL_C_CHAR || ctype == SQL_C_BINARY)
-#endif /* UNICODE_SUPPORT */
- {
- current_param->EXEC_buffer = malloc(cbValue + 1);
- if (!current_param->EXEC_buffer)
- {
- SC_set_error(stmt, STMT_NO_MEMORY_ERROR, "Out of memory in PGAPI_PutData (2)");
- SC_log_error(func, "", stmt);
- return SQL_ERROR;
- }
- memcpy(current_param->EXEC_buffer, rgbValue, cbValue);
- current_param->EXEC_buffer[cbValue] = '\0';
- }
- else
- {
- Int4 used = ctype_length(ctype);
-
- current_param->EXEC_buffer = malloc(used);
- if (!current_param->EXEC_buffer)
- {
- SC_set_error(stmt, STMT_NO_MEMORY_ERROR, "Out of memory in PGAPI_PutData (2)");
- SC_log_error(func, "", stmt);
- return SQL_ERROR;
- }
- memcpy(current_param->EXEC_buffer, rgbValue, used);
- }
+ SC_set_error(stmt, STMT_NO_MEMORY_ERROR, "Out of memory in PGAPI_PutData (2)");
+ SC_log_error(func, "", stmt);
+ return SQL_ERROR;
}
+ memcpy(current_param->EXEC_buffer, putbuf, putlen);
+ current_param->EXEC_buffer[putlen] = '\0';
}
}
else
if (current_iparam->PGType == conn->lobj_type)
{
/* the large object fd is in EXEC_buffer */
- retval = lo_write(stmt->hdbc, stmt->lobj_fd, rgbValue, cbValue);
- mylog("lo_write(2): cbValue = %d, wrote %d bytes\n", cbValue, retval);
+ retval = lo_write(stmt->hdbc, stmt->lobj_fd, putbuf, putlen);
+ mylog("lo_write(2): cbValue = %d, wrote %d bytes\n", putlen, retval);
- *current_param->EXEC_used += cbValue;
+ *current_param->EXEC_used += putlen;
}
else
{
- Int2 ctype = current_param->CType;
-
- if (ctype == SQL_C_DEFAULT)
- ctype = sqltype_to_default_ctype(conn, current_iparam->SQLType);
buffer = current_param->EXEC_buffer;
- if (old_pos = *current_param->EXEC_used, SQL_NTS == old_pos)
- {
-#ifdef UNICODE_SUPPORT
- if (SQL_C_WCHAR == ctype)
- old_pos = 2 * ucs2strlen((SQLWCHAR *) buffer);
- else
-#endif /* UNICODE_SUPPORT */
- old_pos = strlen(buffer);
- }
- if (SQL_NTS == cbValue)
- {
-#ifdef UNICODE_SUPPORT
- if (SQL_C_WCHAR == ctype)
- cbValue = 2 * ucs2strlen((SQLWCHAR *) rgbValue);
- else
-#endif /* UNICODE_SUPPORT */
- cbValue = strlen(rgbValue);
- }
- if (cbValue > 0)
+ old_pos = *current_param->EXEC_used;
+ if (putlen > 0)
{
- *current_param->EXEC_used += cbValue;
+ *current_param->EXEC_used += putlen;
- mylog(" cbValue = %d, old_pos = %d, *used = %d\n", cbValue, old_pos, *current_param->EXEC_used);
+ mylog(" cbValue = %d, old_pos = %d, *used = %d\n", putlen, old_pos, *current_param->EXEC_used);
/* dont lose the old pointer in case out of memory */
buffer = realloc(current_param->EXEC_buffer, *current_param->EXEC_used + 1);
return SQL_ERROR;
}
- memcpy(&buffer[old_pos], rgbValue, cbValue);
+ memcpy(&buffer[old_pos], putbuf, putlen);
buffer[*current_param->EXEC_used] = '\0';
/* reassign buffer incase realloc moved it */
}
}
}
+ if (allocbuf)
+ free(allocbuf);
return SQL_SUCCESS;
}
if (fSqlType == SQL_ALL_TYPES || fSqlType == sqlType)
{
+ int pgtcount = 1, cnt;
+
+ if (SQL_INTEGER == sqlType && PG_VERSION_GE(SC_get_conn(stmt), 6.4))
+ pgtcount = 2;
+ for (cnt = 0; cnt < pgtcount; cnt ++)
+ {
+
row = (TupleNode *) malloc(sizeof(TupleNode) + (result_cols - 1) * sizeof(TupleField));
/* These values can't be NULL */
- set_tuplefield_string(&row->tuple[0], pgtype_to_name(stmt, pgType));
+ if (1 == cnt)
+ {
+ set_tuplefield_string(&row->tuple[0], "serial");
+ set_tuplefield_int2(&row->tuple[6], SQL_NO_NULLS);
+inolog("serial in\n");
+ }
+ else
+ {
+ set_tuplefield_string(&row->tuple[0], pgtype_to_name(stmt, pgType));
+ set_tuplefield_int2(&row->tuple[6], pgtype_nullable(stmt, pgType));
+ }
set_tuplefield_int2(&row->tuple[1], (Int2) sqlType);
- set_tuplefield_int2(&row->tuple[6], pgtype_nullable(stmt, pgType));
set_tuplefield_int2(&row->tuple[7], pgtype_case_sensitive(stmt, pgType));
set_tuplefield_int2(&row->tuple[8], pgtype_searchable(stmt, pgType));
set_tuplefield_int2(&row->tuple[10], pgtype_money(stmt, pgType));
set_nullfield_string(&row->tuple[3], pgtype_literal_prefix(stmt, pgType));
set_nullfield_string(&row->tuple[4], pgtype_literal_suffix(stmt, pgType));
set_nullfield_string(&row->tuple[5], pgtype_create_params(stmt, pgType));
- set_nullfield_int2(&row->tuple[9], pgtype_unsigned(stmt, pgType));
- set_nullfield_int2(&row->tuple[11], pgtype_auto_increment(stmt, pgType));
+ if (1 == cnt)
+ {
+ set_nullfield_int2(&row->tuple[9], TRUE);
+ set_nullfield_int2(&row->tuple[11], TRUE);
+ }
+ else
+ {
+ 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));
#if (ODBCVER >=0x0300)
#endif /* ODBCVER */
QR_add_tuple(res, row);
+
+ }
}
}
#endif /* WIN_MULTITHREAD_SUPPORT */
static int mylog_on = 0,
qlog_on = 0;
+
+int get_mylog(void)
+{
+ return mylog_on;
+}
+int get_qlog(void)
+{
+ return qlog_on;
+}
+
void
logs_on_off(int cnopen, int mylog_onoff, int qlog_onoff)
{
#endif
#endif
#define inoqlog qlog
+int get_qlog(void);
+int get_mylog(void);
#ifndef WIN32
#define DIRSEPARATOR "/"
wenc = "BIG5";
break;
}
- if (wenc && stricmp(encstr, wenc))
+ if (wenc && (!encstr || stricmp(encstr, wenc)))
{
QResultClass *res;
char query[64];
return FALSE;
}
+/*
+ * lower the unquoted name
+ */
+static
+void lower_the_name(char *name, ConnectionClass *conn, BOOL dquote)
+{
+ if (!dquote)
+ {
+ char *ptr;
+ encoded_str encstr;
+ make_encoded_str(&encstr, conn, name);
+
+ /* lower case table name */
+ for (ptr = name; *ptr; ptr++)
+ {
+ encoded_nextchar(&encstr);
+ if (ENCODE_STATUS(encstr) != 0)
+ ptr++;
+ else
+ *ptr = tolower((unsigned char) *ptr);
+ }
+ }
+}
char
parse_statement(StatementClass *stmt)
}
if (out_table && !in_table) /* new table */
{
-
+ if (!dquote)
+ {
+ if (token[0] == '(' ||
+ token[0] == ')')
+ continue;
+ }
if (!(stmt->ntab % TAB_INCR))
{
ti = (TABLE_INFO **) realloc(ti, (stmt->ntab + TAB_INCR) * sizeof(TABLE_INFO *));
ti[stmt->ntab]->updatable = 1;
strcpy(ti[stmt->ntab]->name, token);
- if (!dquote)
- {
- char *ptr;
- encoded_str encstr;
- make_encoded_str(&encstr, conn, ti[stmt->ntab]->name);
-
- /* lower case table name */
- for (ptr = ti[stmt->ntab]->name; *ptr; ptr++)
- {
- encoded_nextchar(&encstr);
- if (ENCODE_STATUS(encstr) != 0)
- ptr++;
- else
- *ptr = tolower((unsigned char) *ptr);
- }
- }
+ lower_the_name(ti[stmt->ntab]->name, conn, dquote);
mylog("got table = '%s'\n", ti[stmt->ntab]->name);
if (delim == ',')
{
strcpy(ti[stmt->ntab - 1]->schema, ti[stmt->ntab - 1]->name);
strcpy(ti[stmt->ntab - 1]->name, token);
+ lower_the_name(ti[stmt->ntab - 1]->name, conn, dquote);
in_dot = FALSE;
continue;
}
SQL_CHAR,
#if (ODBCVER >= 0x0300)
SQL_TYPE_DATE,
-#else
- SQL_DATE,
#endif /* ODBCVER */
+ SQL_DATE,
SQL_DECIMAL,
SQL_DOUBLE,
SQL_FLOAT,
#if (ODBCVER >= 0x0300)
SQL_TYPE_TIME,
SQL_TYPE_TIMESTAMP,
-#else
+#endif /* ODBCVER */
SQL_TIME,
SQL_TIMESTAMP,
-#endif /* ODBCVER */
SQL_TINYINT,
SQL_VARBINARY,
SQL_VARCHAR,
0
};
-#if (ODBCVER >= 0x0300) && defined(OBDCINT64)
-/* #define ALLOWED_C_BIGINT SQL_C_SBIGINT */
-#define ALLOWED_C_BIGINT SQL_C_CHAR /* Delphi should be either ? */
+#if (ODBCVER >= 0x0300) && defined(ODBCINT64)
+#define ALLOWED_C_BIGINT SQL_C_SBIGINT
+/* #define ALLOWED_C_BIGINT SQL_C_CHAR */ /* Delphi should be either ? */
#else
#define ALLOWED_C_BIGINT SQL_C_CHAR
#endif
pgType = ci->drivers.bools_as_char ? PG_TYPE_CHAR : PG_TYPE_BOOL;
break;
- case SQL_DATE:
#if (ODBCVER >= 0x0300)
case SQL_TYPE_DATE:
+#else
+ case SQL_DATE:
#endif /* ODBCVER */
pgType = PG_TYPE_DATE;
break;
case PG_TYPE_INT8:
if (ci->int8_as != 0)
return ci->int8_as;
- if (conn->ms_jet)
- return SQL_NUMERIC; /* maybe a little better than SQL_VARCHAR */
+ /***if (conn->ms_jet)
+ return SQL_NUMERIC; ***/ /* maybe a little better than SQL_VARCHAR */
#if (ODBCVER >= 0x0300)
return SQL_BIGINT;
#else
*
* Comments: See "notice.txt" for copyright and license information.
*
- * $Id: psqlodbc.h,v 1.75 2003/01/03 16:08:14 hinoue Exp $
+ * $Id: psqlodbc.h,v 1.76 2003/04/23 09:49:47 hinoue Exp $
*
*/
mylog("end of tuple list -- setting inUse to false: this = %u\n", self);
self->inTuples = FALSE;
- if (self->num_total_rows > 0)
+ qlog(" [ fetched %d rows ]\n", self->num_total_rows);
+ mylog("_next_tuple: 'C' fetch_total = %d & this_fetch = %d\n", self->num_total_rows, self->num_backend_rows);
+ if (self->num_backend_rows > 0)
{
- qlog(" [ fetched %d rows ]\n", self->num_total_rows);
- mylog("_next_tuple: 'C' fetch_max && fcount = %d\n", self->num_total_rows);
-
/* set to first row */
self->tupleField = self->backend_tuples + (offset * self->num_fields);
return TRUE;
else
{
/* We are surely done here (we read 0 tuples) */
- qlog(" [ fetched 0 rows ]\n");
mylog("_next_tuple: 'C': DONE (fcount == 0)\n");
return -1; /* end of tuples */
}
break;
default:
+ SC_set_error(stmt, STMT_FETCH_OUT_OF_RANGE, "Unsupported PGAPI_ExtendedFetch Direction");
SC_log_error(func, "Unsupported PGAPI_ExtendedFetch Direction", stmt);
return SQL_ERROR;
}
if (count)
*count = 0;
if (!(res = SC_get_Curres(stmt)))
+ {
+ SC_set_error(stmt, STMT_INVALID_CURSOR_STATE_ERROR, "Null statement result in SC_pos_reload.");
return SQL_ERROR;
+ }
if (!stmt->ti)
parse_statement(stmt); /* not preferable */
if (!stmt->updatable)
{
stmt->options.scroll_concurrency = SQL_CONCUR_READ_ONLY;
+ SC_set_error(stmt, STMT_INVALID_OPTION_IDENTIFIER, "the statement is read-only");
return SQL_ERROR;
}
res_ridx = global_ridx - stmt->rowset_start + res->base;
if (!(oid = getOid(res, global_ridx)))
+ {
+ SC_set_error(stmt, STMT_ROW_VERSION_CHANGED, "the row was already deleted ?");
return SQL_SUCCESS_WITH_INFO;
+ }
getTid(res, global_ridx, &blocknum, &offset);
sprintf(tidval, "(%u, %u)", blocknum, offset);
res_cols = getNumResultCols(res);
mylog("SC_pos_reload_needed\n");
if (!(res = SC_get_Curres(stmt)))
+ {
+ SC_set_error(stmt, STMT_INVALID_CURSOR_STATE_ERROR, "Null statement result in SC_pos_reload_needed.");
return SQL_ERROR;
+ }
if (!stmt->ti)
parse_statement(stmt); /* not preferable */
if (!stmt->updatable)
{
stmt->options.scroll_concurrency = SQL_CONCUR_READ_ONLY;
+ SC_set_error(stmt, STMT_INVALID_OPTION_IDENTIFIER, "the statement is read-only");
return SQL_ERROR;
}
limitrow = stmt->rowset_start + res->rowset_size;
mylog("positioned new ti=%x\n", stmt->ti);
if (!(res = SC_get_Curres(stmt)))
+ {
+ SC_set_error(stmt, STMT_INVALID_CURSOR_STATE_ERROR, "Null statement result in SC_pos_newload.");
return SQL_ERROR;
+ }
if (!stmt->ti)
parse_statement(stmt); /* not preferable */
if (!stmt->updatable)
{
stmt->options.scroll_concurrency = SQL_CONCUR_READ_ONLY;
+ SC_set_error(stmt, STMT_INVALID_OPTION_IDENTIFIER, "the statement is read-only");
return SQL_ERROR;
}
if (qres = positioned_load(stmt, tidRef ? USE_INSERTED_TID : 0, oid, NULL), qres)
UInt2 pgoffset;
Int4 *used, bind_size = opts->bind_size;
- mylog("POS UPDATE %d+%d fi=%x ti=%x\n", irow, SC_get_Curres(stmt)->base,fi, stmt->ti);
if (!(res = SC_get_Curres(stmt)))
+ {
+ SC_set_error(stmt, STMT_INVALID_CURSOR_STATE_ERROR, "Null statement result in SC_pos_update.");
return SQL_ERROR;
+ }
+ mylog("POS UPDATE %d+%d fi=%x ti=%x\n", irow, res->base, fi, stmt->ti);
if (!stmt->ti)
parse_statement(stmt); /* not preferable */
if (!stmt->updatable)
{
stmt->options.scroll_concurrency = SQL_CONCUR_READ_ONLY;
+ SC_set_error(stmt, STMT_INVALID_OPTION_IDENTIFIER, "the statement is read-only");
return SQL_ERROR;
}
if (!(oid = getOid(res, global_ridx)))
{
- SC_set_errormsg(stmt, "The row is already deleted");
+ SC_set_error(stmt, STMT_INVALID_CURSOR_POSITION, "The row is already deleted ?");
return SQL_ERROR;
}
getTid(res, global_ridx, &blocknum, &pgoffset);
blocknum, pgoffset, oid);
mylog("updstr=%s\n", updstr);
if (PGAPI_AllocStmt(conn, &hstmt) != SQL_SUCCESS)
+ {
+ SC_set_error(stmt, STMT_NO_MEMORY_ERROR, "internal AllocStmt error");
return SQL_ERROR;
+ }
qstmt = (StatementClass *) hstmt;
apdopts = SC_get_APD(qstmt);
apdopts->param_bind_type = opts->bind_size;
else
{
ret = SQL_SUCCESS_WITH_INFO;
- SC_set_errormsg(stmt, "update list null");
+ SC_set_error(stmt, STMT_INVALID_CURSOR_STATE_ERROR, "update list null");
}
if (SQL_SUCCESS == ret && res->keyset)
{
mylog("POS DELETE ti=%x\n", stmt->ti);
if (!(res = SC_get_Curres(stmt)))
+ {
+ SC_set_error(stmt, STMT_INVALID_CURSOR_STATE_ERROR, "Null statement result in SC_pos_delete.");
return SQL_ERROR;
+ }
if (!stmt->ti)
parse_statement(stmt); /* not preferable */
if (!stmt->updatable)
{
stmt->options.scroll_concurrency = SQL_CONCUR_READ_ONLY;
+ SC_set_error(stmt, STMT_INVALID_OPTION_IDENTIFIER, "the statement is read-only");
return SQL_ERROR;
}
if (!(oid = getOid(res, global_ridx)))
{
- SC_set_errormsg(stmt, "The row is already deleted");
+ SC_set_error(stmt, STMT_INVALID_CURSOR_POSITION, "The row is already deleted ?");
return SQL_ERROR;
}
getTid(res, global_ridx, &blocknum, &offset);
mylog("POS ADD fi=%x ti=%x\n", fi, stmt->ti);
if (!(res = SC_get_Curres(stmt)))
+ {
+ SC_set_error(stmt, STMT_INVALID_CURSOR_STATE_ERROR, "Null statement result in SC_pos_add.");
return SQL_ERROR;
+ }
if (!stmt->ti)
parse_statement(stmt); /* not preferable */
if (!stmt->updatable)
{
stmt->options.scroll_concurrency = SQL_CONCUR_READ_ONLY;
+ SC_set_error(stmt, STMT_INVALID_OPTION_IDENTIFIER, "the statement is read-only");
return SQL_ERROR;
}
num_cols = irdflds->nfields;
else
sprintf(addstr, "insert into \"%s\" (", stmt->ti[0]->name);
if (PGAPI_AllocStmt(conn, &hstmt) != SQL_SUCCESS)
+ {
+ SC_set_error(stmt, STMT_NO_MEMORY_ERROR, "internal AllocStmt error");
return SQL_ERROR;
+ }
if (opts->row_offset_ptr)
offset = *opts->row_offset_ptr;
else
else
{
ret = SQL_SUCCESS_WITH_INFO;
- SC_set_errormsg(stmt, "insert list null");
+ SC_set_error(stmt, STMT_INVALID_CURSOR_STATE_ERROR, "insert list null");
}
PGAPI_FreeStmt(hstmt, SQL_DROP);
if (SQL_SUCCESS == ret && res->keyset)
if (!(res = SC_get_Curres(stmt)))
{
- SC_set_error(stmt, STMT_SEQUENCE_ERROR, "Null statement result in PGAPI_SetPos.");
+ SC_set_error(stmt, STMT_INVALID_CURSOR_STATE_ERROR, "Null statement result in PGAPI_SetPos.");
SC_log_error(func, "", stmt);
return SQL_ERROR;
}
}
else
{
- if (irow > stmt->last_fetch_count)
+ if (SQL_ADD != fOption && irow > stmt->last_fetch_count)
{
SC_set_error(stmt, STMT_ROW_OUT_OF_RANGE, "Row value out of range");
SC_log_error(func, "", stmt);
else if (SC_get_IRD(stmt)->rowsFetched)
*(SC_get_IRD(stmt)->rowsFetched) = processed;
res->recent_processed_row_count = stmt->diag_row_count = processed;
-inolog("rowset=%d processed=%d ret=%d\n", opts->rowset_size, processed, ret);
return ret;
}
}
/* Update ODBC.INI */
- writeDriverCommoninfo(&lpsetupdlg->ci);
+ writeDriverCommoninfo(ODBC_INI, lpsetupdlg->ci.dsn, &(lpsetupdlg->ci.drivers));
writeDSNinfo(&lpsetupdlg->ci);
/* If the data source name has changed, remove the old name */
rv->updatable = FALSE;
rv->error_recsize = -1;
rv->diag_row_count = 0;
+ rv->stmt_time = 0;
INIT_STMT_CS(rv);
}
return rv;
}
+time_t
+SC_get_time(StatementClass *stmt)
+{
+ if (!stmt)
+ return time(NULL);
+ if (!stmt->stmt_time)
+ stmt->stmt_time = time(NULL);
+ return stmt->stmt_time;
+}
/*
* Currently, the driver offers very simple bookmark support -- it is
* just the current row number. But it could be more sophisticated
#define __STATEMENT_H__
#include "psqlodbc.h"
+#include <time.h>
#include "bind.h"
#include "descriptor.h"
Int4 from_pos;
Int4 where_pos;
Int4 last_fetch_count_include_ommitted;
+ time_t stmt_time;
#if defined(WIN_MULTITHREAD_SUPPORT)
CRITICAL_SECTION cs;
#elif defined(POSIX_MULTITHREAD_SUPPORT)
RETCODE SC_fetch(StatementClass *self);
void SC_free_params(StatementClass *self, char option);
void SC_log_error(const char *func, const char *desc, const StatementClass *self);
+time_t SC_get_time(StatementClass *self);
unsigned long SC_get_bookmark(StatementClass *self);
RETCODE SC_pos_update(StatementClass *self, UWORD irow, UDWORD index);
RETCODE SC_pos_delete(StatementClass *self, UWORD irow, UDWORD index);
#ifndef __VERSION_H__
#define __VERSION_H__
-#define POSTGRESDRIVERVERSION "07.02.0005"
-#define POSTGRES_RESOURCE_VERSION "07.02.0005\0"
-#define PG_DRVFILE_VERSION 7,2,0,05
+#define POSTGRESDRIVERVERSION "07.03.0001"
+#define POSTGRES_RESOURCE_VERSION "07.03.0001\0"
+#define PG_DRVFILE_VERSION 7,3,0,01
#endif