Commit 4b47467a authored by Hiroshi Inoue's avatar Hiroshi Inoue

1) Implement SQLParamOptions().

2) Handle Multiple results and implement SQLMoreResult().
3) Improve multibyte handling thanks to Eiji Tokuya.
4) Add new options.
   LF <-> CR/LF converion.
   TRUE is -1 (for VB).
5) Introduce unicode(UCS-2) support.
6) Reduce the length of connection strings.
7) Improve SQLError, SQLGetDiagRec(ODBC 3.0).
8) Implement SQLTablePrivileges().
9) Miscellaneous changes for ODBC 3.0 support.
parent 21f8aa39
...@@ -7,7 +7,7 @@ ...@@ -7,7 +7,7 @@
* Classes: BindInfoClass, ParameterInfoClass * Classes: BindInfoClass, ParameterInfoClass
* *
* API functions: SQLBindParameter, SQLBindCol, SQLDescribeParam, SQLNumParams, * API functions: SQLBindParameter, SQLBindCol, SQLDescribeParam, SQLNumParams,
* SQLParamOptions(NI) * SQLParamOptions
* *
* Comments: See "notice.txt" for copyright and license information. * Comments: See "notice.txt" for copyright and license information.
*------- *-------
...@@ -331,17 +331,9 @@ PGAPI_ParamOptions( ...@@ -331,17 +331,9 @@ PGAPI_ParamOptions(
mylog("%s: entering... %d %x\n", func, crow, pirow); mylog("%s: entering... %d %x\n", func, crow, pirow);
if (crow == 1) /* temporary solution and must be stmt->options.paramset_size = crow;
* rewritten later */ stmt->options.param_processed_ptr = pirow;
{ return SQL_SUCCESS;
if (pirow)
*pirow = 1;
return SQL_SUCCESS;
}
stmt->errornumber = CONN_UNSUPPORTED_OPTION;
stmt->errormsg = "Function not implemented";
SC_log_error(func, "Function not implemented", (StatementClass *) hstmt);
return SQL_ERROR;
} }
......
...@@ -75,7 +75,8 @@ PGAPI_AllocConnect( ...@@ -75,7 +75,8 @@ PGAPI_AllocConnect(
return SQL_ERROR; return SQL_ERROR;
} }
*phdbc = (HDBC) conn; if (phdbc)
*phdbc = (HDBC) conn;
return SQL_SUCCESS; return SQL_SUCCESS;
} }
...@@ -228,6 +229,16 @@ PGAPI_FreeConnect( ...@@ -228,6 +229,16 @@ PGAPI_FreeConnect(
} }
void
CC_conninfo_init(ConnInfo *conninfo)
{
memset(conninfo, 0, sizeof(ConnInfo));
conninfo->disallow_premature = -1;
conninfo->updatable_cursors = -1;
conninfo->lf_conversion = -1;
conninfo->true_is_minus1 = -1;
memcpy(&(conninfo->drivers), &globals, sizeof(globals));
}
/* /*
* IMPLEMENTATION CONNECTION CLASS * IMPLEMENTATION CONNECTION CLASS
*/ */
...@@ -249,11 +260,7 @@ CC_Constructor() ...@@ -249,11 +260,7 @@ CC_Constructor()
rv->status = CONN_NOT_CONNECTED; rv->status = CONN_NOT_CONNECTED;
rv->transact_status = CONN_IN_AUTOCOMMIT; /* autocommit by default */ rv->transact_status = CONN_IN_AUTOCOMMIT; /* autocommit by default */
memset(&rv->connInfo, 0, sizeof(ConnInfo)); CC_conninfo_init(&(rv->connInfo));
#ifdef DRIVER_CURSOR_IMPLEMENT
rv->connInfo.updatable_cursors = 1;
#endif /* DRIVER_CURSOR_IMPLEMENT */
memcpy(&(rv->connInfo.drivers), &globals, sizeof(globals));
rv->sock = SOCK_Constructor(rv); rv->sock = SOCK_Constructor(rv);
if (!rv->sock) if (!rv->sock)
return NULL; return NULL;
...@@ -280,6 +287,7 @@ CC_Constructor() ...@@ -280,6 +287,7 @@ CC_Constructor()
rv->pg_version_major = 0; rv->pg_version_major = 0;
rv->pg_version_minor = 0; rv->pg_version_minor = 0;
rv->ms_jet = 0; rv->ms_jet = 0;
rv->unicode = 0;
#ifdef MULTIBYTE #ifdef MULTIBYTE
rv->client_encoding = NULL; rv->client_encoding = NULL;
rv->server_encoding = NULL; rv->server_encoding = NULL;
...@@ -338,7 +346,7 @@ CC_cursor_count(ConnectionClass *self) ...@@ -338,7 +346,7 @@ CC_cursor_count(ConnectionClass *self)
for (i = 0; i < self->num_stmts; i++) for (i = 0; i < self->num_stmts; i++)
{ {
stmt = self->stmts[i]; stmt = self->stmts[i];
if (stmt && stmt->result && stmt->result->cursor) if (stmt && SC_get_Result(stmt) && SC_get_Result(stmt)->cursor)
count++; count++;
} }
...@@ -366,18 +374,18 @@ CC_begin(ConnectionClass *self) ...@@ -366,18 +374,18 @@ CC_begin(ConnectionClass *self)
char ret = TRUE; char ret = TRUE;
if (!CC_is_in_trans(self)) if (!CC_is_in_trans(self))
{ {
QResultClass *res = CC_send_query(self, "BEGIN", NULL); QResultClass *res = CC_send_query(self, "BEGIN", NULL, TRUE);
mylog("CC_begin: sending BEGIN!\n"); mylog("CC_begin: sending BEGIN!\n");
if (res != NULL) if (res != NULL)
{ {
ret = (!QR_aborted(res) && QR_command_successful(res)); ret = QR_command_successful(res);
QR_Destructor(res); QR_Destructor(res);
if (ret) if (ret)
CC_set_in_trans(self); CC_set_in_trans(self);
} }
else else
ret = FALSE; return FALSE;
} }
return ret; return ret;
...@@ -393,7 +401,7 @@ CC_commit(ConnectionClass *self) ...@@ -393,7 +401,7 @@ CC_commit(ConnectionClass *self)
char ret = FALSE; char ret = FALSE;
if (CC_is_in_trans(self)) if (CC_is_in_trans(self))
{ {
QResultClass *res = CC_send_query(self, "COMMIT", NULL); QResultClass *res = CC_send_query(self, "COMMIT", NULL, TRUE);
mylog("CC_commit: sending COMMIT!\n"); mylog("CC_commit: sending COMMIT!\n");
CC_set_no_trans(self); CC_set_no_trans(self);
...@@ -404,7 +412,7 @@ CC_commit(ConnectionClass *self) ...@@ -404,7 +412,7 @@ CC_commit(ConnectionClass *self)
QR_Destructor(res); QR_Destructor(res);
} }
else else
ret = FALSE; return FALSE;
} }
return ret; return ret;
...@@ -419,7 +427,7 @@ CC_abort(ConnectionClass *self) ...@@ -419,7 +427,7 @@ CC_abort(ConnectionClass *self)
{ {
if (CC_is_in_trans(self)) if (CC_is_in_trans(self))
{ {
QResultClass *res = CC_send_query(self, "ROLLBACK", NULL); QResultClass *res = CC_send_query(self, "ROLLBACK", NULL, TRUE);
mylog("CC_abort: sending ABORT!\n"); mylog("CC_abort: sending ABORT!\n");
CC_set_no_trans(self); CC_set_no_trans(self);
...@@ -488,11 +496,7 @@ CC_cleanup(ConnectionClass *self) ...@@ -488,11 +496,7 @@ CC_cleanup(ConnectionClass *self)
self->status = CONN_NOT_CONNECTED; self->status = CONN_NOT_CONNECTED;
self->transact_status = CONN_IN_AUTOCOMMIT; self->transact_status = CONN_IN_AUTOCOMMIT;
memset(&self->connInfo, 0, sizeof(ConnInfo)); CC_conninfo_init(&(self->connInfo));
#ifdef DRIVER_CURSOR_IMPLEMENT
self->connInfo.updatable_cursors = 1;
#endif /* DRIVER_CURSOR_IMPLEMENT */
memcpy(&(self->connInfo.drivers), &globals, sizeof(globals));
#ifdef MULTIBYTE #ifdef MULTIBYTE
if (self->client_encoding) if (self->client_encoding)
free(self->client_encoding); free(self->client_encoding);
...@@ -578,12 +582,12 @@ md5_auth_send(ConnectionClass *self, const char *salt) ...@@ -578,12 +582,12 @@ md5_auth_send(ConnectionClass *self, const char *salt)
{ {
free(pwd1); free(pwd1);
return 1; return 1;
} }
if (!(pwd2 = malloc(MD5_PASSWD_LEN + 1))) if (!(pwd2 = malloc(MD5_PASSWD_LEN + 1)))
{ {
free(pwd1); free(pwd1);
return 1; return 1;
} }
if (!EncryptMD5(pwd1 + strlen("md5"), salt, 4, pwd2)) if (!EncryptMD5(pwd1 + strlen("md5"), salt, 4, pwd2))
{ {
free(pwd2); free(pwd2);
...@@ -595,7 +599,7 @@ md5_auth_send(ConnectionClass *self, const char *salt) ...@@ -595,7 +599,7 @@ md5_auth_send(ConnectionClass *self, const char *salt)
SOCK_put_n_char(sock, pwd2, strlen(pwd2) + 1); SOCK_put_n_char(sock, pwd2, strlen(pwd2) + 1);
SOCK_flush_output(sock); SOCK_flush_output(sock);
free(pwd2); free(pwd2);
return 0; return 0;
} }
char char
...@@ -608,7 +612,7 @@ CC_connect(ConnectionClass *self, char do_password) ...@@ -608,7 +612,7 @@ CC_connect(ConnectionClass *self, char do_password)
ConnInfo *ci = &(self->connInfo); ConnInfo *ci = &(self->connInfo);
int areq = -1; int areq = -1;
int beresp; int beresp;
char msgbuffer[ERROR_MSG_LENGTH]; static char msgbuffer[ERROR_MSG_LENGTH];
char salt[5]; char salt[5];
static char *func = "CC_connect"; static char *func = "CC_connect";
...@@ -651,15 +655,16 @@ CC_connect(ConnectionClass *self, char do_password) ...@@ -651,15 +655,16 @@ CC_connect(ConnectionClass *self, char do_password)
if (encoding && strcmp(encoding, "OTHER")) if (encoding && strcmp(encoding, "OTHER"))
self->client_encoding = strdup(encoding); self->client_encoding = strdup(encoding);
} }
if (self->client_encoding)
self->ccsc = pg_CS_code(self->client_encoding);
qlog(" extra_systable_prefixes='%s', conn_settings='%s' conn_encoding='%s'\n", qlog(" extra_systable_prefixes='%s', conn_settings='%s' conn_encoding='%s'\n",
ci->drivers.extra_systable_prefixes, ci->drivers.extra_systable_prefixes,
ci->drivers.conn_settings, ci->drivers.conn_settings,
encoding ? encoding : ""); encoding ? encoding : "");
#else #else
qlog(" extra_systable_prefixes='%s', conn_settings='%s', protocol='%s'\n", qlog(" extra_systable_prefixes='%s', conn_settings='%s'\n",
ci->drivers.extra_systable_prefixes, ci->drivers.extra_systable_prefixes,
ci->drivers.conn_settings, ci->drivers.conn_settings);
ci->protocol);
#endif #endif
if (self->status != CONN_NOT_CONNECTED) if (self->status != CONN_NOT_CONNECTED)
...@@ -914,7 +919,7 @@ another_version_retry: ...@@ -914,7 +919,7 @@ another_version_retry:
*/ */
mylog("sending an empty query...\n"); mylog("sending an empty query...\n");
res = CC_send_query(self, " ", NULL); res = CC_send_query(self, " ", NULL, TRUE);
if (res == NULL || QR_get_status(res) != PGRES_EMPTY_QUERY) if (res == NULL || QR_get_status(res) != PGRES_EMPTY_QUERY)
{ {
mylog("got no result from the empty query. (probably database does not exist)\n"); mylog("got no result from the empty query. (probably database does not exist)\n");
...@@ -942,13 +947,55 @@ another_version_retry: ...@@ -942,13 +947,55 @@ another_version_retry:
* function instead. * function instead.
*/ */
CC_send_settings(self); CC_send_settings(self);
CC_lookup_lo(self); /* a hack to get the oid of our large CC_lookup_lo(self); /* a hack to get the oid of
* object oid type */ our large object oid type */
#ifdef MULTIBYTE CC_lookup_pg_version(self); /* Get PostgreSQL version for
CC_lookup_characterset(self); SQLGetInfo use */
#endif
CC_lookup_pg_version(self); /* Get PostgreSQL version for SQLGetInfo /*
* use */ * Multibyte handling is available ?
*/
#ifdef MULTIBYTE
if (PG_VERSION_GE(self, 7.0))
{
CC_lookup_characterset(self);
if (self->errornumber != 0)
return 0;
#ifdef UNICODE_SUPPORT
if (self->unicode)
{
if (!self->client_encoding ||
stricmp(self->client_encoding, "UNICODE"))
{
QResultClass *res;
if (PG_VERSION_LT(self, 7.1))
{
self->errornumber = CONN_NOT_IMPLEMENTED_ERROR;
self->errormsg = "UTF-8 conversion isn't implemented before 7.1";
return 0;
}
if (self->client_encoding)
free(self->client_encoding);
self->client_encoding = NULL;
if (res = CC_send_query(self, "set client_encoding to 'UTF8'", NULL, TRUE), res)
{
self->client_encoding = strdup("UNICODE");
QR_Destructor(res);
}
}
}
#endif /* UNICODE_SUPPORT */
}
#ifdef UNICODE_SUPPORT
else if (self->unicode)
{
self->errornumber = CONN_NOT_IMPLEMENTED_ERROR;
self->errormsg = "Unicode isn't supported before 7.0";
return 0;
}
#endif /* UNICODE_SUPPORT */
#endif /* MULTIBYTE */
CC_clear_error(self); /* clear any initial command errors */ CC_clear_error(self); /* clear any initial command errors */
self->status = CONN_CONNECTED; self->status = CONN_CONNECTED;
...@@ -1081,11 +1128,12 @@ CC_get_error(ConnectionClass *self, int *number, char **message) ...@@ -1081,11 +1128,12 @@ CC_get_error(ConnectionClass *self, int *number, char **message)
* 'declare cursor C3326857 for ...' and 'fetch 100 in C3326857' statements. * 'declare cursor C3326857 for ...' and 'fetch 100 in C3326857' statements.
*/ */
QResultClass * QResultClass *
CC_send_query(ConnectionClass *self, char *query, QueryInfo *qi) CC_send_query(ConnectionClass *self, char *query, QueryInfo *qi, BOOL clear_result_on_abort)
{ {
QResultClass *result_in = NULL, QResultClass *result_in = NULL,
*res = NULL, *cmdres = NULL,
*retres = NULL; *retres = NULL,
*res = NULL;
char swallow, char swallow,
*wq; *wq;
int id; int id;
...@@ -1094,9 +1142,9 @@ CC_send_query(ConnectionClass *self, char *query, QueryInfo *qi) ...@@ -1094,9 +1142,9 @@ CC_send_query(ConnectionClass *self, char *query, QueryInfo *qi)
empty_reqs; empty_reqs;
BOOL msg_truncated, BOOL msg_truncated,
ReadyToReturn, ReadyToReturn,
tuples_return = FALSE,
query_completed = FALSE, query_completed = FALSE,
before_64 = PG_VERSION_LT(self, 6.4), before_64 = PG_VERSION_LT(self, 6.4),
aborted = FALSE,
used_passed_result_object = FALSE; used_passed_result_object = FALSE;
/* ERROR_MSG_LENGTH is suffcient */ /* ERROR_MSG_LENGTH is suffcient */
...@@ -1156,6 +1204,20 @@ CC_send_query(ConnectionClass *self, char *query, QueryInfo *qi) ...@@ -1156,6 +1204,20 @@ CC_send_query(ConnectionClass *self, char *query, QueryInfo *qi)
; ;
if (*wq == '\0') if (*wq == '\0')
empty_reqs = 1; empty_reqs = 1;
cmdres = qi ? qi->result_in : NULL;
if (cmdres)
used_passed_result_object = TRUE;
else
{
cmdres = QR_Constructor();
if (!cmdres)
{
self->errornumber = CONNECTION_COULD_NOT_RECEIVE;
self->errormsg = "Could not create result info in send_query.";
return NULL;
}
}
res = cmdres;
while (!ReadyToReturn) while (!ReadyToReturn)
{ {
/* what type of message is coming now ? */ /* what type of message is coming now ? */
...@@ -1199,12 +1261,14 @@ CC_send_query(ConnectionClass *self, char *query, QueryInfo *qi) ...@@ -1199,12 +1261,14 @@ CC_send_query(ConnectionClass *self, char *query, QueryInfo *qi)
{ {
mylog("send_query: ok - 'C' - %s\n", cmdbuffer); mylog("send_query: ok - 'C' - %s\n", cmdbuffer);
if (res == NULL) /* allow for "show" style info */ if (query_completed) /* allow for "show" style notices */
res = QR_Constructor(); {
res->next = QR_Constructor();
res = res->next;
}
mylog("send_query: setting cmdbuffer = '%s'\n", cmdbuffer); mylog("send_query: setting cmdbuffer = '%s'\n", cmdbuffer);
/* Only save the first command */
if (QR_command_successful(res)) if (QR_command_successful(res))
QR_set_status(res, PGRES_COMMAND_OK); QR_set_status(res, PGRES_COMMAND_OK);
QR_set_command(res, cmdbuffer); QR_set_command(res, cmdbuffer);
...@@ -1233,44 +1297,19 @@ CC_send_query(ConnectionClass *self, char *query, QueryInfo *qi) ...@@ -1233,44 +1297,19 @@ CC_send_query(ConnectionClass *self, char *query, QueryInfo *qi)
if (empty_reqs == 0) if (empty_reqs == 0)
{ {
ReadyToReturn = TRUE; ReadyToReturn = TRUE;
if (res && QR_get_aborted(res)) if (aborted || query_completed)
retres = res; retres = cmdres;
else if (tuples_return)
retres = result_in;
else if (query_completed)
retres = res;
else else
ReadyToReturn = FALSE; ReadyToReturn = FALSE;
} }
break; break;
case 'N': /* INFO, NOTICE, WARNING */ case 'N': /* NOTICE: */
msg_truncated = SOCK_get_string(sock, cmdbuffer, ERROR_MSG_LENGTH); msg_truncated = SOCK_get_string(sock, cmdbuffer, ERROR_MSG_LENGTH);
if (!res)
res = QR_Constructor();
if (QR_command_successful(res)) if (QR_command_successful(res))
QR_set_status(res, PGRES_NONFATAL_ERROR); QR_set_status(res, PGRES_NONFATAL_ERROR);
QR_set_notice(res, cmdbuffer); /* will dup this string */ QR_set_notice(res, cmdbuffer); /* will dup this string */
#ifdef MULTIBYTE mylog("~~~ NOTICE: '%s'\n", cmdbuffer);
if (strstr(cmdbuffer,"encoding is")) qlog("NOTICE from backend during send_query: '%s'\n", cmdbuffer);
{
if (strstr(cmdbuffer,"Current client encoding is"))
strcpy(PG_CCSS, cmdbuffer + 36);
if (strstr(cmdbuffer,"Current server encoding is"))
strcpy(PG_SCSS, cmdbuffer + 36);
mylog("~~~ WARNING: '%s'\n", cmdbuffer);
qlog("WARNING from backend during send_query: '%s'\n ClientEncoding = %s\n ServerEncoding = %s\n", cmdbuffer, PG_CCSS, PG_SCSS);
}
else
{
mylog("~~~ WARNING: '%s'\n", cmdbuffer);
qlog("WARNING from backend during send_query: '%s'\n", cmdbuffer);
}
#else
mylog("~~~ WARNING: '%s'\n", cmdbuffer);
qlog("WARNING from backend during send_query: '%s'\n", cmdbuffer);
#endif
while (msg_truncated) while (msg_truncated)
msg_truncated = SOCK_get_string(sock, cmdbuffer, ERROR_MSG_LENGTH); msg_truncated = SOCK_get_string(sock, cmdbuffer, ERROR_MSG_LENGTH);
...@@ -1280,15 +1319,13 @@ CC_send_query(ConnectionClass *self, char *query, QueryInfo *qi) ...@@ -1280,15 +1319,13 @@ CC_send_query(ConnectionClass *self, char *query, QueryInfo *qi)
case 'I': /* The server sends an empty query */ case 'I': /* The server sends an empty query */
/* There is a closing '\0' following the 'I', so we eat it */ /* There is a closing '\0' following the 'I', so we eat it */
swallow = SOCK_get_char(sock); swallow = SOCK_get_char(sock);
if (!res)
res = QR_Constructor();
if ((swallow != '\0') || SOCK_get_errcode(sock) != 0) if ((swallow != '\0') || SOCK_get_errcode(sock) != 0)
{ {
self->errornumber = CONNECTION_BACKEND_CRAZY; self->errornumber = CONNECTION_BACKEND_CRAZY;
self->errormsg = "Unexpected protocol character from backend (send_query - I)"; self->errormsg = "Unexpected protocol character from backend (send_query - I)";
QR_set_status(res, PGRES_FATAL_ERROR); QR_set_status(res, PGRES_FATAL_ERROR);
ReadyToReturn = TRUE; ReadyToReturn = TRUE;
retres = res; retres = cmdres;
break; break;
} }
else else
...@@ -1315,8 +1352,6 @@ CC_send_query(ConnectionClass *self, char *query, QueryInfo *qi) ...@@ -1315,8 +1352,6 @@ CC_send_query(ConnectionClass *self, char *query, QueryInfo *qi)
qlog("ERROR from backend during send_query: '%s'\n", self->errormsg); qlog("ERROR from backend during send_query: '%s'\n", self->errormsg);
/* We should report that an error occured. Zoltan */ /* We should report that an error occured. Zoltan */
if (!res)
res = QR_Constructor();
if (!strncmp(self->errormsg, "FATAL", 5)) if (!strncmp(self->errormsg, "FATAL", 5))
{ {
...@@ -1327,6 +1362,7 @@ CC_send_query(ConnectionClass *self, char *query, QueryInfo *qi) ...@@ -1327,6 +1362,7 @@ CC_send_query(ConnectionClass *self, char *query, QueryInfo *qi)
self->errornumber = CONNECTION_SERVER_REPORTED_WARNING; self->errornumber = CONNECTION_SERVER_REPORTED_WARNING;
QR_set_status(res, PGRES_FATAL_ERROR); QR_set_status(res, PGRES_FATAL_ERROR);
QR_set_aborted(res, TRUE); QR_set_aborted(res, TRUE);
aborted = TRUE;
while (msg_truncated) while (msg_truncated)
msg_truncated = SOCK_get_string(sock, cmdbuffer, ERROR_MSG_LENGTH); msg_truncated = SOCK_get_string(sock, cmdbuffer, ERROR_MSG_LENGTH);
...@@ -1337,13 +1373,11 @@ CC_send_query(ConnectionClass *self, char *query, QueryInfo *qi) ...@@ -1337,13 +1373,11 @@ CC_send_query(ConnectionClass *self, char *query, QueryInfo *qi)
SOCK_get_string(sock, msgbuffer, ERROR_MSG_LENGTH); SOCK_get_string(sock, msgbuffer, ERROR_MSG_LENGTH);
break; break;
case 'T': /* Tuple results start here */ case 'T': /* Tuple results start here */
result_in = qi ? qi->result_in : NULL; if (query_completed)
if (result_in == NULL)
{ {
result_in = QR_Constructor(); res->next = QR_Constructor();
mylog("send_query: 'T' no result_in: res = %u\n", result_in); mylog("send_query: 'T' no result_in: res = %u\n", res->next);
if (!result_in) if (!res->next)
{ {
self->errornumber = CONNECTION_COULD_NOT_RECEIVE; self->errornumber = CONNECTION_COULD_NOT_RECEIVE;
self->errormsg = "Could not create result info in send_query."; self->errormsg = "Could not create result info in send_query.";
...@@ -1351,55 +1385,60 @@ CC_send_query(ConnectionClass *self, char *query, QueryInfo *qi) ...@@ -1351,55 +1385,60 @@ CC_send_query(ConnectionClass *self, char *query, QueryInfo *qi)
retres = NULL; retres = NULL;
break; break;
} }
res = res->next;
if (qi) if (qi)
QR_set_cache_size(result_in, qi->row_size); QR_set_cache_size(res, qi->row_size);
}
if (!QR_fetch_tuples(result_in, self, qi ? qi->cursor : NULL)) if (!used_passed_result_object)
{
if (!QR_fetch_tuples(res, self, qi ? qi->cursor : NULL))
{ {
self->errornumber = CONNECTION_COULD_NOT_RECEIVE; self->errornumber = CONNECTION_COULD_NOT_RECEIVE;
self->errormsg = QR_get_message(result_in); self->errormsg = QR_get_message(res);
ReadyToReturn = TRUE; ReadyToReturn = TRUE;
retres = NULL; retres = NULL;
break; break;
} }
query_completed = TRUE;
} }
else else
{ /* next fetch, so reuse an existing result */ { /* next fetch, so reuse an existing result */
used_passed_result_object = TRUE;
/* /*
* called from QR_next_tuple and must return * called from QR_next_tuple and must return
* immediately. * immediately.
*/ */
ReadyToReturn = TRUE; ReadyToReturn = TRUE;
if (!QR_fetch_tuples(result_in, NULL, NULL)) if (!QR_fetch_tuples(res, NULL, NULL))
{ {
self->errornumber = CONNECTION_COULD_NOT_RECEIVE; self->errornumber = CONNECTION_COULD_NOT_RECEIVE;
self->errormsg = QR_get_message(result_in); self->errormsg = QR_get_message(res);
retres = NULL; retres = NULL;
break; break;
} }
retres = result_in; retres = cmdres;
} }
tuples_return = TRUE;
break; break;
case 'D': /* Copy in command began successfully */ case 'D': /* Copy in command began successfully */
if (!res) if (query_completed)
res = QR_Constructor(); {
if (QR_command_successful(res)) res->next = QR_Constructor();
QR_set_status(res, PGRES_COPY_IN); res = res->next;
}
QR_set_status(res, PGRES_COPY_IN);
ReadyToReturn = TRUE; ReadyToReturn = TRUE;
retres = res; retres = cmdres;
break; break;
case 'B': /* Copy out command began successfully */ case 'B': /* Copy out command began successfully */
if (!res) if (query_completed)
res = QR_Constructor(); {
if (QR_command_successful(res)) res->next = QR_Constructor();
QR_set_status(res, PGRES_COPY_OUT); res = res->next;
}
QR_set_status(res, PGRES_COPY_OUT);
ReadyToReturn = TRUE; ReadyToReturn = TRUE;
retres = res; retres = cmdres;
break; break;
default: default:
self->errornumber = CONNECTION_BACKEND_CRAZY; self->errornumber = CONNECTION_BACKEND_CRAZY;
...@@ -1417,7 +1456,7 @@ CC_send_query(ConnectionClass *self, char *query, QueryInfo *qi) ...@@ -1417,7 +1456,7 @@ CC_send_query(ConnectionClass *self, char *query, QueryInfo *qi)
*/ */
if (before_64) if (before_64)
{ {
if (empty_reqs == 0 && (query_completed || tuples_return)) if (empty_reqs == 0 && query_completed)
break; break;
} }
} }
...@@ -1426,34 +1465,44 @@ CC_send_query(ConnectionClass *self, char *query, QueryInfo *qi) ...@@ -1426,34 +1465,44 @@ CC_send_query(ConnectionClass *self, char *query, QueryInfo *qi)
* Break before being ready to return. * Break before being ready to return.
*/ */
if (!ReadyToReturn) if (!ReadyToReturn)
{ retres = cmdres;
if (res && QR_get_aborted(res))
retres = res;
else if (tuples_return)
retres = result_in;
else
retres = res;
}
/* /*
* set notice message to result_in. * Cleanup garbage results before returning.
*/ */
if (result_in && res && retres == result_in) if (cmdres && retres != cmdres && !used_passed_result_object)
{ QR_Destructor(cmdres);
if (QR_command_successful(result_in))
QR_set_status(result_in, QR_get_status(res));
QR_set_notice(result_in, QR_get_notice(res));
}
/* /*
* Cleanup garbage results before returning. * Cleanup the aborted result if specified
*/ */
if (res && retres != res) if (retres)
QR_Destructor(res);
if (result_in && retres != result_in)
{ {
if (!used_passed_result_object) if (aborted)
QR_Destructor(result_in); {
if (clear_result_on_abort)
{
if (!used_passed_result_object)
{
QR_Destructor(retres);
retres = NULL;
}
}
else
{
/*
* discard results other than errors.
*/
QResultClass *qres;
for (qres = retres; qres->next; qres = retres)
{
if (QR_get_aborted(qres))
break;
retres = qres->next;
qres->next = NULL;
QR_Destructor(qres);
}
}
}
} }
return retres; return retres;
} }
...@@ -1591,7 +1640,7 @@ CC_send_function(ConnectionClass *self, int fnid, void *result_buf, int *actual_ ...@@ -1591,7 +1640,7 @@ CC_send_function(ConnectionClass *self, int fnid, void *result_buf, int *actual_
SOCK_get_string(sock, msgbuffer, ERROR_MSG_LENGTH); SOCK_get_string(sock, msgbuffer, ERROR_MSG_LENGTH);
mylog("send_function(G): 'N' - %s\n", msgbuffer); mylog("send_function(G): 'N' - %s\n", msgbuffer);
qlog("WARNING from backend during send_function: '%s'\n", msgbuffer); qlog("NOTICE from backend during send_function: '%s'\n", msgbuffer);
continue; /* dont return a result -- continue continue; /* dont return a result -- continue
* reading */ * reading */
...@@ -1869,7 +1918,7 @@ CC_lookup_pg_version(ConnectionClass *self) ...@@ -1869,7 +1918,7 @@ CC_lookup_pg_version(ConnectionClass *self)
void void
CC_log_error(char *func, char *desc, ConnectionClass *self) CC_log_error(const char *func, const char *desc, const ConnectionClass *self)
{ {
#ifdef PRN_NULLCHECK #ifdef PRN_NULLCHECK
#define nullcheck(a) (a ? a : "(NULL)") #define nullcheck(a) (a ? a : "(NULL)")
...@@ -1894,7 +1943,10 @@ CC_log_error(char *func, char *desc, ConnectionClass *self) ...@@ -1894,7 +1943,10 @@ CC_log_error(char *func, char *desc, ConnectionClass *self)
} }
} }
else else
{
qlog("INVALID CONNECTION HANDLE ERROR: func=%s, desc='%s'\n", func, desc); qlog("INVALID CONNECTION HANDLE ERROR: func=%s, desc='%s'\n", func, desc);
mylog("INVALID CONNECTION HANDLE ERROR: func=%s, desc='%s'\n", func, desc);
}
#undef PRN_NULLCHECK #undef PRN_NULLCHECK
} }
......
...@@ -151,6 +151,8 @@ typedef struct ...@@ -151,6 +151,8 @@ typedef struct
char focus_password; char focus_password;
char disallow_premature; char disallow_premature;
char updatable_cursors; char updatable_cursors;
char lf_conversion;
char true_is_minus1;
GLOBAL_VALUES drivers; /* moved from driver's option */ GLOBAL_VALUES drivers; /* moved from driver's option */
} ConnInfo; } ConnInfo;
...@@ -271,6 +273,7 @@ struct ConnectionClass_ ...@@ -271,6 +273,7 @@ struct ConnectionClass_
char *client_encoding; char *client_encoding;
char *server_encoding; char *server_encoding;
#endif /* MULTIBYTE */ #endif /* MULTIBYTE */
int ccsc;
}; };
...@@ -290,6 +293,7 @@ struct ConnectionClass_ ...@@ -290,6 +293,7 @@ struct ConnectionClass_
/* prototypes */ /* prototypes */
ConnectionClass *CC_Constructor(void); ConnectionClass *CC_Constructor(void);
void CC_conninfo_init(ConnInfo *conninfo);
char CC_Destructor(ConnectionClass *self); char CC_Destructor(ConnectionClass *self);
int CC_cursor_count(ConnectionClass *self); int CC_cursor_count(ConnectionClass *self);
char CC_cleanup(ConnectionClass *self); char CC_cleanup(ConnectionClass *self);
...@@ -301,7 +305,7 @@ char CC_connect(ConnectionClass *self, char do_password); ...@@ -301,7 +305,7 @@ char CC_connect(ConnectionClass *self, char do_password);
char CC_add_statement(ConnectionClass *self, StatementClass *stmt); char CC_add_statement(ConnectionClass *self, StatementClass *stmt);
char CC_remove_statement(ConnectionClass *self, StatementClass *stmt); char CC_remove_statement(ConnectionClass *self, StatementClass *stmt);
char CC_get_error(ConnectionClass *self, int *number, char **message); char CC_get_error(ConnectionClass *self, int *number, char **message);
QResultClass *CC_send_query(ConnectionClass *self, char *query, QueryInfo *qi); QResultClass *CC_send_query(ConnectionClass *self, char *query, QueryInfo *qi, BOOL);
void CC_clear_error(ConnectionClass *self); void CC_clear_error(ConnectionClass *self);
char *CC_create_errormsg(ConnectionClass *self); char *CC_create_errormsg(ConnectionClass *self);
int CC_send_function(ConnectionClass *conn, int fnid, void *result_buf, int *actual_result_len, int result_is_int, LO_ARG *argv, int nargs); int CC_send_function(ConnectionClass *conn, int fnid, void *result_buf, int *actual_result_len, int result_is_int, LO_ARG *argv, int nargs);
...@@ -309,7 +313,7 @@ char CC_send_settings(ConnectionClass *self); ...@@ -309,7 +313,7 @@ char CC_send_settings(ConnectionClass *self);
void CC_lookup_lo(ConnectionClass *conn); void CC_lookup_lo(ConnectionClass *conn);
void CC_lookup_pg_version(ConnectionClass *conn); void CC_lookup_pg_version(ConnectionClass *conn);
void CC_initialize_pg_version(ConnectionClass *conn); void CC_initialize_pg_version(ConnectionClass *conn);
void CC_log_error(char *func, char *desc, ConnectionClass *self); void CC_log_error(const char *func, const char *desc, const ConnectionClass *self);
int CC_get_max_query_len(const ConnectionClass *self); int CC_get_max_query_len(const ConnectionClass *self);
#endif #endif
...@@ -335,12 +335,15 @@ copy_and_convert_field(StatementClass *stmt, Int4 field_type, void *value, Int2 ...@@ -335,12 +335,15 @@ copy_and_convert_field(StatementClass *stmt, Int4 field_type, void *value, Int2
int bind_row = stmt->bind_row; int bind_row = stmt->bind_row;
int bind_size = stmt->options.bind_size; int bind_size = stmt->options.bind_size;
int result = COPY_OK; int result = COPY_OK;
BOOL changed; BOOL changed, true_is_minus1 = FALSE;
const char *neut_str = value; const char *neut_str = value;
char midtemp[2][32]; char midtemp[2][32];
int mtemp_cnt = 0; int mtemp_cnt = 0;
static BindInfoClass sbic; static BindInfoClass sbic;
BindInfoClass *pbic; BindInfoClass *pbic;
#ifdef UNICODE_SUPPORT
BOOL wchanged = FALSE;
#endif /* UNICODE_SUPPORT */
if (stmt->current_col >= 0) if (stmt->current_col >= 0)
{ {
...@@ -474,15 +477,23 @@ copy_and_convert_field(StatementClass *stmt, Int4 field_type, void *value, Int2 ...@@ -474,15 +477,23 @@ copy_and_convert_field(StatementClass *stmt, Int4 field_type, void *value, Int2
char *s; char *s;
s = midtemp[mtemp_cnt]; s = midtemp[mtemp_cnt];
strcpy(s, (char *) value); switch (((char *)value)[0])
if (s[0] == 'f' || s[0] == 'F' || s[0] == 'n' || s[0] == 'N' || s[0] == '0') {
s[0] = '0'; case 'f':
else case 'F':
s[0] = '1'; case 'n':
s[1] = '\0'; case 'N':
case '0':
strcpy(s, "0");
break;
default:
if (true_is_minus1)
strcpy(s, "-1");
else
strcpy(s, "1");
}
neut_str = midtemp[mtemp_cnt]; neut_str = midtemp[mtemp_cnt];
mtemp_cnt++; mtemp_cnt++;
} }
break; break;
...@@ -567,7 +578,11 @@ copy_and_convert_field(StatementClass *stmt, Int4 field_type, void *value, Int2 ...@@ -567,7 +578,11 @@ copy_and_convert_field(StatementClass *stmt, Int4 field_type, void *value, Int2
rgbValueBindRow = (char *) rgbValue + rgbValueOffset; rgbValueBindRow = (char *) rgbValue + rgbValueOffset;
#ifdef UNICODE_SUPPORT
if (fCType == SQL_C_CHAR || fCType == SQL_C_WCHAR)
#else
if (fCType == SQL_C_CHAR) if (fCType == SQL_C_CHAR)
#endif /* UNICODE_SUPPORT */
{ {
/* Special character formatting as required */ /* Special character formatting as required */
...@@ -599,7 +614,7 @@ copy_and_convert_field(StatementClass *stmt, Int4 field_type, void *value, Int2 ...@@ -599,7 +614,7 @@ copy_and_convert_field(StatementClass *stmt, Int4 field_type, void *value, Int2
break; break;
case PG_TYPE_BOOL: case PG_TYPE_BOOL:
len = 1; len = strlen(neut_str);
if (cbValueMax > len) if (cbValueMax > len)
{ {
strcpy(rgbValueBindRow, neut_str); strcpy(rgbValueBindRow, neut_str);
...@@ -637,8 +652,18 @@ copy_and_convert_field(StatementClass *stmt, Int4 field_type, void *value, Int2 ...@@ -637,8 +652,18 @@ copy_and_convert_field(StatementClass *stmt, Int4 field_type, void *value, Int2
pbic = &stmt->bindings[stmt->current_col]; pbic = &stmt->bindings[stmt->current_col];
if (pbic->data_left < 0) if (pbic->data_left < 0)
{ {
BOOL lf_conv = SC_get_conn(stmt)->connInfo.lf_conversion;
#ifdef UNICODE_SUPPORT
if (fCType == SQL_C_WCHAR)
{
len = utf8_to_ucs2(neut_str, -1, NULL, 0);
len *= 2;
wchanged = changed = TRUE;
}
else
#endif /* UNICODE_SUPPORT */
/* convert linefeeds to carriage-return/linefeed */ /* convert linefeeds to carriage-return/linefeed */
len = convert_linefeeds(neut_str, NULL, 0, &changed); len = convert_linefeeds(neut_str, NULL, 0, lf_conv, &changed);
if (cbValueMax == 0) /* just returns length if (cbValueMax == 0) /* just returns length
* info */ * info */
{ {
...@@ -654,7 +679,14 @@ copy_and_convert_field(StatementClass *stmt, Int4 field_type, void *value, Int2 ...@@ -654,7 +679,14 @@ copy_and_convert_field(StatementClass *stmt, Int4 field_type, void *value, Int2
pbic->ttlbuf = realloc(pbic->ttlbuf, len + 1); pbic->ttlbuf = realloc(pbic->ttlbuf, len + 1);
pbic->ttlbuflen = len + 1; pbic->ttlbuflen = len + 1;
} }
convert_linefeeds(neut_str, pbic->ttlbuf, pbic->ttlbuflen, &changed); #ifdef UNICODE_SUPPORT
if (fCType == SQL_C_WCHAR)
{
utf8_to_ucs2(neut_str, -1, (SQLWCHAR *) pbic->ttlbuf, len / 2);
}
else
#endif /* UNICODE_SUPPORT */
convert_linefeeds(neut_str, pbic->ttlbuf, pbic->ttlbuflen, lf_conv, &changed);
ptr = pbic->ttlbuf; ptr = pbic->ttlbuf;
} }
else else
...@@ -715,7 +747,25 @@ copy_and_convert_field(StatementClass *stmt, Int4 field_type, void *value, Int2 ...@@ -715,7 +747,25 @@ copy_and_convert_field(StatementClass *stmt, Int4 field_type, void *value, Int2
mylog(" SQL_C_CHAR, default: len = %d, cbValueMax = %d, rgbValueBindRow = '%s'\n", len, cbValueMax, rgbValueBindRow); mylog(" SQL_C_CHAR, default: len = %d, cbValueMax = %d, rgbValueBindRow = '%s'\n", len, cbValueMax, rgbValueBindRow);
break; break;
} }
#ifdef UNICODE_SUPPORT
if (SQL_C_WCHAR == fCType && ! wchanged)
{
if (cbValueMax > 2 * len)
{
char *str = strdup(rgbValueBindRow);
UInt4 ucount = utf8_to_ucs2(str, len, (SQLWCHAR *) rgbValueBindRow, cbValueMax / 2);
if (cbValueMax < 2 * (SDWORD) ucount)
result = COPY_RESULT_TRUNCATED;
len = ucount * 2;
free(str);
}
else
{
len *= 2;
result = COPY_RESULT_TRUNCATED;
}
}
#endif /* UNICODE_SUPPORT */
} }
else else
...@@ -1107,11 +1157,11 @@ do { \ ...@@ -1107,11 +1157,11 @@ do { \
*/ */
#define CVT_SPECIAL_CHARS(buf, used) \ #define CVT_SPECIAL_CHARS(buf, used) \
do { \ do { \
int cnvlen = convert_special_chars(buf, NULL, used); \ int cnvlen = convert_special_chars(buf, NULL, used, lf_conv, conn->ccsc); \
unsigned int newlimit = npos + cnvlen; \ unsigned int newlimit = npos + cnvlen; \
\ \
ENLARGE_NEWSTATEMENT(newlimit); \ ENLARGE_NEWSTATEMENT(newlimit); \
convert_special_chars(buf, &new_statement[npos], used); \ convert_special_chars(buf, &new_statement[npos], used, lf_conv, conn->ccsc); \
npos += cnvlen; \ npos += cnvlen; \
} while (0) } while (0)
...@@ -1181,9 +1231,9 @@ table_for_update(const char *stmt, int *endpos) ...@@ -1181,9 +1231,9 @@ table_for_update(const char *stmt, int *endpos)
} }
#ifdef MULTIBYTE #ifdef MULTIBYTE
#define my_strchr(s1,c1) multibyte_strchr(s1,c1) #define my_strchr(conn, s1,c1) pg_mbschr(conn->ccsc, s1,c1)
#else #else
#define my_strchr(s1,c1) strchr(s1,c1) #define my_strchr(conn, s1,c1) strchr(s1,c1)
#endif #endif
/* /*
* This function inserts parameters into an SQL statements. * This function inserts parameters into an SQL statements.
...@@ -1213,8 +1263,7 @@ copy_statement_with_parameters(StatementClass *stmt) ...@@ -1213,8 +1263,7 @@ copy_statement_with_parameters(StatementClass *stmt)
time_t t = time(NULL); time_t t = time(NULL);
struct tm *tim; struct tm *tim;
SDWORD used; SDWORD used;
char *buffer, char *buffer, *buf, *allocbuf;
*buf;
BOOL in_quote = FALSE, BOOL in_quote = FALSE,
in_dquote = FALSE, in_dquote = FALSE,
in_escape = FALSE; in_escape = FALSE;
...@@ -1234,6 +1283,10 @@ copy_statement_with_parameters(StatementClass *stmt) ...@@ -1234,6 +1283,10 @@ copy_statement_with_parameters(StatementClass *stmt)
BOOL prev_token_end; BOOL prev_token_end;
UInt4 offset = stmt->options.param_offset_ptr ? *stmt->options.param_offset_ptr : 0; UInt4 offset = stmt->options.param_offset_ptr ? *stmt->options.param_offset_ptr : 0;
UInt4 current_row = stmt->exec_current_row < 0 ? 0 : stmt->exec_current_row; UInt4 current_row = stmt->exec_current_row < 0 ? 0 : stmt->exec_current_row;
BOOL lf_conv = ci->lf_conversion;
#ifdef MULTIBYTE
encoded_str encstr;
#endif /* MULTIBYTE */
#ifdef DRIVER_CURSOR_IMPLEMENT #ifdef DRIVER_CURSOR_IMPLEMENT
BOOL search_from_pos = FALSE; BOOL search_from_pos = FALSE;
...@@ -1311,14 +1364,14 @@ copy_statement_with_parameters(StatementClass *stmt) ...@@ -1311,14 +1364,14 @@ copy_statement_with_parameters(StatementClass *stmt)
} }
param_number = -1; param_number = -1;
#ifdef MULTIBYTE #ifdef MULTIBYTE
multibyte_init(); make_encoded_str(&encstr, conn, old_statement);
#endif #endif
for (opos = 0; opos < oldstmtlen; opos++) for (opos = 0; opos < oldstmtlen; opos++)
{ {
oldchar = old_statement[opos];
#ifdef MULTIBYTE #ifdef MULTIBYTE
if (multibyte_char_check(oldchar) != 0) oldchar = encoded_byte_check(&encstr, opos);
if (ENCODE_STATUS(encstr) != 0)
{ {
CVT_APPEND_CHAR(oldchar); CVT_APPEND_CHAR(oldchar);
continue; continue;
...@@ -1327,6 +1380,8 @@ copy_statement_with_parameters(StatementClass *stmt) ...@@ -1327,6 +1380,8 @@ copy_statement_with_parameters(StatementClass *stmt)
/* /*
* From here we are guaranteed to handle a 1-byte character. * From here we are guaranteed to handle a 1-byte character.
*/ */
#else
oldchar = old_statement[opos];
#endif #endif
if (in_escape) /* escape check */ if (in_escape) /* escape check */
...@@ -1352,7 +1407,7 @@ copy_statement_with_parameters(StatementClass *stmt) ...@@ -1352,7 +1407,7 @@ copy_statement_with_parameters(StatementClass *stmt)
* nor a double quote. * nor a double quote.
*/ */
/* Squeeze carriage-return/linefeed pairs to linefeed only */ /* Squeeze carriage-return/linefeed pairs to linefeed only */
else if (oldchar == '\r' && opos + 1 < oldstmtlen && else if (lf_conv && oldchar == '\r' && opos + 1 < oldstmtlen &&
old_statement[opos + 1] == '\n') old_statement[opos + 1] == '\n')
continue; continue;
...@@ -1390,11 +1445,12 @@ copy_statement_with_parameters(StatementClass *stmt) ...@@ -1390,11 +1445,12 @@ copy_statement_with_parameters(StatementClass *stmt)
} }
opos += lit_call_len; opos += lit_call_len;
CVT_APPEND_STR("SELECT "); CVT_APPEND_STR("SELECT ");
if (my_strchr(&old_statement[opos], '(')) if (my_strchr(conn, &old_statement[opos], '('))
proc_no_param = FALSE; proc_no_param = FALSE;
continue; continue;
} }
if (convert_escape(begin, stmt, &npos, &new_stsize, &end) != CONVERT_ESCAPE_OK) if (convert_escape(begin, stmt, &npos, &new_stsize, &end
) != CONVERT_ESCAPE_OK)
{ {
stmt->errormsg = "ODBC escape convert error"; stmt->errormsg = "ODBC escape convert error";
stmt->errornumber = STMT_EXEC_ERROR; stmt->errornumber = STMT_EXEC_ERROR;
...@@ -1585,7 +1641,7 @@ copy_statement_with_parameters(StatementClass *stmt) ...@@ -1585,7 +1641,7 @@ copy_statement_with_parameters(StatementClass *stmt)
if (param_ctype == SQL_C_DEFAULT) if (param_ctype == SQL_C_DEFAULT)
param_ctype = sqltype_to_default_ctype(param_sqltype); param_ctype = sqltype_to_default_ctype(param_sqltype);
buf = NULL; allocbuf = buf = NULL;
param_string[0] = '\0'; param_string[0] = '\0';
cbuf[0] = '\0'; cbuf[0] = '\0';
...@@ -1597,6 +1653,13 @@ copy_statement_with_parameters(StatementClass *stmt) ...@@ -1597,6 +1653,13 @@ copy_statement_with_parameters(StatementClass *stmt)
buf = buffer; buf = buffer;
break; break;
#ifdef UNICODE_SUPPORT
case SQL_C_WCHAR:
buf = allocbuf = ucs2_to_utf8((SQLWCHAR *) buffer, used / 2, &used);
used *= 2;
break;
#endif /* UNICODE_SUPPORT */
case SQL_C_DOUBLE: case SQL_C_DOUBLE:
sprintf(param_string, "%.15g", sprintf(param_string, "%.15g",
*((SDOUBLE *) buffer)); *((SDOUBLE *) buffer));
...@@ -1729,6 +1792,11 @@ copy_statement_with_parameters(StatementClass *stmt) ...@@ -1729,6 +1792,11 @@ copy_statement_with_parameters(StatementClass *stmt)
case SQL_CHAR: case SQL_CHAR:
case SQL_VARCHAR: case SQL_VARCHAR:
case SQL_LONGVARCHAR: case SQL_LONGVARCHAR:
#ifdef UNICODE_SUPPORT
case SQL_WCHAR:
case SQL_WVARCHAR:
case SQL_WLONGVARCHAR:
#endif /* UNICODE_SUPPORT */
CVT_APPEND_CHAR('\''); /* Open Quote */ CVT_APPEND_CHAR('\''); /* Open Quote */
...@@ -1801,7 +1869,7 @@ copy_statement_with_parameters(StatementClass *stmt) ...@@ -1801,7 +1869,7 @@ copy_statement_with_parameters(StatementClass *stmt)
tmp[0] = '\''; tmp[0] = '\'';
/* Time zone stuff is unreliable */ /* Time zone stuff is unreliable */
stime2timestamp(&st, tmp + 1, USE_ZONE, PG_VERSION_GE(conn, 7.2)); stime2timestamp(&st, tmp + 1, USE_ZONE, PG_VERSION_GE(conn, 7.2));
strcat(tmp, "'"); strcat(tmp, "'::timestamp");
CVT_APPEND_STR(tmp); CVT_APPEND_STR(tmp);
...@@ -1942,6 +2010,10 @@ copy_statement_with_parameters(StatementClass *stmt) ...@@ -1942,6 +2010,10 @@ copy_statement_with_parameters(StatementClass *stmt)
break; break;
} }
#ifdef UNICODE_SUPPORT
if (allocbuf)
free(allocbuf);
#endif /* UNICODE_SUPPORT */
} /* end, for */ } /* end, for */
/* make sure new_statement is always null-terminated */ /* make sure new_statement is always null-terminated */
...@@ -2032,7 +2104,7 @@ int inner_convert_escape(const ConnectionClass *conn, const char *value, ...@@ -2032,7 +2104,7 @@ int inner_convert_escape(const ConnectionClass *conn, const char *value,
while ((*valptr != '\0') && isspace((unsigned char) *valptr)) while ((*valptr != '\0') && isspace((unsigned char) *valptr))
valptr++; valptr++;
if (end = my_strchr(valptr, '}'), NULL == end) if (end = my_strchr(conn, valptr, '}'), NULL == end)
{ {
mylog("%s couldn't find the ending }\n",func); mylog("%s couldn't find the ending }\n",func);
return CONVERT_ESCAPE_ERROR; return CONVERT_ESCAPE_ERROR;
...@@ -2226,13 +2298,16 @@ int processParameters(const ConnectionClass *conn, const char *value, ...@@ -2226,13 +2298,16 @@ int processParameters(const ConnectionClass *conn, const char *value,
const char *valptr; const char *valptr;
char buf[1024]; char buf[1024];
BOOL in_quote, in_dquote, in_escape, leadingSpace; BOOL in_quote, in_dquote, in_escape, leadingSpace;
#ifdef MULTIBYTE
encoded_str encstr;
#endif /* MULTIBYTE */
buf[sizeof(buf)-1] = '\0'; buf[sizeof(buf)-1] = '\0';
innerParenthesis = 0; innerParenthesis = 0;
in_quote = in_dquote = in_escape = leadingSpace = FALSE; in_quote = in_dquote = in_escape = leadingSpace = FALSE;
param_count = 0; param_count = 0;
#ifdef MULTIBYTE #ifdef MULTIBYTE
multibyte_init(); make_encoded_str(&encstr, conn, value);
#endif /* MULTIBYTE */ #endif /* MULTIBYTE */
/* begin with outer '(' */ /* begin with outer '(' */
for (stop = FALSE, valptr = value, ipos = count = 0; *valptr != '\0'; ipos++, valptr++) for (stop = FALSE, valptr = value, ipos = count = 0; *valptr != '\0'; ipos++, valptr++)
...@@ -2250,7 +2325,8 @@ int processParameters(const ConnectionClass *conn, const char *value, ...@@ -2250,7 +2325,8 @@ int processParameters(const ConnectionClass *conn, const char *value,
return CONVERT_ESCAPE_OVERFLOW; return CONVERT_ESCAPE_OVERFLOW;
} }
#ifdef MULTIBYTE #ifdef MULTIBYTE
if (multibyte_char_check(*valptr) != 0) encoded_byte_check(&encstr, ipos);
if (ENCODE_STATUS(encstr) != 0)
{ {
result[count++] = *valptr; result[count++] = *valptr;
continue; continue;
...@@ -2468,7 +2544,7 @@ parse_datetime(char *buf, SIMPLE_TIME *st) ...@@ -2468,7 +2544,7 @@ parse_datetime(char *buf, SIMPLE_TIME *st)
/* Change linefeed to carriage-return/linefeed */ /* Change linefeed to carriage-return/linefeed */
int int
convert_linefeeds(const char *si, char *dst, size_t max, BOOL *changed) convert_linefeeds(const char *si, char *dst, size_t max, BOOL convlf, BOOL *changed)
{ {
size_t i = 0, size_t i = 0,
out = 0; out = 0;
...@@ -2478,7 +2554,7 @@ convert_linefeeds(const char *si, char *dst, size_t max, BOOL *changed) ...@@ -2478,7 +2554,7 @@ convert_linefeeds(const char *si, char *dst, size_t max, BOOL *changed)
*changed = FALSE; *changed = FALSE;
for (i = 0; si[i] && out < max - 1; i++) for (i = 0; si[i] && out < max - 1; i++)
{ {
if (si[i] == '\n') if (convlf && si[i] == '\n')
{ {
/* Only add the carriage-return if needed */ /* Only add the carriage-return if needed */
if (i > 0 && si[i - 1] == '\r') if (i > 0 && si[i - 1] == '\r')
...@@ -2518,12 +2594,15 @@ convert_linefeeds(const char *si, char *dst, size_t max, BOOL *changed) ...@@ -2518,12 +2594,15 @@ convert_linefeeds(const char *si, char *dst, size_t max, BOOL *changed)
* Plus, escape any special characters. * Plus, escape any special characters.
*/ */
int int
convert_special_chars(const char *si, char *dst, int used) convert_special_chars(const char *si, char *dst, int used, BOOL convlf, int ccsc)
{ {
size_t i = 0, size_t i = 0,
out = 0, out = 0,
max; max;
char *p = NULL; char *p = NULL;
#ifdef MULTIBYTE
encoded_str encstr;
#endif
if (used == SQL_NTS) if (used == SQL_NTS)
...@@ -2536,13 +2615,14 @@ convert_special_chars(const char *si, char *dst, int used) ...@@ -2536,13 +2615,14 @@ convert_special_chars(const char *si, char *dst, int used)
p[0] = '\0'; p[0] = '\0';
} }
#ifdef MULTIBYTE #ifdef MULTIBYTE
multibyte_init(); encoded_str_constr(&encstr, ccsc, si);
#endif #endif
for (i = 0; i < max && si[i]; i++) for (i = 0; i < max && si[i]; i++)
{ {
#ifdef MULTIBYTE #ifdef MULTIBYTE
if (multibyte_char_check(si[i]) != 0) encoded_nextchar(&encstr);
if (ENCODE_STATUS(encstr) != 0)
{ {
if (p) if (p)
p[out] = si[i]; p[out] = si[i];
...@@ -2550,7 +2630,7 @@ convert_special_chars(const char *si, char *dst, int used) ...@@ -2550,7 +2630,7 @@ convert_special_chars(const char *si, char *dst, int used)
continue; continue;
} }
#endif #endif
if (si[i] == '\r' && si[i + 1] == '\n') if (convlf && si[i] == '\r' && si[i + 1] == '\n')
continue; continue;
else if (si[i] == '\'' || si[i] == '\\') else if (si[i] == '\'' || si[i] == '\\')
{ {
......
...@@ -21,7 +21,7 @@ ...@@ -21,7 +21,7 @@
/* convert_escape results */ /* convert_escape results */
#define CONVERT_ESCAPE_OK 0 #define CONVERT_ESCAPE_OK 0
#define CONVERT_ESCAPE_OVERFLOW 1 #define CONVERT_ESCAPE_OVERFLOW 1
#define CONVERT_ESCAPE_ERROR 2 #define CONVERT_ESCAPE_ERROR -1
typedef struct typedef struct
{ {
...@@ -43,8 +43,8 @@ int convert_escape(const char *value, StatementClass *stmt, ...@@ -43,8 +43,8 @@ int convert_escape(const char *value, StatementClass *stmt,
int *npos, int *stsize, const char **val_resume); int *npos, int *stsize, const char **val_resume);
BOOL convert_money(const char *s, char *sout, size_t soutmax); BOOL convert_money(const char *s, char *sout, size_t soutmax);
char parse_datetime(char *buf, SIMPLE_TIME *st); char parse_datetime(char *buf, SIMPLE_TIME *st);
int convert_linefeeds(const char *s, char *dst, size_t max, BOOL *changed); int convert_linefeeds(const char *s, char *dst, size_t max, BOOL convlf, BOOL *changed);
int convert_special_chars(const char *si, char *dst, int used); int convert_special_chars(const char *si, char *dst, int used, BOOL convlf,int ccsc);
int convert_pgbinary_to_char(const char *value, char *rgbValue, int cbValueMax); 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_from_pgbinary(const unsigned char *value, unsigned char *rgbValue, int cbValueMax);
......
...@@ -123,7 +123,7 @@ driver_optionsDraw(HWND hdlg, const ConnInfo *ci, int src, BOOL enable) ...@@ -123,7 +123,7 @@ driver_optionsDraw(HWND hdlg, const ConnInfo *ci, int src, BOOL enable)
CheckDlgButton(hdlg, DRV_OPTIMIZER, comval->disable_optimizer); CheckDlgButton(hdlg, DRV_OPTIMIZER, comval->disable_optimizer);
CheckDlgButton(hdlg, DRV_KSQO, comval->ksqo); CheckDlgButton(hdlg, DRV_KSQO, comval->ksqo);
CheckDlgButton(hdlg, DRV_UNIQUEINDEX, comval->unique_index); CheckDlgButton(hdlg, DRV_UNIQUEINDEX, comval->unique_index);
EnableWindow(GetDlgItem(hdlg, DRV_UNIQUEINDEX), enable); /* EnableWindow(GetDlgItem(hdlg, DRV_UNIQUEINDEX), enable); */
CheckDlgButton(hdlg, DRV_READONLY, comval->onlyread); CheckDlgButton(hdlg, DRV_READONLY, comval->onlyread);
EnableWindow(GetDlgItem(hdlg, DRV_READONLY), enable); EnableWindow(GetDlgItem(hdlg, DRV_READONLY), enable);
CheckDlgButton(hdlg, DRV_USEDECLAREFETCH, comval->use_declarefetch); CheckDlgButton(hdlg, DRV_USEDECLAREFETCH, comval->use_declarefetch);
...@@ -332,6 +332,8 @@ ds_optionsProc(HWND hdlg, ...@@ -332,6 +332,8 @@ ds_optionsProc(HWND hdlg,
CheckDlgButton(hdlg, DS_ROWVERSIONING, atoi(ci->row_versioning)); CheckDlgButton(hdlg, DS_ROWVERSIONING, atoi(ci->row_versioning));
CheckDlgButton(hdlg, DS_SHOWSYSTEMTABLES, atoi(ci->show_system_tables)); CheckDlgButton(hdlg, DS_SHOWSYSTEMTABLES, atoi(ci->show_system_tables));
CheckDlgButton(hdlg, DS_DISALLOWPREMATURE, ci->disallow_premature); CheckDlgButton(hdlg, DS_DISALLOWPREMATURE, ci->disallow_premature);
CheckDlgButton(hdlg, DS_LFCONVERSION, ci->lf_conversion);
CheckDlgButton(hdlg, DS_TRUEISMINUS1, ci->true_is_minus1);
EnableWindow(GetDlgItem(hdlg, DS_FAKEOIDINDEX), atoi(ci->show_oid_column)); EnableWindow(GetDlgItem(hdlg, DS_FAKEOIDINDEX), atoi(ci->show_oid_column));
...@@ -367,6 +369,8 @@ ds_optionsProc(HWND hdlg, ...@@ -367,6 +369,8 @@ ds_optionsProc(HWND hdlg,
sprintf(ci->row_versioning, "%d", IsDlgButtonChecked(hdlg, DS_ROWVERSIONING)); sprintf(ci->row_versioning, "%d", IsDlgButtonChecked(hdlg, DS_ROWVERSIONING));
ci->disallow_premature = IsDlgButtonChecked(hdlg, DS_DISALLOWPREMATURE); ci->disallow_premature = IsDlgButtonChecked(hdlg, DS_DISALLOWPREMATURE);
ci->lf_conversion = IsDlgButtonChecked(hdlg, DS_LFCONVERSION);
ci->true_is_minus1 = IsDlgButtonChecked(hdlg, DS_TRUEISMINUS1);
/* OID Options */ /* OID Options */
sprintf(ci->fake_oid_index, "%d", IsDlgButtonChecked(hdlg, DS_FAKEOIDINDEX)); sprintf(ci->fake_oid_index, "%d", IsDlgButtonChecked(hdlg, DS_FAKEOIDINDEX));
...@@ -525,60 +529,186 @@ makeConnectString(char *connect_string, const ConnInfo *ci, UWORD len) ...@@ -525,60 +529,186 @@ makeConnectString(char *connect_string, const ConnInfo *ci, UWORD len)
hlen = strlen(connect_string); hlen = strlen(connect_string);
if (!abbrev) if (!abbrev)
sprintf(&connect_string[hlen], sprintf(&connect_string[hlen],
";READONLY=%s;PROTOCOL=%s;FAKEOIDINDEX=%s;SHOWOIDCOLUMN=%s;ROWVERSIONING=%s;SHOWSYSTEMTABLES=%s;CONNSETTINGS=%s;FETCH=%d;SOCKET=%d;UNKNOWNSIZES=%d;MAXVARCHARSIZE=%d;MAXLONGVARCHARSIZE=%d;DEBUG=%d;COMMLOG=%d;OPTIMIZER=%d;KSQO=%d;USEDECLAREFETCH=%d;TEXTASLONGVARCHAR=%d;UNKNOWNSASLONGVARCHAR=%d;BOOLSASCHAR=%d;PARSE=%d;CANCELASFREESTMT=%d;EXTRASYSTABLEPREFIXES=%s", ";%s=%s;%s=%s;%s=%s;%s=%s;%s=%s;%s=%s;%s=%s;%s=%d;%s=%d;%s=%d;%s=%d;%s=%d;%s=%d;%s=%d;%s=%d;%s=%d;%s=%d;%s=%d;%s=%d;%s=%d;%s=%d;%s=%d;%s=%s;%s=%d;%s=%d;%s=%d;%s=%d",
INI_READONLY,
ci->onlyread, ci->onlyread,
INI_PROTOCOL,
ci->protocol, ci->protocol,
INI_FAKEOIDINDEX,
ci->fake_oid_index, ci->fake_oid_index,
INI_SHOWOIDCOLUMN,
ci->show_oid_column, ci->show_oid_column,
INI_ROWVERSIONING,
ci->row_versioning, ci->row_versioning,
INI_SHOWSYSTEMTABLES,
ci->show_system_tables, ci->show_system_tables,
INI_CONNSETTINGS,
encoded_conn_settings, encoded_conn_settings,
INI_FETCH,
ci->drivers.fetch_max, ci->drivers.fetch_max,
INI_SOCKET,
ci->drivers.socket_buffersize, ci->drivers.socket_buffersize,
INI_UNKNOWNSIZES,
ci->drivers.unknown_sizes, ci->drivers.unknown_sizes,
INI_MAXVARCHARSIZE,
ci->drivers.max_varchar_size, ci->drivers.max_varchar_size,
INI_MAXLONGVARCHARSIZE,
ci->drivers.max_longvarchar_size, ci->drivers.max_longvarchar_size,
INI_DEBUG,
ci->drivers.debug, ci->drivers.debug,
INI_COMMLOG,
ci->drivers.commlog, ci->drivers.commlog,
INI_OPTIMIZER,
ci->drivers.disable_optimizer, ci->drivers.disable_optimizer,
INI_KSQO,
ci->drivers.ksqo, ci->drivers.ksqo,
INI_USEDECLAREFETCH,
ci->drivers.use_declarefetch, ci->drivers.use_declarefetch,
INI_TEXTASLONGVARCHAR,
ci->drivers.text_as_longvarchar, ci->drivers.text_as_longvarchar,
INI_UNKNOWNSASLONGVARCHAR,
ci->drivers.unknowns_as_longvarchar, ci->drivers.unknowns_as_longvarchar,
INI_BOOLSASCHAR,
ci->drivers.bools_as_char, ci->drivers.bools_as_char,
INI_PARSE,
ci->drivers.parse, ci->drivers.parse,
INI_CANCELASFREESTMT,
ci->drivers.cancel_as_freestmt, ci->drivers.cancel_as_freestmt,
ci->drivers.extra_systable_prefixes); INI_EXTRASYSTABLEPREFIXES,
ci->drivers.extra_systable_prefixes,
INI_LFCONVERSION,
ci->lf_conversion,
INI_UPDATABLECURSORS,
ci->updatable_cursors,
INI_DISALLOWPREMATURE,
ci->disallow_premature,
INI_TRUEISMINUS1,
ci->true_is_minus1);
/* Abbrebiation is needed ? */ /* Abbrebiation is needed ? */
if (abbrev || strlen(connect_string) >= len) if (abbrev || strlen(connect_string) >= len)
{
unsigned long flag = 0;
if (ci->disallow_premature)
flag |= BIT_DISALLOWPREMATURE;
if (ci->updatable_cursors)
flag |= BIT_UPDATABLECURSORS;
if (ci->lf_conversion)
flag |= BIT_LFCONVERSION;
if (ci->drivers.unique_index)
flag |= BIT_UNIQUEINDEX;
if (strncmp(ci->protocol, PG64, strlen(PG64)) == 0)
flag |= BIT_PROTOCOL_64;
else if (strncmp(ci->protocol, PG63, strlen(PG63)) == 0)
flag |= BIT_PROTOCOL_63;
switch (ci->drivers.unknown_sizes)
{
case UNKNOWNS_AS_DONTKNOW:
flag |= BIT_UNKNOWN_DONTKNOW;
break;
case UNKNOWNS_AS_MAX:
flag |= BIT_UNKNOWN_ASMAX;
break;
}
if (ci->drivers.disable_optimizer)
flag |= BIT_OPTIMIZER;
if (ci->drivers.ksqo)
flag |= BIT_KSQO;
if (ci->drivers.commlog)
flag |= BIT_COMMLOG;
if (ci->drivers.debug)
flag |= BIT_DEBUG;
if (ci->drivers.parse)
flag |= BIT_PARSE;
if (ci->drivers.cancel_as_freestmt)
flag |= BIT_CANCELASFREESTMT;
if (ci->drivers.use_declarefetch)
flag |= BIT_USEDECLAREFETCH;
if (ci->onlyread[0] == '1')
flag |= BIT_READONLY;
if (ci->drivers.text_as_longvarchar)
flag |= BIT_TEXTASLONGVARCHAR;
if (ci->drivers.unknowns_as_longvarchar)
flag |= BIT_UNKNOWNSASLONGVARCHAR;
if (ci->drivers.bools_as_char)
flag |= BIT_BOOLSASCHAR;
if (ci->row_versioning[0] == '1')
flag |= BIT_ROWVERSIONING;
if (ci->show_system_tables[0] == '1')
flag |= BIT_SHOWSYSTEMTABLES;
if (ci->show_oid_column[0] == '1')
flag |= BIT_SHOWOIDCOLUMN;
if (ci->fake_oid_index[0] == '1')
flag |= BIT_FAKEOIDINDEX;
if (ci->true_is_minus1)
flag |= BIT_TRUEISMINUS1;
sprintf(&connect_string[hlen], sprintf(&connect_string[hlen],
";A0=%s;A1=%s;A2=%s;A3=%s;A4=%s;A5=%s;A6=%s;A7=%d;A8=%d;A9=%d;B0=%d;B1=%d;B2=%d;B3=%d;B4=%d;B5=%d;B6=%d;B7=%d;B8=%d;B9=%d;C0=%d;C1=%d;C2=%s", ";A6=%s;A7=%d;A8=%d;B0=%d;B1=%d;C2=%s;CX=%02x%x",
ci->onlyread,
ci->protocol,
ci->fake_oid_index,
ci->show_oid_column,
ci->row_versioning,
ci->show_system_tables,
encoded_conn_settings, encoded_conn_settings,
ci->drivers.fetch_max, ci->drivers.fetch_max,
ci->drivers.socket_buffersize, ci->drivers.socket_buffersize,
ci->drivers.unknown_sizes,
ci->drivers.max_varchar_size, ci->drivers.max_varchar_size,
ci->drivers.max_longvarchar_size, ci->drivers.max_longvarchar_size,
ci->drivers.debug, ci->drivers.extra_systable_prefixes,
ci->drivers.commlog, EFFECTIVE_BIT_COUNT,
ci->drivers.disable_optimizer, flag);
ci->drivers.ksqo, }
ci->drivers.use_declarefetch,
ci->drivers.text_as_longvarchar,
ci->drivers.unknowns_as_longvarchar,
ci->drivers.bools_as_char,
ci->drivers.parse,
ci->drivers.cancel_as_freestmt,
ci->drivers.extra_systable_prefixes);
} }
static void
unfoldCXAttribute(ConnInfo *ci, const char *value)
{
int count;
unsigned long flag;
if (strlen(value) < 2)
{
count = 3;
sscanf(value, "%x", &flag);
}
else
{
char cnt[8];
memcpy(cnt, value, 2);
cnt[2] = '\0';
sscanf(cnt, "%x", &count);
sscanf(value + 2, "%x", &flag);
}
ci->disallow_premature = (char)((flag & BIT_DISALLOWPREMATURE) != 0);
ci->updatable_cursors = (char)((flag & BIT_UPDATABLECURSORS) != 0);
ci->lf_conversion = (char)((flag & BIT_LFCONVERSION) != 0);
if (count < 4)
return;
ci->drivers.unique_index = (char)((flag & BIT_UNIQUEINDEX) != 0);
if ((flag & BIT_PROTOCOL_64) != 0)
strcpy(ci->protocol, PG64);
else if ((flag & BIT_PROTOCOL_63) != 0)
strcpy(ci->protocol, PG63);
else
strcpy(ci->protocol, PG62);
if ((flag & BIT_UNKNOWN_DONTKNOW) != 0)
ci->drivers.unknown_sizes = UNKNOWNS_AS_DONTKNOW;
else if ((flag & BIT_UNKNOWN_ASMAX) != 0)
ci->drivers.unknown_sizes = UNKNOWNS_AS_MAX;
else
ci->drivers.unknown_sizes = UNKNOWNS_AS_LONGEST;
ci->drivers.disable_optimizer = (char)((flag & BIT_OPTIMIZER) != 0);
ci->drivers.ksqo = (char)((flag & BIT_KSQO) != 0);
ci->drivers.commlog = (char)((flag & BIT_COMMLOG) != 0);
ci->drivers.debug = (char)((flag & BIT_DEBUG) != 0);
ci->drivers.parse = (char)((flag & BIT_PARSE) != 0);
ci->drivers.cancel_as_freestmt = (char)((flag & BIT_CANCELASFREESTMT) != 0);
ci->drivers.use_declarefetch = (char)((flag & BIT_USEDECLAREFETCH) != 0);
sprintf(ci->onlyread, "%d", (char)((flag & BIT_READONLY) != 0));
ci->drivers.text_as_longvarchar = (char)((flag & BIT_TEXTASLONGVARCHAR) !=0);
ci->drivers.unknowns_as_longvarchar = (char)((flag & BIT_UNKNOWNSASLONGVARCHAR) !=0);
ci->drivers.bools_as_char = (char)((flag & BIT_BOOLSASCHAR) != 0);
sprintf(ci->row_versioning, "%d", (char)((flag & BIT_ROWVERSIONING) != 0));
sprintf(ci->show_system_tables, "%d", (char)((flag & BIT_SHOWSYSTEMTABLES) != 0));
sprintf(ci->show_oid_column, "%d", (char)((flag & BIT_SHOWOIDCOLUMN) != 0));
sprintf(ci->fake_oid_index, "%d", (char)((flag & BIT_FAKEOIDINDEX) != 0));
ci->true_is_minus1 = (char)((flag & BIT_TRUEISMINUS1) != 0);
}
void void
copyAttributes(ConnInfo *ci, const char *attribute, const char *value) copyAttributes(ConnInfo *ci, const char *attribute, const char *value)
{ {
...@@ -630,6 +760,12 @@ copyAttributes(ConnInfo *ci, const char *attribute, const char *value) ...@@ -630,6 +760,12 @@ copyAttributes(ConnInfo *ci, const char *attribute, const char *value)
ci->disallow_premature = atoi(value); ci->disallow_premature = atoi(value);
else if (stricmp(attribute, INI_UPDATABLECURSORS) == 0 || stricmp(attribute, "C4") == 0) else if (stricmp(attribute, INI_UPDATABLECURSORS) == 0 || stricmp(attribute, "C4") == 0)
ci->updatable_cursors = atoi(value); ci->updatable_cursors = atoi(value);
else if (stricmp(attribute, INI_LFCONVERSION) == 0)
ci->lf_conversion = atoi(value);
else if (stricmp(attribute, INI_TRUEISMINUS1) == 0)
ci->true_is_minus1 = atoi(value);
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, ci->port, ci->onlyread, ci->protocol, ci->conn_settings, ci->disallow_premature);
} }
...@@ -720,6 +856,15 @@ getDSNdefaults(ConnInfo *ci) ...@@ -720,6 +856,15 @@ getDSNdefaults(ConnInfo *ci)
if (ci->row_versioning[0] == '\0') if (ci->row_versioning[0] == '\0')
sprintf(ci->row_versioning, "%d", DEFAULT_ROWVERSIONING); sprintf(ci->row_versioning, "%d", DEFAULT_ROWVERSIONING);
if (ci->disallow_premature < 0)
ci->disallow_premature = DEFAULT_DISALLOWPREMATURE;
if (ci->updatable_cursors < 0)
ci->updatable_cursors = DEFAULT_UPDATABLECURSORS;
if (ci->lf_conversion < 0)
ci->lf_conversion = DEFAULT_LFCONVERSION;
if (ci->true_is_minus1 < 0)
ci->true_is_minus1 = DEFAULT_TRUEISMINUS1;
} }
...@@ -797,16 +942,32 @@ getDSNinfo(ConnInfo *ci, char overwrite) ...@@ -797,16 +942,32 @@ getDSNinfo(ConnInfo *ci, char overwrite)
if (ci->translation_option[0] == '\0' || overwrite) if (ci->translation_option[0] == '\0' || overwrite)
SQLGetPrivateProfileString(DSN, INI_TRANSLATIONOPTION, "", ci->translation_option, sizeof(ci->translation_option), ODBC_INI); SQLGetPrivateProfileString(DSN, INI_TRANSLATIONOPTION, "", ci->translation_option, sizeof(ci->translation_option), ODBC_INI);
if (ci->disallow_premature == 0 || overwrite) if (ci->disallow_premature < 0 || overwrite)
{ {
SQLGetPrivateProfileString(DSN, INI_DISALLOWPREMATURE, "", temp, sizeof(temp), ODBC_INI); SQLGetPrivateProfileString(DSN, INI_DISALLOWPREMATURE, "", temp, sizeof(temp), ODBC_INI);
ci->disallow_premature = atoi(temp); if (temp[0])
ci->disallow_premature = atoi(temp);
} }
if (ci->updatable_cursors == 0 || overwrite) if (ci->updatable_cursors < 0 || overwrite)
{ {
SQLGetPrivateProfileString(DSN, INI_UPDATABLECURSORS, "", temp, sizeof(temp), ODBC_INI); SQLGetPrivateProfileString(DSN, INI_UPDATABLECURSORS, "", temp, sizeof(temp), ODBC_INI);
ci->updatable_cursors = atoi(temp); if (temp[0])
ci->updatable_cursors = atoi(temp);
}
if (ci->lf_conversion < 0 || overwrite)
{
SQLGetPrivateProfileString(DSN, INI_LFCONVERSION, "", temp, sizeof(temp), ODBC_INI);
if (temp[0])
ci->lf_conversion = atoi(temp);
}
if (ci->true_is_minus1 < 0 || overwrite)
{
SQLGetPrivateProfileString(DSN, INI_TRUEISMINUS1, "", temp, sizeof(temp), ODBC_INI);
if (temp[0])
ci->true_is_minus1 = atoi(temp);
} }
/* Allow override of odbcinst.ini parameters here */ /* Allow override of odbcinst.ini parameters here */
...@@ -927,6 +1088,16 @@ writeDSNinfo(const ConnInfo *ci) ...@@ -927,6 +1088,16 @@ writeDSNinfo(const ConnInfo *ci)
INI_UPDATABLECURSORS, INI_UPDATABLECURSORS,
temp, temp,
ODBC_INI); ODBC_INI);
sprintf(temp, "%d", ci->lf_conversion);
SQLWritePrivateProfileString(DSN,
INI_LFCONVERSION,
temp,
ODBC_INI);
sprintf(temp, "%d", ci->true_is_minus1);
SQLWritePrivateProfileString(DSN,
INI_TRUEISMINUS1,
temp,
ODBC_INI);
} }
......
...@@ -89,6 +89,35 @@ ...@@ -89,6 +89,35 @@
#define INI_TRANSLATIONOPTION "TranslationOption" #define INI_TRANSLATIONOPTION "TranslationOption"
#define INI_DISALLOWPREMATURE "DisallowPremature" #define INI_DISALLOWPREMATURE "DisallowPremature"
#define INI_UPDATABLECURSORS "UpdatableCursors" #define INI_UPDATABLECURSORS "UpdatableCursors"
#define INI_LFCONVERSION "LFConversion"
#define INI_TRUEISMINUS1 "TrueIsMinus1"
/* Bit representaion for abbreviated connection strings */
#define BIT_LFCONVERSION (1L)
#define BIT_UPDATABLECURSORS (1L<<1)
#define BIT_DISALLOWPREMATURE (1L<<2)
#define BIT_UNIQUEINDEX (1L<<3)
#define BIT_PROTOCOL_63 (1L<<4)
#define BIT_PROTOCOL_64 (1L<<5)
#define BIT_UNKNOWN_DONTKNOW (1L<<6)
#define BIT_UNKNOWN_ASMAX (1L<<7)
#define BIT_OPTIMIZER (1L<<8)
#define BIT_KSQO (1L<<9)
#define BIT_COMMLOG (1L<<10)
#define BIT_DEBUG (1L<<11)
#define BIT_PARSE (1L<<12)
#define BIT_CANCELASFREESTMT (1L<<13)
#define BIT_USEDECLAREFETCH (1L<<14)
#define BIT_READONLY (1L<<15)
#define BIT_TEXTASLONGVARCHAR (1L<<16)
#define BIT_UNKNOWNSASLONGVARCHAR (1L<<17)
#define BIT_BOOLSASCHAR (1L<<18)
#define BIT_ROWVERSIONING (1L<<19)
#define BIT_SHOWSYSTEMTABLES (1L<<20)
#define BIT_SHOWOIDCOLUMN (1L<<21)
#define BIT_FAKEOIDINDEX (1L<<22)
#define BIT_TRUEISMINUS1 (1L<<23)
#define EFFECTIVE_BIT_COUNT 24
/* Connection Defaults */ /* Connection Defaults */
...@@ -119,6 +148,19 @@ ...@@ -119,6 +148,19 @@
#define DEFAULT_EXTRASYSTABLEPREFIXES "dd_;" #define DEFAULT_EXTRASYSTABLEPREFIXES "dd_;"
#define DEFAULT_DISALLOWPREMATURE 0
#define DEFAULT_TRUEISMINUS1 0
#ifdef DRIVER_CURSOR_IMPLEMENT
#define DEFAULT_UPDATABLECURSORS 1
#else
#define DEFAULT_UPDATABLECURSORS 0
#endif /* DRIVER_CURSOR_IMPLEMENT */
#ifdef WIN32
#define DEFAULT_LFCONVERSION 1
#else
#define DEFAULT_LFCONVERSION 0
#endif /* WIN32 */
/* prototypes */ /* prototypes */
void getCommonDefaults(const char *section, const char *filename, ConnInfo *ci); void getCommonDefaults(const char *section, const char *filename, ConnInfo *ci);
......
...@@ -242,7 +242,7 @@ dialog: ...@@ -242,7 +242,7 @@ dialog:
qlog("conn=%u, PGAPI_DriverConnect(out)='%s'\n", conn, szConnStrOut); qlog("conn=%u, PGAPI_DriverConnect(out)='%s'\n", conn, szConnStrOut);
mylog("PGAPI_DRiverConnect: returning %d\n", result); mylog("PGAPI_DriverConnect: returning %d\n", result);
return result; return result;
} }
...@@ -351,10 +351,7 @@ dconn_get_connect_attributes(const UCHAR FAR * connect_string, ConnInfo *ci) ...@@ -351,10 +351,7 @@ dconn_get_connect_attributes(const UCHAR FAR * connect_string, ConnInfo *ci)
*equals; *equals;
char *strtok_arg; char *strtok_arg;
memset(ci, 0, sizeof(ConnInfo)); CC_conninfo_init(ci);
#ifdef DRIVER_CURSOR_IMPLEMENT
ci->updatable_cursors = 1;
#endif /* DRIVER_CURSOR_IMPLEMENT */
our_connect_string = strdup(connect_string); our_connect_string = strdup(connect_string);
strtok_arg = our_connect_string; strtok_arg = our_connect_string;
......
...@@ -78,408 +78,450 @@ PGAPI_FreeEnv(HENV henv) ...@@ -78,408 +78,450 @@ PGAPI_FreeEnv(HENV henv)
} }
#define DRVMNGRDIV 511
/* Returns the next SQL error information. */ /* Returns the next SQL error information. */
RETCODE SQL_API RETCODE SQL_API
PGAPI_Error( PGAPI_StmtError( HSTMT hstmt,
HENV henv, SWORD RecNumber,
HDBC hdbc,
HSTMT hstmt,
UCHAR FAR * szSqlState, UCHAR FAR * szSqlState,
SDWORD FAR * pfNativeError, SDWORD FAR * pfNativeError,
UCHAR FAR * szErrorMsg, UCHAR FAR * szErrorMsg,
SWORD cbErrorMsgMax, SWORD cbErrorMsgMax,
SWORD FAR * pcbErrorMsg) SWORD FAR * pcbErrorMsg,
UWORD flag)
{ {
char *msg; /* CC: return an error of a hstmt */
int status; StatementClass *stmt = (StatementClass *) hstmt;
BOOL once_again = FALSE; char *msg;
SWORD msglen; int status;
BOOL once_again = FALSE,
partial_ok = (flag & PODBC_ALLOW_PARTIAL_EXTRACT != 0),
clear_str = (flag & PODBC_ERROR_CLEAR != 0);
SWORD msglen, stapos, wrtlen, pcblen;
mylog("**** PGAPI_Error: henv=%u, hdbc=%u, hstmt=%u <%d>\n", henv, hdbc, hstmt, cbErrorMsgMax); mylog("**** PGAPI_StmtError: hstmt=%u <%d>\n", hstmt, cbErrorMsgMax);
if (cbErrorMsgMax < 0) if (cbErrorMsgMax < 0)
return SQL_ERROR; return SQL_ERROR;
if (SQL_NULL_HSTMT != hstmt)
{
/* CC: return an error of a hstmt */
StatementClass *stmt = (StatementClass *) hstmt;
if (SC_get_error(stmt, &status, &msg)) if (!SC_get_error(stmt, &status, &msg) || NULL == msg || !msg[0])
{ {
mylog("SC_get_error: status = %d, msg = #%s#\n", status, msg); mylog("SC_Get_error returned nothing.\n");
if (NULL == msg) if (NULL != szSqlState)
{ strcpy(szSqlState, "00000");
if (NULL != szSqlState) if (NULL != pcbErrorMsg)
strcpy(szSqlState, "00000"); *pcbErrorMsg = 0;
if (NULL != pcbErrorMsg) if ((NULL != szErrorMsg) && (cbErrorMsgMax > 0))
*pcbErrorMsg = 0; szErrorMsg[0] = '\0';
if ((NULL != szErrorMsg) && (cbErrorMsgMax > 0))
szErrorMsg[0] = '\0'; return SQL_NO_DATA_FOUND;
}
return SQL_NO_DATA_FOUND; mylog("SC_get_error: status = %d, msg = #%s#\n", status, msg);
} msglen = (SWORD) strlen(msg);
msglen = (SWORD) strlen(msg); /*
if (NULL != pcbErrorMsg) * Even though an application specifies a larger error message
{ * buffer, the driver manager changes it silently.
*pcbErrorMsg = msglen; * Therefore we divide the error message into ...
if (cbErrorMsgMax == 0) */
once_again = TRUE; if (stmt->error_recsize < 0)
else if (msglen >= cbErrorMsgMax) {
{ if (cbErrorMsgMax > 0)
once_again = TRUE; stmt->error_recsize = cbErrorMsgMax - 1; /* apply the first request */
*pcbErrorMsg = cbErrorMsgMax - 1;
}
}
if ((NULL != szErrorMsg) && (cbErrorMsgMax > 0))
strncpy_null(szErrorMsg, msg, cbErrorMsgMax);
if (NULL != pfNativeError)
*pfNativeError = status;
if (NULL != szSqlState)
switch (status)
{
/* now determine the SQLSTATE to be returned */
case STMT_ROW_VERSION_CHANGED:
strcpy(szSqlState, "01001");
/* data truncated */
break;
case STMT_TRUNCATED:
strcpy(szSqlState, "01004");
/* data truncated */
break;
case STMT_INFO_ONLY:
strcpy(szSqlState, "00000");
/* just information that is returned, no error */
break;
case STMT_BAD_ERROR:
strcpy(szSqlState, "08S01");
/* communication link failure */
break;
case STMT_CREATE_TABLE_ERROR:
strcpy(szSqlState, "S0001");
/* table already exists */
break;
case STMT_STATUS_ERROR:
case STMT_SEQUENCE_ERROR:
strcpy(szSqlState, "S1010");
/* Function sequence error */
break;
case STMT_NO_MEMORY_ERROR:
strcpy(szSqlState, "S1001");
/* memory allocation failure */
break;
case STMT_COLNUM_ERROR:
strcpy(szSqlState, "S1002");
/* invalid column number */
break;
case STMT_NO_STMTSTRING:
strcpy(szSqlState, "S1001");
/* having no stmtstring is also a malloc problem */
break;
case STMT_ERROR_TAKEN_FROM_BACKEND:
strcpy(szSqlState, "S1000");
/* general error */
break;
case STMT_INTERNAL_ERROR:
strcpy(szSqlState, "S1000");
/* general error */
break;
case STMT_ROW_OUT_OF_RANGE:
strcpy(szSqlState, "S1107");
break;
case STMT_OPERATION_CANCELLED:
strcpy(szSqlState, "S1008");
break;
case STMT_NOT_IMPLEMENTED_ERROR:
strcpy(szSqlState, "S1C00"); /* == 'driver not
* capable' */
break;
case STMT_OPTION_OUT_OF_RANGE_ERROR:
strcpy(szSqlState, "S1092");
break;
case STMT_BAD_PARAMETER_NUMBER_ERROR:
strcpy(szSqlState, "S1093");
break;
case STMT_INVALID_COLUMN_NUMBER_ERROR:
strcpy(szSqlState, "S1002");
break;
case STMT_RESTRICTED_DATA_TYPE_ERROR:
strcpy(szSqlState, "07006");
break;
case STMT_INVALID_CURSOR_STATE_ERROR:
strcpy(szSqlState, "24000");
break;
case STMT_OPTION_VALUE_CHANGED:
strcpy(szSqlState, "01S02");
break;
case STMT_POS_BEFORE_RECORDSET:
strcpy(szSqlState, "01S06");
break;
case STMT_INVALID_CURSOR_NAME:
strcpy(szSqlState, "34000");
break;
case STMT_NO_CURSOR_NAME:
strcpy(szSqlState, "S1015");
break;
case STMT_INVALID_ARGUMENT_NO:
strcpy(szSqlState, "S1009");
/* invalid argument value */
break;
case STMT_INVALID_CURSOR_POSITION:
strcpy(szSqlState, "S1109");
break;
case STMT_RETURN_NULL_WITHOUT_INDICATOR:
strcpy(szSqlState, "22002");
break;
case STMT_VALUE_OUT_OF_RANGE:
strcpy(szSqlState, "22003");
break;
case STMT_OPERATION_INVALID:
strcpy(szSqlState, "S1011");
break;
case STMT_INVALID_OPTION_IDENTIFIER:
strcpy(szSqlState, "HY092");
break;
case STMT_EXEC_ERROR:
default:
strcpy(szSqlState, "S1000");
/* also a general error */
break;
}
mylog(" szSqlState = '%s', szError='%s'\n", szSqlState, szErrorMsg);
}
else else
{ stmt->error_recsize = DRVMNGRDIV;
if (NULL != szSqlState) }
strcpy(szSqlState, "00000"); if (RecNumber < 0)
if (NULL != pcbErrorMsg) {
*pcbErrorMsg = 0; if (0 == stmt->errorpos)
if ((NULL != szErrorMsg) && (cbErrorMsgMax > 0)) RecNumber = 1;
szErrorMsg[0] = '\0'; else
RecNumber = 2 + (stmt->errorpos - 1) / stmt->error_recsize;
}
stapos = (RecNumber - 1) * stmt->error_recsize;
if (stapos > msglen)
return SQL_NO_DATA_FOUND;
pcblen = wrtlen = msglen - stapos;
if (pcblen > stmt->error_recsize)
pcblen = stmt->error_recsize;
if (0 == cbErrorMsgMax)
wrtlen = 0;
else if (wrtlen >= cbErrorMsgMax)
{
if (partial_ok)
wrtlen = cbErrorMsgMax - 1;
else if (cbErrorMsgMax <= stmt->error_recsize)
wrtlen = 0;
else
wrtlen = stmt->error_recsize;
}
if (wrtlen > pcblen)
wrtlen = pcblen;
if (NULL != pcbErrorMsg)
*pcbErrorMsg = pcblen;
mylog(" returning NO_DATA_FOUND\n"); if ((NULL != szErrorMsg) && (cbErrorMsgMax > 0))
{
memcpy(szErrorMsg, msg + stapos, wrtlen);
szErrorMsg[wrtlen] = '\0';
}
return SQL_NO_DATA_FOUND; if (NULL != pfNativeError)
} *pfNativeError = status;
if (NULL != szSqlState)
if (once_again) switch (status)
{ {
int outlen; /* now determine the SQLSTATE to be returned */
case STMT_ROW_VERSION_CHANGED:
stmt->errornumber = status; strcpy(szSqlState, "01001");
if (cbErrorMsgMax > 0) /* data truncated */
outlen = *pcbErrorMsg; break;
else case STMT_TRUNCATED:
outlen = 0; strcpy(szSqlState, "01004");
if (!stmt->errormsg_malloced || !stmt->errormsg) /* data truncated */
{ break;
stmt->errormsg = malloc(msglen - outlen + 1); case STMT_INFO_ONLY:
stmt->errormsg_malloced = TRUE; strcpy(szSqlState, "00000");
} /* just information that is returned, no error */
memmove(stmt->errormsg, msg + outlen, msglen - outlen + 1); break;
case STMT_BAD_ERROR:
strcpy(szSqlState, "08S01");
/* communication link failure */
break;
case STMT_CREATE_TABLE_ERROR:
strcpy(szSqlState, "S0001");
/* table already exists */
break;
case STMT_STATUS_ERROR:
case STMT_SEQUENCE_ERROR:
strcpy(szSqlState, "S1010");
/* Function sequence error */
break;
case STMT_NO_MEMORY_ERROR:
strcpy(szSqlState, "S1001");
/* memory allocation failure */
break;
case STMT_COLNUM_ERROR:
strcpy(szSqlState, "S1002");
/* invalid column number */
break;
case STMT_NO_STMTSTRING:
strcpy(szSqlState, "S1001");
/* having no stmtstring is also a malloc problem */
break;
case STMT_ERROR_TAKEN_FROM_BACKEND:
strcpy(szSqlState, "S1000");
/* general error */
break;
case STMT_INTERNAL_ERROR:
strcpy(szSqlState, "S1000");
/* general error */
break;
case STMT_ROW_OUT_OF_RANGE:
strcpy(szSqlState, "S1107");
break;
case STMT_OPERATION_CANCELLED:
strcpy(szSqlState, "S1008");
break;
case STMT_NOT_IMPLEMENTED_ERROR:
strcpy(szSqlState, "S1C00"); /* == 'driver not
* capable' */
break;
case STMT_OPTION_OUT_OF_RANGE_ERROR:
strcpy(szSqlState, "S1092");
break;
case STMT_BAD_PARAMETER_NUMBER_ERROR:
strcpy(szSqlState, "S1093");
break;
case STMT_INVALID_COLUMN_NUMBER_ERROR:
strcpy(szSqlState, "S1002");
break;
case STMT_RESTRICTED_DATA_TYPE_ERROR:
strcpy(szSqlState, "07006");
break;
case STMT_INVALID_CURSOR_STATE_ERROR:
strcpy(szSqlState, "24000");
break;
case STMT_OPTION_VALUE_CHANGED:
strcpy(szSqlState, "01S02");
break;
case STMT_POS_BEFORE_RECORDSET:
strcpy(szSqlState, "01S06");
break;
case STMT_INVALID_CURSOR_NAME:
strcpy(szSqlState, "34000");
break;
case STMT_NO_CURSOR_NAME:
strcpy(szSqlState, "S1015");
break;
case STMT_INVALID_ARGUMENT_NO:
strcpy(szSqlState, "S1009");
/* invalid argument value */
break;
case STMT_INVALID_CURSOR_POSITION:
strcpy(szSqlState, "S1109");
break;
case STMT_RETURN_NULL_WITHOUT_INDICATOR:
strcpy(szSqlState, "22002");
break;
case STMT_VALUE_OUT_OF_RANGE:
strcpy(szSqlState, "22003");
break;
case STMT_OPERATION_INVALID:
strcpy(szSqlState, "S1011");
break;
case STMT_INVALID_OPTION_IDENTIFIER:
strcpy(szSqlState, "HY092");
break;
case STMT_EXEC_ERROR:
default:
strcpy(szSqlState, "S1000");
/* also a general error */
break;
} }
else if (stmt->errormsg_malloced) mylog(" szSqlState = '%s',len=%d, szError='%s'\n", szSqlState, pcblen, szErrorMsg);
if (clear_str)
{
stmt->errorpos = stapos + wrtlen;
if (stmt->errorpos >= msglen)
SC_clear_error(stmt); SC_clear_error(stmt);
if (cbErrorMsgMax == 0)
return SQL_SUCCESS_WITH_INFO;
else
return SQL_SUCCESS;
} }
else if (SQL_NULL_HDBC != hdbc) if (wrtlen == 0)
{ return SQL_SUCCESS_WITH_INFO;
ConnectionClass *conn = (ConnectionClass *) hdbc; else
return SQL_SUCCESS;
mylog("calling CC_get_error\n"); }
if (CC_get_error(conn, &status, &msg))
{
mylog("CC_get_error: status = %d, msg = #%s#\n", status, msg);
if (NULL == msg)
{
if (NULL != szSqlState)
strcpy(szSqlState, "00000");
if (NULL != pcbErrorMsg)
*pcbErrorMsg = 0;
if ((NULL != szErrorMsg) && (cbErrorMsgMax > 0))
szErrorMsg[0] = '\0';
return SQL_NO_DATA_FOUND;
}
msglen = strlen(msg);
if (NULL != pcbErrorMsg)
{
*pcbErrorMsg = msglen;
if (cbErrorMsgMax == 0)
once_again = TRUE;
else if (msglen >= cbErrorMsgMax)
*pcbErrorMsg = cbErrorMsgMax - 1;
}
if ((NULL != szErrorMsg) && (cbErrorMsgMax > 0))
strncpy_null(szErrorMsg, msg, cbErrorMsgMax);
if (NULL != pfNativeError)
*pfNativeError = status;
if (NULL != szSqlState)
switch (status)
{
case STMT_OPTION_VALUE_CHANGED:
case CONN_OPTION_VALUE_CHANGED:
strcpy(szSqlState, "01S02");
break;
case STMT_TRUNCATED:
case CONN_TRUNCATED:
strcpy(szSqlState, "01004");
/* data truncated */
break;
case CONN_INIREAD_ERROR:
strcpy(szSqlState, "IM002");
/* data source not found */
break;
case CONN_OPENDB_ERROR:
strcpy(szSqlState, "08001");
/* unable to connect to data source */
break;
case CONN_INVALID_AUTHENTICATION:
case CONN_AUTH_TYPE_UNSUPPORTED:
strcpy(szSqlState, "28000");
break;
case CONN_STMT_ALLOC_ERROR:
strcpy(szSqlState, "S1001");
/* memory allocation failure */
break;
case CONN_IN_USE:
strcpy(szSqlState, "S1000");
/* general error */
break;
case CONN_UNSUPPORTED_OPTION:
strcpy(szSqlState, "IM001");
/* driver does not support this function */
case CONN_INVALID_ARGUMENT_NO:
strcpy(szSqlState, "S1009");
/* invalid argument value */
break;
case CONN_TRANSACT_IN_PROGRES:
strcpy(szSqlState, "S1010");
/*
* when the user tries to switch commit mode in a
* transaction
*/
/* -> function sequence error */
break;
case CONN_NO_MEMORY_ERROR:
strcpy(szSqlState, "S1001");
break;
case CONN_NOT_IMPLEMENTED_ERROR:
case STMT_NOT_IMPLEMENTED_ERROR:
strcpy(szSqlState, "S1C00");
break;
case STMT_RETURN_NULL_WITHOUT_INDICATOR:
strcpy(szSqlState, "22002");
break;
case CONN_VALUE_OUT_OF_RANGE:
case STMT_VALUE_OUT_OF_RANGE:
strcpy(szSqlState, "22003");
break;
default:
strcpy(szSqlState, "S1000");
/* general error */
break;
}
}
else
{
mylog("CC_Get_error returned nothing.\n");
if (NULL != szSqlState)
strcpy(szSqlState, "00000");
if (NULL != pcbErrorMsg)
*pcbErrorMsg = 0;
if ((NULL != szErrorMsg) && (cbErrorMsgMax > 0))
szErrorMsg[0] = '\0';
return SQL_NO_DATA_FOUND; RETCODE SQL_API
} PGAPI_ConnectError( HDBC hdbc,
SWORD RecNumber,
UCHAR FAR * szSqlState,
SDWORD FAR * pfNativeError,
UCHAR FAR * szErrorMsg,
SWORD cbErrorMsgMax,
SWORD FAR * pcbErrorMsg,
UWORD flag)
{
ConnectionClass *conn = (ConnectionClass *) hdbc;
char *msg;
int status;
BOOL once_again = FALSE;
SWORD msglen;
if (once_again) if (RecNumber != 1)
{ return SQL_NO_DATA_FOUND;
conn->errornumber = status; if (cbErrorMsgMax < 0)
return SQL_SUCCESS_WITH_INFO; return SQL_ERROR;
} if (!CC_get_error(conn, &status, &msg) || NULL == msg)
else {
return SQL_SUCCESS; mylog("CC_Get_error returned nothing.\n");
if (NULL != szSqlState)
strcpy(szSqlState, "00000");
if (NULL != pcbErrorMsg)
*pcbErrorMsg = 0;
if ((NULL != szErrorMsg) && (cbErrorMsgMax > 0))
szErrorMsg[0] = '\0';
return SQL_NO_DATA_FOUND;
} }
else if (SQL_NULL_HENV != henv) mylog("CC_get_error: status = %d, msg = #%s#\n", status, msg);
msglen = strlen(msg);
if (NULL != pcbErrorMsg)
{ {
EnvironmentClass *env = (EnvironmentClass *) henv; *pcbErrorMsg = msglen;
if (cbErrorMsgMax == 0)
once_again = TRUE;
else if (msglen >= cbErrorMsgMax)
*pcbErrorMsg = cbErrorMsgMax - 1;
}
if ((NULL != szErrorMsg) && (cbErrorMsgMax > 0))
strncpy_null(szErrorMsg, msg, cbErrorMsgMax);
if (NULL != pfNativeError)
*pfNativeError = status;
if (EN_get_error(env, &status, &msg)) if (NULL != szSqlState)
{ switch (status)
mylog("EN_get_error: status = %d, msg = #%s#\n", status, msg);
if (NULL == msg)
{
if (NULL != szSqlState)
strcpy(szSqlState, "00000");
if (NULL != pcbErrorMsg)
*pcbErrorMsg = 0;
if ((NULL != szErrorMsg) && (cbErrorMsgMax > 0))
szErrorMsg[0] = '\0';
return SQL_NO_DATA_FOUND;
}
if (NULL != pcbErrorMsg)
*pcbErrorMsg = (SWORD) strlen(msg);
if ((NULL != szErrorMsg) && (cbErrorMsgMax > 0))
strncpy_null(szErrorMsg, msg, cbErrorMsgMax);
if (NULL != pfNativeError)
*pfNativeError = status;
if (szSqlState)
{
switch (status)
{
case ENV_ALLOC_ERROR:
/* memory allocation failure */
strcpy(szSqlState, "S1001");
break;
default:
strcpy(szSqlState, "S1000");
/* general error */
break;
}
}
}
else
{ {
if (NULL != szSqlState) case STMT_OPTION_VALUE_CHANGED:
strcpy(szSqlState, "00000"); case CONN_OPTION_VALUE_CHANGED:
if (NULL != pcbErrorMsg) strcpy(szSqlState, "01S02");
*pcbErrorMsg = 0; break;
if ((NULL != szErrorMsg) && (cbErrorMsgMax > 0)) case STMT_TRUNCATED:
szErrorMsg[0] = '\0'; case CONN_TRUNCATED:
strcpy(szSqlState, "01004");
return SQL_NO_DATA_FOUND; /* data truncated */
break;
case CONN_INIREAD_ERROR:
strcpy(szSqlState, "IM002");
/* data source not found */
break;
case CONN_OPENDB_ERROR:
strcpy(szSqlState, "08001");
/* unable to connect to data source */
break;
case CONN_INVALID_AUTHENTICATION:
case CONN_AUTH_TYPE_UNSUPPORTED:
strcpy(szSqlState, "28000");
break;
case CONN_STMT_ALLOC_ERROR:
strcpy(szSqlState, "S1001");
/* memory allocation failure */
break;
case CONN_IN_USE:
strcpy(szSqlState, "S1000");
/* general error */
break;
case CONN_UNSUPPORTED_OPTION:
strcpy(szSqlState, "IM001");
/* driver does not support this function */
case CONN_INVALID_ARGUMENT_NO:
strcpy(szSqlState, "S1009");
/* invalid argument value */
break;
case CONN_TRANSACT_IN_PROGRES:
strcpy(szSqlState, "S1010");
/*
* when the user tries to switch commit mode in a
* transaction
*/
/* -> function sequence error */
break;
case CONN_NO_MEMORY_ERROR:
strcpy(szSqlState, "S1001");
break;
case CONN_NOT_IMPLEMENTED_ERROR:
case STMT_NOT_IMPLEMENTED_ERROR:
strcpy(szSqlState, "S1C00");
break;
case STMT_RETURN_NULL_WITHOUT_INDICATOR:
strcpy(szSqlState, "22002");
break;
case CONN_VALUE_OUT_OF_RANGE:
case STMT_VALUE_OUT_OF_RANGE:
strcpy(szSqlState, "22003");
break;
default:
strcpy(szSqlState, "S1000");
/* general error */
break;
} }
if (once_again)
{
conn->errornumber = status;
return SQL_SUCCESS_WITH_INFO;
}
else
return SQL_SUCCESS; return SQL_SUCCESS;
}
RETCODE SQL_API
PGAPI_EnvError( HENV henv,
SWORD RecNumber,
UCHAR FAR * szSqlState,
SDWORD FAR * pfNativeError,
UCHAR FAR * szErrorMsg,
SWORD cbErrorMsgMax,
SWORD FAR * pcbErrorMsg,
UWORD flag)
{
EnvironmentClass *env = (EnvironmentClass *) henv;
char *msg;
int status;
if (RecNumber != 1)
return SQL_NO_DATA_FOUND;
if (cbErrorMsgMax < 0)
return SQL_ERROR;
if (!EN_get_error(env, &status, &msg) || NULL == msg)
{
mylog("EN_get_error: status = %d, msg = #%s#\n", status, msg);
if (NULL != szSqlState)
strcpy(szSqlState, "00000");
if (NULL != pcbErrorMsg)
*pcbErrorMsg = 0;
if ((NULL != szErrorMsg) && (cbErrorMsgMax > 0))
szErrorMsg[0] = '\0';
return SQL_NO_DATA_FOUND;
} }
mylog("EN_get_error: status = %d, msg = #%s#\n", status, msg);
if (NULL != szSqlState)
strcpy(szSqlState, "00000");
if (NULL != pcbErrorMsg) if (NULL != pcbErrorMsg)
*pcbErrorMsg = 0; *pcbErrorMsg = (SWORD) strlen(msg);
if ((NULL != szErrorMsg) && (cbErrorMsgMax > 0)) if ((NULL != szErrorMsg) && (cbErrorMsgMax > 0))
szErrorMsg[0] = '\0'; strncpy_null(szErrorMsg, msg, cbErrorMsgMax);
if (NULL != pfNativeError)
*pfNativeError = status;
return SQL_NO_DATA_FOUND; if (szSqlState)
{
switch (status)
{
case ENV_ALLOC_ERROR:
/* memory allocation failure */
strcpy(szSqlState, "S1001");
break;
default:
strcpy(szSqlState, "S1000");
/* general error */
break;
}
}
return SQL_SUCCESS;
} }
/* Returns the next SQL error information. */
RETCODE SQL_API
PGAPI_Error(
HENV henv,
HDBC hdbc,
HSTMT hstmt,
UCHAR FAR * szSqlState,
SDWORD FAR * pfNativeError,
UCHAR FAR * szErrorMsg,
SWORD cbErrorMsgMax,
SWORD FAR * pcbErrorMsg)
{
RETCODE ret;
UWORD flag = PODBC_ALLOW_PARTIAL_EXTRACT | PODBC_ERROR_CLEAR;
mylog("**** PGAPI_Error: henv=%u, hdbc=%u hstmt=%d\n", henv, hdbc, hstmt);
if (cbErrorMsgMax < 0)
return SQL_ERROR;
if (SQL_NULL_HSTMT != hstmt)
ret = PGAPI_StmtError(hstmt, -1, szSqlState, pfNativeError,
szErrorMsg, cbErrorMsgMax, pcbErrorMsg, flag);
else if (SQL_NULL_HDBC != hdbc)
ret = PGAPI_ConnectError(hdbc, -1, szSqlState, pfNativeError,
szErrorMsg, cbErrorMsgMax, pcbErrorMsg, flag);
else if (SQL_NULL_HENV != hdbc)
ret = PGAPI_EnvError(henv, -1, szSqlState, pfNativeError,
szErrorMsg, cbErrorMsgMax, pcbErrorMsg, flag);
else
{
if (NULL != szSqlState)
strcpy(szSqlState, "00000");
if (NULL != pcbErrorMsg)
*pcbErrorMsg = 0;
if ((NULL != szErrorMsg) && (cbErrorMsgMax > 0))
szErrorMsg[0] = '\0';
ret = SQL_NO_DATA_FOUND;
}
mylog("**** PGAPI_Error exit code=%d\n", ret);
return ret;
}
/* /*
* EnvironmentClass implementation * EnvironmentClass implementation
*/ */
...@@ -493,6 +535,7 @@ EN_Constructor(void) ...@@ -493,6 +535,7 @@ EN_Constructor(void)
{ {
rv->errormsg = 0; rv->errormsg = 0;
rv->errornumber = 0; rv->errornumber = 0;
rv->flag = 0;
} }
return rv; return rv;
......
...@@ -17,7 +17,8 @@ ...@@ -17,7 +17,8 @@
struct EnvironmentClass_ struct EnvironmentClass_
{ {
char *errormsg; char *errormsg;
int errornumber; int errornumber;
Int4 flag;
}; };
/* Environment prototypes */ /* Environment prototypes */
...@@ -28,4 +29,10 @@ char EN_add_connection(EnvironmentClass *self, ConnectionClass *conn); ...@@ -28,4 +29,10 @@ char EN_add_connection(EnvironmentClass *self, ConnectionClass *conn);
char EN_remove_connection(EnvironmentClass *self, ConnectionClass *conn); char EN_remove_connection(EnvironmentClass *self, ConnectionClass *conn);
void EN_log_error(char *func, char *desc, EnvironmentClass *self); void EN_log_error(char *func, char *desc, EnvironmentClass *self);
#define EN_OV_ODBC2 1L
#define EN_is_odbc2(env) ((env->flag & EN_OV_ODBC2) != 0)
#define EN_is_odbc3(env) ((env->flag & EN_OV_ODBC2) == 0)
#define EN_set_odbc2(env) (env->flag |= EN_OV_ODBC2)
#define EN_set_odbc3(env) (env->flag &= EN_OV_ODBC2)
#endif #endif
...@@ -267,6 +267,7 @@ PGAPI_Execute( ...@@ -267,6 +267,7 @@ PGAPI_Execute(
if (stmt->status == STMT_FINISHED) if (stmt->status == STMT_FINISHED)
{ {
mylog("%s: recycling statement (should have been done by app)...\n", func); mylog("%s: recycling statement (should have been done by app)...\n", func);
/******** Is this really NEEDED ? ******/
SC_recycle_statement(stmt); SC_recycle_statement(stmt);
} }
...@@ -291,6 +292,7 @@ PGAPI_Execute( ...@@ -291,6 +292,7 @@ PGAPI_Execute(
{ {
if (stmt->options.param_processed_ptr) if (stmt->options.param_processed_ptr)
*stmt->options.param_processed_ptr = 0; *stmt->options.param_processed_ptr = 0;
SC_recycle_statement(stmt);
} }
next_param_row: next_param_row:
...@@ -434,26 +436,24 @@ next_param_row: ...@@ -434,26 +436,24 @@ next_param_row:
} }
/* we are now in a transaction */ /* we are now in a transaction */
CC_set_in_trans(conn); CC_set_in_trans(conn);
stmt->result = res = CC_send_query(conn, stmt->stmt_with_params, NULL); res = CC_send_query(conn, stmt->stmt_with_params, NULL, TRUE);
if (!res || QR_aborted(res)) if (!res)
{ {
CC_abort(conn); CC_abort(conn);
stmt->errornumber = STMT_EXEC_ERROR; stmt->errornumber = STMT_EXEC_ERROR;
stmt->errormsg = "Handle prepare error"; stmt->errormsg = "Handle prepare error";
return SQL_ERROR; return SQL_ERROR;
} }
else SC_set_Result(stmt, res);
if (CC_is_in_autocommit(conn))
{ {
if (CC_is_in_autocommit(conn)) if (issued_begin)
{ CC_commit(conn);
if (issued_begin) else if (!in_trans && begin_included)
CC_commit(conn); CC_set_no_trans(conn);
else if (!in_trans && begin_included)
CC_set_no_trans(conn);
}
stmt->status = STMT_FINISHED;
return SQL_SUCCESS;
} }
stmt->status = STMT_FINISHED;
return SQL_SUCCESS;
} }
else else
return SQL_SUCCESS; return SQL_SUCCESS;
...@@ -518,7 +518,7 @@ PGAPI_Transact( ...@@ -518,7 +518,7 @@ PGAPI_Transact(
{ {
mylog("PGAPI_Transact: sending on conn %d '%s'\n", conn, stmt_string); mylog("PGAPI_Transact: sending on conn %d '%s'\n", conn, stmt_string);
res = CC_send_query(conn, stmt_string, NULL); res = CC_send_query(conn, stmt_string, NULL, TRUE);
CC_set_no_trans(conn); CC_set_no_trans(conn);
if (!res) if (!res)
...@@ -721,7 +721,7 @@ PGAPI_ParamData( ...@@ -721,7 +721,7 @@ PGAPI_ParamData(
/* commit transaction if needed */ /* commit transaction if needed */
if (!ci->drivers.use_declarefetch && CC_is_in_autocommit(stmt->hdbc)) if (!ci->drivers.use_declarefetch && CC_is_in_autocommit(stmt->hdbc))
{ {
if (!CC_commit(stmt->hdbc)) if (CC_commit(stmt->hdbc))
{ {
stmt->errormsg = "Could not commit (in-line) a transaction"; stmt->errormsg = "Could not commit (in-line) a transaction";
stmt->errornumber = STMT_EXEC_ERROR; stmt->errornumber = STMT_EXEC_ERROR;
...@@ -902,6 +902,14 @@ PGAPI_PutData( ...@@ -902,6 +902,14 @@ PGAPI_PutData(
} }
else else
{ {
Int2 ctype = current_param->CType;
if (ctype == SQL_C_DEFAULT)
ctype = sqltype_to_default_ctype(current_param->SQLType);
#ifdef UNICODE_SUPPORT
if (SQL_NTS == cbValue && SQL_C_WCHAR == ctype)
cbValue = 2 * ucs2strlen((SQLWCHAR *) rgbValue);
#endif /* UNICODE_SUPPORT */
/* for handling fields */ /* for handling fields */
if (cbValue == SQL_NTS) if (cbValue == SQL_NTS)
{ {
...@@ -916,11 +924,11 @@ PGAPI_PutData( ...@@ -916,11 +924,11 @@ PGAPI_PutData(
} }
else else
{ {
Int2 ctype = current_param->CType; #ifdef UNICODE_SUPPORT
if (ctype == SQL_C_CHAR || ctype == SQL_C_BINARY || ctype == SQL_C_WCHAR)
if (ctype == SQL_C_DEFAULT) #else
ctype = sqltype_to_default_ctype(current_param->SQLType);
if (ctype == SQL_C_CHAR || ctype == SQL_C_BINARY) if (ctype == SQL_C_CHAR || ctype == SQL_C_BINARY)
#endif /* UNICODE_SUPPORT */
{ {
current_param->EXEC_buffer = malloc(cbValue + 1); current_param->EXEC_buffer = malloc(cbValue + 1);
if (!current_param->EXEC_buffer) if (!current_param->EXEC_buffer)
...@@ -965,31 +973,31 @@ PGAPI_PutData( ...@@ -965,31 +973,31 @@ PGAPI_PutData(
} }
else else
{ {
buffer = current_param->EXEC_buffer; Int2 ctype = current_param->CType;
if (cbValue == SQL_NTS) if (ctype == SQL_C_DEFAULT)
ctype = sqltype_to_default_ctype(current_param->SQLType);
buffer = current_param->EXEC_buffer;
if (old_pos = *current_param->EXEC_used, SQL_NTS == old_pos)
{ {
buffer = realloc(buffer, strlen(buffer) + strlen(rgbValue) + 1); #ifdef UNICODE_SUPPORT
if (!buffer) if (SQL_C_WCHAR == ctype)
{ old_pos = 2 * ucs2strlen((SQLWCHAR *) buffer);
stmt->errornumber = STMT_NO_MEMORY_ERROR; else
stmt->errormsg = "Out of memory in PGAPI_PutData (3)"; #endif /* UNICODE_SUPPORT */
SC_log_error(func, "", stmt); old_pos = strlen(buffer);
return SQL_ERROR;
}
strcat(buffer, rgbValue);
mylog(" cbValue = SQL_NTS: strlen(buffer) = %d\n", strlen(buffer));
*current_param->EXEC_used = cbValue;
/* reassign buffer incase realloc moved it */
current_param->EXEC_buffer = buffer;
} }
else if (cbValue > 0) 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;
*current_param->EXEC_used += cbValue; *current_param->EXEC_used += cbValue;
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", cbValue, old_pos, *current_param->EXEC_used);
......
...@@ -10,7 +10,7 @@ ...@@ -10,7 +10,7 @@
* SQLTables, SQLColumns, SQLStatistics, SQLSpecialColumns, * SQLTables, SQLColumns, SQLStatistics, SQLSpecialColumns,
* SQLPrimaryKeys, SQLForeignKeys, * SQLPrimaryKeys, SQLForeignKeys,
* SQLProcedureColumns(NI), SQLProcedures, * SQLProcedureColumns(NI), SQLProcedures,
* SQLTablePrivileges(NI), SQLColumnPrivileges(NI) * SQLTablePrivileges, SQLColumnPrivileges(NI)
* *
* Comments: See "notice.txt" for copyright and license information. * Comments: See "notice.txt" for copyright and license information.
*-------- *--------
...@@ -231,13 +231,14 @@ PGAPI_GetInfo( ...@@ -231,13 +231,14 @@ PGAPI_GetInfo(
case SQL_FETCH_DIRECTION: /* ODBC 1.0 */ case SQL_FETCH_DIRECTION: /* ODBC 1.0 */
len = 4; len = 4;
value = ci->drivers.use_declarefetch ? (SQL_FD_FETCH_NEXT) : (SQL_FD_FETCH_NEXT | value = ci->drivers.use_declarefetch ? (SQL_FD_FETCH_NEXT) :
SQL_FD_FETCH_FIRST | (SQL_FD_FETCH_NEXT |
SQL_FD_FETCH_LAST | SQL_FD_FETCH_FIRST |
SQL_FD_FETCH_PRIOR | SQL_FD_FETCH_LAST |
SQL_FD_FETCH_ABSOLUTE | SQL_FD_FETCH_PRIOR |
SQL_FD_FETCH_RELATIVE | SQL_FD_FETCH_ABSOLUTE |
SQL_FD_FETCH_BOOKMARK); SQL_FD_FETCH_RELATIVE |
SQL_FD_FETCH_BOOKMARK);
break; break;
case SQL_FILE_USAGE: /* ODBC 2.0 */ case SQL_FILE_USAGE: /* ODBC 2.0 */
...@@ -665,7 +666,6 @@ PGAPI_GetInfo( ...@@ -665,7 +666,6 @@ PGAPI_GetInfo(
/* unrecognized key */ /* unrecognized key */
conn->errormsg = "Unrecognized key passed to PGAPI_GetInfo."; conn->errormsg = "Unrecognized key passed to PGAPI_GetInfo.";
conn->errornumber = CONN_NOT_IMPLEMENTED_ERROR; conn->errornumber = CONN_NOT_IMPLEMENTED_ERROR;
CC_log_error(func, "", conn);
return SQL_ERROR; return SQL_ERROR;
} }
...@@ -685,12 +685,20 @@ PGAPI_GetInfo( ...@@ -685,12 +685,20 @@ PGAPI_GetInfo(
if (rgbInfoValue) if (rgbInfoValue)
{ {
#ifdef UNICODE_SUPPORT
if (conn->unicode)
{
len = utf8_to_ucs2(p, len, (SQLWCHAR *) rgbInfoValue, cbInfoValueMax / 2);
len *= 2;
}
else
#endif /* UNICODE_SUPPORT */
strncpy_null((char *) rgbInfoValue, p, (size_t) cbInfoValueMax); strncpy_null((char *) rgbInfoValue, p, (size_t) cbInfoValueMax);
if (len >= cbInfoValueMax) if (len >= cbInfoValueMax)
{ {
result = SQL_SUCCESS_WITH_INFO; result = SQL_SUCCESS_WITH_INFO;
conn->errornumber = STMT_TRUNCATED; conn->errornumber = CONN_TRUNCATED;
conn->errormsg = "The buffer was too small for tthe InfoValue."; conn->errormsg = "The buffer was too small for tthe InfoValue.";
} }
} }
...@@ -721,6 +729,7 @@ PGAPI_GetTypeInfo( ...@@ -721,6 +729,7 @@ PGAPI_GetTypeInfo(
{ {
static char *func = "PGAPI_GetTypeInfo"; static char *func = "PGAPI_GetTypeInfo";
StatementClass *stmt = (StatementClass *) hstmt; StatementClass *stmt = (StatementClass *) hstmt;
QResultClass *res;
TupleNode *row; TupleNode *row;
int i; int i;
...@@ -737,31 +746,31 @@ PGAPI_GetTypeInfo( ...@@ -737,31 +746,31 @@ PGAPI_GetTypeInfo(
} }
stmt->manual_result = TRUE; stmt->manual_result = TRUE;
stmt->result = QR_Constructor(); if (res = QR_Constructor(), !res)
if (!stmt->result)
{ {
SC_log_error(func, "Error creating result.", stmt); SC_log_error(func, "Error creating result.", stmt);
return SQL_ERROR; return SQL_ERROR;
} }
SC_set_Result(stmt, res);
extend_bindings(stmt, 15); extend_bindings(stmt, 15);
QR_set_num_fields(stmt->result, 15); QR_set_num_fields(res, 15);
QR_set_field_info(stmt->result, 0, "TYPE_NAME", PG_TYPE_TEXT, MAX_INFO_STRING); QR_set_field_info(res, 0, "TYPE_NAME", PG_TYPE_TEXT, MAX_INFO_STRING);
QR_set_field_info(stmt->result, 1, "DATA_TYPE", PG_TYPE_INT2, 2); QR_set_field_info(res, 1, "DATA_TYPE", PG_TYPE_INT2, 2);
QR_set_field_info(stmt->result, 2, "PRECISION", PG_TYPE_INT4, 4); QR_set_field_info(res, 2, "PRECISION", PG_TYPE_INT4, 4);
QR_set_field_info(stmt->result, 3, "LITERAL_PREFIX", PG_TYPE_TEXT, MAX_INFO_STRING); QR_set_field_info(res, 3, "LITERAL_PREFIX", PG_TYPE_TEXT, MAX_INFO_STRING);
QR_set_field_info(stmt->result, 4, "LITERAL_SUFFIX", PG_TYPE_TEXT, MAX_INFO_STRING); QR_set_field_info(res, 4, "LITERAL_SUFFIX", PG_TYPE_TEXT, MAX_INFO_STRING);
QR_set_field_info(stmt->result, 5, "CREATE_PARAMS", PG_TYPE_TEXT, MAX_INFO_STRING); QR_set_field_info(res, 5, "CREATE_PARAMS", PG_TYPE_TEXT, MAX_INFO_STRING);
QR_set_field_info(stmt->result, 6, "NULLABLE", PG_TYPE_INT2, 2); QR_set_field_info(res, 6, "NULLABLE", PG_TYPE_INT2, 2);
QR_set_field_info(stmt->result, 7, "CASE_SENSITIVE", PG_TYPE_INT2, 2); QR_set_field_info(res, 7, "CASE_SENSITIVE", PG_TYPE_INT2, 2);
QR_set_field_info(stmt->result, 8, "SEARCHABLE", PG_TYPE_INT2, 2); QR_set_field_info(res, 8, "SEARCHABLE", PG_TYPE_INT2, 2);
QR_set_field_info(stmt->result, 9, "UNSIGNED_ATTRIBUTE", PG_TYPE_INT2, 2); QR_set_field_info(res, 9, "UNSIGNED_ATTRIBUTE", PG_TYPE_INT2, 2);
QR_set_field_info(stmt->result, 10, "MONEY", PG_TYPE_INT2, 2); QR_set_field_info(res, 10, "MONEY", PG_TYPE_INT2, 2);
QR_set_field_info(stmt->result, 11, "AUTO_INCREMENT", PG_TYPE_INT2, 2); QR_set_field_info(res, 11, "AUTO_INCREMENT", PG_TYPE_INT2, 2);
QR_set_field_info(stmt->result, 12, "LOCAL_TYPE_NAME", PG_TYPE_TEXT, MAX_INFO_STRING); QR_set_field_info(res, 12, "LOCAL_TYPE_NAME", PG_TYPE_TEXT, MAX_INFO_STRING);
QR_set_field_info(stmt->result, 13, "MINIMUM_SCALE", PG_TYPE_INT2, 2); QR_set_field_info(res, 13, "MINIMUM_SCALE", PG_TYPE_INT2, 2);
QR_set_field_info(stmt->result, 14, "MAXIMUM_SCALE", PG_TYPE_INT2, 2); QR_set_field_info(res, 14, "MAXIMUM_SCALE", PG_TYPE_INT2, 2);
for (i = 0, sqlType = sqlTypes[0]; sqlType; sqlType = sqlTypes[++i]) for (i = 0, sqlType = sqlTypes[0]; sqlType; sqlType = sqlTypes[++i])
{ {
...@@ -795,7 +804,7 @@ PGAPI_GetTypeInfo( ...@@ -795,7 +804,7 @@ PGAPI_GetTypeInfo(
set_nullfield_int2(&row->tuple[13], pgtype_scale(stmt, pgType, PG_STATIC)); 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[14], pgtype_scale(stmt, pgType, PG_STATIC));
QR_add_tuple(stmt->result, row); QR_add_tuple(res, row);
} }
} }
...@@ -898,7 +907,7 @@ PGAPI_GetFunctions( ...@@ -898,7 +907,7 @@ PGAPI_GetFunctions(
pfExists[SQL_API_SQLMORERESULTS] = TRUE; pfExists[SQL_API_SQLMORERESULTS] = TRUE;
pfExists[SQL_API_SQLNATIVESQL] = TRUE; pfExists[SQL_API_SQLNATIVESQL] = TRUE;
pfExists[SQL_API_SQLNUMPARAMS] = TRUE; pfExists[SQL_API_SQLNUMPARAMS] = TRUE;
pfExists[SQL_API_SQLPARAMOPTIONS] = FALSE; pfExists[SQL_API_SQLPARAMOPTIONS] = TRUE;
pfExists[SQL_API_SQLPRIMARYKEYS] = TRUE; pfExists[SQL_API_SQLPRIMARYKEYS] = TRUE;
pfExists[SQL_API_SQLPROCEDURECOLUMNS] = FALSE; pfExists[SQL_API_SQLPROCEDURECOLUMNS] = FALSE;
if (PG_VERSION_LT(conn, 6.5)) if (PG_VERSION_LT(conn, 6.5))
...@@ -907,7 +916,7 @@ PGAPI_GetFunctions( ...@@ -907,7 +916,7 @@ PGAPI_GetFunctions(
pfExists[SQL_API_SQLPROCEDURES] = TRUE; pfExists[SQL_API_SQLPROCEDURES] = TRUE;
pfExists[SQL_API_SQLSETPOS] = TRUE; pfExists[SQL_API_SQLSETPOS] = TRUE;
pfExists[SQL_API_SQLSETSCROLLOPTIONS] = TRUE; /* odbc 1.0 */ pfExists[SQL_API_SQLSETSCROLLOPTIONS] = TRUE; /* odbc 1.0 */
pfExists[SQL_API_SQLTABLEPRIVILEGES] = FALSE; pfExists[SQL_API_SQLTABLEPRIVILEGES] = TRUE;
} }
} }
else else
...@@ -1070,7 +1079,7 @@ PGAPI_GetFunctions( ...@@ -1070,7 +1079,7 @@ PGAPI_GetFunctions(
*pfExists = TRUE; *pfExists = TRUE;
break; break;
case SQL_API_SQLPARAMOPTIONS: case SQL_API_SQLPARAMOPTIONS:
*pfExists = FALSE; *pfExists = TRUE;
break; break;
case SQL_API_SQLPRIMARYKEYS: case SQL_API_SQLPRIMARYKEYS:
*pfExists = TRUE; *pfExists = TRUE;
...@@ -1091,7 +1100,7 @@ PGAPI_GetFunctions( ...@@ -1091,7 +1100,7 @@ PGAPI_GetFunctions(
*pfExists = TRUE; *pfExists = TRUE;
break; /* odbc 1.0 */ break; /* odbc 1.0 */
case SQL_API_SQLTABLEPRIVILEGES: case SQL_API_SQLTABLEPRIVILEGES:
*pfExists = FALSE; *pfExists = TRUE;
break; break;
} }
} }
...@@ -1115,6 +1124,7 @@ PGAPI_Tables( ...@@ -1115,6 +1124,7 @@ PGAPI_Tables(
static char *func = "PGAPI_Tables"; static char *func = "PGAPI_Tables";
StatementClass *stmt = (StatementClass *) hstmt; StatementClass *stmt = (StatementClass *) hstmt;
StatementClass *tbl_stmt; StatementClass *tbl_stmt;
QResultClass *res;
TupleNode *row; TupleNode *row;
HSTMT htbl_stmt; HSTMT htbl_stmt;
RETCODE result; RETCODE result;
...@@ -1291,8 +1301,7 @@ PGAPI_Tables( ...@@ -1291,8 +1301,7 @@ PGAPI_Tables(
return SQL_ERROR; return SQL_ERROR;
} }
stmt->result = QR_Constructor(); if (res = QR_Constructor(), !res)
if (!stmt->result)
{ {
stmt->errormsg = "Couldn't allocate memory for PGAPI_Tables result."; stmt->errormsg = "Couldn't allocate memory for PGAPI_Tables result.";
stmt->errornumber = STMT_NO_MEMORY_ERROR; stmt->errornumber = STMT_NO_MEMORY_ERROR;
...@@ -1300,6 +1309,7 @@ PGAPI_Tables( ...@@ -1300,6 +1309,7 @@ PGAPI_Tables(
PGAPI_FreeStmt(htbl_stmt, SQL_DROP); PGAPI_FreeStmt(htbl_stmt, SQL_DROP);
return SQL_ERROR; return SQL_ERROR;
} }
SC_set_Result(stmt, res);
/* the binding structure for a statement is not set up until */ /* the binding structure for a statement is not set up until */
...@@ -1310,12 +1320,12 @@ PGAPI_Tables( ...@@ -1310,12 +1320,12 @@ PGAPI_Tables(
extend_bindings(stmt, 5); extend_bindings(stmt, 5);
/* set the field names */ /* set the field names */
QR_set_num_fields(stmt->result, 5); QR_set_num_fields(res, 5);
QR_set_field_info(stmt->result, 0, "TABLE_QUALIFIER", PG_TYPE_TEXT, MAX_INFO_STRING); QR_set_field_info(res, 0, "TABLE_QUALIFIER", PG_TYPE_TEXT, MAX_INFO_STRING);
QR_set_field_info(stmt->result, 1, "TABLE_OWNER", PG_TYPE_TEXT, MAX_INFO_STRING); QR_set_field_info(res, 1, "TABLE_OWNER", PG_TYPE_TEXT, MAX_INFO_STRING);
QR_set_field_info(stmt->result, 2, "TABLE_NAME", PG_TYPE_TEXT, MAX_INFO_STRING); QR_set_field_info(res, 2, "TABLE_NAME", PG_TYPE_TEXT, MAX_INFO_STRING);
QR_set_field_info(stmt->result, 3, "TABLE_TYPE", PG_TYPE_TEXT, MAX_INFO_STRING); QR_set_field_info(res, 3, "TABLE_TYPE", PG_TYPE_TEXT, MAX_INFO_STRING);
QR_set_field_info(stmt->result, 4, "REMARKS", PG_TYPE_TEXT, 254); QR_set_field_info(res, 4, "REMARKS", PG_TYPE_TEXT, 254);
/* add the tuples */ /* add the tuples */
result = PGAPI_Fetch(htbl_stmt); result = PGAPI_Fetch(htbl_stmt);
...@@ -1372,6 +1382,7 @@ PGAPI_Tables( ...@@ -1372,6 +1382,7 @@ PGAPI_Tables(
row = (TupleNode *) malloc(sizeof(TupleNode) + (5 - 1) *sizeof(TupleField)); row = (TupleNode *) malloc(sizeof(TupleNode) + (5 - 1) *sizeof(TupleField));
/*set_tuplefield_string(&row->tuple[0], "");*/ /*set_tuplefield_string(&row->tuple[0], "");*/
/*set_tuplefield_string(&row->tuple[0], "cat0");*/
set_tuplefield_null(&row->tuple[0]); set_tuplefield_null(&row->tuple[0]);
/* /*
...@@ -1389,9 +1400,10 @@ PGAPI_Tables( ...@@ -1389,9 +1400,10 @@ PGAPI_Tables(
set_tuplefield_null(&row->tuple[1]); set_tuplefield_null(&row->tuple[1]);
set_tuplefield_string(&row->tuple[2], table_name); set_tuplefield_string(&row->tuple[2], table_name);
set_tuplefield_string(&row->tuple[3], systable ? "SYSTEM TABLE" : (view ? "VIEW" : "TABLE")); set_tuplefield_string(&row->tuple[3], systable ? "SYSTEM TABLE" : (view ? "VIEW" : "TABLE"));
set_tuplefield_string(&row->tuple[4], ""); /*set_tuplefield_string(&row->tuple[4], "");*/
set_tuplefield_string(&row->tuple[4], "TABLE");
QR_add_tuple(stmt->result, row); QR_add_tuple(res, row);
} }
result = PGAPI_Fetch(htbl_stmt); result = PGAPI_Fetch(htbl_stmt);
} }
...@@ -1425,11 +1437,14 @@ PGAPI_Tables( ...@@ -1425,11 +1437,14 @@ PGAPI_Tables(
* PostgreSQL needs 2 '\\' to escape '_' and '%'. * PostgreSQL needs 2 '\\' to escape '_' and '%'.
*/ */
static int static int
reallyEscapeCatalogEscapes(const char *src, int srclen, char *dest, int dst_len) reallyEscapeCatalogEscapes(const char *src, int srclen, char *dest, int dst_len, int ccsc)
{ {
int i, outlen; int i, outlen;
const char *in; const char *in;
BOOL escape_in = FALSE; BOOL escape_in = FALSE;
#ifdef MULTIBYTE
encoded_str encstr;
#endif
if (srclen == SQL_NULL_DATA) if (srclen == SQL_NULL_DATA)
{ {
...@@ -1441,12 +1456,13 @@ reallyEscapeCatalogEscapes(const char *src, int srclen, char *dest, int dst_len) ...@@ -1441,12 +1456,13 @@ reallyEscapeCatalogEscapes(const char *src, int srclen, char *dest, int dst_len)
if (srclen <= 0) if (srclen <= 0)
return STRCPY_FAIL; return STRCPY_FAIL;
#ifdef MULTIBYTE #ifdef MULTIBYTE
multibyte_init(); encoded_str_constr(&encstr, ccsc, src);
#endif #endif
for (i = 0, in = src, outlen = 0; i < srclen && outlen < dst_len; i++, in++) for (i = 0, in = src, outlen = 0; i < srclen && outlen < dst_len; i++, in++)
{ {
#ifdef MULTIBYTE #ifdef MULTIBYTE
if (multibyte_char_check(*in) != 0) encoded_nextchar(&encstr);
if (ENCODE_STATUS(encstr) != 0)
{ {
dest[outlen++] = *in; dest[outlen++] = *in;
continue; continue;
...@@ -1496,6 +1512,7 @@ PGAPI_Columns( ...@@ -1496,6 +1512,7 @@ PGAPI_Columns(
{ {
static char *func = "PGAPI_Columns"; static char *func = "PGAPI_Columns";
StatementClass *stmt = (StatementClass *) hstmt; StatementClass *stmt = (StatementClass *) hstmt;
QResultClass *res;
TupleNode *row; TupleNode *row;
HSTMT hcol_stmt; HSTMT hcol_stmt;
StatementClass *col_stmt; StatementClass *col_stmt;
...@@ -1505,7 +1522,7 @@ PGAPI_Columns( ...@@ -1505,7 +1522,7 @@ PGAPI_Columns(
table_name[MAX_INFO_STRING], table_name[MAX_INFO_STRING],
field_name[MAX_INFO_STRING], field_name[MAX_INFO_STRING],
field_type_name[MAX_INFO_STRING]; field_type_name[MAX_INFO_STRING];
Int2 field_number, Int2 field_number, sqltype,
result_cols, result_cols,
scale; scale;
Int4 field_type, Int4 field_type,
...@@ -1556,7 +1573,7 @@ PGAPI_Columns( ...@@ -1556,7 +1573,7 @@ PGAPI_Columns(
char esc_table_name[MAX_TABLE_LEN * 2]; char esc_table_name[MAX_TABLE_LEN * 2];
int escTbnamelen; int escTbnamelen;
escTbnamelen = reallyEscapeCatalogEscapes(szTableName, cbTableName, esc_table_name, sizeof(esc_table_name)); escTbnamelen = reallyEscapeCatalogEscapes(szTableName, cbTableName, esc_table_name, sizeof(esc_table_name), conn->ccsc);
my_strcat(columns_query, " and c.relname like '%.*s'", esc_table_name, escTbnamelen); my_strcat(columns_query, " and c.relname like '%.*s'", esc_table_name, escTbnamelen);
my_strcat(columns_query, " and u.usename like '%.*s'", szTableOwner, cbTableOwner); my_strcat(columns_query, " and u.usename like '%.*s'", szTableOwner, cbTableOwner);
my_strcat(columns_query, " and a.attname like '%.*s'", szColumnName, cbColumnName); my_strcat(columns_query, " and a.attname like '%.*s'", szColumnName, cbColumnName);
...@@ -1701,8 +1718,7 @@ PGAPI_Columns( ...@@ -1701,8 +1718,7 @@ PGAPI_Columns(
return SQL_ERROR; return SQL_ERROR;
} }
stmt->result = QR_Constructor(); if (res = QR_Constructor(), !res)
if (!stmt->result)
{ {
stmt->errormsg = "Couldn't allocate memory for PGAPI_Columns result."; stmt->errormsg = "Couldn't allocate memory for PGAPI_Columns result.";
stmt->errornumber = STMT_NO_MEMORY_ERROR; stmt->errornumber = STMT_NO_MEMORY_ERROR;
...@@ -1710,6 +1726,7 @@ PGAPI_Columns( ...@@ -1710,6 +1726,7 @@ PGAPI_Columns(
PGAPI_FreeStmt(hcol_stmt, SQL_DROP); PGAPI_FreeStmt(hcol_stmt, SQL_DROP);
return SQL_ERROR; return SQL_ERROR;
} }
SC_set_Result(stmt, res);
/* the binding structure for a statement is not set up until */ /* the binding structure for a statement is not set up until */
...@@ -1721,23 +1738,32 @@ PGAPI_Columns( ...@@ -1721,23 +1738,32 @@ PGAPI_Columns(
extend_bindings(stmt, result_cols); extend_bindings(stmt, result_cols);
/* set the field names */ /* set the field names */
QR_set_num_fields(stmt->result, result_cols); QR_set_num_fields(res, result_cols);
QR_set_field_info(stmt->result, 0, "TABLE_QUALIFIER", PG_TYPE_TEXT, MAX_INFO_STRING); QR_set_field_info(res, 0, "TABLE_QUALIFIER", PG_TYPE_TEXT, MAX_INFO_STRING);
QR_set_field_info(stmt->result, 1, "TABLE_OWNER", PG_TYPE_TEXT, MAX_INFO_STRING); QR_set_field_info(res, 1, "TABLE_OWNER", PG_TYPE_TEXT, MAX_INFO_STRING);
QR_set_field_info(stmt->result, 2, "TABLE_NAME", PG_TYPE_TEXT, MAX_INFO_STRING); QR_set_field_info(res, 2, "TABLE_NAME", PG_TYPE_TEXT, MAX_INFO_STRING);
QR_set_field_info(stmt->result, 3, "COLUMN_NAME", PG_TYPE_TEXT, MAX_INFO_STRING); QR_set_field_info(res, 3, "COLUMN_NAME", PG_TYPE_TEXT, MAX_INFO_STRING);
QR_set_field_info(stmt->result, 4, "DATA_TYPE", PG_TYPE_INT2, 2); QR_set_field_info(res, 4, "DATA_TYPE", PG_TYPE_INT2, 2);
QR_set_field_info(stmt->result, 5, "TYPE_NAME", PG_TYPE_TEXT, MAX_INFO_STRING); QR_set_field_info(res, 5, "TYPE_NAME", PG_TYPE_TEXT, MAX_INFO_STRING);
QR_set_field_info(stmt->result, 6, "PRECISION", PG_TYPE_INT4, 4); QR_set_field_info(res, 6, "PRECISION", PG_TYPE_INT4, 4);
QR_set_field_info(stmt->result, 7, "LENGTH", PG_TYPE_INT4, 4); QR_set_field_info(res, 7, "LENGTH", PG_TYPE_INT4, 4);
QR_set_field_info(stmt->result, 8, "SCALE", PG_TYPE_INT2, 2); QR_set_field_info(res, 8, "SCALE", PG_TYPE_INT2, 2);
QR_set_field_info(stmt->result, 9, "RADIX", PG_TYPE_INT2, 2); QR_set_field_info(res, 9, "RADIX", PG_TYPE_INT2, 2);
QR_set_field_info(stmt->result, 10, "NULLABLE", PG_TYPE_INT2, 2); QR_set_field_info(res, 10, "NULLABLE", PG_TYPE_INT2, 2);
QR_set_field_info(stmt->result, 11, "REMARKS", PG_TYPE_TEXT, 254); QR_set_field_info(res, 11, "REMARKS", PG_TYPE_TEXT, 254);
/* User defined fields */ /* User defined fields */
QR_set_field_info(stmt->result, 12, "DISPLAY_SIZE", PG_TYPE_INT4, 4); #if (ODBCVER >= 0x0300)
QR_set_field_info(stmt->result, 13, "FIELD_TYPE", PG_TYPE_INT4, 4); QR_set_field_info(res, 12, "COLUMN_DEF", PG_TYPE_INT4, 254);
QR_set_field_info(res, 13, "SQL_DATA_TYPE", PG_TYPE_INT2, 2);
QR_set_field_info(res, 14, "SQL_DATETIME_SUB", PG_TYPE_INT2, 2);
QR_set_field_info(res, 15, "CHAR_OCTET_LENGTH", PG_TYPE_INT4, 4);
QR_set_field_info(res, 16, "ORDINAL_POSITION", PG_TYPE_INT4, 4);
QR_set_field_info(res, 17, "IS_NULLABLE", PG_TYPE_TEXT, 254);
#else
QR_set_field_info(res, 12, "DISPLAY_SIZE", PG_TYPE_INT4, 4);
QR_set_field_info(res, 13, "FIELD_TYPE", PG_TYPE_INT4, 4);
#endif /* ODBCVER */
result = PGAPI_Fetch(hcol_stmt); result = PGAPI_Fetch(hcol_stmt);
...@@ -1764,7 +1790,8 @@ PGAPI_Columns( ...@@ -1764,7 +1790,8 @@ PGAPI_Columns(
set_tuplefield_string(&row->tuple[1], ""); set_tuplefield_string(&row->tuple[1], "");
set_tuplefield_string(&row->tuple[2], table_name); set_tuplefield_string(&row->tuple[2], table_name);
set_tuplefield_string(&row->tuple[3], "oid"); set_tuplefield_string(&row->tuple[3], "oid");
set_tuplefield_int2(&row->tuple[4], pgtype_to_sqltype(stmt, the_type)); sqltype = pgtype_to_sqltype(stmt, the_type);
set_tuplefield_int2(&row->tuple[4], sqltype);
set_tuplefield_string(&row->tuple[5], "OID"); set_tuplefield_string(&row->tuple[5], "OID");
set_tuplefield_int4(&row->tuple[7], pgtype_length(stmt, the_type, PG_STATIC, PG_STATIC)); set_tuplefield_int4(&row->tuple[7], pgtype_length(stmt, the_type, PG_STATIC, PG_STATIC));
...@@ -1775,10 +1802,14 @@ PGAPI_Columns( ...@@ -1775,10 +1802,14 @@ PGAPI_Columns(
set_tuplefield_int2(&row->tuple[10], SQL_NO_NULLS); set_tuplefield_int2(&row->tuple[10], SQL_NO_NULLS);
set_tuplefield_string(&row->tuple[11], ""); set_tuplefield_string(&row->tuple[11], "");
#if (ODBCVER >= 0x0300)
set_tuplefield_int2(&row->tuple[13], sqltype);
#else
set_tuplefield_int4(&row->tuple[12], pgtype_display_size(stmt, the_type, PG_STATIC, PG_STATIC)); set_tuplefield_int4(&row->tuple[12], pgtype_display_size(stmt, the_type, PG_STATIC, PG_STATIC));
set_tuplefield_int4(&row->tuple[13], the_type); set_tuplefield_int4(&row->tuple[13], the_type);
#endif /* ODBCVER */
QR_add_tuple(stmt->result, row); QR_add_tuple(res, row);
} }
} }
...@@ -1794,7 +1825,8 @@ PGAPI_Columns( ...@@ -1794,7 +1825,8 @@ PGAPI_Columns(
set_tuplefield_string(&row->tuple[1], ""); set_tuplefield_string(&row->tuple[1], "");
set_tuplefield_string(&row->tuple[2], table_name); set_tuplefield_string(&row->tuple[2], table_name);
set_tuplefield_string(&row->tuple[3], field_name); set_tuplefield_string(&row->tuple[3], field_name);
set_tuplefield_int2(&row->tuple[4], pgtype_to_sqltype(stmt, field_type)); sqltype = pgtype_to_sqltype(stmt, field_type);
set_tuplefield_int2(&row->tuple[4], sqltype);
set_tuplefield_string(&row->tuple[5], field_type_name); set_tuplefield_string(&row->tuple[5], field_type_name);
...@@ -1812,7 +1844,7 @@ PGAPI_Columns( ...@@ -1812,7 +1844,7 @@ PGAPI_Columns(
*---------- *----------
*/ */
qlog("PGAPI_Columns: table='%s',field_name='%s',type=%d,sqltype=%d,name='%s'\n", qlog("PGAPI_Columns: table='%s',field_name='%s',type=%d,sqltype=%d,name='%s'\n",
table_name, field_name, field_type, pgtype_to_sqltype(stmt,field_type), field_type_name); table_name, field_name, field_type, pgtype_to_sqltype, field_type_name);
useStaticPrecision = TRUE; useStaticPrecision = TRUE;
...@@ -1869,9 +1901,31 @@ PGAPI_Columns( ...@@ -1869,9 +1901,31 @@ PGAPI_Columns(
set_nullfield_int2(&row->tuple[9], pgtype_radix(stmt, field_type)); set_nullfield_int2(&row->tuple[9], pgtype_radix(stmt, field_type));
set_tuplefield_int2(&row->tuple[10], (Int2) (not_null[0] == '1' ? SQL_NO_NULLS : pgtype_nullable(stmt, field_type))); set_tuplefield_int2(&row->tuple[10], (Int2) (not_null[0] == '1' ? SQL_NO_NULLS : pgtype_nullable(stmt, field_type)));
set_tuplefield_string(&row->tuple[11], ""); set_tuplefield_string(&row->tuple[11], "");
#if (ODBCVER >= 0x0300)
switch (sqltype)
{
case SQL_TYPE_DATE:
set_tuplefield_int2(&row->tuple[13], SQL_DATETIME);
set_tuplefield_int2(&row->tuple[14], SQL_CODE_DATE);
break;
case SQL_TYPE_TIME:
set_tuplefield_int2(&row->tuple[13], SQL_DATETIME);
set_tuplefield_int2(&row->tuple[14], SQL_CODE_TIME);
break;
case SQL_TYPE_TIMESTAMP:
set_tuplefield_int2(&row->tuple[13], SQL_DATETIME);
set_tuplefield_int2(&row->tuple[14], SQL_CODE_TIMESTAMP);
break;
default:
set_tuplefield_int2(&row->tuple[13], sqltype);
break;
}
set_tuplefield_int4(&row->tuple[16], field_number);
#else
set_tuplefield_int4(&row->tuple[13], field_type); set_tuplefield_int4(&row->tuple[13], field_type);
#endif /* ODBCVER */
QR_add_tuple(stmt->result, row); QR_add_tuple(res, row);
result = PGAPI_Fetch(hcol_stmt); result = PGAPI_Fetch(hcol_stmt);
...@@ -1913,7 +1967,7 @@ PGAPI_Columns( ...@@ -1913,7 +1967,7 @@ PGAPI_Columns(
set_tuplefield_int4(&row->tuple[12], pgtype_display_size(stmt, the_type, PG_STATIC, PG_STATIC)); set_tuplefield_int4(&row->tuple[12], pgtype_display_size(stmt, the_type, PG_STATIC, PG_STATIC));
set_tuplefield_int4(&row->tuple[13], the_type); set_tuplefield_int4(&row->tuple[13], the_type);
QR_add_tuple(stmt->result, row); QR_add_tuple(res, row);
} }
/* /*
...@@ -1949,6 +2003,7 @@ PGAPI_SpecialColumns( ...@@ -1949,6 +2003,7 @@ PGAPI_SpecialColumns(
static char *func = "PGAPI_SpecialColumns"; static char *func = "PGAPI_SpecialColumns";
TupleNode *row; TupleNode *row;
StatementClass *stmt = (StatementClass *) hstmt; StatementClass *stmt = (StatementClass *) hstmt;
QResultClass *res;
ConnInfo *ci; ConnInfo *ci;
HSTMT hcol_stmt; HSTMT hcol_stmt;
StatementClass *col_stmt; StatementClass *col_stmt;
...@@ -2017,18 +2072,19 @@ PGAPI_SpecialColumns( ...@@ -2017,18 +2072,19 @@ PGAPI_SpecialColumns(
result = PGAPI_Fetch(hcol_stmt); result = PGAPI_Fetch(hcol_stmt);
PGAPI_FreeStmt(hcol_stmt, SQL_DROP); PGAPI_FreeStmt(hcol_stmt, SQL_DROP);
stmt->result = QR_Constructor(); res = QR_Constructor();
SC_set_Result(stmt, res);
extend_bindings(stmt, 8); extend_bindings(stmt, 8);
QR_set_num_fields(stmt->result, 8); QR_set_num_fields(res, 8);
QR_set_field_info(stmt->result, 0, "SCOPE", PG_TYPE_INT2, 2); QR_set_field_info(res, 0, "SCOPE", PG_TYPE_INT2, 2);
QR_set_field_info(stmt->result, 1, "COLUMN_NAME", PG_TYPE_TEXT, MAX_INFO_STRING); QR_set_field_info(res, 1, "COLUMN_NAME", PG_TYPE_TEXT, MAX_INFO_STRING);
QR_set_field_info(stmt->result, 2, "DATA_TYPE", PG_TYPE_INT2, 2); QR_set_field_info(res, 2, "DATA_TYPE", PG_TYPE_INT2, 2);
QR_set_field_info(stmt->result, 3, "TYPE_NAME", PG_TYPE_TEXT, MAX_INFO_STRING); QR_set_field_info(res, 3, "TYPE_NAME", PG_TYPE_TEXT, MAX_INFO_STRING);
QR_set_field_info(stmt->result, 4, "PRECISION", PG_TYPE_INT4, 4); QR_set_field_info(res, 4, "PRECISION", PG_TYPE_INT4, 4);
QR_set_field_info(stmt->result, 5, "LENGTH", PG_TYPE_INT4, 4); QR_set_field_info(res, 5, "LENGTH", PG_TYPE_INT4, 4);
QR_set_field_info(stmt->result, 6, "SCALE", PG_TYPE_INT2, 2); QR_set_field_info(res, 6, "SCALE", PG_TYPE_INT2, 2);
QR_set_field_info(stmt->result, 7, "PSEUDO_COLUMN", PG_TYPE_INT2, 2); QR_set_field_info(res, 7, "PSEUDO_COLUMN", PG_TYPE_INT2, 2);
if (relhasrules[0] != '1') if (relhasrules[0] != '1')
{ {
...@@ -2046,7 +2102,7 @@ PGAPI_SpecialColumns( ...@@ -2046,7 +2102,7 @@ PGAPI_SpecialColumns(
set_tuplefield_int2(&row->tuple[6], pgtype_scale(stmt, PG_TYPE_OID, PG_STATIC)); set_tuplefield_int2(&row->tuple[6], pgtype_scale(stmt, PG_TYPE_OID, PG_STATIC));
set_tuplefield_int2(&row->tuple[7], SQL_PC_PSEUDO); set_tuplefield_int2(&row->tuple[7], SQL_PC_PSEUDO);
QR_add_tuple(stmt->result, row); QR_add_tuple(res, row);
} }
else if (fColType == SQL_ROWVER) else if (fColType == SQL_ROWVER)
...@@ -2066,7 +2122,7 @@ PGAPI_SpecialColumns( ...@@ -2066,7 +2122,7 @@ PGAPI_SpecialColumns(
set_tuplefield_int2(&row->tuple[6], pgtype_scale(stmt, the_type, PG_STATIC)); set_tuplefield_int2(&row->tuple[6], pgtype_scale(stmt, the_type, PG_STATIC));
set_tuplefield_int2(&row->tuple[7], SQL_PC_PSEUDO); set_tuplefield_int2(&row->tuple[7], SQL_PC_PSEUDO);
QR_add_tuple(stmt->result, row); QR_add_tuple(res, row);
} }
} }
} }
...@@ -2095,6 +2151,7 @@ PGAPI_Statistics( ...@@ -2095,6 +2151,7 @@ PGAPI_Statistics(
{ {
static char *func = "PGAPI_Statistics"; static char *func = "PGAPI_Statistics";
StatementClass *stmt = (StatementClass *) hstmt; StatementClass *stmt = (StatementClass *) hstmt;
QResultClass *res;
char index_query[INFO_INQUIRY_LEN]; char index_query[INFO_INQUIRY_LEN];
HSTMT hindx_stmt; HSTMT hindx_stmt;
RETCODE result; RETCODE result;
...@@ -2133,14 +2190,14 @@ PGAPI_Statistics( ...@@ -2133,14 +2190,14 @@ PGAPI_Statistics(
ci = &(SC_get_conn(stmt)->connInfo); ci = &(SC_get_conn(stmt)->connInfo);
stmt->result = QR_Constructor(); if (res = QR_Constructor(), !res)
if (!stmt->result)
{ {
stmt->errormsg = "Couldn't allocate memory for PGAPI_Statistics result."; stmt->errormsg = "Couldn't allocate memory for PGAPI_Statistics result.";
stmt->errornumber = STMT_NO_MEMORY_ERROR; stmt->errornumber = STMT_NO_MEMORY_ERROR;
SC_log_error(func, "", stmt); SC_log_error(func, "", stmt);
return SQL_ERROR; return SQL_ERROR;
} }
SC_set_Result(stmt, res);
/* the binding structure for a statement is not set up until */ /* the binding structure for a statement is not set up until */
...@@ -2151,20 +2208,20 @@ PGAPI_Statistics( ...@@ -2151,20 +2208,20 @@ PGAPI_Statistics(
extend_bindings(stmt, 13); extend_bindings(stmt, 13);
/* set the field names */ /* set the field names */
QR_set_num_fields(stmt->result, 13); QR_set_num_fields(res, 13);
QR_set_field_info(stmt->result, 0, "TABLE_QUALIFIER", PG_TYPE_TEXT, MAX_INFO_STRING); QR_set_field_info(res, 0, "TABLE_QUALIFIER", PG_TYPE_TEXT, MAX_INFO_STRING);
QR_set_field_info(stmt->result, 1, "TABLE_OWNER", PG_TYPE_TEXT, MAX_INFO_STRING); QR_set_field_info(res, 1, "TABLE_OWNER", PG_TYPE_TEXT, MAX_INFO_STRING);
QR_set_field_info(stmt->result, 2, "TABLE_NAME", PG_TYPE_TEXT, MAX_INFO_STRING); QR_set_field_info(res, 2, "TABLE_NAME", PG_TYPE_TEXT, MAX_INFO_STRING);
QR_set_field_info(stmt->result, 3, "NON_UNIQUE", PG_TYPE_INT2, 2); QR_set_field_info(res, 3, "NON_UNIQUE", PG_TYPE_INT2, 2);
QR_set_field_info(stmt->result, 4, "INDEX_QUALIFIER", PG_TYPE_TEXT, MAX_INFO_STRING); QR_set_field_info(res, 4, "INDEX_QUALIFIER", PG_TYPE_TEXT, MAX_INFO_STRING);
QR_set_field_info(stmt->result, 5, "INDEX_NAME", PG_TYPE_TEXT, MAX_INFO_STRING); QR_set_field_info(res, 5, "INDEX_NAME", PG_TYPE_TEXT, MAX_INFO_STRING);
QR_set_field_info(stmt->result, 6, "TYPE", PG_TYPE_INT2, 2); QR_set_field_info(res, 6, "TYPE", PG_TYPE_INT2, 2);
QR_set_field_info(stmt->result, 7, "SEQ_IN_INDEX", PG_TYPE_INT2, 2); QR_set_field_info(res, 7, "SEQ_IN_INDEX", PG_TYPE_INT2, 2);
QR_set_field_info(stmt->result, 8, "COLUMN_NAME", PG_TYPE_TEXT, MAX_INFO_STRING); QR_set_field_info(res, 8, "COLUMN_NAME", PG_TYPE_TEXT, MAX_INFO_STRING);
QR_set_field_info(stmt->result, 9, "COLLATION", PG_TYPE_CHAR, 1); QR_set_field_info(res, 9, "COLLATION", PG_TYPE_CHAR, 1);
QR_set_field_info(stmt->result, 10, "CARDINALITY", PG_TYPE_INT4, 4); QR_set_field_info(res, 10, "CARDINALITY", PG_TYPE_INT4, 4);
QR_set_field_info(stmt->result, 11, "PAGES", PG_TYPE_INT4, 4); QR_set_field_info(res, 11, "PAGES", PG_TYPE_INT4, 4);
QR_set_field_info(stmt->result, 12, "FILTER_CONDITION", PG_TYPE_TEXT, MAX_INFO_STRING); QR_set_field_info(res, 12, "FILTER_CONDITION", PG_TYPE_TEXT, MAX_INFO_STRING);
/* /*
* only use the table name... the owner should be redundant, and we * only use the table name... the owner should be redundant, and we
...@@ -2395,7 +2452,7 @@ PGAPI_Statistics( ...@@ -2395,7 +2452,7 @@ PGAPI_Statistics(
set_tuplefield_null(&row->tuple[11]); set_tuplefield_null(&row->tuple[11]);
set_tuplefield_null(&row->tuple[12]); set_tuplefield_null(&row->tuple[12]);
QR_add_tuple(stmt->result, row); QR_add_tuple(res, row);
} }
result = PGAPI_Fetch(hindx_stmt); result = PGAPI_Fetch(hindx_stmt);
...@@ -2457,7 +2514,7 @@ PGAPI_Statistics( ...@@ -2457,7 +2514,7 @@ PGAPI_Statistics(
set_tuplefield_null(&row->tuple[11]); set_tuplefield_null(&row->tuple[11]);
set_tuplefield_null(&row->tuple[12]); set_tuplefield_null(&row->tuple[12]);
QR_add_tuple(stmt->result, row); QR_add_tuple(res, row);
i++; i++;
} }
} }
...@@ -2520,12 +2577,15 @@ PGAPI_ColumnPrivileges( ...@@ -2520,12 +2577,15 @@ PGAPI_ColumnPrivileges(
SWORD cbColumnName) SWORD cbColumnName)
{ {
static char *func = "PGAPI_ColumnPrivileges"; static char *func = "PGAPI_ColumnPrivileges";
StatementClass *stmt = (StatementClass *) hstmt;
mylog("%s: entering...\n", func); mylog("%s: entering...\n", func);
/* Neither Access or Borland care about this. */ /* Neither Access or Borland care about this. */
SC_log_error(func, "Function not implemented", (StatementClass *) hstmt); stmt->errornumber = STMT_NOT_IMPLEMENTED_ERROR;
stmt->errormsg = "not implemented";
SC_log_error(func, "Function not implemented", stmt);
return SQL_ERROR; return SQL_ERROR;
} }
...@@ -2547,6 +2607,7 @@ PGAPI_PrimaryKeys( ...@@ -2547,6 +2607,7 @@ PGAPI_PrimaryKeys(
{ {
static char *func = "PGAPI_PrimaryKeys"; static char *func = "PGAPI_PrimaryKeys";
StatementClass *stmt = (StatementClass *) hstmt; StatementClass *stmt = (StatementClass *) hstmt;
QResultClass *res;
ConnectionClass *conn; ConnectionClass *conn;
TupleNode *row; TupleNode *row;
RETCODE result; RETCODE result;
...@@ -2572,14 +2633,14 @@ PGAPI_PrimaryKeys( ...@@ -2572,14 +2633,14 @@ PGAPI_PrimaryKeys(
stmt->manual_result = TRUE; stmt->manual_result = TRUE;
stmt->errormsg_created = TRUE; stmt->errormsg_created = TRUE;
stmt->result = QR_Constructor(); if (res = QR_Constructor(), !res)
if (!stmt->result)
{ {
stmt->errormsg = "Couldn't allocate memory for PGAPI_PrimaryKeys result."; stmt->errormsg = "Couldn't allocate memory for PGAPI_PrimaryKeys result.";
stmt->errornumber = STMT_NO_MEMORY_ERROR; stmt->errornumber = STMT_NO_MEMORY_ERROR;
SC_log_error(func, "", stmt); SC_log_error(func, "", stmt);
return SQL_ERROR; return SQL_ERROR;
} }
SC_set_Result(stmt, res);
/* the binding structure for a statement is not set up until */ /* the binding structure for a statement is not set up until */
...@@ -2591,13 +2652,13 @@ PGAPI_PrimaryKeys( ...@@ -2591,13 +2652,13 @@ PGAPI_PrimaryKeys(
extend_bindings(stmt, result_cols); extend_bindings(stmt, result_cols);
/* set the field names */ /* set the field names */
QR_set_num_fields(stmt->result, result_cols); QR_set_num_fields(res, result_cols);
QR_set_field_info(stmt->result, 0, "TABLE_QUALIFIER", PG_TYPE_TEXT, MAX_INFO_STRING); QR_set_field_info(res, 0, "TABLE_QUALIFIER", PG_TYPE_TEXT, MAX_INFO_STRING);
QR_set_field_info(stmt->result, 1, "TABLE_OWNER", PG_TYPE_TEXT, MAX_INFO_STRING); QR_set_field_info(res, 1, "TABLE_OWNER", PG_TYPE_TEXT, MAX_INFO_STRING);
QR_set_field_info(stmt->result, 2, "TABLE_NAME", PG_TYPE_TEXT, MAX_INFO_STRING); QR_set_field_info(res, 2, "TABLE_NAME", PG_TYPE_TEXT, MAX_INFO_STRING);
QR_set_field_info(stmt->result, 3, "COLUMN_NAME", PG_TYPE_TEXT, MAX_INFO_STRING); QR_set_field_info(res, 3, "COLUMN_NAME", PG_TYPE_TEXT, MAX_INFO_STRING);
QR_set_field_info(stmt->result, 4, "KEY_SEQ", PG_TYPE_INT2, 2); QR_set_field_info(res, 4, "KEY_SEQ", PG_TYPE_INT2, 2);
QR_set_field_info(stmt->result, 5, "PK_NAME", PG_TYPE_TEXT, MAX_INFO_STRING); QR_set_field_info(res, 5, "PK_NAME", PG_TYPE_TEXT, MAX_INFO_STRING);
result = PGAPI_AllocStmt(stmt->hdbc, &htbl_stmt); result = PGAPI_AllocStmt(stmt->hdbc, &htbl_stmt);
...@@ -2709,7 +2770,7 @@ PGAPI_PrimaryKeys( ...@@ -2709,7 +2770,7 @@ PGAPI_PrimaryKeys(
set_tuplefield_int2(&row->tuple[4], (Int2) (++seq)); set_tuplefield_int2(&row->tuple[4], (Int2) (++seq));
set_tuplefield_null(&row->tuple[5]); set_tuplefield_null(&row->tuple[5]);
QR_add_tuple(stmt->result, row); QR_add_tuple(res, row);
mylog(">> primaryKeys: pktab = '%s', attname = '%s', seq = %d\n", pktab, attname, seq); mylog(">> primaryKeys: pktab = '%s', attname = '%s', seq = %d\n", pktab, attname, seq);
...@@ -2775,7 +2836,7 @@ getClientTableName(ConnectionClass *conn, char *serverTableName, BOOL *nameAlloc ...@@ -2775,7 +2836,7 @@ getClientTableName(ConnectionClass *conn, char *serverTableName, BOOL *nameAlloc
return ret; return ret;
if (!conn->server_encoding) if (!conn->server_encoding)
{ {
if (res = CC_send_query(conn, "select getdatabaseencoding()", NULL), res) if (res = CC_send_query(conn, "select getdatabaseencoding()", NULL, TRUE), res)
{ {
if (QR_get_num_tuples(res) > 0) if (QR_get_num_tuples(res) > 0)
conn->server_encoding = strdup(QR_get_value_backend_row(res, 0, 0)); conn->server_encoding = strdup(QR_get_value_backend_row(res, 0, 0));
...@@ -2785,25 +2846,16 @@ getClientTableName(ConnectionClass *conn, char *serverTableName, BOOL *nameAlloc ...@@ -2785,25 +2846,16 @@ getClientTableName(ConnectionClass *conn, char *serverTableName, BOOL *nameAlloc
if (!conn->server_encoding) if (!conn->server_encoding)
return ret; return ret;
sprintf(query, "SET CLIENT_ENCODING TO '%s'", conn->server_encoding); sprintf(query, "SET CLIENT_ENCODING TO '%s'", conn->server_encoding);
if (res = CC_send_query(conn, query, NULL), res) bError = (CC_send_query(conn, query, NULL, TRUE) == NULL);
{
bError = QR_get_aborted(res);
QR_Destructor(res);
}
else
bError = TRUE;
if (!bError && continueExec) if (!bError && continueExec)
{ {
sprintf(query, "select OID from pg_class where relname = '%s'", serverTableName); sprintf(query, "select OID from pg_class where relname = '%s'", serverTableName);
if (res = CC_send_query(conn, query, NULL), res) if (res = CC_send_query(conn, query, NULL, TRUE), res)
{ {
if (QR_get_num_tuples(res) > 0) if (QR_get_num_tuples(res) > 0)
strcpy(saveoid, QR_get_value_backend_row(res, 0, 0)); strcpy(saveoid, QR_get_value_backend_row(res, 0, 0));
else else
{
continueExec = FALSE; continueExec = FALSE;
bError = QR_get_aborted(res);
}
QR_Destructor(res); QR_Destructor(res);
} }
else else
...@@ -2817,17 +2869,11 @@ getClientTableName(ConnectionClass *conn, char *serverTableName, BOOL *nameAlloc ...@@ -2817,17 +2869,11 @@ getClientTableName(ConnectionClass *conn, char *serverTableName, BOOL *nameAlloc
} }
/* restore the client encoding */ /* restore the client encoding */
sprintf(query, "SET CLIENT_ENCODING TO '%s'", conn->client_encoding); sprintf(query, "SET CLIENT_ENCODING TO '%s'", conn->client_encoding);
if (res = CC_send_query(conn, query, NULL), res) bError = (CC_send_query(conn, query, NULL, TRUE) == NULL);
{
bError = QR_get_aborted(res);
QR_Destructor(res);
}
else
bError = TRUE;
if (bError || !continueExec) if (bError || !continueExec)
return ret; return ret;
sprintf(query, "select relname from pg_class where OID = %s", saveoid); sprintf(query, "select relname from pg_class where OID = %s", saveoid);
if (res = CC_send_query(conn, query, NULL), res) if (res = CC_send_query(conn, query, NULL, TRUE), res)
{ {
if (QR_get_num_tuples(res) > 0) if (QR_get_num_tuples(res) > 0)
{ {
...@@ -2854,7 +2900,7 @@ getClientColumnName(ConnectionClass *conn, const char *serverTableName, char *se ...@@ -2854,7 +2900,7 @@ getClientColumnName(ConnectionClass *conn, const char *serverTableName, char *se
return ret; return ret;
if (!conn->server_encoding) if (!conn->server_encoding)
{ {
if (res = CC_send_query(conn, "select getdatabaseencoding()", NULL), res) if (res = CC_send_query(conn, "select getdatabaseencoding()", NULL, TRUE), res)
{ {
if (QR_get_num_tuples(res) > 0) if (QR_get_num_tuples(res) > 0)
conn->server_encoding = strdup(QR_get_value_backend_row(res, 0, 0)); conn->server_encoding = strdup(QR_get_value_backend_row(res, 0, 0));
...@@ -2864,19 +2910,13 @@ getClientColumnName(ConnectionClass *conn, const char *serverTableName, char *se ...@@ -2864,19 +2910,13 @@ getClientColumnName(ConnectionClass *conn, const char *serverTableName, char *se
if (!conn->server_encoding) if (!conn->server_encoding)
return ret; return ret;
sprintf(query, "SET CLIENT_ENCODING TO '%s'", conn->server_encoding); sprintf(query, "SET CLIENT_ENCODING TO '%s'", conn->server_encoding);
if (res = CC_send_query(conn, query, NULL), res) bError = (CC_send_query(conn, query, NULL, TRUE) == NULL);
{
bError = QR_get_aborted(res);
QR_Destructor(res);
}
else
bError = TRUE;
if (!bError && continueExec) if (!bError && continueExec)
{ {
sprintf(query, "select attrelid, attnum from pg_class, pg_attribute " sprintf(query, "select attrelid, attnum from pg_class, pg_attribute "
"where relname = '%s' and attrelid = pg_class.oid " "where relname = '%s' and attrelid = pg_class.oid "
"and attname = '%s'", serverTableName, serverColumnName); "and attname = '%s'", serverTableName, serverColumnName);
if (res = CC_send_query(conn, query, NULL), res) if (res = CC_send_query(conn, query, NULL, TRUE), res)
{ {
if (QR_get_num_tuples(res) > 0) if (QR_get_num_tuples(res) > 0)
{ {
...@@ -2884,10 +2924,7 @@ getClientColumnName(ConnectionClass *conn, const char *serverTableName, char *se ...@@ -2884,10 +2924,7 @@ getClientColumnName(ConnectionClass *conn, const char *serverTableName, char *se
strcpy(saveattnum, QR_get_value_backend_row(res, 0, 1)); strcpy(saveattnum, QR_get_value_backend_row(res, 0, 1));
} }
else else
{
continueExec = FALSE; continueExec = FALSE;
bError = QR_get_aborted(res);
}
QR_Destructor(res); QR_Destructor(res);
} }
else else
...@@ -2901,17 +2938,11 @@ getClientColumnName(ConnectionClass *conn, const char *serverTableName, char *se ...@@ -2901,17 +2938,11 @@ getClientColumnName(ConnectionClass *conn, const char *serverTableName, char *se
} }
/* restore the cleint encoding */ /* restore the cleint encoding */
sprintf(query, "SET CLIENT_ENCODING TO '%s'", conn->client_encoding); sprintf(query, "SET CLIENT_ENCODING TO '%s'", conn->client_encoding);
if (res = CC_send_query(conn, query, NULL), res) bError = (CC_send_query(conn, query, NULL, TRUE) == NULL);
{
bError = QR_get_aborted(res);
QR_Destructor(res);
}
else
bError = TRUE;
if (bError || !continueExec) if (bError || !continueExec)
return ret; return ret;
sprintf(query, "select attname from pg_attribute where attrelid = %s and attnum = %s", saveattrelid, saveattnum); sprintf(query, "select attname from pg_attribute where attrelid = %s and attnum = %s", saveattrelid, saveattnum);
if (res = CC_send_query(conn, query, NULL), res) if (res = CC_send_query(conn, query, NULL, TRUE), res)
{ {
if (QR_get_num_tuples(res) > 0) if (QR_get_num_tuples(res) > 0)
{ {
...@@ -2942,6 +2973,7 @@ PGAPI_ForeignKeys( ...@@ -2942,6 +2973,7 @@ PGAPI_ForeignKeys(
{ {
static char *func = "PGAPI_ForeignKeys"; static char *func = "PGAPI_ForeignKeys";
StatementClass *stmt = (StatementClass *) hstmt; StatementClass *stmt = (StatementClass *) hstmt;
QResultClass *res;
TupleNode *row; TupleNode *row;
HSTMT htbl_stmt, HSTMT htbl_stmt,
hpkey_stmt; hpkey_stmt;
...@@ -2997,14 +3029,14 @@ PGAPI_ForeignKeys( ...@@ -2997,14 +3029,14 @@ PGAPI_ForeignKeys(
stmt->manual_result = TRUE; stmt->manual_result = TRUE;
stmt->errormsg_created = TRUE; stmt->errormsg_created = TRUE;
stmt->result = QR_Constructor(); if (res = QR_Constructor(), !res)
if (!stmt->result)
{ {
stmt->errormsg = "Couldn't allocate memory for PGAPI_ForeignKeys result."; stmt->errormsg = "Couldn't allocate memory for PGAPI_ForeignKeys result.";
stmt->errornumber = STMT_NO_MEMORY_ERROR; stmt->errornumber = STMT_NO_MEMORY_ERROR;
SC_log_error(func, "", stmt); SC_log_error(func, "", stmt);
return SQL_ERROR; return SQL_ERROR;
} }
SC_set_Result(stmt, res);
/* the binding structure for a statement is not set up until */ /* the binding structure for a statement is not set up until */
...@@ -3016,23 +3048,23 @@ PGAPI_ForeignKeys( ...@@ -3016,23 +3048,23 @@ PGAPI_ForeignKeys(
extend_bindings(stmt, result_cols); extend_bindings(stmt, result_cols);
/* set the field names */ /* set the field names */
QR_set_num_fields(stmt->result, result_cols); QR_set_num_fields(res, result_cols);
QR_set_field_info(stmt->result, 0, "PKTABLE_QUALIFIER", PG_TYPE_TEXT, MAX_INFO_STRING); QR_set_field_info(res, 0, "PKTABLE_QUALIFIER", PG_TYPE_TEXT, MAX_INFO_STRING);
QR_set_field_info(stmt->result, 1, "PKTABLE_OWNER", PG_TYPE_TEXT, MAX_INFO_STRING); QR_set_field_info(res, 1, "PKTABLE_OWNER", PG_TYPE_TEXT, MAX_INFO_STRING);
QR_set_field_info(stmt->result, 2, "PKTABLE_NAME", PG_TYPE_TEXT, MAX_INFO_STRING); QR_set_field_info(res, 2, "PKTABLE_NAME", PG_TYPE_TEXT, MAX_INFO_STRING);
QR_set_field_info(stmt->result, 3, "PKCOLUMN_NAME", PG_TYPE_TEXT, MAX_INFO_STRING); QR_set_field_info(res, 3, "PKCOLUMN_NAME", PG_TYPE_TEXT, MAX_INFO_STRING);
QR_set_field_info(stmt->result, 4, "FKTABLE_QUALIFIER", PG_TYPE_TEXT, MAX_INFO_STRING); QR_set_field_info(res, 4, "FKTABLE_QUALIFIER", PG_TYPE_TEXT, MAX_INFO_STRING);
QR_set_field_info(stmt->result, 5, "FKTABLE_OWNER", PG_TYPE_TEXT, MAX_INFO_STRING); QR_set_field_info(res, 5, "FKTABLE_OWNER", PG_TYPE_TEXT, MAX_INFO_STRING);
QR_set_field_info(stmt->result, 6, "FKTABLE_NAME", PG_TYPE_TEXT, MAX_INFO_STRING); QR_set_field_info(res, 6, "FKTABLE_NAME", PG_TYPE_TEXT, MAX_INFO_STRING);
QR_set_field_info(stmt->result, 7, "FKCOLUMN_NAME", PG_TYPE_TEXT, MAX_INFO_STRING); QR_set_field_info(res, 7, "FKCOLUMN_NAME", PG_TYPE_TEXT, MAX_INFO_STRING);
QR_set_field_info(stmt->result, 8, "KEY_SEQ", PG_TYPE_INT2, 2); QR_set_field_info(res, 8, "KEY_SEQ", PG_TYPE_INT2, 2);
QR_set_field_info(stmt->result, 9, "UPDATE_RULE", PG_TYPE_INT2, 2); QR_set_field_info(res, 9, "UPDATE_RULE", PG_TYPE_INT2, 2);
QR_set_field_info(stmt->result, 10, "DELETE_RULE", PG_TYPE_INT2, 2); QR_set_field_info(res, 10, "DELETE_RULE", PG_TYPE_INT2, 2);
QR_set_field_info(stmt->result, 11, "FK_NAME", PG_TYPE_TEXT, MAX_INFO_STRING); QR_set_field_info(res, 11, "FK_NAME", PG_TYPE_TEXT, MAX_INFO_STRING);
QR_set_field_info(stmt->result, 12, "PK_NAME", PG_TYPE_TEXT, MAX_INFO_STRING); QR_set_field_info(res, 12, "PK_NAME", PG_TYPE_TEXT, MAX_INFO_STRING);
QR_set_field_info(stmt->result, 13, "TRIGGER_NAME", PG_TYPE_TEXT, MAX_INFO_STRING); QR_set_field_info(res, 13, "TRIGGER_NAME", PG_TYPE_TEXT, MAX_INFO_STRING);
#if (ODBCVER >= 0x0300) #if (ODBCVER >= 0x0300)
QR_set_field_info(stmt->result, 14, "DEFERRABILITY", PG_TYPE_INT2, 2); QR_set_field_info(res, 14, "DEFERRABILITY", PG_TYPE_INT2, 2);
#endif /* ODBCVER >= 0x0300 */ #endif /* ODBCVER >= 0x0300 */
/* /*
...@@ -3369,7 +3401,7 @@ PGAPI_ForeignKeys( ...@@ -3369,7 +3401,7 @@ PGAPI_ForeignKeys(
set_tuplefield_int2(&row->tuple[14], defer_type); set_tuplefield_int2(&row->tuple[14], defer_type);
#endif /* ODBCVER >= 0x0300 */ #endif /* ODBCVER >= 0x0300 */
QR_add_tuple(stmt->result, row); QR_add_tuple(res, row);
#ifdef MULTIBYTE #ifdef MULTIBYTE
if (fkey_alloced) if (fkey_alloced)
free(fkey_text); free(fkey_text);
...@@ -3623,7 +3655,7 @@ PGAPI_ForeignKeys( ...@@ -3623,7 +3655,7 @@ PGAPI_ForeignKeys(
set_tuplefield_int2(&row->tuple[14], defer_type); set_tuplefield_int2(&row->tuple[14], defer_type);
#endif /* ODBCVER >= 0x0300 */ #endif /* ODBCVER >= 0x0300 */
QR_add_tuple(stmt->result, row); QR_add_tuple(res, row);
#ifdef MULTIBYTE #ifdef MULTIBYTE
if (pkey_alloced) if (pkey_alloced)
free(pkey_text); free(pkey_text);
...@@ -3687,10 +3719,13 @@ PGAPI_ProcedureColumns( ...@@ -3687,10 +3719,13 @@ PGAPI_ProcedureColumns(
SWORD cbColumnName) SWORD cbColumnName)
{ {
static char *func = "PGAPI_ProcedureColumns"; static char *func = "PGAPI_ProcedureColumns";
StatementClass *stmt = (StatementClass *) hstmt;
mylog("%s: entering...\n", func); mylog("%s: entering...\n", func);
SC_log_error(func, "Function not implemented", (StatementClass *) hstmt); stmt->errornumber = STMT_NOT_IMPLEMENTED_ERROR;
stmt->errormsg = "not implemented";
SC_log_error(func, "Function not implemented", stmt);
return SQL_ERROR; return SQL_ERROR;
} }
...@@ -3717,7 +3752,7 @@ PGAPI_Procedures( ...@@ -3717,7 +3752,7 @@ PGAPI_Procedures(
{ {
stmt->errornumber = STMT_NOT_IMPLEMENTED_ERROR; stmt->errornumber = STMT_NOT_IMPLEMENTED_ERROR;
stmt->errormsg = "Version is too old"; stmt->errormsg = "Version is too old";
SC_log_error(func, "Function not implemented", (StatementClass *) hstmt); SC_log_error(func, "Function not implemented", stmt);
return SQL_ERROR; return SQL_ERROR;
} }
if (!SC_recycle_statement(stmt)) if (!SC_recycle_statement(stmt))
...@@ -3733,16 +3768,13 @@ PGAPI_Procedures( ...@@ -3733,16 +3768,13 @@ PGAPI_Procedures(
" case when prorettype = 0 then 1::int2 else 2::int2 end as " "PROCEDURE_TYPE" " from pg_proc"); " case when prorettype = 0 then 1::int2 else 2::int2 end as " "PROCEDURE_TYPE" " from pg_proc");
my_strcat(proc_query, " where proname like '%.*s'", szProcName, cbProcName); my_strcat(proc_query, " where proname like '%.*s'", szProcName, cbProcName);
res = CC_send_query(conn, proc_query, NULL); if (res = CC_send_query(conn, proc_query, NULL, TRUE), !res)
if (!res || QR_aborted(res))
{ {
if (res)
QR_Destructor(res);
stmt->errornumber = STMT_EXEC_ERROR; stmt->errornumber = STMT_EXEC_ERROR;
stmt->errormsg = "PGAPI_Procedures query error"; stmt->errormsg = "PGAPI_Procedures query error";
return SQL_ERROR; return SQL_ERROR;
} }
stmt->result = res; SC_set_Result(stmt, res);
/* /*
* also, things need to think that this statement is finished so the * also, things need to think that this statement is finished so the
...@@ -3759,6 +3791,52 @@ PGAPI_Procedures( ...@@ -3759,6 +3791,52 @@ PGAPI_Procedures(
} }
#define ACLMAX 8
#define ALL_PRIVILIGES "arwdRxt"
static int
usracl_auth(char *usracl, const char *auth)
{
int i, j, addcnt = 0;
for (i = 0; auth[i]; i++)
{
for (j = 0; j < ACLMAX; j++)
{
if (usracl[j] == auth[i])
break;
else if (!usracl[j])
{
usracl[j]= auth[i];
addcnt++;
break;
}
}
}
return addcnt;
}
static void
useracl_upd(char (*useracl)[ACLMAX], QResultClass *allures, const char *user, const char *auth)
{
int usercount = QR_get_num_tuples(allures), i, addcnt = 0;
mylog("user=%s auth=%s\n", user, auth);
if (user[0])
for (i = 0; i < usercount; i++)
{
if (strcmp(QR_get_value_backend_row(allures, i, 0), user) == 0)
{
addcnt += usracl_auth(useracl[i], auth);
break;
}
}
else
for (i = 0; i < usercount; i++)
{
addcnt += usracl_auth(useracl[i], auth);
}
mylog("addcnt=%d\n", addcnt);
}
RETCODE SQL_API RETCODE SQL_API
PGAPI_TablePrivileges( PGAPI_TablePrivileges(
HSTMT hstmt, HSTMT hstmt,
...@@ -3767,13 +3845,24 @@ PGAPI_TablePrivileges( ...@@ -3767,13 +3845,24 @@ PGAPI_TablePrivileges(
UCHAR FAR * szTableOwner, UCHAR FAR * szTableOwner,
SWORD cbTableOwner, SWORD cbTableOwner,
UCHAR FAR * szTableName, UCHAR FAR * szTableName,
SWORD cbTableName) SWORD cbTableName,
UWORD flag)
{ {
StatementClass *stmt = (StatementClass *) hstmt; StatementClass *stmt = (StatementClass *) hstmt;
static char *func = "PGAPI_TablePrivileges"; static char *func = "PGAPI_TablePrivileges";
ConnectionClass *conn = SC_get_conn(stmt);
Int2 result_cols; Int2 result_cols;
char proc_query[INFO_INQUIRY_LEN];
QResultClass *res, *allures = NULL;
TupleNode *row;
int tablecount, usercount, i, j, k;
BOOL grpauth, sys, su;
char (*useracl)[ACLMAX], *acl, *user, *delim, *auth;
char *reln, *owner, *priv;
mylog("%s: entering...\n", func); mylog("%s: entering...\n", func);
if (!SC_recycle_statement(stmt))
return SQL_ERROR;
/* /*
* a statement is actually executed, so we'll have to do this * a statement is actually executed, so we'll have to do this
...@@ -3784,16 +3873,187 @@ PGAPI_TablePrivileges( ...@@ -3784,16 +3873,187 @@ PGAPI_TablePrivileges(
/* set the field names */ /* set the field names */
stmt->manual_result = TRUE; stmt->manual_result = TRUE;
stmt->result = QR_Constructor(); res = QR_Constructor();
QR_set_num_fields(stmt->result, result_cols); SC_set_Result(stmt, res);
QR_set_field_info(stmt->result, 0, "TABLE_CAT", PG_TYPE_TEXT, MAX_INFO_STRING); QR_set_num_fields(res, result_cols);
QR_set_field_info(stmt->result, 1, "TABLE_SCHEM", PG_TYPE_TEXT, MAX_INFO_STRING); QR_set_field_info(res, 0, "TABLE_CAT", PG_TYPE_TEXT, MAX_INFO_STRING);
QR_set_field_info(stmt->result, 2, "TABLE_NAME", PG_TYPE_TEXT, MAX_INFO_STRING); QR_set_field_info(res, 1, "TABLE_SCHEM", PG_TYPE_TEXT, MAX_INFO_STRING);
QR_set_field_info(stmt->result, 3, "GRANTOR", PG_TYPE_TEXT, MAX_INFO_STRING); QR_set_field_info(res, 2, "TABLE_NAME", PG_TYPE_TEXT, MAX_INFO_STRING);
QR_set_field_info(stmt->result, 4, "GRANTEE", PG_TYPE_TEXT, MAX_INFO_STRING); QR_set_field_info(res, 3, "GRANTOR", PG_TYPE_TEXT, MAX_INFO_STRING);
QR_set_field_info(stmt->result, 5, "PRIVILEGE", PG_TYPE_TEXT, MAX_INFO_STRING); QR_set_field_info(res, 4, "GRANTEE", PG_TYPE_TEXT, MAX_INFO_STRING);
QR_set_field_info(stmt->result, 6, "IS_GRANTABLE", PG_TYPE_TEXT, MAX_INFO_STRING); QR_set_field_info(res, 5, "PRIVILEGE", PG_TYPE_TEXT, MAX_INFO_STRING);
QR_set_field_info(res, 6, "IS_GRANTABLE", PG_TYPE_TEXT, MAX_INFO_STRING);
SC_log_error(func, "Function not implemented", (StatementClass *) hstmt);
return SQL_ERROR; /*
* 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;
stmt->current_col = -1;
strncpy_null(proc_query, "select relname, usename, relacl from pg_class , pg_user where", sizeof(proc_query));
if ((flag & PODBC_NOT_SEARCH_PATTERN) != 0)
my_strcat(proc_query, " relname = '%.*s' and", szTableName, cbTableName);
else
{
char esc_table_name[MAX_TABLE_LEN * 2];
int escTbnamelen;
escTbnamelen = reallyEscapeCatalogEscapes(szTableName, cbTableName, esc_table_name, sizeof(esc_table_name), conn->ccsc);
my_strcat(proc_query, " relname like '%.*s' and", esc_table_name, escTbnamelen);
}
strcat(proc_query, " pg_user.usesysid = relowner");
if (res = CC_send_query(conn, proc_query, NULL, TRUE), !res)
{
stmt->errornumber = STMT_EXEC_ERROR;
stmt->errormsg = "PGAPI_TablePrivileges query error";
return SQL_ERROR;
}
strncpy_null(proc_query, "select usename, usesysid, usesuper from pg_user", sizeof(proc_query));
tablecount = QR_get_num_tuples(res);
if (allures = CC_send_query(conn, proc_query, NULL, TRUE), !allures)
{
QR_Destructor(res);
stmt->errornumber = STMT_EXEC_ERROR;
stmt->errormsg = "PGAPI_TablePrivileges query error";
return SQL_ERROR;
}
usercount = QR_get_num_tuples(allures);
useracl = (char (*)[ACLMAX]) malloc(usercount * sizeof(char [ACLMAX]));
for (i = 0; i < tablecount; i++)
{
memset(useracl, 0, usercount * sizeof(char[ACLMAX]));
acl = (char *) QR_get_value_backend_row(res, i, 2);
if (acl && acl[0] == '{')
user = acl + 1;
else
user = NULL;
for (; user && *user;)
{
grpauth = FALSE;
if (user[0] == '"' && strncmp(user + 1, "group ", 6) == 0)
{
user += 7;
grpauth = TRUE;
}
if (delim = strchr(user, '='), !delim)
break;
*delim = '\0';
auth = delim + 1;
if (grpauth)
{
if (delim = strchr(auth, '"'), delim)
{
*delim = '\0';
delim++;
}
}
else if (delim = strchr(auth, ','), delim)
*delim = '\0';
else if (delim = strchr(auth, '}'), delim)
*delim = '\0';
if (grpauth) /* handle group privilege */
{
QResultClass *gres;
int i;
char *grolist, *uid, *delm;
snprintf(proc_query, sizeof(proc_query) - 1, "select grolist from pg_group where groname = '%s'", user);
if (gres = CC_send_query(conn, proc_query, NULL, TRUE))
{
grolist = QR_get_value_backend_row(gres, 0, 0);
if (grolist && grolist[0] == '{')
{
for (uid = grolist + 1; *uid;)
{
if (delm = strchr(uid, ','), delm)
*delm = '\0';
else if (delm = strchr(uid, '}'), delm)
*delm = '\0';
mylog("guid=%s\n", uid);
for (i = 0; i < usercount; i++)
{
if (strcmp(QR_get_value_backend_row(allures, i, 1), uid) == 0)
useracl_upd(useracl, allures, QR_get_value_backend_row(allures, i, 0), auth);
}
uid = delm + 1;
}
}
QR_Destructor(gres);
}
}
else
useracl_upd(useracl, allures, user, auth);
if (!delim)
break;
user = delim + 1;
}
reln = QR_get_value_backend_row(res, i, 0);
owner = QR_get_value_backend_row(res, i, 1);
/* The owner has all privileges */
useracl_upd(useracl, allures, owner, ALL_PRIVILIGES);
for (j = 0; j < usercount; j++)
{
user = QR_get_value_backend_row(allures, j, 0);
su = (strcmp(QR_get_value_backend_row(allures, j, 2), "t") == 0);
sys = (strcmp(user, owner) == 0);
/* Super user has all privileges */
if (su)
useracl_upd(useracl, allures, user, ALL_PRIVILIGES);
for (k = 0; k < ACLMAX; k++)
{
if (!useracl[j][k])
break;
switch (useracl[j][k])
{
case 'R': /* rule */
case 't': /* trigger */
continue;
}
row = (TupleNode *) malloc(sizeof(TupleNode) + (7 - 1) *sizeof(TupleField));
set_tuplefield_string(&row->tuple[0], "");
set_tuplefield_string(&row->tuple[1], "");
set_tuplefield_string(&row->tuple[2], reln);
if (su || sys)
set_tuplefield_string(&row->tuple[3], "_SYSTEM");
else
set_tuplefield_string(&row->tuple[3], owner);
mylog("user=%s\n", user);
set_tuplefield_string(&row->tuple[4], user);
switch (useracl[j][k])
{
case 'a':
priv = "INSERT";
break;
case 'r':
priv = "SELECT";
break;
case 'w':
priv = "UPDATE";
break;
case 'd':
priv = "DELETE";
break;
case 'x':
priv = "REFERENCES";
break;
default:
priv = "";
}
set_tuplefield_string(&row->tuple[5], priv);
/* The owner and the super user are grantable */
if (sys || su)
set_tuplefield_string(&row->tuple[6], "YES");
else
set_tuplefield_string(&row->tuple[6], "NO");
QR_add_tuple(SC_get_Result(stmt), row);
}
}
}
free(useracl);
QR_Destructor(res);
QR_Destructor(allures);
return SQL_SUCCESS;
} }
...@@ -19,6 +19,7 @@ PGAPI_GetInfo30(HDBC hdbc, UWORD fInfoType, PTR rgbInfoValue, ...@@ -19,6 +19,7 @@ PGAPI_GetInfo30(HDBC hdbc, UWORD fInfoType, PTR rgbInfoValue,
{ {
static char *func = "PGAPI_GetInfo30"; static char *func = "PGAPI_GetInfo30";
ConnectionClass *conn = (ConnectionClass *) hdbc; ConnectionClass *conn = (ConnectionClass *) hdbc;
ConnInfo *ci = &(conn->connInfo);
char *p = NULL; char *p = NULL;
int len = 0, int len = 0,
value = 0; value = 0;
...@@ -50,35 +51,60 @@ PGAPI_GetInfo30(HDBC hdbc, UWORD fInfoType, PTR rgbInfoValue, ...@@ -50,35 +51,60 @@ PGAPI_GetInfo30(HDBC hdbc, UWORD fInfoType, PTR rgbInfoValue,
| SQL_CA1_RELATIVE | SQL_CA1_BOOKMARK | SQL_CA1_RELATIVE | SQL_CA1_BOOKMARK
| SQL_CA1_LOCK_NO_CHANGE | SQL_CA1_POS_POSITION | SQL_CA1_LOCK_NO_CHANGE | SQL_CA1_POS_POSITION
| SQL_CA1_POS_UPDATE | SQL_CA1_POS_DELETE | SQL_CA1_POS_UPDATE | SQL_CA1_POS_DELETE
| SQL_CA1_POS_REFRESH | SQL_CA1_POS_REFRESH;
/* | SQL_CA1_BULK_ADD if (ci->drivers.lie)
value |=
( SQL_CA1_BULK_ADD
| SQL_CA1_BULK_UPDATE_BY_BOOKMARK | SQL_CA1_BULK_UPDATE_BY_BOOKMARK
| SQL_CA1_BULK_DELETE_BY_BOOKMARK | SQL_CA1_BULK_DELETE_BY_BOOKMARK
| SQL_CA1_BULK_FETCH_BY_BOOKMARK */ | SQL_CA1_BULK_FETCH_BY_BOOKMARK
;
| SQL_CA1_LOCK_EXCLUSIVE
| SQL_CA1_LOCK_UNLOCK
| SQL_CA1_POSITIONED_UPDATE
| SQL_CA1_POSITIONED_DELETE
| SQL_CA1_SELECT_FOR_UPDATE
);
break; break;
case SQL_KEYSET_CURSOR_ATTRIBUTES2: case SQL_KEYSET_CURSOR_ATTRIBUTES2:
len = 4; len = 4;
value = SQL_CA2_OPT_ROWVER_CONCURRENCY | value = SQL_CA2_OPT_ROWVER_CONCURRENCY
SQL_CA2_SENSITIVITY_ADDITIONS | | SQL_CA2_SENSITIVITY_ADDITIONS
SQL_CA2_SENSITIVITY_DELETIONS | | SQL_CA2_SENSITIVITY_DELETIONS
SQL_CA2_SENSITIVITY_UPDATES; | SQL_CA2_SENSITIVITY_UPDATES;
if (ci->drivers.lie)
value |=
( SQL_CA2_READ_ONLY_CONCURRENCY
| SQL_CA2_LOCK_CONCURRENCY
| SQL_CA2_OPT_VALUES_CONCURRENCY
| SQL_CA2_MAX_ROWS_SELECT
| SQL_CA2_MAX_ROWS_INSERT
| SQL_CA2_MAX_ROWS_DELETE
| SQL_CA2_MAX_ROWS_UPDATE
| SQL_CA2_MAX_ROWS_CATALOG
| SQL_CA2_MAX_ROWS_AFFECTS_ALL
| SQL_CA2_CRC_EXACT
| SQL_CA2_CRC_APPROXIMATE
| SQL_CA2_SIMULATE_NON_UNIQUE
| SQL_CA2_SIMULATE_TRY_UNIQUE
| SQL_CA2_SIMULATE_UNIQUE
);
break; break;
case SQL_STATIC_CURSOR_ATTRIBUTES1: case SQL_STATIC_CURSOR_ATTRIBUTES1:
len = 4; len = 4;
value = SQL_CA1_NEXT | SQL_CA1_ABSOLUTE | value = SQL_CA1_NEXT | SQL_CA1_ABSOLUTE
SQL_CA1_RELATIVE | SQL_CA1_BOOKMARK | | SQL_CA1_RELATIVE | SQL_CA1_BOOKMARK
SQL_CA1_LOCK_NO_CHANGE | SQL_CA1_POS_POSITION | | SQL_CA1_LOCK_NO_CHANGE | SQL_CA1_POS_POSITION
SQL_CA1_POS_UPDATE | SQL_CA1_POS_DELETE | | SQL_CA1_POS_UPDATE | SQL_CA1_POS_DELETE
SQL_CA1_POS_REFRESH; | SQL_CA1_POS_REFRESH;
break; break;
case SQL_STATIC_CURSOR_ATTRIBUTES2: case SQL_STATIC_CURSOR_ATTRIBUTES2:
len = 4; len = 4;
value = SQL_CA2_OPT_ROWVER_CONCURRENCY | value = SQL_CA2_OPT_ROWVER_CONCURRENCY
SQL_CA2_SENSITIVITY_ADDITIONS | | SQL_CA2_SENSITIVITY_ADDITIONS
SQL_CA2_SENSITIVITY_DELETIONS | | SQL_CA2_SENSITIVITY_DELETIONS
SQL_CA2_SENSITIVITY_UPDATES; | SQL_CA2_SENSITIVITY_UPDATES;
break; break;
case SQL_ODBC_INTERFACE_CONFORMANCE: case SQL_ODBC_INTERFACE_CONFORMANCE:
...@@ -103,11 +129,11 @@ PGAPI_GetInfo30(HDBC hdbc, UWORD fInfoType, PTR rgbInfoValue, ...@@ -103,11 +129,11 @@ PGAPI_GetInfo30(HDBC hdbc, UWORD fInfoType, PTR rgbInfoValue,
break; break;
case SQL_BATCH_ROW_COUNT: case SQL_BATCH_ROW_COUNT:
len = 4; len = 4;
value = SQL_BRC_ROLLED_UP | SQL_BRC_EXPLICIT; value = SQL_BRC_EXPLICIT;
break; break;
case SQL_BATCH_SUPPORT: case SQL_BATCH_SUPPORT:
len = 4; len = 4;
value = SQL_BS_ROW_COUNT_EXPLICIT; value = SQL_BS_SELECT_EXPLICIT | SQL_BS_ROW_COUNT_EXPLICIT;
break; break;
case SQL_CATALOG_NAME: case SQL_CATALOG_NAME:
len = 0; len = 0;
...@@ -194,7 +220,7 @@ PGAPI_GetInfo30(HDBC hdbc, UWORD fInfoType, PTR rgbInfoValue, ...@@ -194,7 +220,7 @@ PGAPI_GetInfo30(HDBC hdbc, UWORD fInfoType, PTR rgbInfoValue,
len = 4; len = 4;
value = SQL_DT_DROP_TABLE; value = SQL_DT_DROP_TABLE;
if (PG_VERSION_GT(conn, 7.2)) /* hopefully */ if (PG_VERSION_GT(conn, 7.2)) /* hopefully */
value |= SQL_DT_RESTRICT | SQL_DT_CASCADE; value |= (SQL_DT_RESTRICT | SQL_DT_CASCADE);
break; break;
case SQL_DROP_TRANSLATION: case SQL_DROP_TRANSLATION:
len = 4; len = 4;
...@@ -204,7 +230,7 @@ PGAPI_GetInfo30(HDBC hdbc, UWORD fInfoType, PTR rgbInfoValue, ...@@ -204,7 +230,7 @@ PGAPI_GetInfo30(HDBC hdbc, UWORD fInfoType, PTR rgbInfoValue,
len = 4; len = 4;
value = SQL_DV_DROP_VIEW; value = SQL_DV_DROP_VIEW;
if (PG_VERSION_GT(conn, 7.2)) /* hopefully */ if (PG_VERSION_GT(conn, 7.2)) /* hopefully */
value |= SQL_DV_RESTRICT | SQL_DV_CASCADE; value |= (SQL_DV_RESTRICT | SQL_DV_CASCADE);
break; break;
case SQL_INDEX_KEYWORDS: case SQL_INDEX_KEYWORDS:
len = 4; len = 4;
...@@ -227,11 +253,11 @@ PGAPI_GetInfo30(HDBC hdbc, UWORD fInfoType, PTR rgbInfoValue, ...@@ -227,11 +253,11 @@ PGAPI_GetInfo30(HDBC hdbc, UWORD fInfoType, PTR rgbInfoValue,
break; break;
case SQL_PARAM_ARRAY_ROW_COUNTS: case SQL_PARAM_ARRAY_ROW_COUNTS:
len = 4; len = 4;
value = SQL_PARC_NO_BATCH; value = SQL_PARC_BATCH;
break; break;
case SQL_PARAM_ARRAY_SELECTS: case SQL_PARAM_ARRAY_SELECTS:
len = 4; len = 4;
value = SQL_PAS_NO_SELECT; value = SQL_PAS_BATCH;
break; break;
case SQL_SQL_CONFORMANCE: case SQL_SQL_CONFORMANCE:
len = 4; len = 4;
...@@ -316,6 +342,7 @@ PGAPI_GetInfo30(HDBC hdbc, UWORD fInfoType, PTR rgbInfoValue, ...@@ -316,6 +342,7 @@ PGAPI_GetInfo30(HDBC hdbc, UWORD fInfoType, PTR rgbInfoValue,
return SQL_ERROR; return SQL_ERROR;
} }
result = SQL_SUCCESS; result = SQL_SUCCESS;
mylog("%s: p='%s', len=%d, value=%d, cbMax=%d\n", func, p ? p : "<NULL>", len, value, cbInfoValueMax);
if (p) if (p)
{ {
/* char/binary data */ /* char/binary data */
...@@ -323,6 +350,14 @@ PGAPI_GetInfo30(HDBC hdbc, UWORD fInfoType, PTR rgbInfoValue, ...@@ -323,6 +350,14 @@ PGAPI_GetInfo30(HDBC hdbc, UWORD fInfoType, PTR rgbInfoValue,
if (rgbInfoValue) if (rgbInfoValue)
{ {
#ifdef UNICODE_SUPPORT
if (conn->unicode)
{
len = utf8_to_ucs2(p, len, (SQLWCHAR *) rgbInfoValue, cbInfoValueMax / 2);
len *= 2;
}
else
#endif /* UNICODE_SUPPORT */
strncpy_null((char *) rgbInfoValue, p, (size_t) cbInfoValueMax); strncpy_null((char *) rgbInfoValue, p, (size_t) cbInfoValueMax);
if (len >= cbInfoValueMax) if (len >= cbInfoValueMax)
......
...@@ -15,7 +15,6 @@ ...@@ -15,7 +15,6 @@
#include "psqlodbc.h" #include "psqlodbc.h"
#include <stdio.h> #include <stdio.h>
#include <stdlib.h>
#include <stdarg.h> #include <stdarg.h>
#include <string.h> #include <string.h>
......
...@@ -38,6 +38,7 @@ ...@@ -38,6 +38,7 @@
#define MYLOGDIR "c:" #define MYLOGDIR "c:"
#endif #endif
extern void mylog(char *fmt,...); extern void mylog(char *fmt,...);
#define inolog mylog /* for really temporary debug */
#else #else
#ifndef WIN32 #ifndef WIN32
......
...@@ -16,13 +16,6 @@ ...@@ -16,13 +16,6 @@
#include <stdio.h> #include <stdio.h>
#include <stdlib.h> #include <stdlib.h>
int PG_CCST; /* Client Charcter Status */
int PG_SCSC; /* Server Charcter Set (code) */
int PG_CCSC; /* Client Charcter Set (code) */
unsigned char *PG_SCSS; /* Server Charcter Set (string) */
unsigned char *PG_CCSS; /* Client Charcter Set (string) */
pg_CS CS_Table[] = pg_CS CS_Table[] =
{ {
{ "SQL_ASCII", SQL_ASCII }, { "SQL_ASCII", SQL_ASCII },
...@@ -78,19 +71,29 @@ pg_ismb(int characterset_code) ...@@ -78,19 +71,29 @@ pg_ismb(int characterset_code)
int int
pg_CS_code(const unsigned char *characterset_string) pg_CS_code(const unsigned char *characterset_string)
{ {
int i = 0, c; int i = 0, c = -1;
unsigned len = 0;
for(i = 0; CS_Table[i].code != OTHER; i++) for(i = 0; CS_Table[i].code != OTHER; i++)
{ {
if (strstr(characterset_string,CS_Table[i].name)) if (strstr(characterset_string,CS_Table[i].name))
c = CS_Table[i].code; {
if(strlen(CS_Table[i].name) >= len)
{
len = strlen(CS_Table[i].name);
c = CS_Table[i].code;
}
}
} }
if (c < 0)
c = i;
return (c); return (c);
} }
unsigned char * unsigned char *
pg_CS_name(const int characterset_code) pg_CS_name(int characterset_code)
{ {
int i = 0; int i;
for (i = 0; CS_Table[i].code != OTHER; i++) for (i = 0; CS_Table[i].code != OTHER; i++)
{ {
if (CS_Table[i].code == characterset_code) if (CS_Table[i].code == characterset_code)
...@@ -242,7 +245,7 @@ pg_CS_stat(int stat,unsigned int character,int characterset_code) ...@@ -242,7 +245,7 @@ pg_CS_stat(int stat,unsigned int character,int characterset_code)
unsigned char * unsigned char *
pg_mbschr(const unsigned char *string, unsigned int character) pg_mbschr(int csc, const unsigned char *string, unsigned int character)
{ {
int mb_st = 0; int mb_st = 0;
unsigned char *s; unsigned char *s;
...@@ -250,7 +253,7 @@ pg_mbschr(const unsigned char *string, unsigned int character) ...@@ -250,7 +253,7 @@ pg_mbschr(const unsigned char *string, unsigned int character)
for(;;) for(;;)
{ {
mb_st = pg_CS_stat(mb_st, (unsigned char) *s,PG_CCSC); mb_st = pg_CS_stat(mb_st, (unsigned char) *s, csc);
if (mb_st == 0 && (*s == character || *s == 0)) if (mb_st == 0 && (*s == character || *s == 0))
break; break;
else else
...@@ -260,13 +263,13 @@ pg_mbschr(const unsigned char *string, unsigned int character) ...@@ -260,13 +263,13 @@ pg_mbschr(const unsigned char *string, unsigned int character)
} }
int int
pg_mbslen(const unsigned char *string) pg_mbslen(int csc, const unsigned char *string)
{ {
unsigned char *s; unsigned char *s;
int len, cs_stat; int len, cs_stat;
for (len = 0, cs_stat = 0, s = (unsigned char *) string; *s != 0; s++) for (len = 0, cs_stat = 0, s = (unsigned char *) string; *s != 0; s++)
{ {
cs_stat = pg_CS_stat(cs_stat,(unsigned int) *s, PG_CCSC); cs_stat = pg_CS_stat(cs_stat,(unsigned int) *s, csc);
if (cs_stat < 2) if (cs_stat < 2)
len++; len++;
} }
...@@ -274,12 +277,12 @@ pg_mbslen(const unsigned char *string) ...@@ -274,12 +277,12 @@ pg_mbslen(const unsigned char *string)
} }
unsigned char * unsigned char *
pg_mbsinc(const unsigned char *current ) pg_mbsinc(int csc, const unsigned char *current )
{ {
int mb_stat = 0; int mb_stat = 0;
if (*current != 0) if (*current != 0)
{ {
mb_stat = (int) pg_CS_stat(mb_stat, *current, PG_CCSC); mb_stat = (int) pg_CS_stat(mb_stat, *current, csc);
if (mb_stat == 0) if (mb_stat == 0)
mb_stat = 1; mb_stat = 1;
return ((unsigned char *) current + mb_stat); return ((unsigned char *) current + mb_stat);
...@@ -288,43 +291,100 @@ pg_mbsinc(const unsigned char *current ) ...@@ -288,43 +291,100 @@ pg_mbsinc(const unsigned char *current )
return NULL; return NULL;
} }
void static char *
CC_lookup_characterset(ConnectionClass *self) CC_lookup_cs_new(ConnectionClass *self)
{ {
char *encstr = NULL;
QResultClass *res;
res = CC_send_query(self, "select pg_client_encoding()", NULL, TRUE);
if (res)
{
char *enc = QR_get_value_backend_row(res, 0, 0);
if (enc)
encstr = strdup(enc);
QR_Destructor(res);
}
return encstr;
}
static char *
CC_lookup_cs_old(ConnectionClass *self)
{
char *encstr = NULL;
HSTMT hstmt; HSTMT hstmt;
StatementClass *stmt;
RETCODE result; RETCODE result;
static char *func = "CC_lookup_characterset";
mylog("%s: entering...\n", func);
PG_SCSS = malloc(MAX_CHARACTERSET_NAME);
PG_CCSS = malloc(MAX_CHARACTERSET_NAME);
result = PGAPI_AllocStmt(self, &hstmt); result = PGAPI_AllocStmt(self, &hstmt);
if ((result != SQL_SUCCESS) && (result != SQL_SUCCESS_WITH_INFO)) if ((result != SQL_SUCCESS) && (result != SQL_SUCCESS_WITH_INFO))
return; return encstr;
stmt = (StatementClass *) hstmt;
result = PGAPI_ExecDirect(hstmt, "Show Client_Encoding", SQL_NTS); result = PGAPI_ExecDirect(hstmt, "Show Client_Encoding", SQL_NTS);
if ((result != SQL_SUCCESS) && (result != SQL_SUCCESS_WITH_INFO)) if (result == SQL_SUCCESS_WITH_INFO)
{ {
PGAPI_FreeStmt(hstmt, SQL_DROP); char sqlState[8], errormsg[128], enc[32];
return;
if (PGAPI_Error(NULL, NULL, hstmt, sqlState, NULL, errormsg,
sizeof(errormsg), NULL) == SQL_SUCCESS &&
sscanf(errormsg, "%*s %*s %*s %*s %*s %s", enc) > 0)
encstr = strdup(enc);
} }
result = PGAPI_AllocStmt(self, &hstmt); PGAPI_FreeStmt(hstmt, SQL_DROP);
if ((result != SQL_SUCCESS) && (result != SQL_SUCCESS_WITH_INFO)) return encstr;
return; }
stmt = (StatementClass *) hstmt;
result = PGAPI_ExecDirect(hstmt, "Show Server_Encoding", SQL_NTS); void
if ((result != SQL_SUCCESS) && (result != SQL_SUCCESS_WITH_INFO)) CC_lookup_characterset(ConnectionClass *self)
{
char *encstr;
static char *func = "CC_lookup_characterset";
mylog("%s: entering...\n", func);
if (PG_VERSION_LT(self, 7.2))
encstr = CC_lookup_cs_old(self);
else
encstr = CC_lookup_cs_new(self);
if (self->client_encoding)
free(self->client_encoding);
if (encstr)
{
self->client_encoding = encstr;
self->ccsc = pg_CS_code(encstr);
qlog(" [ Client encoding = '%s' (code = %d) ]\n", self->client_encoding, self->ccsc);
if (stricmp(pg_CS_name(self->ccsc), encstr))
{
qlog(" Client encoding = '%s' and %s\n", self->client_encoding, pg_CS_name(self->ccsc));
self->errornumber = CONN_VALUE_OUT_OF_RANGE;
self->errormsg = "client encoding mismatch";
}
}
else
{ {
PGAPI_FreeStmt(hstmt, SQL_DROP); self->ccsc = SQL_ASCII;
return; self->client_encoding = NULL;
} }
}
strcpy(PG_SCSS , pg_CS_name(PG_SCSC = pg_CS_code(PG_SCSS))); void encoded_str_constr(encoded_str *encstr, int ccsc, const char *str)
strcpy(PG_CCSS , pg_CS_name(PG_CCSC = pg_CS_code(PG_CCSS))); {
encstr->ccsc = ccsc;
encstr->encstr = str;
encstr->pos = -1;
encstr->ccst = 0;
}
int encoded_nextchar(encoded_str *encstr)
{
int chr;
chr = encstr->encstr[++encstr->pos];
encstr->ccst = pg_CS_stat(encstr->ccst, (unsigned int) chr, encstr->ccsc);
return chr;
}
int encoded_byte_check(encoded_str *encstr, int abspos)
{
int chr;
qlog(" [ Server encoding = '%s' (code = %d), Client encoding = '%s' (code = %d) ]\n", PG_SCSS, PG_SCSC, PG_CCSS, PG_CCSC); chr = encstr->encstr[encstr->pos = abspos];
encstr->ccst = pg_CS_stat(encstr->ccst, (unsigned int) chr, encstr->ccsc);
return chr;
} }
...@@ -4,13 +4,14 @@ ...@@ -4,13 +4,14 @@
* *
*/ */
#include "psqlodbc.h" #include "psqlodbc.h"
#include "qresult.h"
/* PostgreSQL client encoding */ /* PostgreSQL client encoding */
#define SQL_ASCII 0 /* SQL/ASCII */ #define SQL_ASCII 0 /* SQL/ASCII */
#define EUC_JP 1 /* EUC for Japanese */ #define EUC_JP 1 /* EUC for Japanese */
#define EUC_CN 2 /* EUC for Chinese */ #define EUC_CN 2 /* EUC for Chinese */
#define EUC_KR 3 /* EUC for Korean */ #define EUC_KR 3 /* EUC for Korean */
#define EUC_TW 4 /* EUC for Taiwan */ #define EUC_TW 4 /* EUC for Taiwan */
#define JOHAB 5 #define JOHAB 5
#define UTF8 6 /* Unicode UTF-8 */ #define UTF8 6 /* Unicode UTF-8 */
#define MULE_INTERNAL 7 /* Mule internal code */ #define MULE_INTERNAL 7 /* Mule internal code */
...@@ -22,66 +23,67 @@ ...@@ -22,66 +23,67 @@
#define LATIN6 13 /* ISO-8859 Latin 6 */ #define LATIN6 13 /* ISO-8859 Latin 6 */
#define LATIN7 14 /* ISO-8859 Latin 7 */ #define LATIN7 14 /* ISO-8859 Latin 7 */
#define LATIN8 15 /* ISO-8859 Latin 8 */ #define LATIN8 15 /* ISO-8859 Latin 8 */
#define LATIN9 16 /* ISO-8859 Latin 9 */ #define LATIN9 16 /* ISO-8859 Latin 9 */
#define LATIN10 17 /* ISO-8859 Latin 10 */ #define LATIN10 17 /* ISO-8859 Latin 10 */
#define WIN1256 18 /* Arabic Windows */ #define WIN1256 18 /* Arabic Windows */
#define TCVN 19 /* Vietnamese Windows */ #define TCVN 19 /* Vietnamese Windows */
#define WIN874 20 /* Thai Windows */ #define WIN874 20 /* Thai Windows */
#define KOI8R 21 /* KOI8-R/U */ #define KOI8R 21 /* KOI8-R/U */
#define WIN1251 22 /* windows-1251 */ #define WIN1251 22 /* windows-1251 */
#define ALT 23 /* Alternativny Variant (MS-DOS CP866) */ #define ALT 23 /* Alternativny Variant (MS-DOS CP866) */
#define ISO_8859_5 24 /* ISO-8859-5 */ #define ISO_8859_5 24 /* ISO-8859-5 */
#define ISO_8859_6 25 /* ISO-8859-6 */ #define ISO_8859_6 25 /* ISO-8859-6 */
#define ISO_8859_7 26 /* ISO-8859-7 */ #define ISO_8859_7 26 /* ISO-8859-7 */
#define ISO_8859_8 27 /* ISO-8859-8 */ #define ISO_8859_8 27 /* ISO-8859-8 */
#define SJIS 28 /* Shift JIS */ #define SJIS 28 /* Shift JIS */
#define BIG5 29 /* Big5 */ #define BIG5 29 /* Big5 */
#define GBK 30 /* GBK */ #define GBK 30 /* GBK */
#define UHC 31 /* UHC */ #define UHC 31 /* UHC */
#define WIN1250 32 /* windows-1250 */ #define WIN1250 32 /* windows-1250 */
#define OTHER -1 #define OTHER -1
#define MAX_CHARACTERSET_NAME 24 #define MAX_CHARACTERSET_NAME 24
#define MAX_CHARACTER_LEN 6 #define MAX_CHARACTER_LEN 6
/* OLD Type */ /* OLD Type */
// extern int multibyte_client_encoding; /* Multibyte client encoding. */ // extern int multibyte_client_encoding; /* Multibyte client encoding. */
// extern int multibyte_status; /* Multibyte charcter status. */ // extern int multibyte_status; /* Multibyte charcter status. */
// //
// void multibyte_init(void); // void multibyte_init(void);
// unsigned char *check_client_encoding(unsigned char *sql_string); // unsigned char *check_client_encoding(unsigned char *sql_string);
// int multibyte_char_check(unsigned char s); // int multibyte_char_check(unsigned char s);
// unsigned char *multibyte_strchr(const unsigned char *string, unsigned int c); // unsigned char *multibyte_strchr(const unsigned char *string, unsigned int c);
/* New Type */ /* New Type */
extern int PG_CCST; /* Client Character StaTus */ extern void CC_lookup_characterset(ConnectionClass *self);
extern int PG_SCSC; /* Server Character Set (Code) */ extern int pg_CS_stat(int stat,unsigned int charcter,int characterset_code);
extern int PG_CCSC; /* Client Character Set (Code) */ extern int pg_CS_code(const unsigned char *stat_string);
extern unsigned char *PG_SCSS; /* Server Character Set (String) */ extern unsigned char *pg_CS_name(int code);
extern unsigned char *PG_CCSS; /* Client Character Set (String) */
typedef struct pg_CS
extern void CC_lookup_characterset(ConnectionClass *self); {
unsigned char *name;
extern int pg_CS_stat(int stat,unsigned int charcter,int characterset_code); int code;
extern int pg_CS_code(const unsigned char *stat_string); }pg_CS;
extern unsigned char *pg_CS_name(const int code); extern int pg_mbslen(int ccsc, const unsigned char *string);
extern unsigned char *pg_mbschr(int ccsc, const unsigned char *string, unsigned int character);
typedef struct pg_CS extern unsigned char *pg_mbsinc(int ccsc, const unsigned char *current );
{
unsigned char *name; /* Old Type Compatible */
int code; typedef struct
}pg_CS; {
extern pg_CS CS_Table[]; int ccsc;
const char *encstr;
extern int pg_mbslen(const unsigned char *string); int pos;
extern unsigned char *pg_mbschr(const unsigned char *string, unsigned int character); int ccst;
extern unsigned char *pg_mbsinc( const unsigned char *current ); } encoded_str;
#define ENCODE_STATUS(enc) ((enc).ccst)
/* Old Type Compatible */
#define multibyte_init() (PG_CCST = 0) void encoded_str_constr(encoded_str *encstr, int ccsc, const char *str);
#define multibyte_char_check(X) pg_CS_stat(PG_CCST, (unsigned int) X, PG_CCSC) #define make_encoded_str(encstr, conn, str) encoded_str_constr(encstr, conn->ccsc, str)
#define multibyte_strchr(X,Y) pg_mbschr(X,Y) extern int encoded_nextchar(encoded_str *encstr);
#define check_client_encoding(X) pg_CS_name(PG_CCSC = pg_CS_code(X)) extern int encoded_byte_check(encoded_str *encstr, int abspos);
#define check_client_encoding(X) pg_CS_name(pg_CS_code(X))
...@@ -174,7 +174,8 @@ SQLError(HENV EnvironmentHandle, ...@@ -174,7 +174,8 @@ SQLError(HENV EnvironmentHandle,
{ {
mylog("[SQLError]"); mylog("[SQLError]");
return PGAPI_Error(EnvironmentHandle, ConnectionHandle, StatementHandle, return PGAPI_Error(EnvironmentHandle, ConnectionHandle, StatementHandle,
Sqlstate, NativeError, MessageText, BufferLength, TextLength); Sqlstate, NativeError, MessageText, BufferLength,
TextLength);
} }
RETCODE SQL_API RETCODE SQL_API
...@@ -281,23 +282,31 @@ SQLGetInfo(HDBC ConnectionHandle, ...@@ -281,23 +282,31 @@ SQLGetInfo(HDBC ConnectionHandle,
SQLUSMALLINT InfoType, PTR InfoValue, SQLUSMALLINT InfoType, PTR InfoValue,
SQLSMALLINT BufferLength, SQLSMALLINT *StringLength) SQLSMALLINT BufferLength, SQLSMALLINT *StringLength)
{ {
#if (ODBCVER >= 0x0300)
RETCODE ret; RETCODE ret;
ConnectionClass *conn = (ConnectionClass *) ConnectionHandle;
CC_clear_error(conn);
#if (ODBCVER >= 0x0300)
mylog("[SQLGetInfo(30)]"); mylog("[SQLGetInfo(30)]");
if ((ret = PGAPI_GetInfo(ConnectionHandle, InfoType, InfoValue, if ((ret = PGAPI_GetInfo(ConnectionHandle, InfoType, InfoValue,
BufferLength, StringLength)) == SQL_ERROR) BufferLength, StringLength)) == SQL_ERROR)
{ {
if (((ConnectionClass *) ConnectionHandle)->driver_version >= 0x0300) if (((ConnectionClass *) ConnectionHandle)->driver_version >= 0x0300)
return PGAPI_GetInfo30(ConnectionHandle, InfoType, InfoValue, {
CC_clear_error(conn);
ret = PGAPI_GetInfo30(ConnectionHandle, InfoType, InfoValue,
BufferLength, StringLength); BufferLength, StringLength);
}
} }
return ret; if (SQL_ERROR == ret)
CC_log_error("SQLGetInfo30", "", conn);
#else #else
mylog("[SQLGetInfo]"); mylog("[SQLGetInfo]");
return PGAPI_GetInfo(ConnectionHandle, InfoType, InfoValue, if (ret = PGAPI_GetInfo(ConnectionHandle, InfoType, InfoValue,
BufferLength, StringLength); BufferLength, StringLength), SQL_ERROR == ret)
CC_log_error("PGAPI_GetInfo", "", conn);
#endif #endif
return ret;
} }
RETCODE SQL_API RETCODE SQL_API
...@@ -638,7 +647,7 @@ SQLTablePrivileges( ...@@ -638,7 +647,7 @@ SQLTablePrivileges(
{ {
mylog("[SQLTablePrivileges]"); mylog("[SQLTablePrivileges]");
return PGAPI_TablePrivileges(hstmt, szCatalogName, cbCatalogName, return PGAPI_TablePrivileges(hstmt, szCatalogName, cbCatalogName,
szSchemaName, cbSchemaName, szTableName, cbTableName); szSchemaName, cbSchemaName, szTableName, cbTableName, 0);
} }
RETCODE SQL_API RETCODE SQL_API
......
...@@ -25,22 +25,27 @@ RETCODE SQL_API SQLErrorW(HENV EnvironmentHandle, ...@@ -25,22 +25,27 @@ RETCODE SQL_API SQLErrorW(HENV EnvironmentHandle,
SQLSMALLINT *TextLength) SQLSMALLINT *TextLength)
{ {
RETCODE ret; RETCODE ret;
SWORD tlen; SWORD tlen, buflen;
char *qst = NULL, *mtxt = NULL; char *qst = NULL, *mtxt = NULL;
mylog("[SQLErrorW]"); mylog("[SQLErrorW]");
if (Sqlstate) if (Sqlstate)
qst = malloc(8); qst = malloc(8);
if (MessageText) buflen = 0;
mtxt = malloc(BufferLength); if (MessageText && BufferLength > 0)
{
buflen = BufferLength * 3 + 1;
mtxt = malloc(buflen);
}
ret = PGAPI_Error(EnvironmentHandle, ConnectionHandle, StatementHandle, ret = PGAPI_Error(EnvironmentHandle, ConnectionHandle, StatementHandle,
qst, NativeError, mtxt, BufferLength, &tlen); qst, NativeError, mtxt, buflen, &tlen);
if (qst) if (qst)
utf8_to_ucs2(qst, strlen(qst), Sqlstate, 5); utf8_to_ucs2(qst, strlen(qst), Sqlstate, 5);
if (TextLength) if (TextLength)
*TextLength = utf8_to_ucs2(mtxt, tlen, MessageText, BufferLength); *TextLength = utf8_to_ucs2(mtxt, tlen, MessageText, BufferLength);
free(qst); free(qst);
free(mtxt); if (mtxt)
free(mtxt);
return ret; return ret;
} }
...@@ -56,6 +61,7 @@ RETCODE SQL_API SQLSetConnectOptionW(HDBC ConnectionHandle, ...@@ -56,6 +61,7 @@ RETCODE SQL_API SQLSetConnectOptionW(HDBC ConnectionHandle,
SQLUSMALLINT Option, SQLUINTEGER Value) SQLUSMALLINT Option, SQLUINTEGER Value)
{ {
mylog("[SQLSetConnectionOptionW]"); mylog("[SQLSetConnectionOptionW]");
if (!ConnectionHandle) return SQL_ERROR;
((ConnectionClass *) ConnectionHandle)->unicode = 1; ((ConnectionClass *) ConnectionHandle)->unicode = 1;
return PGAPI_SetConnectOption(ConnectionHandle, Option, Value); return PGAPI_SetConnectOption(ConnectionHandle, Option, Value);
} }
......
...@@ -144,9 +144,7 @@ SQLEndTran(SQLSMALLINT HandleType, SQLHANDLE Handle, ...@@ -144,9 +144,7 @@ SQLEndTran(SQLSMALLINT HandleType, SQLHANDLE Handle,
default: default:
break; break;
} }
return SQL_ERROR; /* SQLSTATE HY092 ("Invalid return SQL_ERROR;
* attribute/option identifier") */
} }
/* SQLExtendedFetch -> SQLFetchScroll */ /* SQLExtendedFetch -> SQLFetchScroll */
...@@ -246,39 +244,9 @@ SQLGetDiagRec(SQLSMALLINT HandleType, SQLHANDLE Handle, ...@@ -246,39 +244,9 @@ SQLGetDiagRec(SQLSMALLINT HandleType, SQLHANDLE Handle,
SQLINTEGER *NativeError, SQLCHAR *MessageText, SQLINTEGER *NativeError, SQLCHAR *MessageText,
SQLSMALLINT BufferLength, SQLSMALLINT *TextLength) SQLSMALLINT BufferLength, SQLSMALLINT *TextLength)
{ {
RETCODE ret;
mylog("[[SQLGetDiagRec]]\n"); mylog("[[SQLGetDiagRec]]\n");
switch (HandleType) return PGAPI_GetDiagRec(HandleType, Handle, RecNumber, Sqlstate,
{ NativeError, MessageText, BufferLength, TextLength);
case SQL_HANDLE_ENV:
ret = PGAPI_Error(Handle, NULL, NULL, Sqlstate, NativeError,
MessageText, BufferLength, TextLength);
break;
case SQL_HANDLE_DBC:
ret = PGAPI_Error(NULL, Handle, NULL, Sqlstate, NativeError,
MessageText, BufferLength, TextLength);
break;
case SQL_HANDLE_STMT:
ret = PGAPI_Error(NULL, NULL, Handle, Sqlstate, NativeError,
MessageText, BufferLength, TextLength);
break;
default:
ret = SQL_ERROR;
}
if (ret == SQL_SUCCESS_WITH_INFO &&
BufferLength == 0 &&
*TextLength)
{
SQLSMALLINT BufferLength = *TextLength + 4;
SQLCHAR *MessageText = malloc(BufferLength);
ret = SQLGetDiagRec(HandleType, Handle, RecNumber, Sqlstate,
NativeError, MessageText, BufferLength,
TextLength);
free(MessageText);
}
return ret;
} }
/* new function */ /* new function */
...@@ -299,7 +267,7 @@ SQLGetEnvAttr(HENV EnvironmentHandle, ...@@ -299,7 +267,7 @@ SQLGetEnvAttr(HENV EnvironmentHandle,
*((unsigned int *) Value) = SQL_CP_RELAXED_MATCH; *((unsigned int *) Value) = SQL_CP_RELAXED_MATCH;
break; break;
case SQL_ATTR_ODBC_VERSION: case SQL_ATTR_ODBC_VERSION:
*((unsigned int *) Value) = SQL_OV_ODBC3; *((unsigned int *) Value) = EN_is_odbc2(env) ? SQL_OV_ODBC2 : SQL_OV_ODBC3;
break; break;
case SQL_ATTR_OUTPUT_NTS: case SQL_ATTR_OUTPUT_NTS:
*((unsigned int *) Value) = SQL_TRUE; *((unsigned int *) Value) = SQL_TRUE;
...@@ -456,6 +424,7 @@ ARDSetField(StatementClass *stmt, SQLSMALLINT RecNumber, ...@@ -456,6 +424,7 @@ ARDSetField(StatementClass *stmt, SQLSMALLINT RecNumber,
SQLSMALLINT FieldIdentifier, PTR Value, SQLINTEGER BufferLength) SQLSMALLINT FieldIdentifier, PTR Value, SQLINTEGER BufferLength)
{ {
RETCODE ret = SQL_SUCCESS; RETCODE ret = SQL_SUCCESS;
PTR tptr;
switch (FieldIdentifier) switch (FieldIdentifier)
{ {
case SQL_DESC_ARRAY_SIZE: case SQL_DESC_ARRAY_SIZE:
...@@ -470,8 +439,34 @@ ARDSetField(StatementClass *stmt, SQLSMALLINT RecNumber, ...@@ -470,8 +439,34 @@ ARDSetField(StatementClass *stmt, SQLSMALLINT RecNumber,
case SQL_DESC_BIND_TYPE: case SQL_DESC_BIND_TYPE:
stmt->options.bind_size = (SQLUINTEGER) Value; stmt->options.bind_size = (SQLUINTEGER) Value;
break; break;
case SQL_DESC_DATA_PTR:
if (!RecNumber)
stmt->bookmark.buffer = Value;
else
stmt->bindings[RecNumber - 1].buffer = Value;
break;
case SQL_DESC_INDICATOR_PTR:
if (!RecNumber)
tptr = stmt->bookmark.used;
else
tptr = stmt->bindings[RecNumber - 1].used;
if (Value != tptr)
{
ret = SQL_ERROR;
stmt->errornumber = STMT_INVALID_OPTION_IDENTIFIER;
stmt->errormsg = "INDICATOR != OCTET_LENGTH_PTR";
}
break;
case SQL_DESC_OCTET_LENGTH_PTR:
if (!RecNumber)
stmt->bookmark.used = Value;
else
stmt->bindings[RecNumber - 1].used = Value;
break;
default:ret = SQL_ERROR; default:ret = SQL_ERROR;
stmt->errornumber = STMT_INVALID_OPTION_IDENTIFIER; stmt->errornumber = STMT_INVALID_OPTION_IDENTIFIER;
stmt->errormsg = "not implemedted yet";
} }
return ret; return ret;
} }
...@@ -495,6 +490,26 @@ APDSetField(StatementClass *stmt, SQLSMALLINT RecNumber, ...@@ -495,6 +490,26 @@ APDSetField(StatementClass *stmt, SQLSMALLINT RecNumber,
case SQL_DESC_BIND_TYPE: case SQL_DESC_BIND_TYPE:
stmt->options.param_bind_type = (SQLUINTEGER) Value; stmt->options.param_bind_type = (SQLUINTEGER) Value;
break; break;
case SQL_DESC_DATA_PTR:
if (stmt->parameters_allocated < RecNumber)
PGAPI_BindParameter(stmt, RecNumber, 0, 0, 0, 0, 0, 0, 0, 0);
stmt->parameters[RecNumber - 1].buffer = Value;
break;
case SQL_DESC_INDICATOR_PTR:
if (stmt->parameters_allocated < RecNumber ||
Value != stmt->parameters[RecNumber - 1].used)
{
ret = SQL_ERROR;
stmt->errornumber = STMT_INVALID_OPTION_IDENTIFIER;
stmt->errormsg = "INDICATOR != OCTET_LENGTH_PTR";
}
break;
case SQL_DESC_OCTET_LENGTH_PTR:
if (stmt->parameters_allocated < RecNumber)
PGAPI_BindParameter(stmt, RecNumber, 0, 0, 0, 0, 0, 0, 0, 0);
stmt->parameters[RecNumber - 1].used = Value;
break;
default:ret = SQL_ERROR; default:ret = SQL_ERROR;
stmt->errornumber = STMT_INVALID_OPTION_IDENTIFIER; stmt->errornumber = STMT_INVALID_OPTION_IDENTIFIER;
} }
...@@ -549,6 +564,8 @@ SQLSetDescField(SQLHDESC DescriptorHandle, ...@@ -549,6 +564,8 @@ SQLSetDescField(SQLHDESC DescriptorHandle,
HSTMT hstmt; HSTMT hstmt;
SQLUINTEGER descType; SQLUINTEGER descType;
StatementClass *stmt; StatementClass *stmt;
static const char *func = "SQLSetDescField";
mylog("[[SQLSetDescField]] h=%u rec=%d field=%d val=%x\n", DescriptorHandle, RecNumber, FieldIdentifier, Value); mylog("[[SQLSetDescField]] h=%u rec=%d field=%d val=%x\n", DescriptorHandle, RecNumber, FieldIdentifier, Value);
hstmt = statementHandleFromDescHandle(DescriptorHandle, &descType); hstmt = statementHandleFromDescHandle(DescriptorHandle, &descType);
mylog("stmt=%x type=%d\n", hstmt, descType); mylog("stmt=%x type=%d\n", hstmt, descType);
...@@ -569,8 +586,10 @@ SQLSetDescField(SQLHDESC DescriptorHandle, ...@@ -569,8 +586,10 @@ SQLSetDescField(SQLHDESC DescriptorHandle,
break; break;
default:ret = SQL_ERROR; default:ret = SQL_ERROR;
stmt->errornumber = STMT_INTERNAL_ERROR; stmt->errornumber = STMT_INTERNAL_ERROR;
mylog("Error not implemented\n"); stmt->errormsg = "Error not implemented";
} }
if (ret == SQL_ERROR)
SC_log_error(func, "", stmt);
return ret; return ret;
} }
...@@ -583,6 +602,8 @@ SQLSetDescRec(SQLHDESC DescriptorHandle, ...@@ -583,6 +602,8 @@ SQLSetDescRec(SQLHDESC DescriptorHandle,
PTR Data, SQLINTEGER *StringLength, PTR Data, SQLINTEGER *StringLength,
SQLINTEGER *Indicator) SQLINTEGER *Indicator)
{ {
const char *func = "SQLSetDescField";
mylog("[[SQLSetDescRec]]\n"); mylog("[[SQLSetDescRec]]\n");
mylog("Error not implemented\n"); mylog("Error not implemented\n");
return SQL_ERROR; return SQL_ERROR;
...@@ -608,7 +629,10 @@ SQLSetEnvAttr(HENV EnvironmentHandle, ...@@ -608,7 +629,10 @@ SQLSetEnvAttr(HENV EnvironmentHandle,
return SQL_SUCCESS; return SQL_SUCCESS;
case SQL_ATTR_ODBC_VERSION: case SQL_ATTR_ODBC_VERSION:
if ((SQLUINTEGER) Value == SQL_OV_ODBC2) if ((SQLUINTEGER) Value == SQL_OV_ODBC2)
return SQL_SUCCESS; EN_set_odbc2(env);
else
EN_set_odbc3(env);
return SQL_SUCCESS;
break; break;
case SQL_ATTR_OUTPUT_NTS: case SQL_ATTR_OUTPUT_NTS:
if ((SQLUINTEGER) Value == SQL_TRUE) if ((SQLUINTEGER) Value == SQL_TRUE)
...@@ -652,44 +676,46 @@ SQLSetStmtAttr(HSTMT StatementHandle, ...@@ -652,44 +676,46 @@ SQLSetStmtAttr(HSTMT StatementHandle,
* case SQL_ATTR_PREDICATE_PTR: case * case SQL_ATTR_PREDICATE_PTR: case
* SQL_ATTR_PREDICATE_OCTET_LENGTH_PTR: * SQL_ATTR_PREDICATE_OCTET_LENGTH_PTR:
*/ */
case SQL_ATTR_PARAM_OPERATION_PTR: /* 19 */
case SQL_ATTR_PARAM_STATUS_PTR: /* 20 */
case SQL_ATTR_ROW_OPERATION_PTR: /* 24 */
stmt->errornumber = STMT_INVALID_OPTION_IDENTIFIER; stmt->errornumber = STMT_INVALID_OPTION_IDENTIFIER;
stmt->errormsg = "Unsupported statement option (Set)"; stmt->errormsg = "Unsupported statement option (Set)";
SC_log_error(func, "", stmt); SC_log_error(func, "", stmt);
return SQL_ERROR; return SQL_ERROR;
case SQL_ATTR_PARAM_BIND_OFFSET_PTR: /* 17 */
stmt->options.param_offset_ptr = (SQLUINTEGER *) Value;
break;
case SQL_ATTR_ROW_BIND_OFFSET_PTR: /* 23 */
stmt->options.row_offset_ptr = (SQLUINTEGER *) Value;
break;
case SQL_ATTR_FETCH_BOOKMARK_PTR: /* 16 */ case SQL_ATTR_FETCH_BOOKMARK_PTR: /* 16 */
stmt->options.bookmark_ptr = Value; stmt->options.bookmark_ptr = Value;
break; break;
case SQL_ATTR_PARAM_BIND_OFFSET_PTR: /* 17 */
stmt->options.param_offset_ptr = (SQLUINTEGER *) Value;
break;
case SQL_ATTR_PARAM_BIND_TYPE: /* 18 */ case SQL_ATTR_PARAM_BIND_TYPE: /* 18 */
stmt->options.param_bind_type = (SQLUINTEGER) Value; stmt->options.param_bind_type = (SQLUINTEGER) Value;
break; break;
case SQL_ATTR_PARAM_OPERATION_PTR: /* 19 */
stmt->options.param_operation_ptr = Value;
break;
case SQL_ATTR_PARAM_STATUS_PTR: /* 20 */
stmt->options.param_status_ptr = (SQLUSMALLINT *) Value;
break;
case SQL_ATTR_PARAMS_PROCESSED_PTR: /* 21 */ case SQL_ATTR_PARAMS_PROCESSED_PTR: /* 21 */
stmt->options.param_processed_ptr = (SQLUINTEGER *) Value; stmt->options.param_processed_ptr = (SQLUINTEGER *) Value;
break; break;
case SQL_ATTR_PARAMSET_SIZE: /* 22 */ case SQL_ATTR_PARAMSET_SIZE: /* 22 */
stmt->options.paramset_size = (SQLUINTEGER) Value; stmt->options.paramset_size = (SQLUINTEGER) Value;
break; break;
case SQL_ATTR_ROW_BIND_OFFSET_PTR: /* 23 */
stmt->options.row_offset_ptr = (SQLUINTEGER *) Value;
break;
case SQL_ATTR_ROW_OPERATION_PTR: /* 24 */
stmt->options.row_operation_ptr = Value;
break;
case SQL_ATTR_ROW_STATUS_PTR: /* 25 */ case SQL_ATTR_ROW_STATUS_PTR: /* 25 */
stmt->options.rowStatusArray = (SQLUSMALLINT *) Value; stmt->options.rowStatusArray = (SQLUSMALLINT *) Value;
break; break;
case SQL_ATTR_ROWS_FETCHED_PTR: /* 26 */ case SQL_ATTR_ROWS_FETCHED_PTR: /* 26 */
stmt->options.rowsFetched = (SQLUINTEGER *) Value; stmt->options.rowsFetched = (SQLUINTEGER *) Value;
break; break;
case SQL_ATTR_ROW_ARRAY_SIZE: /* 27 */ case SQL_ATTR_ROW_ARRAY_SIZE: /* 27 */
stmt->options.rowset_size = (SQLUINTEGER) Value; stmt->options.rowset_size = (SQLUINTEGER) Value;
break; break;
default: default:
return PGAPI_SetStmtOption(StatementHandle, (UWORD) Attribute, (UDWORD) Value); return PGAPI_SetStmtOption(StatementHandle, (UWORD) Attribute, (UDWORD) Value);
...@@ -704,7 +730,7 @@ SQLSetStmtAttr(HSTMT StatementHandle, ...@@ -704,7 +730,7 @@ SQLSetStmtAttr(HSTMT StatementHandle,
RETCODE SQL_API RETCODE SQL_API
PGAPI_GetFunctions30(HDBC hdbc, UWORD fFunction, UWORD FAR * pfExists) PGAPI_GetFunctions30(HDBC hdbc, UWORD fFunction, UWORD FAR * pfExists)
{ {
ConnectionClass *conn = (ConnectionClass *) hdbc; ConnectionClass *conn = (ConnectionClass *) hdbc;
ConnInfo *ci = &(conn->connInfo); ConnInfo *ci = &(conn->connInfo);
if (fFunction != SQL_API_ODBC3_ALL_FUNCTIONS) if (fFunction != SQL_API_ODBC3_ALL_FUNCTIONS)
...@@ -755,17 +781,14 @@ PGAPI_GetFunctions30(HDBC hdbc, UWORD fFunction, UWORD FAR * pfExists) ...@@ -755,17 +781,14 @@ PGAPI_GetFunctions30(HDBC hdbc, UWORD fFunction, UWORD FAR * pfExists)
SQL_FUNC_ESET(pfExists, SQL_API_SQLPARAMDATA); /* 48 */ SQL_FUNC_ESET(pfExists, SQL_API_SQLPARAMDATA); /* 48 */
SQL_FUNC_ESET(pfExists, SQL_API_SQLPUTDATA); /* 49 */ SQL_FUNC_ESET(pfExists, SQL_API_SQLPUTDATA); /* 49 */
/* /* SQL_FUNC_ESET(pfExists, SQL_API_SQLSETCONNECTIONOPTION); 50 deprecated */
* SQL_FUNC_ESET(pfExists, SQL_API_SQLSETCONNECTIONOPTION); 50
* deprecated
*/
/* SQL_FUNC_ESET(pfExists, SQL_API_SQLSETSTMTOPTION); 51 deprecated */ /* SQL_FUNC_ESET(pfExists, SQL_API_SQLSETSTMTOPTION); 51 deprecated */
SQL_FUNC_ESET(pfExists, SQL_API_SQLSPECIALCOLUMNS); /* 52 */ SQL_FUNC_ESET(pfExists, SQL_API_SQLSPECIALCOLUMNS); /* 52 */
SQL_FUNC_ESET(pfExists, SQL_API_SQLSTATISTICS); /* 53 */ SQL_FUNC_ESET(pfExists, SQL_API_SQLSTATISTICS); /* 53 */
SQL_FUNC_ESET(pfExists, SQL_API_SQLTABLES); /* 54 */ SQL_FUNC_ESET(pfExists, SQL_API_SQLTABLES); /* 54 */
SQL_FUNC_ESET(pfExists, SQL_API_SQLBROWSECONNECT); /* 55 */ SQL_FUNC_ESET(pfExists, SQL_API_SQLBROWSECONNECT); /* 55 */
if (ci->drivers.lie) if (ci->drivers.lie)
SQL_FUNC_ESET(pfExists, SQL_API_SQLCOLUMNPRIVILEGES); /* 56 not implmented yet */ SQL_FUNC_ESET(pfExists, SQL_API_SQLCOLUMNPRIVILEGES); /* 56 not implemented yet */
SQL_FUNC_ESET(pfExists, SQL_API_SQLDATASOURCES); /* 57 */ SQL_FUNC_ESET(pfExists, SQL_API_SQLDATASOURCES); /* 57 */
SQL_FUNC_ESET(pfExists, SQL_API_SQLDESCRIBEPARAM); /* 58 */ SQL_FUNC_ESET(pfExists, SQL_API_SQLDESCRIBEPARAM); /* 58 */
/* SQL_FUNC_ESET(pfExists, SQL_API_SQLEXTENDEDFETCH); 59 deprecated */ /* SQL_FUNC_ESET(pfExists, SQL_API_SQLEXTENDEDFETCH); 59 deprecated */
...@@ -781,12 +804,11 @@ PGAPI_GetFunctions30(HDBC hdbc, UWORD fFunction, UWORD FAR * pfExists) ...@@ -781,12 +804,11 @@ PGAPI_GetFunctions30(HDBC hdbc, UWORD fFunction, UWORD FAR * pfExists)
/* SQL_FUNC_ESET(pfExists, SQL_API_SQLPARAMOPTIONS); 64 deprecated */ /* SQL_FUNC_ESET(pfExists, SQL_API_SQLPARAMOPTIONS); 64 deprecated */
SQL_FUNC_ESET(pfExists, SQL_API_SQLPRIMARYKEYS); /* 65 */ SQL_FUNC_ESET(pfExists, SQL_API_SQLPRIMARYKEYS); /* 65 */
if (ci->drivers.lie) if (ci->drivers.lie)
SQL_FUNC_ESET(pfExists, SQL_API_SQLPROCEDURECOLUMNS); /* 66 not implmented yet */ SQL_FUNC_ESET(pfExists, SQL_API_SQLPROCEDURECOLUMNS); /* 66 not implemeted yet */
SQL_FUNC_ESET(pfExists, SQL_API_SQLPROCEDURES); /* 67 */ SQL_FUNC_ESET(pfExists, SQL_API_SQLPROCEDURES); /* 67 */
SQL_FUNC_ESET(pfExists, SQL_API_SQLSETPOS); /* 68 */ SQL_FUNC_ESET(pfExists, SQL_API_SQLSETPOS); /* 68 */
SQL_FUNC_ESET(pfExists, SQL_API_SQLSETSCROLLOPTIONS); /* 69 deprecated */ /* SQL_FUNC_ESET(pfExists, SQL_API_SQLSETSCROLLOPTIONS); 69 deprecated */
if (ci->drivers.lie) SQL_FUNC_ESET(pfExists, SQL_API_SQLTABLEPRIVILEGES); /* 70 */
SQL_FUNC_ESET(pfExists, SQL_API_SQLTABLEPRIVILEGES); /* 70 not implemented yet */
/* SQL_FUNC_ESET(pfExists, SQL_API_SQLDRIVERS); */ /* 71 */ /* SQL_FUNC_ESET(pfExists, SQL_API_SQLDRIVERS); */ /* 71 */
SQL_FUNC_ESET(pfExists, SQL_API_SQLBINDPARAMETER); /* 72 */ SQL_FUNC_ESET(pfExists, SQL_API_SQLBINDPARAMETER); /* 72 */
...@@ -801,7 +823,7 @@ PGAPI_GetFunctions30(HDBC hdbc, UWORD fFunction, UWORD FAR * pfExists) ...@@ -801,7 +823,7 @@ PGAPI_GetFunctions30(HDBC hdbc, UWORD fFunction, UWORD FAR * pfExists)
if (ci->drivers.lie) if (ci->drivers.lie)
{ {
SQL_FUNC_ESET(pfExists, SQL_API_SQLGETDESCFIELD); /* 1008 not implemented yet */ SQL_FUNC_ESET(pfExists, SQL_API_SQLGETDESCFIELD); /* 1008 not implemented yet */
SQL_FUNC_ESET(pfExists, SQL_API_SQLGETDESCREC); /* 1009 not implemented yet */ SQL_FUNC_ESET(pfExists, SQL_API_SQLGETDESCREC); /* 1009 not implemented yet */
SQL_FUNC_ESET(pfExists, SQL_API_SQLGETDIAGFIELD); /* 1010 not implemented yet */ SQL_FUNC_ESET(pfExists, SQL_API_SQLGETDIAGFIELD); /* 1010 not implemented yet */
} }
SQL_FUNC_ESET(pfExists, SQL_API_SQLGETDIAGREC); /* 1011 */ SQL_FUNC_ESET(pfExists, SQL_API_SQLGETDIAGREC); /* 1011 */
...@@ -810,7 +832,9 @@ PGAPI_GetFunctions30(HDBC hdbc, UWORD fFunction, UWORD FAR * pfExists) ...@@ -810,7 +832,9 @@ PGAPI_GetFunctions30(HDBC hdbc, UWORD fFunction, UWORD FAR * pfExists)
SQL_FUNC_ESET(pfExists, SQL_API_SQLSETCONNECTATTR); /* 1016 */ SQL_FUNC_ESET(pfExists, SQL_API_SQLSETCONNECTATTR); /* 1016 */
SQL_FUNC_ESET(pfExists, SQL_API_SQLSETDESCFIELD); /* 1017 */ SQL_FUNC_ESET(pfExists, SQL_API_SQLSETDESCFIELD); /* 1017 */
if (ci->drivers.lie) if (ci->drivers.lie)
SQL_FUNC_ESET(pfExists, SQL_API_SQLSETDESCREC); /* 1018 not implemented yet */ {
SQL_FUNC_ESET(pfExists, SQL_API_SQLSETDESCREC); /* 1018 not implemented yet */
}
SQL_FUNC_ESET(pfExists, SQL_API_SQLSETENVATTR); /* 1019 */ SQL_FUNC_ESET(pfExists, SQL_API_SQLSETENVATTR); /* 1019 */
SQL_FUNC_ESET(pfExists, SQL_API_SQLSETSTMTATTR); /* 1020 */ SQL_FUNC_ESET(pfExists, SQL_API_SQLSETSTMTATTR); /* 1020 */
SQL_FUNC_ESET(pfExists, SQL_API_SQLFETCHSCROLL); /* 1021 */ SQL_FUNC_ESET(pfExists, SQL_API_SQLFETCHSCROLL); /* 1021 */
......
...@@ -85,22 +85,37 @@ RETCODE SQL_API SQLGetDiagRecW(SWORD fHandleType, ...@@ -85,22 +85,37 @@ RETCODE SQL_API SQLGetDiagRecW(SWORD fHandleType,
SQLSMALLINT *pcbErrorMsg) SQLSMALLINT *pcbErrorMsg)
{ {
RETCODE ret; RETCODE ret;
SWORD tlen; SWORD buflen, tlen;
char *qst = NULL, *mtxt = NULL; char *qstr = NULL, *mtxt = NULL;
mylog("[SQLGetDiagRecW]"); mylog("[SQLGetDiagRecW]");
if (szSqlState) if (szSqlState)
qst = malloc(8); qstr = malloc(8);
if (szErrorMsg) buflen = 0;
mtxt = malloc(cbErrorMsgMax); if (szErrorMsg && cbErrorMsgMax > 0)
ret = PGAPI_GetDiagRec(fHandleType, handle, iRecord, qst, {
pfNativeError, mtxt, cbErrorMsgMax, &tlen); buflen = cbErrorMsgMax;
if (qst) mtxt = malloc(buflen);
utf8_to_ucs2(qst, strlen(qst), szSqlState, 5); }
if (pcbErrorMsg) ret = PGAPI_GetDiagRec(fHandleType, handle, iRecord, qstr,
*pcbErrorMsg = utf8_to_ucs2(mtxt, tlen, szErrorMsg, cbErrorMsgMax); pfNativeError, mtxt, buflen, &tlen);
free(qst); if (ret == SQL_SUCCESS || ret == SQL_SUCCESS_WITH_INFO)
free(mtxt); {
if (qstr)
utf8_to_ucs2(qstr, strlen(qstr), szSqlState, 6);
if (mtxt && tlen <= cbErrorMsgMax)
{
tlen = utf8_to_ucs2(mtxt, tlen, szErrorMsg, cbErrorMsgMax);
if (tlen >= cbErrorMsgMax)
ret = SQL_SUCCESS_WITH_INFO;
}
if (pcbErrorMsg)
*pcbErrorMsg = tlen;
}
if (qstr);
free(qstr);
if (mtxt)
free(mtxt);
return ret; return ret;
} }
......
...@@ -13,7 +13,7 @@ ...@@ -13,7 +13,7 @@
SQLPrepareW, SQLPrimaryKeysW, SQLProcedureColumnsW, SQLPrepareW, SQLPrimaryKeysW, SQLProcedureColumnsW,
SQLProceduresW, SQLSetCursorNameW, SQLProceduresW, SQLSetCursorNameW,
SQLSpecialColumnsW, SQLStatisticsW, SQLTablesW, SQLSpecialColumnsW, SQLStatisticsW, SQLTablesW,
SQLTablePrivilegesW SQLTablePrivilegesW, SQLGetTypeInfoW
*------- *-------
*/ */
...@@ -102,7 +102,11 @@ RETCODE SQL_API SQLDriverConnectW(HDBC hdbc, ...@@ -102,7 +102,11 @@ RETCODE SQL_API SQLDriverConnectW(HDBC hdbc,
ret = PGAPI_DriverConnect(hdbc, hwnd, szIn, (SWORD) inlen, ret = PGAPI_DriverConnect(hdbc, hwnd, szIn, (SWORD) inlen,
szOut, cbConnStrOutMax, &olen, fDriverCompletion); szOut, cbConnStrOutMax, &olen, fDriverCompletion);
if (ret != SQL_ERROR) if (ret != SQL_ERROR)
*pcbConnStrOut = utf8_to_ucs2(szOut, olen, szConnStrOut, cbConnStrOutMax); {
UInt4 outlen = utf8_to_ucs2(szOut, olen, szConnStrOut, cbConnStrOutMax);
if (pcbConnStrOut)
*pcbConnStrOut = outlen;
}
free(szOut); free(szOut);
if (szIn); if (szIn);
free(szIn); free(szIn);
...@@ -129,7 +133,11 @@ RETCODE SQL_API SQLBrowseConnectW( ...@@ -129,7 +133,11 @@ RETCODE SQL_API SQLBrowseConnectW(
ret = PGAPI_BrowseConnect(hdbc, szIn, (SWORD) inlen, ret = PGAPI_BrowseConnect(hdbc, szIn, (SWORD) inlen,
szOut, cbConnStrOutMax, &olen); szOut, cbConnStrOutMax, &olen);
if (ret != SQL_ERROR) if (ret != SQL_ERROR)
*pcbConnStrOut = utf8_to_ucs2(szOut, olen, szConnStrOut, cbConnStrOutMax); {
UInt4 outlen = utf8_to_ucs2(szOut, olen, szConnStrOut, cbConnStrOutMax);
if (pcbConnStrOut)
*pcbConnStrOut = outlen;
}
free(szOut); free(szOut);
if (szIn); if (szIn);
free(szIn); free(szIn);
...@@ -158,15 +166,28 @@ RETCODE SQL_API SQLDescribeColW(HSTMT StatementHandle, ...@@ -158,15 +166,28 @@ RETCODE SQL_API SQLDescribeColW(HSTMT StatementHandle,
SQLSMALLINT *DecimalDigits, SQLSMALLINT *Nullable) SQLSMALLINT *DecimalDigits, SQLSMALLINT *Nullable)
{ {
RETCODE ret; RETCODE ret;
SWORD nmlen; SWORD buflen, nmlen;
char *clName; char *clName;
mylog("[SQLDescribeColW]"); mylog("[SQLDescribeColW]");
clName = malloc(BufferLength); buflen = BufferLength * 3 + 1;
clName = malloc(buflen);
ret = PGAPI_DescribeCol(StatementHandle, ColumnNumber, ret = PGAPI_DescribeCol(StatementHandle, ColumnNumber,
clName, BufferLength, &nmlen, clName, buflen, &nmlen, DataType, ColumnSize,
DataType, ColumnSize, DecimalDigits, Nullable); DecimalDigits, Nullable);
*NameLength = utf8_to_ucs2(clName, nmlen, ColumnName, BufferLength); if (ret == SQL_SUCCESS)
{
UInt4 nmcount = utf8_to_ucs2(clName, nmlen, ColumnName, BufferLength);
if (nmcount > (UInt4) BufferLength)
{
StatementClass *stmt = (StatementClass *) StatementHandle;
ret = SQL_SUCCESS_WITH_INFO;
stmt->errornumber = STMT_TRUNCATED;
stmt->errormsg = "Column name too large";
}
if (NameLength)
*NameLength = nmcount;
}
free(clName); free(clName);
return ret; return ret;
} }
...@@ -192,13 +213,25 @@ RETCODE SQL_API SQLGetCursorNameW(HSTMT StatementHandle, ...@@ -192,13 +213,25 @@ RETCODE SQL_API SQLGetCursorNameW(HSTMT StatementHandle,
{ {
RETCODE ret; RETCODE ret;
char *crName; char *crName;
SWORD clen; SWORD clen, buflen;
mylog("[SQLGetCursorNameW]"); mylog("[SQLGetCursorNameW]");
crName = malloc(BufferLength); buflen = BufferLength * 3 + 1;
ret = PGAPI_GetCursorName(StatementHandle, crName, BufferLength, crName = malloc(buflen);
&clen); ret = PGAPI_GetCursorName(StatementHandle, crName, buflen, &clen);
*NameLength = utf8_to_ucs2(crName, (Int4) clen, CursorName, BufferLength); if (ret == SQL_SUCCESS)
{
UInt4 nmcount = utf8_to_ucs2(crName, (Int4) clen, CursorName, BufferLength);
if (nmcount > (UInt4) BufferLength)
{
StatementClass *stmt = (StatementClass *) StatementHandle;
ret = SQL_SUCCESS_WITH_INFO;
stmt->errornumber = STMT_TRUNCATED;
stmt->errormsg = "Cursor name too large";
}
if (NameLength)
*NameLength = utf8_to_ucs2(crName, (Int4) clen, CursorName, BufferLength);
}
free(crName); free(crName);
return ret; return ret;
} }
...@@ -207,23 +240,33 @@ RETCODE SQL_API SQLGetInfoW(HDBC ConnectionHandle, ...@@ -207,23 +240,33 @@ RETCODE SQL_API SQLGetInfoW(HDBC ConnectionHandle,
SQLUSMALLINT InfoType, PTR InfoValue, SQLUSMALLINT InfoType, PTR InfoValue,
SQLSMALLINT BufferLength, SQLSMALLINT *StringLength) SQLSMALLINT BufferLength, SQLSMALLINT *StringLength)
{ {
ConnectionClass *conn = (ConnectionClass *) ConnectionHandle;
RETCODE ret; RETCODE ret;
((ConnectionClass *) ConnectionHandle)->unicode = 1;
conn->unicode = 1;
CC_clear_error(conn);
#if (ODBCVER >= 0x0300) #if (ODBCVER >= 0x0300)
mylog("[SQLGetInfoW(30)]"); mylog("[SQLGetInfoW(30)]");
if ((ret = PGAPI_GetInfo(ConnectionHandle, InfoType, InfoValue, if ((ret = PGAPI_GetInfo(ConnectionHandle, InfoType, InfoValue,
BufferLength, StringLength)) == SQL_ERROR) BufferLength, StringLength)) == SQL_ERROR)
{ {
if (((ConnectionClass *) ConnectionHandle)->driver_version >= 0x0300) if (conn->driver_version >= 0x0300)
return PGAPI_GetInfo30(ConnectionHandle, InfoType, InfoValue, {
CC_clear_error(conn);
ret = PGAPI_GetInfo30(ConnectionHandle, InfoType, InfoValue,
BufferLength, StringLength); BufferLength, StringLength);
}
} }
return ret; if (SQL_ERROR == ret)
CC_log_error("SQLGetInfoW(30)", "", conn);
#else #else
mylog("[SQLGetInfoW]"); mylog("[SQLGetInfoW]");
return PGAPI_GetInfo(ConnectionHandle, InfoType, InfoValue, ret = PGAPI_GetInfo(ConnectionHandle, InfoType, InfoValue,
BufferLength, StringLength); BufferLength, StringLength);
if (SQL_ERROR == ret)
CC_log_error("SQLGetInfoW", "", conn);
#endif #endif
return ret;
} }
RETCODE SQL_API SQLPrepareW(HSTMT StatementHandle, RETCODE SQL_API SQLPrepareW(HSTMT StatementHandle,
...@@ -428,17 +471,31 @@ RETCODE SQL_API SQLNativeSqlW( ...@@ -428,17 +471,31 @@ RETCODE SQL_API SQLNativeSqlW(
RETCODE ret; RETCODE ret;
char *szIn, *szOut; char *szIn, *szOut;
UInt4 slen; UInt4 slen;
SQLINTEGER olen; SQLINTEGER buflen, olen;
mylog("[SQLNativeSqlW]"); mylog("[SQLNativeSqlW]");
((ConnectionClass *) hdbc)->unicode = 1; ((ConnectionClass *) hdbc)->unicode = 1;
szIn = ucs2_to_utf8(szSqlStrIn, cbSqlStrIn, &slen); szIn = ucs2_to_utf8(szSqlStrIn, cbSqlStrIn, &slen);
szOut = malloc(cbSqlStrMax); buflen = 3 * cbSqlStrMax + 1;
szOut = malloc(buflen);
ret = PGAPI_NativeSql(hdbc, szIn, (SQLINTEGER) slen, ret = PGAPI_NativeSql(hdbc, szIn, (SQLINTEGER) slen,
szOut, cbSqlStrMax, &olen); szOut, buflen, &olen);
if (szIn); if (szIn);
free(szIn); free(szIn);
*pcbSqlStr = utf8_to_ucs2(szOut, olen, szSqlStr, cbSqlStrMax); if (ret == SQL_SUCCESS)
{
UInt4 szcount = utf8_to_ucs2(szOut, olen, szSqlStr, cbSqlStrMax);
if (szcount > (UInt4) cbSqlStrMax)
{
ConnectionClass *conn = (ConnectionClass *) hdbc;
ret = SQL_SUCCESS_WITH_INFO;
conn->errornumber = CONN_TRUNCATED;
conn->errormsg = "Sql string too large";
}
if (pcbSqlStr)
*pcbSqlStr = szcount;
}
free(szOut); free(szOut);
return ret; return ret;
} }
...@@ -560,3 +617,10 @@ RETCODE SQL_API SQLTablePrivilegesW( ...@@ -560,3 +617,10 @@ RETCODE SQL_API SQLTablePrivilegesW(
free(tbName); free(tbName);
return ret; return ret;
} }
RETCODE SQL_API SQLGetTypeInfoW(
SQLHSTMT StatementHandle,
SQLSMALLINT DataType)
{
return PGAPI_GetTypeInfo(StatementHandle, DataType);
}
...@@ -342,12 +342,13 @@ PGAPI_SetConnectOption( ...@@ -342,12 +342,13 @@ PGAPI_SetConnectOption(
break; break;
case SQL_AUTOCOMMIT: case SQL_AUTOCOMMIT:
if (vParam == SQL_AUTOCOMMIT_ON && CC_is_in_autocommit(conn)) if (vParam == SQL_AUTOCOMMIT_ON && CC_is_in_trans(conn))
break; break;
else if (vParam == SQL_AUTOCOMMIT_OFF && !CC_is_in_autocommit(conn)) else if (vParam == SQL_AUTOCOMMIT_OFF && !CC_is_in_trans(conn))
break; break;
if (CC_is_in_trans(conn)) if (CC_is_in_trans(conn))
CC_commit(conn); CC_commit(conn);
mylog("PGAPI_SetConnectOption: AUTOCOMMIT: transact_status=%d, vparam=%d\n", conn->transact_status, vParam); mylog("PGAPI_SetConnectOption: AUTOCOMMIT: transact_status=%d, vparam=%d\n", conn->transact_status, vParam);
switch (vParam) switch (vParam)
...@@ -401,8 +402,21 @@ PGAPI_SetConnectOption( ...@@ -401,8 +402,21 @@ PGAPI_SetConnectOption(
sprintf(option, "fOption=%d, vParam=%ld", fOption, vParam); sprintf(option, "fOption=%d, vParam=%ld", fOption, vParam);
if (fOption == 30002 && vParam) if (fOption == 30002 && vParam)
{ {
if (strcmp((char *) vParam, "Microsoft Jet") == 0) int cmp;
#ifdef UNICODE_SUPPORT
char *asPara;
if (conn->unicode)
{
asPara = ucs2_to_utf8((SQLWCHAR *) vParam, -1, NULL);
cmp = strcmp(asPara, "Microsoft Jet");
free(asPara);
}
else
#endif /* UNICODE_SUPPORT */
cmp = strncmp((char *) vParam, "Microsoft Jet", 13);
if (0 == cmp)
{ {
mylog("Microsoft Jet !!!!\n");
conn->errornumber = 0; conn->errornumber = 0;
conn->ms_jet = 1; conn->ms_jet = 1;
return SQL_SUCCESS; return SQL_SUCCESS;
...@@ -456,7 +470,7 @@ PGAPI_GetConnectOption( ...@@ -456,7 +470,7 @@ PGAPI_GetConnectOption(
case SQL_CURRENT_QUALIFIER: /* don't use qualifiers */ case SQL_CURRENT_QUALIFIER: /* don't use qualifiers */
if (pvParam) if (pvParam)
strcpy(pvParam, ""); ((char *) pvParam)[0] = ((char *) pvParam)[1] = '\0';
break; break;
...@@ -557,7 +571,7 @@ PGAPI_GetStmtOption( ...@@ -557,7 +571,7 @@ PGAPI_GetStmtOption(
case SQL_GET_BOOKMARK: case SQL_GET_BOOKMARK:
case SQL_ROW_NUMBER: case SQL_ROW_NUMBER:
res = stmt->result; res = SC_get_Curres(stmt);
if (stmt->manual_result || !ci->drivers.use_declarefetch) if (stmt->manual_result || !ci->drivers.use_declarefetch)
{ {
......
...@@ -42,18 +42,29 @@ ...@@ -42,18 +42,29 @@
#define TAB_INCR 8 #define TAB_INCR 8
#define COL_INCR 16 #define COL_INCR 16
#ifdef MULTIBYTE
char *getNextToken(int ccsc, char *s, char *token, int smax, char *delim, char *quote, char *dquote, char *numeric);
#else
char *getNextToken(char *s, char *token, int smax, char *delim, char *quote, char *dquote, char *numeric); char *getNextToken(char *s, char *token, int smax, char *delim, char *quote, char *dquote, char *numeric);
#endif /* MULTIBYTE */
void getColInfo(COL_INFO *col_info, FIELD_INFO *fi, int k); void getColInfo(COL_INFO *col_info, FIELD_INFO *fi, int k);
char searchColInfo(COL_INFO *col_info, FIELD_INFO *fi); char searchColInfo(COL_INFO *col_info, FIELD_INFO *fi);
char * char *
getNextToken(char *s, char *token, int smax, char *delim, char *quote, char *dquote, char *numeric) getNextToken(
#ifdef MULTIBYTE
int ccsc, /* client encoding */
#endif /* MULTIBYTE */
char *s, char *token, int smax, char *delim, char *quote, char *dquote, char *numeric)
{ {
int i = 0; int i = 0;
int out = 0; int out = 0;
char qc, char qc,
in_escape = FALSE; in_escape = FALSE;
#ifdef MULTIBYTE
encoded_str encstr;
#endif
if (smax <= 1) if (smax <= 1)
return NULL; return NULL;
...@@ -80,17 +91,22 @@ getNextToken(char *s, char *token, int smax, char *delim, char *quote, char *dqu ...@@ -80,17 +91,22 @@ getNextToken(char *s, char *token, int smax, char *delim, char *quote, char *dqu
if (numeric) if (numeric)
*numeric = FALSE; *numeric = FALSE;
#ifdef MULTIBYTE
encoded_str_constr(&encstr, ccsc, &s[i]);
#endif
/* get the next token */ /* get the next token */
while (!isspace((unsigned char) s[i]) && s[i] != ',' && while (s[i] != '\0' && out < smax)
s[i] != '\0' && out != smax)
{ {
#ifdef MULTIBYTE #ifdef MULTIBYTE
if (multibyte_char_check(s[i]) != 0) encoded_nextchar(&encstr);
if (ENCODE_STATUS(encstr) != 0)
{ {
token[out++] = s[i++]; token[out++] = s[i++];
continue; continue;
} }
#endif #endif
if (isspace((unsigned char) s[i]) || s[i] == ',')
break;
/* Handle quoted stuff */ /* Handle quoted stuff */
if (out == 0 && (s[i] == '\"' || s[i] == '\'')) if (out == 0 && (s[i] == '\"' || s[i] == '\''))
{ {
...@@ -110,7 +126,8 @@ getNextToken(char *s, char *token, int smax, char *delim, char *quote, char *dqu ...@@ -110,7 +126,8 @@ getNextToken(char *s, char *token, int smax, char *delim, char *quote, char *dqu
while (s[i] != '\0' && out != smax) while (s[i] != '\0' && out != smax)
{ {
#ifdef MULTIBYTE #ifdef MULTIBYTE
if (multibyte_char_check(s[i]) != 0) encoded_nextchar(&encstr);
if (ENCODE_STATUS(encstr) != 0)
{ {
token[out++] = s[i++]; token[out++] = s[i++];
continue; continue;
...@@ -197,22 +214,22 @@ getNextToken(char *s, char *token, int smax, char *delim, char *quote, char *dqu ...@@ -197,22 +214,22 @@ getNextToken(char *s, char *token, int smax, char *delim, char *quote, char *dqu
#if 0 #if 0
QR_set_num_fields(stmt->result, 14); QR_set_num_fields(SC_get_Curres(stmt), 14);
QR_set_field_info(stmt->result, 0, "TABLE_QUALIFIER", PG_TYPE_TEXT, MAX_INFO_STRING); QR_set_field_info(SC_get_Curres(stmt), 0, "TABLE_QUALIFIER", PG_TYPE_TEXT, MAX_INFO_STRING);
QR_set_field_info(stmt->result, 1, "TABLE_OWNER", PG_TYPE_TEXT, MAX_INFO_STRING); QR_set_field_info(SC_get_Curres(stmt), 1, "TABLE_OWNER", PG_TYPE_TEXT, MAX_INFO_STRING);
QR_set_field_info(stmt->result, 2, "TABLE_NAME", PG_TYPE_TEXT, MAX_INFO_STRING); QR_set_field_info(SC_get_Curres(stmt), 2, "TABLE_NAME", PG_TYPE_TEXT, MAX_INFO_STRING);
QR_set_field_info(stmt->result, 3, "COLUMN_NAME", PG_TYPE_TEXT, MAX_INFO_STRING); QR_set_field_info(SC_get_Curres(stmt), 3, "COLUMN_NAME", PG_TYPE_TEXT, MAX_INFO_STRING);
QR_set_field_info(stmt->result, 4, "DATA_TYPE", PG_TYPE_INT2, 2); QR_set_field_info(SC_get_Curres(stmt), 4, "DATA_TYPE", PG_TYPE_INT2, 2);
QR_set_field_info(stmt->result, 5, "TYPE_NAME", PG_TYPE_TEXT, MAX_INFO_STRING); QR_set_field_info(SC_get_Curres(stmt), 5, "TYPE_NAME", PG_TYPE_TEXT, MAX_INFO_STRING);
QR_set_field_info(stmt->result, 6, "PRECISION", PG_TYPE_INT4, 4); QR_set_field_info(SC_get_Curres(stmt), 6, "PRECISION", PG_TYPE_INT4, 4);
QR_set_field_info(stmt->result, 7, "LENGTH", PG_TYPE_INT4, 4); QR_set_field_info(SC_get_Curres(stmt), 7, "LENGTH", PG_TYPE_INT4, 4);
QR_set_field_info(stmt->result, 8, "SCALE", PG_TYPE_INT2, 2); QR_set_field_info(SC_get_Curres(stmt), 8, "SCALE", PG_TYPE_INT2, 2);
QR_set_field_info(stmt->result, 9, "RADIX", PG_TYPE_INT2, 2); QR_set_field_info(SC_get_Curres(stmt), 9, "RADIX", PG_TYPE_INT2, 2);
QR_set_field_info(stmt->result, 10, "NULLABLE", PG_TYPE_INT2, 2); QR_set_field_info(SC_get_Curres(stmt), 10, "NULLABLE", PG_TYPE_INT2, 2);
QR_set_field_info(stmt->result, 11, "REMARKS", PG_TYPE_TEXT, 254); QR_set_field_info(SC_get_Curres(stmt), 11, "REMARKS", PG_TYPE_TEXT, 254);
/* User defined fields */ /* User defined fields */
QR_set_field_info(stmt->result, 12, "DISPLAY_SIZE", PG_TYPE_INT4, 4); QR_set_field_info(SC_get_Curres(stmt), 12, "DISPLAY_SIZE", PG_TYPE_INT4, 4);
QR_set_field_info(stmt->result, 13, "FIELD_TYPE", PG_TYPE_INT4, 4); QR_set_field_info(SC_get_Curres(stmt), 13, "FIELD_TYPE", PG_TYPE_INT4, 4);
#endif #endif
void void
...@@ -312,9 +329,10 @@ parse_statement(StatementClass *stmt) ...@@ -312,9 +329,10 @@ parse_statement(StatementClass *stmt)
stmt->ntab = 0; stmt->ntab = 0;
#ifdef MULTIBYTE #ifdef MULTIBYTE
multibyte_init(); while (pptr = ptr, (ptr = getNextToken(conn->ccsc, pptr, token, sizeof(token), &delim, &quote, &dquote, &numeric)) != NULL)
#endif #else
while (pptr = ptr, (ptr = getNextToken(pptr, token, sizeof(token), &delim, &quote, &dquote, &numeric)) != NULL) while (pptr = ptr, (ptr = getNextToken(pptr, token, sizeof(token), &delim, &quote, &dquote, &numeric)) != NULL)
#endif
{ {
unquoted = !(quote || dquote); unquoted = !(quote || dquote);
...@@ -607,12 +625,17 @@ parse_statement(StatementClass *stmt) ...@@ -607,12 +625,17 @@ parse_statement(StatementClass *stmt)
if (!dquote) if (!dquote)
{ {
char *ptr; char *ptr;
#ifdef MULTIBYTE
encoded_str encstr;
make_encoded_str(&encstr, conn, ti[stmt->ntab]->name);
#endif /* MULTIBYTE */
/* lower case table name */ /* lower case table name */
for (ptr = ti[stmt->ntab]->name; *ptr; ptr++) for (ptr = ti[stmt->ntab]->name; *ptr; ptr++)
{ {
#ifdef MULTIBYTE #ifdef MULTIBYTE
if ((unsigned char) *ptr >= 0x80) encoded_nextchar(&encstr);
if (ENCODE_STATUS(encstr) != 0)
ptr++; ptr++;
else else
#endif /* MULTIBYTE */ #endif /* MULTIBYTE */
...@@ -773,13 +796,13 @@ parse_statement(StatementClass *stmt) ...@@ -773,13 +796,13 @@ parse_statement(StatementClass *stmt)
* structure * structure
*/ */
strcpy(conn->col_info[conn->ntables]->name, ti[i]->name); strcpy(conn->col_info[conn->ntables]->name, ti[i]->name);
conn->col_info[conn->ntables]->result = col_stmt->result; conn->col_info[conn->ntables]->result = SC_get_Curres(col_stmt);
/* /*
* The connection will now free the result structures, so * The connection will now free the result structures, so
* make sure that the statement doesn't free it * make sure that the statement doesn't free it
*/ */
col_stmt->result = NULL; SC_set_Result(col_stmt, NULL);
conn->ntables++; conn->ntables++;
......
...@@ -36,37 +36,92 @@ PGAPI_GetDiagRec(SQLSMALLINT HandleType, SQLHANDLE Handle, ...@@ -36,37 +36,92 @@ PGAPI_GetDiagRec(SQLSMALLINT HandleType, SQLHANDLE Handle,
RETCODE ret; RETCODE ret;
static const char *func = "PGAPI_GetDiagRec"; static const char *func = "PGAPI_GetDiagRec";
mylog("%s entering ", func); mylog("%s entering rec=%d", func, RecNumber);
switch (HandleType) switch (HandleType)
{ {
case SQL_HANDLE_ENV: case SQL_HANDLE_ENV:
ret = PGAPI_Error(Handle, NULL, NULL, Sqlstate, NativeError, ret = PGAPI_EnvError(Handle, RecNumber, Sqlstate,
MessageText, BufferLength, TextLength); NativeError, MessageText,
BufferLength, TextLength, 0);
break; break;
case SQL_HANDLE_DBC: case SQL_HANDLE_DBC:
ret = PGAPI_Error(NULL, Handle, NULL, Sqlstate, NativeError, ret = PGAPI_ConnectError(Handle, RecNumber, Sqlstate,
MessageText, BufferLength, TextLength); NativeError, MessageText, BufferLength,
TextLength, 0);
break; break;
case SQL_HANDLE_STMT: case SQL_HANDLE_STMT:
ret = PGAPI_Error(NULL, NULL, Handle, Sqlstate, NativeError, ret = PGAPI_StmtError(Handle, RecNumber, Sqlstate,
MessageText, BufferLength, TextLength); NativeError, MessageText, BufferLength,
TextLength, 0);
break; break;
default: default:
ret = SQL_ERROR; ret = SQL_ERROR;
} }
if (ret == SQL_SUCCESS_WITH_INFO && mylog("%s exiting %d\n", func, ret);
BufferLength == 0 && return ret;
*TextLength) }
{
SQLSMALLINT BufferLength = *TextLength + 4; RETCODE SQL_API
SQLCHAR *MessageText = malloc(BufferLength); PGAPI_GetDiagField(SQLSMALLINT HandleType, SQLHANDLE Handle,
SQLSMALLINT RecNumber, SQLSMALLINT DiagIdentifier,
PTR DiagInfoPtr, SQLSMALLINT BufferLength,
SQLSMALLINT *StringLengthPtr)
{
RETCODE ret = SQL_SUCCESS;
static const char *func = "PGAPI_GetDiagField";
ret = PGAPI_GetDiagRec(HandleType, Handle, RecNumber, Sqlstate, mylog("%s entering rec=%d", func, RecNumber);
NativeError, MessageText, BufferLength, switch (HandleType)
TextLength); {
free(MessageText); case SQL_HANDLE_ENV:
switch (DiagIdentifier)
{
case SQL_DIAG_CLASS_ORIGIN:
case SQL_DIAG_SUBCLASS_ORIGIN:
case SQL_DIAG_CONNECTION_NAME:
case SQL_DIAG_MESSAGE_TEXT:
case SQL_DIAG_NATIVE:
case SQL_DIAG_NUMBER:
case SQL_DIAG_RETURNCODE:
case SQL_DIAG_SERVER_NAME:
case SQL_DIAG_SQLSTATE:
break;
}
break;
case SQL_HANDLE_DBC:
switch (DiagIdentifier)
{
case SQL_DIAG_CLASS_ORIGIN:
case SQL_DIAG_SUBCLASS_ORIGIN:
case SQL_DIAG_CONNECTION_NAME:
case SQL_DIAG_MESSAGE_TEXT:
case SQL_DIAG_NATIVE:
case SQL_DIAG_NUMBER:
case SQL_DIAG_RETURNCODE:
case SQL_DIAG_SERVER_NAME:
case SQL_DIAG_SQLSTATE:
break;
}
break;
case SQL_HANDLE_STMT:
switch (DiagIdentifier)
{
case SQL_DIAG_CLASS_ORIGIN:
case SQL_DIAG_SUBCLASS_ORIGIN:
case SQL_DIAG_CONNECTION_NAME:
case SQL_DIAG_MESSAGE_TEXT:
case SQL_DIAG_NATIVE:
case SQL_DIAG_NUMBER:
case SQL_DIAG_RETURNCODE:
case SQL_DIAG_SERVER_NAME:
case SQL_DIAG_SQLSTATE:
break;
}
break;
default:
ret = SQL_ERROR;
} }
mylog("%s exiting\n", func); mylog("%s exiting %d\n", func, ret);
return ret; return ret;
} }
...@@ -87,7 +142,7 @@ PGAPI_GetConnectAttr(HDBC ConnectionHandle, ...@@ -87,7 +142,7 @@ PGAPI_GetConnectAttr(HDBC ConnectionHandle,
case SQL_ATTR_CONNECTION_TIMEOUT: case SQL_ATTR_CONNECTION_TIMEOUT:
case SQL_ATTR_METADATA_ID: case SQL_ATTR_METADATA_ID:
conn->errornumber = STMT_INVALID_OPTION_IDENTIFIER; conn->errornumber = STMT_INVALID_OPTION_IDENTIFIER;
conn->errormsg = "Unsupported connection option (Set)"; conn->errormsg = "Unsupported connect attribute (Get)";
return SQL_ERROR; return SQL_ERROR;
} }
return PGAPI_GetConnectOption(ConnectionHandle, (UWORD) Attribute, Value); return PGAPI_GetConnectOption(ConnectionHandle, (UWORD) Attribute, Value);
...@@ -373,7 +428,7 @@ PGAPI_SetConnectAttr(HDBC ConnectionHandle, ...@@ -373,7 +428,7 @@ PGAPI_SetConnectAttr(HDBC ConnectionHandle,
case SQL_ATTR_CONNECTION_TIMEOUT: case SQL_ATTR_CONNECTION_TIMEOUT:
case SQL_ATTR_METADATA_ID: case SQL_ATTR_METADATA_ID:
conn->errornumber = STMT_INVALID_OPTION_IDENTIFIER; conn->errornumber = STMT_INVALID_OPTION_IDENTIFIER;
conn->errormsg = "Unsupported connection option (Set)"; conn->errormsg = "Unsupported connect attribute (Set)";
return SQL_ERROR; return SQL_ERROR;
} }
return PGAPI_SetConnectOption(ConnectionHandle, (UWORD) Attribute, (UDWORD) Value); return PGAPI_SetConnectOption(ConnectionHandle, (UWORD) Attribute, (UDWORD) Value);
......
...@@ -11,6 +11,8 @@ ...@@ -11,6 +11,8 @@
#include <string.h> #include <string.h>
#define PODBC_NOT_SEARCH_PATTERN 1L #define PODBC_NOT_SEARCH_PATTERN 1L
#define PODBC_ALLOW_PARTIAL_EXTRACT 1L
#define PODBC_ERROR_CLEAR (1L << 1)
RETCODE SQL_API PGAPI_AllocConnect(HENV EnvironmentHandle, RETCODE SQL_API PGAPI_AllocConnect(HENV EnvironmentHandle,
HDBC FAR * ConnectionHandle); HDBC FAR * ConnectionHandle);
...@@ -56,6 +58,20 @@ RETCODE SQL_API PGAPI_Error(HENV EnvironmentHandle, ...@@ -56,6 +58,20 @@ RETCODE SQL_API PGAPI_Error(HENV EnvironmentHandle,
SQLCHAR *Sqlstate, SQLINTEGER *NativeError, SQLCHAR *Sqlstate, SQLINTEGER *NativeError,
SQLCHAR *MessageText, SQLSMALLINT BufferLength, SQLCHAR *MessageText, SQLSMALLINT BufferLength,
SQLSMALLINT *TextLength); SQLSMALLINT *TextLength);
/* Helper functions for Error handling */
RETCODE SQL_API PGAPI_EnvError(HENV EnvironmentHandle, SWORD RecNumber,
SQLCHAR *Sqlstate, SQLINTEGER *NativeError,
SQLCHAR *MessageText, SQLSMALLINT BufferLength,
SQLSMALLINT *TextLength, UWORD flag);
RETCODE SQL_API PGAPI_ConnectError(HDBC ConnectionHandle, SWORD RecNumber,
SQLCHAR *Sqlstate, SQLINTEGER *NativeError,
SQLCHAR *MessageText, SQLSMALLINT BufferLength,
SQLSMALLINT *TextLength, UWORD flag);
RETCODE SQL_API PGAPI_StmtError(HSTMT StatementHandle, SWORD RecNumber,
SQLCHAR *Sqlstate, SQLINTEGER *NativeError,
SQLCHAR *MessageText, SQLSMALLINT BufferLength,
SQLSMALLINT *TextLength, UWORD flag);
RETCODE SQL_API PGAPI_ExecDirect(HSTMT StatementHandle, RETCODE SQL_API PGAPI_ExecDirect(HSTMT StatementHandle,
SQLCHAR *StatementText, SQLINTEGER TextLength); SQLCHAR *StatementText, SQLINTEGER TextLength);
RETCODE SQL_API PGAPI_Execute(HSTMT StatementHandle); RETCODE SQL_API PGAPI_Execute(HSTMT StatementHandle);
...@@ -225,7 +241,8 @@ RETCODE SQL_API PGAPI_TablePrivileges( ...@@ -225,7 +241,8 @@ RETCODE SQL_API PGAPI_TablePrivileges(
SQLCHAR *szSchemaName, SQLCHAR *szSchemaName,
SQLSMALLINT cbSchemaName, SQLSMALLINT cbSchemaName,
SQLCHAR *szTableName, SQLCHAR *szTableName,
SQLSMALLINT cbTableName); SQLSMALLINT cbTableName,
UWORD flag);
RETCODE SQL_API PGAPI_BindParameter( RETCODE SQL_API PGAPI_BindParameter(
HSTMT hstmt, HSTMT hstmt,
SQLUSMALLINT ipar, SQLUSMALLINT ipar,
...@@ -243,4 +260,25 @@ RETCODE SQL_API PGAPI_SetScrollOptions( ...@@ -243,4 +260,25 @@ RETCODE SQL_API PGAPI_SetScrollOptions(
SDWORD crowKeyset, SDWORD crowKeyset,
UWORD crowRowset); UWORD crowRowset);
#if (ODBCVER >= 0x0300)
RETCODE SQL_API PGAPI_GetDiagRec(SQLSMALLINT HandleType, SQLHANDLE Handle,
SQLSMALLINT RecNumber, SQLCHAR *Sqlstate,
SQLINTEGER *NativeError, SQLCHAR *MessageText,
SQLSMALLINT BufferLength, SQLSMALLINT *TextLength);
RETCODE SQL_API PGAPI_GetConnectAttr(HDBC ConnectionHandle,
SQLINTEGER Attribute, PTR Value,
SQLINTEGER BufferLength, SQLINTEGER *StringLength);
RETCODE SQL_API PGAPI_GetStmtAttr(HSTMT StatementHandle,
SQLINTEGER Attribute, PTR Value,
SQLINTEGER BufferLength, SQLINTEGER *StringLength);
RETCODE SQL_API PGAPI_SetConnectAttr(HDBC ConnectionHandle,
SQLINTEGER Attribute, PTR Value,
SQLINTEGER StringLength);
RETCODE SQL_API PGAPI_SetStmtAttr(HSTMT StatementHandle,
SQLINTEGER Attribute, PTR Value,
SQLINTEGER StringLength);
RETCODE SQL_API PGAPI_SetDescField(SQLHDESC DescriptorHandle,
SQLSMALLINT RecNumber, SQLSMALLINT FieldIdentifier,
PTR Value, SQLINTEGER BufferLength);
#endif /* ODBCVER */
#endif /* define_PG_API_FUNC_H__ */ #endif /* define_PG_API_FUNC_H__ */
...@@ -21,6 +21,7 @@ ...@@ -21,6 +21,7 @@
#include "dlg_specific.h" #include "dlg_specific.h"
#include "statement.h" #include "statement.h"
#include "connection.h" #include "connection.h"
#include "environ.h"
#include "qresult.h" #include "qresult.h"
...@@ -90,15 +91,26 @@ Int2 sqlTypes[] = { ...@@ -90,15 +91,26 @@ Int2 sqlTypes[] = {
SQL_TINYINT, SQL_TINYINT,
SQL_VARBINARY, SQL_VARBINARY,
SQL_VARCHAR, SQL_VARCHAR,
#ifdef UNICODE_SUPPORT
SQL_WCHAR,
SQL_WVARCHAR,
SQL_WLONGVARCHAR,
#endif /* UNICODE_SUPPORT */
0 0
}; };
#if (ODBCVER >= 0x0300) && defined(OBDCINT64)
#define ALLOWED_C_BIGINT SQL_C_SBIGINT
#else
#define ALLOWED_C_BIGINT SQL_C_CHAR
#endif
Int4 Int4
sqltype_to_pgtype(StatementClass *stmt, SWORD fSqlType) sqltype_to_pgtype(StatementClass *stmt, SWORD fSqlType)
{ {
Int4 pgType; Int4 pgType;
ConnInfo *ci = &(SC_get_conn(stmt)->connInfo); ConnectionClass *conn = SC_get_conn(stmt);
ConnInfo *ci = &(conn->connInfo);
switch (fSqlType) switch (fSqlType)
{ {
...@@ -110,11 +122,20 @@ sqltype_to_pgtype(StatementClass *stmt, SWORD fSqlType) ...@@ -110,11 +122,20 @@ sqltype_to_pgtype(StatementClass *stmt, SWORD fSqlType)
pgType = PG_TYPE_BPCHAR; pgType = PG_TYPE_BPCHAR;
break; break;
#ifdef UNICODE_SUPPORT
case SQL_WCHAR:
pgType = PG_TYPE_BPCHAR;
break;
#endif /* UNICODE_SUPPORT */
case SQL_BIT: case SQL_BIT:
pgType = ci->drivers.bools_as_char ? PG_TYPE_CHAR : PG_TYPE_BOOL; pgType = ci->drivers.bools_as_char ? PG_TYPE_CHAR : PG_TYPE_BOOL;
break; break;
case SQL_DATE: case SQL_DATE:
#if (ODBCVER >= 0x0300)
case SQL_TYPE_DATE:
#endif /* ODBCVER */
pgType = PG_TYPE_DATE; pgType = PG_TYPE_DATE;
break; break;
...@@ -144,6 +165,12 @@ sqltype_to_pgtype(StatementClass *stmt, SWORD fSqlType) ...@@ -144,6 +165,12 @@ sqltype_to_pgtype(StatementClass *stmt, SWORD fSqlType)
pgType = ci->drivers.text_as_longvarchar ? PG_TYPE_TEXT : PG_TYPE_VARCHAR; pgType = ci->drivers.text_as_longvarchar ? PG_TYPE_TEXT : PG_TYPE_VARCHAR;
break; break;
#ifdef UNICODE_SUPPORT
case SQL_WLONGVARCHAR:
pgType = ci->drivers.text_as_longvarchar ? PG_TYPE_TEXT : PG_TYPE_VARCHAR;
break;
#endif /* UNICODE_SUPPORT */
case SQL_REAL: case SQL_REAL:
pgType = PG_TYPE_FLOAT4; pgType = PG_TYPE_FLOAT4;
break; break;
...@@ -154,10 +181,16 @@ sqltype_to_pgtype(StatementClass *stmt, SWORD fSqlType) ...@@ -154,10 +181,16 @@ sqltype_to_pgtype(StatementClass *stmt, SWORD fSqlType)
break; break;
case SQL_TIME: case SQL_TIME:
#if (ODBCVER >= 0x0300)
case SQL_TYPE_TIME:
#endif /* ODBCVER */
pgType = PG_TYPE_TIME; pgType = PG_TYPE_TIME;
break; break;
case SQL_TIMESTAMP: case SQL_TIMESTAMP:
#if (ODBCVER >= 0x0300)
case SQL_TYPE_TIMESTAMP:
#endif /* ODBCVER */
pgType = PG_TYPE_DATETIME; pgType = PG_TYPE_DATETIME;
break; break;
...@@ -169,6 +202,12 @@ sqltype_to_pgtype(StatementClass *stmt, SWORD fSqlType) ...@@ -169,6 +202,12 @@ sqltype_to_pgtype(StatementClass *stmt, SWORD fSqlType)
pgType = PG_TYPE_VARCHAR; pgType = PG_TYPE_VARCHAR;
break; break;
#if UNICODE_SUPPORT
case SQL_WVARCHAR:
pgType = PG_TYPE_VARCHAR;
break;
#endif /* UNICODE_SUPPORT */
default: default:
pgType = 0; /* ??? */ pgType = 0; /* ??? */
break; break;
...@@ -193,7 +232,9 @@ sqltype_to_pgtype(StatementClass *stmt, SWORD fSqlType) ...@@ -193,7 +232,9 @@ sqltype_to_pgtype(StatementClass *stmt, SWORD fSqlType)
Int2 Int2
pgtype_to_sqltype(StatementClass *stmt, Int4 type) pgtype_to_sqltype(StatementClass *stmt, Int4 type)
{ {
ConnInfo *ci = &(SC_get_conn(stmt)->connInfo); ConnectionClass *conn = SC_get_conn(stmt);
ConnInfo *ci = &(conn->connInfo);
EnvironmentClass *env = (EnvironmentClass *) (conn->henv);
switch (type) switch (type)
{ {
...@@ -204,6 +245,19 @@ pgtype_to_sqltype(StatementClass *stmt, Int4 type) ...@@ -204,6 +245,19 @@ pgtype_to_sqltype(StatementClass *stmt, Int4 type)
case PG_TYPE_NAME: case PG_TYPE_NAME:
return SQL_CHAR; return SQL_CHAR;
#ifdef UNICODE_SUPPORT
case PG_TYPE_BPCHAR:
return conn->unicode ? SQL_WCHAR : SQL_CHAR;
case PG_TYPE_VARCHAR:
return conn->unicode ? SQL_WVARCHAR : SQL_VARCHAR;
case PG_TYPE_TEXT:
return ci->drivers.text_as_longvarchar ?
(conn->unicode ? SQL_WLONGVARCHAR : SQL_LONGVARCHAR) :
(conn->unicode ? SQL_WVARCHAR : SQL_VARCHAR);
#else
case PG_TYPE_BPCHAR: case PG_TYPE_BPCHAR:
return SQL_CHAR; return SQL_CHAR;
...@@ -212,6 +266,7 @@ pgtype_to_sqltype(StatementClass *stmt, Int4 type) ...@@ -212,6 +266,7 @@ pgtype_to_sqltype(StatementClass *stmt, Int4 type)
case PG_TYPE_TEXT: case PG_TYPE_TEXT:
return ci->drivers.text_as_longvarchar ? SQL_LONGVARCHAR : SQL_VARCHAR; return ci->drivers.text_as_longvarchar ? SQL_LONGVARCHAR : SQL_VARCHAR;
#endif /* UNICODE_SUPPORT */
case PG_TYPE_BYTEA: case PG_TYPE_BYTEA:
return SQL_VARBINARY; return SQL_VARBINARY;
...@@ -229,10 +284,10 @@ pgtype_to_sqltype(StatementClass *stmt, Int4 type) ...@@ -229,10 +284,10 @@ pgtype_to_sqltype(StatementClass *stmt, Int4 type)
/* Change this to SQL_BIGINT for ODBC v3 bjm 2001-01-23 */ /* Change this to SQL_BIGINT for ODBC v3 bjm 2001-01-23 */
case PG_TYPE_INT8: case PG_TYPE_INT8:
#if (ODBCVER >= 0x0300) #if (ODBCVER >= 0x0300)
return SQL_BIGINT; if (!conn->ms_jet)
#else return SQL_BIGINT;
return SQL_CHAR;
#endif /* ODBCVER */ #endif /* ODBCVER */
return SQL_CHAR;
case PG_TYPE_NUMERIC: case PG_TYPE_NUMERIC:
return SQL_NUMERIC; return SQL_NUMERIC;
...@@ -242,12 +297,24 @@ pgtype_to_sqltype(StatementClass *stmt, Int4 type) ...@@ -242,12 +297,24 @@ pgtype_to_sqltype(StatementClass *stmt, Int4 type)
case PG_TYPE_FLOAT8: case PG_TYPE_FLOAT8:
return SQL_FLOAT; return SQL_FLOAT;
case PG_TYPE_DATE: case PG_TYPE_DATE:
#if (ODBCVER >= 0x0300)
if (EN_is_odbc3(env))
return SQL_TYPE_DATE;
#endif /* ODBCVER */
return SQL_DATE; return SQL_DATE;
case PG_TYPE_TIME: case PG_TYPE_TIME:
#if (ODBCVER >= 0x0300)
if (EN_is_odbc3(env))
return SQL_TYPE_TIME;
#endif /* ODBCVER */
return SQL_TIME; return SQL_TIME;
case PG_TYPE_ABSTIME: case PG_TYPE_ABSTIME:
case PG_TYPE_DATETIME: case PG_TYPE_DATETIME:
case PG_TYPE_TIMESTAMP: case PG_TYPE_TIMESTAMP:
#if (ODBCVER >= 0x0300)
if (EN_is_odbc3(env))
return SQL_TYPE_TIMESTAMP;
#endif /* ODBCVER */
return SQL_TIMESTAMP; return SQL_TIMESTAMP;
case PG_TYPE_MONEY: case PG_TYPE_MONEY:
return SQL_FLOAT; return SQL_FLOAT;
...@@ -273,16 +340,18 @@ pgtype_to_sqltype(StatementClass *stmt, Int4 type) ...@@ -273,16 +340,18 @@ pgtype_to_sqltype(StatementClass *stmt, Int4 type)
Int2 Int2
pgtype_to_ctype(StatementClass *stmt, Int4 type) pgtype_to_ctype(StatementClass *stmt, Int4 type)
{ {
ConnInfo *ci = &(SC_get_conn(stmt)->connInfo); ConnectionClass *conn = SC_get_conn(stmt);
ConnInfo *ci = &(conn->connInfo);
EnvironmentClass *env = (EnvironmentClass *) (conn->henv);
switch (type) switch (type)
{ {
case PG_TYPE_INT8: case PG_TYPE_INT8:
#if (ODBCVER >= 0x0300) #if (ODBCVER >= 0x0300)
return SQL_C_SBIGINT; if (!conn->ms_jet)
#else return ALLOWED_C_BIGINT;
#endif /* ODBCVER */
return SQL_C_CHAR; return SQL_C_CHAR;
#endif
case PG_TYPE_NUMERIC: case PG_TYPE_NUMERIC:
return SQL_C_CHAR; return SQL_C_CHAR;
case PG_TYPE_INT2: case PG_TYPE_INT2:
...@@ -297,24 +366,24 @@ pgtype_to_ctype(StatementClass *stmt, Int4 type) ...@@ -297,24 +366,24 @@ pgtype_to_ctype(StatementClass *stmt, Int4 type)
return SQL_C_DOUBLE; return SQL_C_DOUBLE;
case PG_TYPE_DATE: case PG_TYPE_DATE:
#if (ODBCVER >= 0x0300) #if (ODBCVER >= 0x0300)
return SQL_C_TYPE_DATE; if (EN_is_odbc3(env))
#else return SQL_C_TYPE_DATE;
return SQL_C_DATE;
#endif /* ODBCVER */ #endif /* ODBCVER */
return SQL_C_DATE;
case PG_TYPE_TIME: case PG_TYPE_TIME:
#if (ODBCVER >= 0x0300) #if (ODBCVER >= 0x0300)
return SQL_C_TYPE_TIME; if (EN_is_odbc3(env))
#else return SQL_C_TYPE_TIME;
return SQL_C_TIME;
#endif /* ODBCVER */ #endif /* ODBCVER */
return SQL_C_TIME;
case PG_TYPE_ABSTIME: case PG_TYPE_ABSTIME:
case PG_TYPE_DATETIME: case PG_TYPE_DATETIME:
case PG_TYPE_TIMESTAMP: case PG_TYPE_TIMESTAMP:
#if (ODBCVER >= 0x0300) #if (ODBCVER >= 0x0300)
return SQL_C_TYPE_TIMESTAMP; if (EN_is_odbc3(env))
#else return SQL_C_TYPE_TIMESTAMP;
return SQL_C_TIMESTAMP;
#endif /* ODBCVER */ #endif /* ODBCVER */
return SQL_C_TIMESTAMP;
case PG_TYPE_MONEY: case PG_TYPE_MONEY:
return SQL_C_FLOAT; return SQL_C_FLOAT;
case PG_TYPE_BOOL: case PG_TYPE_BOOL:
...@@ -324,6 +393,12 @@ pgtype_to_ctype(StatementClass *stmt, Int4 type) ...@@ -324,6 +393,12 @@ pgtype_to_ctype(StatementClass *stmt, Int4 type)
return SQL_C_BINARY; return SQL_C_BINARY;
case PG_TYPE_LO: case PG_TYPE_LO:
return SQL_C_BINARY; return SQL_C_BINARY;
#ifdef UNICODE_SUPPORT
case PG_TYPE_BPCHAR:
case PG_TYPE_VARCHAR:
case PG_TYPE_TEXT:
return conn->unicode ? SQL_C_WCHAR : SQL_C_CHAR;
#endif /* UNICODE_SUPPORT */
default: default:
/* hack until permanent type is available */ /* hack until permanent type is available */
...@@ -416,7 +491,7 @@ getNumericScale(StatementClass *stmt, Int4 type, int col) ...@@ -416,7 +491,7 @@ getNumericScale(StatementClass *stmt, Int4 type, int col)
if (col < 0) if (col < 0)
return PG_NUMERIC_MAX_SCALE; return PG_NUMERIC_MAX_SCALE;
result = SC_get_Result(stmt); result = SC_get_Curres(stmt);
/* /*
* Manual Result Sets -- use assigned column width (i.e., from * Manual Result Sets -- use assigned column width (i.e., from
...@@ -457,7 +532,7 @@ getNumericPrecision(StatementClass *stmt, Int4 type, int col) ...@@ -457,7 +532,7 @@ getNumericPrecision(StatementClass *stmt, Int4 type, int col)
if (col < 0) if (col < 0)
return PG_NUMERIC_MAX_PRECISION; return PG_NUMERIC_MAX_PRECISION;
result = SC_get_Result(stmt); result = SC_get_Curres(stmt);
/* /*
* Manual Result Sets -- use assigned column width (i.e., from * Manual Result Sets -- use assigned column width (i.e., from
...@@ -520,10 +595,6 @@ getCharPrecision(StatementClass *stmt, Int4 type, int col, int handle_unknown_si ...@@ -520,10 +595,6 @@ getCharPrecision(StatementClass *stmt, Int4 type, int col, int handle_unknown_si
break; break;
} }
/*
* Static Precision (i.e., the Maximum Precision of the datatype) This
* has nothing to do with a result set.
*/
if (maxsize == TEXT_FIELD_SIZE + 1) /* magic length for testing */ if (maxsize == TEXT_FIELD_SIZE + 1) /* magic length for testing */
{ {
if (PG_VERSION_GE(SC_get_conn(stmt), 7.1)) if (PG_VERSION_GE(SC_get_conn(stmt), 7.1))
...@@ -531,10 +602,14 @@ getCharPrecision(StatementClass *stmt, Int4 type, int col, int handle_unknown_si ...@@ -531,10 +602,14 @@ getCharPrecision(StatementClass *stmt, Int4 type, int col, int handle_unknown_si
else else
maxsize = TEXT_FIELD_SIZE; maxsize = TEXT_FIELD_SIZE;
} }
/*
* Static Precision (i.e., the Maximum Precision of the datatype) This
* has nothing to do with a result set.
*/
if (col < 0) if (col < 0)
return maxsize; return maxsize;
result = SC_get_Result(stmt); result = SC_get_Curres(stmt);
/* /*
* Manual Result Sets -- use assigned column width (i.e., from * Manual Result Sets -- use assigned column width (i.e., from
...@@ -553,16 +628,20 @@ getCharPrecision(StatementClass *stmt, Int4 type, int col, int handle_unknown_si ...@@ -553,16 +628,20 @@ getCharPrecision(StatementClass *stmt, Int4 type, int col, int handle_unknown_si
if (QR_get_atttypmod(result, col) > -1) if (QR_get_atttypmod(result, col) > -1)
return QR_get_atttypmod(result, col); return QR_get_atttypmod(result, col);
/* The type is really unknown */
if (type == PG_TYPE_BPCHAR || handle_unknown_size_as == UNKNOWNS_AS_LONGEST) if (type == PG_TYPE_BPCHAR || handle_unknown_size_as == UNKNOWNS_AS_LONGEST)
{ {
p = QR_get_display_size(result, col); p = QR_get_display_size(result, col);
mylog("getCharPrecision: LONGEST: p = %d\n", p); mylog("getCharPrecision: LONGEST: p = %d\n", p);
if (p >= 0)
return p;
} }
if (p < 0 && handle_unknown_size_as == UNKNOWNS_AS_MAX) if (handle_unknown_size_as == UNKNOWNS_AS_MAX)
return maxsize; return maxsize;
else else /* handle_unknown_size_as == DONT_KNOW */
return p; return -1;
} }
static Int2 static Int2
...@@ -580,7 +659,7 @@ getTimestampScale(StatementClass *stmt, Int4 type, int col) ...@@ -580,7 +659,7 @@ getTimestampScale(StatementClass *stmt, Int4 type, int col)
if (PG_VERSION_LT(conn, 7.2)) if (PG_VERSION_LT(conn, 7.2))
return 0; return 0;
result = SC_get_Result(stmt); result = SC_get_Curres(stmt);
/* /*
* Manual Result Sets -- use assigned column width (i.e., from * Manual Result Sets -- use assigned column width (i.e., from
...@@ -615,10 +694,7 @@ getTimestampPrecision(StatementClass *stmt, Int4 type, int col) ...@@ -615,10 +694,7 @@ getTimestampPrecision(StatementClass *stmt, Int4 type, int col)
fixed = 8; fixed = 8;
break; break;
case PG_TYPE_TIME_WITH_TMZONE: case PG_TYPE_TIME_WITH_TMZONE:
if (USE_ZONE) fixed = 11;
fixed = 11;
else
fixed = 8;
break; break;
case PG_TYPE_TIMESTAMP_NO_TMZONE: case PG_TYPE_TIMESTAMP_NO_TMZONE:
fixed = 19; fixed = 19;
...@@ -692,7 +768,10 @@ pgtype_precision(StatementClass *stmt, Int4 type, int col, int handle_unknown_si ...@@ -692,7 +768,10 @@ pgtype_precision(StatementClass *stmt, Int4 type, int col, int handle_unknown_si
return getTimestampPrecision(stmt, type, col); return getTimestampPrecision(stmt, type, col);
case PG_TYPE_BOOL: case PG_TYPE_BOOL:
return 1; {
BOOL true_is_minus1 = FALSE;
return true_is_minus1 ? 2 : 1;
}
case PG_TYPE_LO: case PG_TYPE_LO:
return SQL_NO_TOTAL; return SQL_NO_TOTAL;
...@@ -756,6 +835,8 @@ pgtype_display_size(StatementClass *stmt, Int4 type, int col, int handle_unknown ...@@ -756,6 +835,8 @@ pgtype_display_size(StatementClass *stmt, Int4 type, int col, int handle_unknown
Int4 Int4
pgtype_length(StatementClass *stmt, Int4 type, int col, int handle_unknown_size_as) pgtype_length(StatementClass *stmt, Int4 type, int col, int handle_unknown_size_as)
{ {
ConnectionClass *conn = SC_get_conn(stmt);
switch (type) switch (type)
{ {
case PG_TYPE_INT2: case PG_TYPE_INT2:
...@@ -791,15 +872,27 @@ pgtype_length(StatementClass *stmt, Int4 type, int col, int handle_unknown_size_ ...@@ -791,15 +872,27 @@ pgtype_length(StatementClass *stmt, Int4 type, int col, int handle_unknown_size_
/* Character types (and NUMERIC) use the default precision */ /* Character types (and NUMERIC) use the default precision */
case PG_TYPE_VARCHAR: case PG_TYPE_VARCHAR:
case PG_TYPE_BPCHAR: case PG_TYPE_BPCHAR:
{
int coef = 1;
Int4 prec = pgtype_precision(stmt, type, col, handle_unknown_size_as), maxvarc;
if (conn->unicode)
return (prec + 1) * 2;
#ifdef MULTIBYTE #ifdef MULTIBYTE
/* after 7.2 */ /* after 7.2 */
if (PG_VERSION_GE(SC_get_conn(stmt), 7.2)) if (PG_VERSION_GE(conn, 7.2))
return 3 * pgtype_precision(stmt, type, col, handle_unknown_size_as); coef = 3;
else else
#else
/* CR -> CR/LF */
return 2 * pgtype_precision(stmt, type, col, handle_unknown_size_as);
#endif /* MULTIBYTE */ #endif /* MULTIBYTE */
if ((conn->connInfo).lf_conversion)
/* CR -> CR/LF */
coef = 2;
if (coef == 1)
return prec + 1;
maxvarc = conn->connInfo.drivers.max_varchar_size;
if (prec <= maxvarc && prec * coef > maxvarc)
return maxvarc;
return coef * prec;
}
default: default:
return pgtype_precision(stmt, type, col, handle_unknown_size_as); return pgtype_precision(stmt, type, col, handle_unknown_size_as);
} }
...@@ -885,8 +978,8 @@ pgtype_auto_increment(StatementClass *stmt, Int4 type) ...@@ -885,8 +978,8 @@ pgtype_auto_increment(StatementClass *stmt, Int4 type)
case PG_TYPE_NUMERIC: case PG_TYPE_NUMERIC:
case PG_TYPE_DATE: case PG_TYPE_DATE:
case PG_TYPE_TIME:
case PG_TYPE_TIME_WITH_TMZONE: case PG_TYPE_TIME_WITH_TMZONE:
case PG_TYPE_TIME:
case PG_TYPE_ABSTIME: case PG_TYPE_ABSTIME:
case PG_TYPE_DATETIME: case PG_TYPE_DATETIME:
case PG_TYPE_TIMESTAMP: case PG_TYPE_TIMESTAMP:
...@@ -1058,9 +1151,16 @@ sqltype_to_default_ctype(Int2 sqltype) ...@@ -1058,9 +1151,16 @@ sqltype_to_default_ctype(Int2 sqltype)
#else #else
return SQL_C_CHAR; return SQL_C_CHAR;
case SQL_BIGINT: case SQL_BIGINT:
return SQL_C_SBIGINT; return ALLOWED_C_BIGINT;
#endif #endif
#ifdef UNICODE_SUPPORT
case SQL_WCHAR:
case SQL_WVARCHAR:
case SQL_WLONGVARCHAR:
return SQL_C_WCHAR;
#endif /* UNICODE_SUPPORT */
case SQL_BIT: case SQL_BIT:
return SQL_C_BIT; return SQL_C_BIT;
...@@ -1086,24 +1186,23 @@ sqltype_to_default_ctype(Int2 sqltype) ...@@ -1086,24 +1186,23 @@ sqltype_to_default_ctype(Int2 sqltype)
return SQL_C_BINARY; return SQL_C_BINARY;
case SQL_DATE: case SQL_DATE:
#if (ODBCVER >= 0x0300)
return SQL_C_TYPE_DATE;
#else
return SQL_C_DATE; return SQL_C_DATE;
#endif /* ODBCVER */
case SQL_TIME: case SQL_TIME:
#if (ODBCVER >= 0x0300)
return SQL_C_TYPE_TIME;
#else
return SQL_C_TIME; return SQL_C_TIME;
#endif /* ODBCVER */
case SQL_TIMESTAMP: case SQL_TIMESTAMP:
return SQL_C_TIMESTAMP;
#if (ODBCVER >= 0x0300) #if (ODBCVER >= 0x0300)
case SQL_TYPE_DATE:
return SQL_C_TYPE_DATE;
case SQL_TYPE_TIME:
return SQL_C_TYPE_TIME;
case SQL_TYPE_TIMESTAMP:
return SQL_C_TYPE_TIMESTAMP; return SQL_C_TYPE_TIMESTAMP;
#else
return SQL_C_TIMESTAMP;
#endif /* ODBCVER */ #endif /* ODBCVER */
default: default:
...@@ -1167,6 +1266,7 @@ ctype_length(Int2 ctype) ...@@ -1167,6 +1266,7 @@ ctype_length(Int2 ctype)
case SQL_C_BINARY: case SQL_C_BINARY:
case SQL_C_CHAR: case SQL_C_CHAR:
case SQL_C_WCHAR:
return 0; return 0;
default: /* should never happen */ default: /* should never happen */
......
...@@ -5,7 +5,7 @@ ...@@ -5,7 +5,7 @@
* *
* Comments: See "notice.txt" for copyright and license information. * Comments: See "notice.txt" for copyright and license information.
* *
* $Id: psqlodbc.h,v 1.57 2002/02/18 03:16:11 inoue Exp $ * $Id: psqlodbc.h,v 1.58 2002/03/08 08:52:53 inoue Exp $
* *
*/ */
...@@ -87,7 +87,7 @@ typedef UInt4 Oid; ...@@ -87,7 +87,7 @@ typedef UInt4 Oid;
#define DBMS_NAME "PostgreSQL" #define DBMS_NAME "PostgreSQL"
#endif /* ODBCVER */ #endif /* ODBCVER */
#define POSTGRESDRIVERVERSION "07.01.0010" #define POSTGRESDRIVERVERSION "07.01.0011"
#ifdef WIN32 #ifdef WIN32
#if (ODBCVER >= 0x0300) #if (ODBCVER >= 0x0300)
...@@ -254,6 +254,11 @@ void logs_on_off(int cnopen, int, int); ...@@ -254,6 +254,11 @@ void logs_on_off(int cnopen, int, int);
#include "misc.h" #include "misc.h"
#ifdef UNICODE_SUPPORT
UInt4 ucs2strlen(const SQLWCHAR *ucs2str);
char *ucs2_to_utf8(const SQLWCHAR *ucs2str, Int4 ilen, UInt4 *olen);
UInt4 utf8_to_ucs2(const char * utf8str, Int4 ilen, SQLWCHAR *ucs2str, UInt4 buflen);
#endif /* UNICODE_SUPPORT */
#ifdef _MEMORY_DEBUG_ #ifdef _MEMORY_DEBUG_
void *debug_alloc(size_t); void *debug_alloc(size_t);
void *debug_realloc(void *, size_t); void *debug_realloc(void *, size_t);
......
...@@ -138,7 +138,7 @@ BEGIN ...@@ -138,7 +138,7 @@ BEGIN
BS_NOTIFY | WS_TABSTOP,247,205,40,10 BS_NOTIFY | WS_TABSTOP,247,205,40,10
END END
DLG_OPTIONS_DS DIALOG DISCARDABLE 0, 0, 267, 161 DLG_OPTIONS_DS DIALOG DISCARDABLE 0, 0, 267, 176
STYLE DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU STYLE DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU
CAPTION "Advanced Options (DataSource)" CAPTION "Advanced Options (DataSource)"
FONT 10, "Terminal" FONT 10, "Terminal"
...@@ -151,23 +151,27 @@ BEGIN ...@@ -151,23 +151,27 @@ BEGIN
BS_AUTOCHECKBOX | WS_TABSTOP,45,28,88,10 BS_AUTOCHECKBOX | WS_TABSTOP,45,28,88,10
CONTROL "Disallow &Premature",DS_DISALLOWPREMATURE,"Button", CONTROL "Disallow &Premature",DS_DISALLOWPREMATURE,"Button",
BS_AUTOCHECKBOX | WS_TABSTOP,149,28,86,10 BS_AUTOCHECKBOX | WS_TABSTOP,149,28,86,10
GROUPBOX "Protocol",IDC_STATIC,43,44,180,25 CONTROL "LF <-> CR/LF convert",DS_LFCONVERSION,"Button",
BS_AUTOCHECKBOX | WS_TABSTOP,45,43,92,10
CONTROL "True is -1",DS_TRUEISMINUS1,"Button",
BS_AUTOCHECKBOX | WS_TABSTOP,149,43,86,10
GROUPBOX "Protocol",IDC_STATIC,43,59,180,25
CONTROL "7.X,6.4+",DS_PG64,"Button",BS_AUTORADIOBUTTON | CONTROL "7.X,6.4+",DS_PG64,"Button",BS_AUTORADIOBUTTON |
WS_GROUP,53,54,47,10 WS_GROUP,53,69,47,10
CONTROL "6.3",DS_PG63,"Button",BS_AUTORADIOBUTTON | WS_TABSTOP, CONTROL "6.3",DS_PG63,"Button",BS_AUTORADIOBUTTON | WS_TABSTOP,
131,54,26,10 131,69,26,10
CONTROL "6.2",DS_PG62,"Button",BS_AUTORADIOBUTTON | WS_TABSTOP, CONTROL "6.2",DS_PG62,"Button",BS_AUTORADIOBUTTON | WS_TABSTOP,
187,54,26,10 187,69,26,10
GROUPBOX "OID Options",IDC_STATIC,43,74,180,25 GROUPBOX "OID Options",IDC_STATIC,43,89,180,25
CONTROL "Show &Column",DS_SHOWOIDCOLUMN,"Button",BS_AUTOCHECKBOX | CONTROL "Show &Column",DS_SHOWOIDCOLUMN,"Button",BS_AUTOCHECKBOX |
WS_GROUP | WS_TABSTOP,53,85,59,10 WS_GROUP | WS_TABSTOP,53,100,59,10
CONTROL "Fake &Index",DS_FAKEOIDINDEX,"Button",BS_AUTOCHECKBOX | CONTROL "Fake &Index",DS_FAKEOIDINDEX,"Button",BS_AUTOCHECKBOX |
WS_GROUP | WS_TABSTOP,161,85,55,10 WS_GROUP | WS_TABSTOP,161,100,55,10
LTEXT "Connect &Settings:",IDC_STATIC,10,105,35,25 LTEXT "Connect &Settings:",IDC_STATIC,10,120,35,25
EDITTEXT DS_CONNSETTINGS,50,105,200,20,ES_MULTILINE | EDITTEXT DS_CONNSETTINGS,50,120,200,20,ES_MULTILINE |
ES_AUTOVSCROLL | ES_AUTOHSCROLL | ES_WANTRETURN ES_AUTOVSCROLL | ES_AUTOHSCROLL | ES_WANTRETURN
DEFPUSHBUTTON "OK",IDOK,71,135,50,14,WS_GROUP DEFPUSHBUTTON "OK",IDOK,71,150,50,14,WS_GROUP
PUSHBUTTON "Cancel",IDCANCEL,146,135,50,14 PUSHBUTTON "Cancel",IDCANCEL,146,150,50,14
END END
#else #else
DLG_CONFIG DIALOG DISCARDABLE 65, 43, 292, 116 DLG_CONFIG DIALOG DISCARDABLE 65, 43, 292, 116
...@@ -255,7 +259,7 @@ BEGIN ...@@ -255,7 +259,7 @@ BEGIN
BS_NOTIFY | WS_TABSTOP,233,224,40,10 BS_NOTIFY | WS_TABSTOP,233,224,40,10
END END
DLG_OPTIONS_DS DIALOG DISCARDABLE 0, 0, 267, 161 DLG_OPTIONS_DS DIALOG DISCARDABLE 0, 0, 267, 176
STYLE DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU STYLE DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU
CAPTION "Advanced Options (DataSource)" CAPTION "Advanced Options (DataSource)"
FONT 8, "MS Sans Serif" FONT 8, "MS Sans Serif"
...@@ -268,23 +272,27 @@ BEGIN ...@@ -268,23 +272,27 @@ BEGIN
BS_AUTOCHECKBOX | WS_TABSTOP,25,25,85,10 BS_AUTOCHECKBOX | WS_TABSTOP,25,25,85,10
CONTROL "Disallow &Premature",DS_DISALLOWPREMATURE,"Button", CONTROL "Disallow &Premature",DS_DISALLOWPREMATURE,"Button",
BS_AUTOCHECKBOX | WS_TABSTOP,130,25,85,10 BS_AUTOCHECKBOX | WS_TABSTOP,130,25,85,10
GROUPBOX "Protocol",IDC_STATIC,15,40,180,25 CONTROL "LF <-> CR/LF convert",DS_LFCONVERSION,"Button",
BS_AUTOCHECKBOX | WS_TABSTOP,45,40,92,10
CONTROL "True is -1",DS_TRUEISMINUS1,"Button",
BS_AUTOCHECKBOX | WS_TABSTOP,149,40,86,10
GROUPBOX "Protocol",IDC_STATIC,15,55,180,25
CONTROL "7.X,6.4+",DS_PG64,"Button",BS_AUTORADIOBUTTON | WS_GROUP,25, CONTROL "7.X,6.4+",DS_PG64,"Button",BS_AUTORADIOBUTTON | WS_GROUP,25,
50,35,10 65,35,10
CONTROL "6.3",DS_PG63,"Button",BS_AUTORADIOBUTTON | WS_TABSTOP, CONTROL "6.3",DS_PG63,"Button",BS_AUTORADIOBUTTON | WS_TABSTOP,
75,50,26,10 75,65,26,10
CONTROL "6.2",DS_PG62,"Button",BS_AUTORADIOBUTTON | WS_TABSTOP, CONTROL "6.2",DS_PG62,"Button",BS_AUTORADIOBUTTON | WS_TABSTOP,
130,50,26,10 130,65,26,10
GROUPBOX "OID Options",IDC_STATIC,15,70,180,25 GROUPBOX "OID Options",IDC_STATIC,15,86,180,25
CONTROL "Show &Column",DS_SHOWOIDCOLUMN,"Button",BS_AUTOCHECKBOX | CONTROL "Show &Column",DS_SHOWOIDCOLUMN,"Button",BS_AUTOCHECKBOX |
WS_GROUP | WS_TABSTOP,25,81,59,10 WS_GROUP | WS_TABSTOP,25,96,59,10
CONTROL "Fake &Index",DS_FAKEOIDINDEX,"Button",BS_AUTOCHECKBOX | CONTROL "Fake &Index",DS_FAKEOIDINDEX,"Button",BS_AUTOCHECKBOX |
WS_GROUP | WS_TABSTOP,115,81,51,10 WS_GROUP | WS_TABSTOP,115,96,51,10
RTEXT "Connect &Settings:",IDC_STATIC,10,105,35,25 RTEXT "Connect &Settings:",IDC_STATIC,10,120,35,25
EDITTEXT DS_CONNSETTINGS,50,105,200,20,ES_MULTILINE | EDITTEXT DS_CONNSETTINGS,50,120,200,20,ES_MULTILINE |
ES_AUTOVSCROLL | ES_AUTOHSCROLL | ES_WANTRETURN ES_AUTOVSCROLL | ES_AUTOHSCROLL | ES_WANTRETURN
DEFPUSHBUTTON "OK",IDOK,71,135,50,14,WS_GROUP DEFPUSHBUTTON "OK",IDOK,71,150,50,14,WS_GROUP
PUSHBUTTON "Cancel",IDCANCEL,146,135,50,14 PUSHBUTTON "Cancel",IDCANCEL,146,150,50,14
END END
#endif #endif
...@@ -354,8 +362,8 @@ END ...@@ -354,8 +362,8 @@ END
// //
VS_VERSION_INFO VERSIONINFO VS_VERSION_INFO VERSIONINFO
FILEVERSION 7,1,0,10 FILEVERSION 7,1,0,11
PRODUCTVERSION 7,1,0,10 PRODUCTVERSION 7,1,0,11
FILEFLAGSMASK 0x3L FILEFLAGSMASK 0x3L
#ifdef _DEBUG #ifdef _DEBUG
FILEFLAGS 0x1L FILEFLAGS 0x1L
...@@ -377,14 +385,14 @@ BEGIN ...@@ -377,14 +385,14 @@ BEGIN
VALUE "CompanyName", "Insight Distribution Systems\0" VALUE "CompanyName", "Insight Distribution Systems\0"
#endif #endif
VALUE "FileDescription", "PostgreSQL Driver\0" VALUE "FileDescription", "PostgreSQL Driver\0"
VALUE "FileVersion", " 07.01.0010\0" VALUE "FileVersion", " 07.01.0011\0"
VALUE "InternalName", "psqlodbc\0" VALUE "InternalName", "psqlodbc\0"
VALUE "LegalCopyright", "\0" VALUE "LegalCopyright", "\0"
VALUE "LegalTrademarks", "ODBC(TM) is a trademark of Microsoft Corporation. Microsoft is a registered trademark of Microsoft Corporation. Windows(TM) is a trademark of Microsoft Corporation.\0" VALUE "LegalTrademarks", "ODBC(TM) is a trademark of Microsoft Corporation. Microsoft is a registered trademark of Microsoft Corporation. Windows(TM) is a trademark of Microsoft Corporation.\0"
VALUE "OriginalFilename", "psqlodbc.dll\0" VALUE "OriginalFilename", "psqlodbc.dll\0"
VALUE "PrivateBuild", "\0" VALUE "PrivateBuild", "\0"
VALUE "ProductName", "Microsoft Open Database Connectivity\0" VALUE "ProductName", "Microsoft Open Database Connectivity\0"
VALUE "ProductVersion", " 07.01.0010\0" VALUE "ProductVersion", " 07.01.0011\0"
VALUE "SpecialBuild", "\0" VALUE "SpecialBuild", "\0"
END END
END END
......
LIBRARY psqlodbc30
EXPORTS
SQLAllocConnect @1
SQLAllocEnv @2
SQLAllocStmt @3
SQLBindCol @4
SQLCancel @5
SQLColAttributes @6
SQLConnect @7
SQLDescribeCol @8
SQLDisconnect @9
SQLError @10
SQLExecDirect @11
SQLExecute @12
SQLFetch @13
SQLFreeConnect @14
SQLFreeEnv @15
SQLFreeStmt @16
SQLGetCursorName @17
SQLNumResultCols @18
SQLPrepare @19
SQLRowCount @20
SQLSetCursorName @21
SQLTransact @23
SQLColumns @40
SQLDriverConnect @41
SQLGetData @43
SQLGetFunctions @44
SQLGetInfo @45
SQLGetStmtOption @46
SQLGetTypeInfo @47
SQLParamData @48
SQLPutData @49
SQLSpecialColumns @52
SQLStatistics @53
SQLTables @54
SQLBrowseConnect @55
SQLColumnPrivileges @56
SQLDescribeParam @58
SQLExtendedFetch @59
SQLForeignKeys @60
SQLMoreResults @61
SQLNativeSql @62
SQLNumParams @63
SQLParamOptions @64
SQLPrimaryKeys @65
SQLProcedureColumns @66
SQLProcedures @67
SQLSetPos @68
SQLSetScrollOptions @69
SQLTablePrivileges @70
SQLBindParameter @72
SQLAllocHandle @80
SQLBindParam @81
SQLCloseCursor @82
SQLColAttribute @83
SQLCopyDesc @84
SQLEndTran @85
SQLFetchScroll @86
SQLFreeHandle @87
SQLGetDescField @88
SQLGetDescRec @89
SQLGetDiagField @90
SQLGetDiagRec @91
SQLGetEnvAttr @92
SQLGetConnectAttr @93
SQLGetStmtAttr @94
SQLSetConnectAttr @95
SQLSetDescField @96
SQLSetDescRec @97
SQLSetEnvAttr @98
SQLSetStmtAttr @99
SQLDummyOrdinal @199
dconn_FDriverConnectProc @200
DllMain @201
ConfigDSN @202
SQLColAttributeW @101
SQLColumnPrivilegesW @102
SQLColumnsW @103
SQLConnectW @104
SQLDescribeColW @106
SQLExecDirectW @107
SQLForeignKeysW @108
SQLGetConnectAttrW @109
SQLGetCursorNameW @110
SQLGetInfoW @111
SQLNativeSqlW @112
SQLPrepareW @113
SQLPrimaryKeysW @114
SQLProcedureColumnsW @115
SQLProceduresW @116
SQLSetConnectAttrW @117
SQLSetCursorNameW @118
SQLSpecialColumnsW @119
SQLStatisticsW @120
SQLTablesW @121
SQLTablePrivilegesW @122
SQLDriverConnectW @123
SQLGetDiagRecW @124
SQLGetStmtAttrW @125
SQLSetStmtAttrW @126
SQLSetDescFieldW @127
SQLGetTypeInfoW @128
LIBRARY psqlodbc
EXPORTS
SQLAllocConnect @1
SQLAllocEnv @2
SQLAllocStmt @3
SQLBindCol @4
SQLCancel @5
SQLColAttributes @6
SQLConnect @7
SQLDescribeCol @8
SQLDisconnect @9
SQLError @10
SQLExecDirect @11
SQLExecute @12
SQLFetch @13
SQLFreeConnect @14
SQLFreeEnv @15
SQLFreeStmt @16
SQLGetCursorName @17
SQLNumResultCols @18
SQLPrepare @19
SQLRowCount @20
SQLSetCursorName @21
SQLTransact @23
SQLColumns @40
SQLDriverConnect @41
SQLGetConnectOption @42
SQLGetData @43
SQLGetFunctions @44
SQLGetInfo @45
SQLGetStmtOption @46
SQLGetTypeInfo @47
SQLParamData @48
SQLPutData @49
SQLSetConnectOption @50
SQLSetStmtOption @51
SQLSpecialColumns @52
SQLStatistics @53
SQLTables @54
SQLBrowseConnect @55
SQLColumnPrivileges @56
SQLDescribeParam @58
SQLExtendedFetch @59
SQLForeignKeys @60
SQLMoreResults @61
SQLNativeSql @62
SQLNumParams @63
SQLParamOptions @64
SQLPrimaryKeys @65
SQLProcedureColumns @66
SQLProcedures @67
SQLSetPos @68
SQLSetScrollOptions @69
SQLTablePrivileges @70
SQLBindParameter @72
SQLColAttributesW @101
SQLColumnPrivilegesW @102
SQLColumnsW @103
SQLConnectW @104
SQLDescribeColW @106
SQLExecDirectW @107
SQLForeignKeysW @108
SQLGetConnectOptionW @109
SQLGetCursorNameW @110
SQLGetInfoW @111
SQLNativeSqlW @112
SQLPrepareW @113
SQLPrimaryKeysW @114
SQLProcedureColumnsW @115
SQLProceduresW @116
SQLSetConnectOptionW @117
SQLSetCursorNameW @118
SQLSpecialColumnsW @119
SQLStatisticsW @120
SQLTablesW @121
SQLTablePrivilegesW @122
SQLDriverConnectW @123
SQLErrorW @124
SQLGetTypeInfoW @128
dconn_FDriverConnectProc @200
DllMain @201
ConfigDSN @202
...@@ -108,6 +108,7 @@ QR_Constructor() ...@@ -108,6 +108,7 @@ QR_Constructor()
rv->command = NULL; rv->command = NULL;
rv->notice = NULL; rv->notice = NULL;
rv->conn = NULL; rv->conn = NULL;
rv->next = NULL;
rv->inTuples = FALSE; rv->inTuples = FALSE;
rv->fcount = 0; rv->fcount = 0;
rv->fetch_count = 0; rv->fetch_count = 0;
...@@ -160,6 +161,9 @@ QR_Destructor(QResultClass *self) ...@@ -160,6 +161,9 @@ QR_Destructor(QResultClass *self)
/* Free notice info (this is from strdup()) */ /* Free notice info (this is from strdup()) */
if (self->notice) if (self->notice)
free(self->notice); free(self->notice);
/* Destruct the result object in the chain */
if (self->next)
QR_Destructor(self->next);
free(self); free(self);
...@@ -247,6 +251,7 @@ QR_fetch_tuples(QResultClass *self, ConnectionClass *conn, char *cursor) ...@@ -247,6 +251,7 @@ QR_fetch_tuples(QResultClass *self, ConnectionClass *conn, char *cursor)
if (self->cursor) if (self->cursor)
free(self->cursor); free(self->cursor);
self->cursor = NULL;
if (fetch_cursor) if (fetch_cursor)
{ {
...@@ -342,7 +347,7 @@ QR_close(QResultClass *self) ...@@ -342,7 +347,7 @@ QR_close(QResultClass *self)
sprintf(buf, "close %s", self->cursor); sprintf(buf, "close %s", self->cursor);
mylog("QResult: closing cursor: '%s'\n", buf); mylog("QResult: closing cursor: '%s'\n", buf);
res = CC_send_query(self->conn, buf, NULL); res = CC_send_query(self->conn, buf, NULL, TRUE);
self->inTuples = FALSE; self->inTuples = FALSE;
self->currTuple = -1; self->currTuple = -1;
...@@ -487,13 +492,11 @@ QR_next_tuple(QResultClass *self) ...@@ -487,13 +492,11 @@ QR_next_tuple(QResultClass *self)
qi.row_size = self->cache_size; qi.row_size = self->cache_size;
qi.result_in = self; qi.result_in = self;
qi.cursor = NULL; qi.cursor = NULL;
res = CC_send_query(self->conn, fetch, &qi); res = CC_send_query(self->conn, fetch, &qi, TRUE);
if (res == NULL || QR_get_aborted(res)) if (res == NULL)
{ {
self->status = PGRES_FATAL_ERROR; self->status = PGRES_FATAL_ERROR;
QR_set_message(self, "Error fetching next group."); QR_set_message(self, "Error fetching next group.");
if (res)
QR_Destructor(res);
return FALSE; return FALSE;
} }
self->inTuples = TRUE; self->inTuples = TRUE;
...@@ -689,7 +692,7 @@ QR_read_tuple(QResultClass *self, char binary) ...@@ -689,7 +692,7 @@ QR_read_tuple(QResultClass *self, char binary)
*/ */
flds = self->fields; flds = self->fields;
if (flds->display_size[field_lf] < len) if (flds && flds->display_size && flds->display_size[field_lf] < len)
flds->display_size[field_lf] = len; flds->display_size[field_lf] = len;
} }
......
...@@ -45,6 +45,7 @@ struct QResultClass_ ...@@ -45,6 +45,7 @@ struct QResultClass_
TupleListClass *manual_tuples; /* manual result tuple list */ TupleListClass *manual_tuples; /* manual result tuple list */
ConnectionClass *conn; /* the connection this result is using ConnectionClass *conn; /* the connection this result is using
* (backend) */ * (backend) */
QResultClass *next; /* the following result class */
/* Stuff for declare/fetch tuples */ /* Stuff for declare/fetch tuples */
int count_allocated; /* m(re)alloced count */ int count_allocated; /* m(re)alloced count */
......
...@@ -52,6 +52,8 @@ ...@@ -52,6 +52,8 @@
#define DRV_OR_DSN 1059 #define DRV_OR_DSN 1059
#define DRV_DEBUG 1060 #define DRV_DEBUG 1060
#define DS_DISALLOWPREMATURE 1061 #define DS_DISALLOWPREMATURE 1061
#define DS_LFCONVERSION 1062
#define DS_TRUEISMINUS1 1063
/* Next default values for new objects */ /* Next default values for new objects */
/* */ /* */
......
...@@ -8,7 +8,7 @@ ...@@ -8,7 +8,7 @@
* *
* API functions: SQLRowCount, SQLNumResultCols, SQLDescribeCol, * API functions: SQLRowCount, SQLNumResultCols, SQLDescribeCol,
* SQLColAttributes, SQLGetData, SQLFetch, SQLExtendedFetch, * SQLColAttributes, SQLGetData, SQLFetch, SQLExtendedFetch,
* SQLMoreResults(NI), SQLSetPos, SQLSetScrollOptions(NI), * SQLMoreResults, SQLSetPos, SQLSetScrollOptions(NI),
* SQLSetCursorName, SQLGetCursorName * SQLSetCursorName, SQLGetCursorName
* *
* Comments: See "notice.txt" for copyright and license information. * Comments: See "notice.txt" for copyright and license information.
...@@ -45,6 +45,7 @@ PGAPI_RowCount( ...@@ -45,6 +45,7 @@ PGAPI_RowCount(
*ptr; *ptr;
ConnInfo *ci; ConnInfo *ci;
mylog("%s: entering...\n", func);
if (!stmt) if (!stmt)
{ {
SC_log_error(func, "", NULL); SC_log_error(func, "", NULL);
...@@ -62,7 +63,7 @@ PGAPI_RowCount( ...@@ -62,7 +63,7 @@ PGAPI_RowCount(
{ {
if (stmt->status == STMT_FINISHED) if (stmt->status == STMT_FINISHED)
{ {
res = SC_get_Result(stmt); res = SC_get_Curres(stmt);
if (res && pcrow) if (res && pcrow)
{ {
...@@ -73,7 +74,7 @@ PGAPI_RowCount( ...@@ -73,7 +74,7 @@ PGAPI_RowCount(
} }
else else
{ {
res = SC_get_Result(stmt); res = SC_get_Curres(stmt);
if (res && pcrow) if (res && pcrow)
{ {
msg = QR_get_command(res); msg = QR_get_command(res);
...@@ -115,6 +116,7 @@ PGAPI_NumResultCols( ...@@ -115,6 +116,7 @@ PGAPI_NumResultCols(
char parse_ok; char parse_ok;
ConnInfo *ci; ConnInfo *ci;
mylog("%s: entering...\n", func);
if (!stmt) if (!stmt)
{ {
SC_log_error(func, "", NULL); SC_log_error(func, "", NULL);
...@@ -144,7 +146,7 @@ PGAPI_NumResultCols( ...@@ -144,7 +146,7 @@ PGAPI_NumResultCols(
if (!parse_ok) if (!parse_ok)
{ {
SC_pre_execute(stmt); SC_pre_execute(stmt);
result = SC_get_Result(stmt); result = SC_get_Curres(stmt);
mylog("PGAPI_NumResultCols: result = %u, status = %d, numcols = %d\n", result, stmt->status, result != NULL ? QR_NumResultCols(result) : -1); mylog("PGAPI_NumResultCols: result = %u, status = %d, numcols = %d\n", result, stmt->status, result != NULL ? QR_NumResultCols(result) : -1);
if ((!result) || ((stmt->status != STMT_FINISHED) && (stmt->status != STMT_PREMATURE))) if ((!result) || ((stmt->status != STMT_FINISHED) && (stmt->status != STMT_PREMATURE)))
...@@ -210,6 +212,25 @@ PGAPI_DescribeCol( ...@@ -210,6 +212,25 @@ PGAPI_DescribeCol(
SC_clear_error(stmt); SC_clear_error(stmt);
#if (ODBCVER >= 0x0300)
if (0 == icol) /* bookmark column */
{
SQLSMALLINT fType = SQL_INTEGER;
if (szColName && cbColNameMax > 0)
*szColName = '\0';
if (pcbColName)
*pcbColName = 0;
if (pfSqlType)
*pfSqlType = fType;
if (pcbColDef)
*pcbColDef = 10;
if (pibScale)
*pibScale = 0;
if (pfNullable)
*pfNullable = SQL_NO_NULLS;
return SQL_SUCCESS;
}
#endif /* ODBCVER */
/* /*
* Dont check for bookmark column. This is the responsibility of the * Dont check for bookmark column. This is the responsibility of the
* driver manager. * driver manager.
...@@ -262,7 +283,7 @@ PGAPI_DescribeCol( ...@@ -262,7 +283,7 @@ PGAPI_DescribeCol(
{ {
SC_pre_execute(stmt); SC_pre_execute(stmt);
res = SC_get_Result(stmt); res = SC_get_Curres(stmt);
mylog("**** PGAPI_DescribeCol: res = %u, stmt->status = %d, !finished=%d, !premature=%d\n", res, stmt->status, stmt->status != STMT_FINISHED, stmt->status != STMT_PREMATURE); mylog("**** PGAPI_DescribeCol: res = %u, stmt->status = %d, !finished=%d, !premature=%d\n", res, stmt->status, stmt->status != STMT_FINISHED, stmt->status != STMT_PREMATURE);
if ((NULL == res) || ((stmt->status != STMT_FINISHED) && (stmt->status != STMT_PREMATURE))) if ((NULL == res) || ((stmt->status != STMT_FINISHED) && (stmt->status != STMT_PREMATURE)))
...@@ -305,7 +326,7 @@ PGAPI_DescribeCol( ...@@ -305,7 +326,7 @@ PGAPI_DescribeCol(
if (pcbColName) if (pcbColName)
*pcbColName = len; *pcbColName = len;
if (szColName) if (szColName && cbColNameMax > 0)
{ {
strncpy_null(szColName, col_name, cbColNameMax); strncpy_null(szColName, col_name, cbColNameMax);
...@@ -379,17 +400,19 @@ PGAPI_ColAttributes( ...@@ -379,17 +400,19 @@ PGAPI_ColAttributes(
{ {
static char *func = "PGAPI_ColAttributes"; static char *func = "PGAPI_ColAttributes";
StatementClass *stmt = (StatementClass *) hstmt; StatementClass *stmt = (StatementClass *) hstmt;
Int4 field_type = 0; Int4 col_idx, field_type = 0;
ConnInfo *ci; ConnectionClass *conn;
ConnInfo *ci;
int unknown_sizes; int unknown_sizes;
int cols = 0; int cols = 0;
char parse_ok; char parse_ok;
RETCODE result; RETCODE result;
char *p = NULL; const char *p = NULL;
int len = 0, int len = 0,
value = 0; value = 0;
const FIELD_INFO *fi = NULL;
mylog("%s: entering...\n", func); mylog("%s: entering..col=%d %d.\n", func, icol, fDescType);
if (!stmt) if (!stmt)
{ {
...@@ -397,7 +420,8 @@ PGAPI_ColAttributes( ...@@ -397,7 +420,8 @@ PGAPI_ColAttributes(
return SQL_INVALID_HANDLE; return SQL_INVALID_HANDLE;
} }
ci = &(SC_get_conn(stmt)->connInfo); conn = SC_get_conn(stmt);
ci = &(conn->connInfo);
/* /*
* Dont check for bookmark column. This is the responsibility of the * Dont check for bookmark column. This is the responsibility of the
...@@ -405,7 +429,24 @@ PGAPI_ColAttributes( ...@@ -405,7 +429,24 @@ PGAPI_ColAttributes(
* is ignored anyway, so it may be 0. * is ignored anyway, so it may be 0.
*/ */
icol--; #if (ODBCVER >= 0x0300)
if (0 == icol) /* bookmark column */
{
switch (fDescType)
{
case SQL_DESC_OCTET_LENGTH:
if (pfDesc)
*pfDesc = 4;
break;
case SQL_DESC_TYPE:
if (pfDesc)
*pfDesc = SQL_INTEGER;
break;
}
return SQL_SUCCESS;
}
#endif /* ODBCVER */
col_idx = icol - 1;
/* atoi(ci->unknown_sizes); */ /* atoi(ci->unknown_sizes); */
unknown_sizes = ci->drivers.unknown_sizes; unknown_sizes = ci->drivers.unknown_sizes;
...@@ -437,28 +478,30 @@ PGAPI_ColAttributes( ...@@ -437,28 +478,30 @@ PGAPI_ColAttributes(
return SQL_SUCCESS; return SQL_SUCCESS;
} }
if (stmt->parse_status != STMT_PARSE_FATAL && stmt->fi && stmt->fi[icol]) if (stmt->parse_status != STMT_PARSE_FATAL && stmt->fi && stmt->fi[col_idx])
{ {
if (icol >= cols) if (col_idx >= cols)
{ {
stmt->errornumber = STMT_INVALID_COLUMN_NUMBER_ERROR; stmt->errornumber = STMT_INVALID_COLUMN_NUMBER_ERROR;
stmt->errormsg = "Invalid column number in ColAttributes."; stmt->errormsg = "Invalid column number in ColAttributes.";
SC_log_error(func, "", stmt); SC_log_error(func, "", stmt);
return SQL_ERROR; return SQL_ERROR;
} }
field_type = stmt->fi[icol]->type; field_type = stmt->fi[col_idx]->type;
if (field_type > 0) if (field_type > 0)
parse_ok = TRUE; parse_ok = TRUE;
} }
} }
if (!parse_ok) if (parse_ok)
fi = stmt->fi[col_idx];
else
{ {
SC_pre_execute(stmt); SC_pre_execute(stmt);
mylog("**** PGAPI_ColAtt: result = %u, status = %d, numcols = %d\n", stmt->result, stmt->status, stmt->result != NULL ? QR_NumResultCols(stmt->result) : -1); mylog("**** PGAPI_ColAtt: result = %u, status = %d, numcols = %d\n", SC_get_Curres(stmt), stmt->status, SC_get_Curres(stmt) != NULL ? QR_NumResultCols(SC_get_Curres(stmt)) : -1);
if ((NULL == stmt->result) || ((stmt->status != STMT_FINISHED) && (stmt->status != STMT_PREMATURE))) if ((NULL == SC_get_Curres(stmt)) || ((stmt->status != STMT_FINISHED) && (stmt->status != STMT_PREMATURE)))
{ {
stmt->errormsg = "Can't get column attributes: no result found."; stmt->errormsg = "Can't get column attributes: no result found.";
stmt->errornumber = STMT_SEQUENCE_ERROR; stmt->errornumber = STMT_SEQUENCE_ERROR;
...@@ -466,13 +509,17 @@ PGAPI_ColAttributes( ...@@ -466,13 +509,17 @@ PGAPI_ColAttributes(
return SQL_ERROR; return SQL_ERROR;
} }
cols = QR_NumResultCols(stmt->result); cols = QR_NumResultCols(SC_get_Curres(stmt));
/* /*
* Column Count is a special case. The Column number is ignored * Column Count is a special case. The Column number is ignored
* in this case. * in this case.
*/ */
#if (ODBCVER >= 0x0300)
if (fDescType == SQL_DESC_COUNT)
#else
if (fDescType == SQL_COLUMN_COUNT) if (fDescType == SQL_COLUMN_COUNT)
#endif /* ODBCVER */
{ {
if (pfDesc) if (pfDesc)
*pfDesc = cols; *pfDesc = cols;
...@@ -480,7 +527,7 @@ PGAPI_ColAttributes( ...@@ -480,7 +527,7 @@ PGAPI_ColAttributes(
return SQL_SUCCESS; return SQL_SUCCESS;
} }
if (icol >= cols) if (col_idx >= cols)
{ {
stmt->errornumber = STMT_INVALID_COLUMN_NUMBER_ERROR; stmt->errornumber = STMT_INVALID_COLUMN_NUMBER_ERROR;
stmt->errormsg = "Invalid column number in ColAttributes."; stmt->errormsg = "Invalid column number in ColAttributes.";
...@@ -488,21 +535,21 @@ PGAPI_ColAttributes( ...@@ -488,21 +535,21 @@ PGAPI_ColAttributes(
return SQL_ERROR; return SQL_ERROR;
} }
field_type = QR_get_field_type(stmt->result, icol); field_type = QR_get_field_type(SC_get_Curres(stmt), col_idx);
} }
mylog("colAttr: col %d field_type = %d\n", icol, field_type); mylog("colAttr: col %d field_type = %d\n", col_idx, field_type);
switch (fDescType) switch (fDescType)
{ {
case SQL_COLUMN_AUTO_INCREMENT: case SQL_COLUMN_AUTO_INCREMENT: /* == SQL_DESC_AUTO_UNIQUE_VALUE */
value = pgtype_auto_increment(stmt, field_type); value = pgtype_auto_increment(stmt, field_type);
if (value == -1) /* non-numeric becomes FALSE (ODBC Doc) */ if (value == -1) /* non-numeric becomes FALSE (ODBC Doc) */
value = FALSE; value = FALSE;
break; break;
case SQL_COLUMN_CASE_SENSITIVE: case SQL_COLUMN_CASE_SENSITIVE: /* == SQL_DESC_CASE_SENSITIVE */
value = pgtype_case_sensitive(stmt, field_type); value = pgtype_case_sensitive(stmt, field_type);
break; break;
...@@ -511,17 +558,17 @@ PGAPI_ColAttributes( ...@@ -511,17 +558,17 @@ PGAPI_ColAttributes(
* *
* case SQL_COLUMN_COUNT: * case SQL_COLUMN_COUNT:
*/ */
case SQL_COLUMN_DISPLAY_SIZE: case SQL_COLUMN_DISPLAY_SIZE: /* == SQL_DESC_DISPLAY_SIZE */
value = (parse_ok) ? stmt->fi[icol]->display_size : pgtype_display_size(stmt, field_type, icol, unknown_sizes); value = fi ? fi->display_size : pgtype_display_size(stmt, field_type, col_idx, unknown_sizes);
mylog("PGAPI_ColAttributes: col %d, display_size= %d\n", icol, value); mylog("PGAPI_ColAttributes: col %d, display_size= %d\n", col_idx, value);
break; break;
case SQL_COLUMN_LABEL: case SQL_COLUMN_LABEL: /* == SQL_DESC_LABEL */
if (parse_ok && stmt->fi[icol]->alias[0] != '\0') if (fi && fi->alias[0] != '\0')
{ {
p = stmt->fi[icol]->alias; p = fi->alias;
mylog("PGAPI_ColAttr: COLUMN_LABEL = '%s'\n", p); mylog("PGAPI_ColAttr: COLUMN_LABEL = '%s'\n", p);
break; break;
...@@ -529,70 +576,78 @@ PGAPI_ColAttributes( ...@@ -529,70 +576,78 @@ PGAPI_ColAttributes(
} }
/* otherwise same as column name -- FALL THROUGH!!! */ /* otherwise same as column name -- FALL THROUGH!!! */
#if (ODBCVER >= 0x0300)
case SQL_DESC_NAME:
#else
case SQL_COLUMN_NAME: case SQL_COLUMN_NAME:
p = (parse_ok) ? stmt->fi[icol]->name : QR_get_fieldname(stmt->result, icol); #endif /* ODBCVER */
p = fi ? (fi->alias[0] ? fi->alias : fi->name) : QR_get_fieldname(SC_get_Curres(stmt), col_idx);
mylog("PGAPI_ColAttr: COLUMN_NAME = '%s'\n", p); mylog("PGAPI_ColAttr: COLUMN_NAME = '%s'\n", p);
break; break;
case SQL_COLUMN_LENGTH: case SQL_COLUMN_LENGTH:
value = (parse_ok) ? stmt->fi[icol]->length : pgtype_length(stmt, field_type, icol, unknown_sizes); value = fi ? fi->length : pgtype_length(stmt, field_type, col_idx, unknown_sizes);
mylog("PGAPI_ColAttributes: col %d, length = %d\n", icol, value); mylog("PGAPI_ColAttributes: col %d, length = %d\n", col_idx, value);
break; break;
case SQL_COLUMN_MONEY: case SQL_COLUMN_MONEY: /* == SQL_DESC_FIXED_PREC_SCALE */
value = pgtype_money(stmt, field_type); value = pgtype_money(stmt, field_type);
break; break;
#if (ODBCVER >= 0x0300)
case SQL_DESC_NULLABLE:
#else
case SQL_COLUMN_NULLABLE: case SQL_COLUMN_NULLABLE:
value = (parse_ok) ? stmt->fi[icol]->nullable : pgtype_nullable(stmt, field_type); #endif /* ODBCVER */
value = fi ? fi->nullable : pgtype_nullable(stmt, field_type);
break; break;
case SQL_COLUMN_OWNER_NAME: case SQL_COLUMN_OWNER_NAME: /* == SQL_DESC_SCHEMA_NAME */
p = ""; p = "";
break; break;
case SQL_COLUMN_PRECISION: case SQL_COLUMN_PRECISION:
value = (parse_ok) ? stmt->fi[icol]->precision : pgtype_precision(stmt, field_type, icol, unknown_sizes); value = fi ? fi->precision : pgtype_precision(stmt, field_type, col_idx, unknown_sizes);
mylog("PGAPI_ColAttributes: col %d, precision = %d\n", icol, value); mylog("PGAPI_ColAttributes: col %d, precision = %d\n", col_idx, value);
break; break;
case SQL_COLUMN_QUALIFIER_NAME: case SQL_COLUMN_QUALIFIER_NAME: /* == SQL_DESC_CATALOG_NAME */
p = ""; p = "";
break; break;
case SQL_COLUMN_SCALE: case SQL_COLUMN_SCALE:
value = pgtype_scale(stmt, field_type, icol); value = pgtype_scale(stmt, field_type, col_idx);
break; break;
case SQL_COLUMN_SEARCHABLE: case SQL_COLUMN_SEARCHABLE: /* SQL_DESC_SEARCHABLE */
value = pgtype_searchable(stmt, field_type); value = pgtype_searchable(stmt, field_type);
break; break;
case SQL_COLUMN_TABLE_NAME: case SQL_COLUMN_TABLE_NAME: /* == SQL_DESC_TABLE_NAME */
p = (parse_ok && stmt->fi[icol]->ti) ? stmt->fi[icol]->ti->name : ""; p = fi && (fi->ti) ? fi->ti->name : "";
mylog("PGAPI_ColAttr: TABLE_NAME = '%s'\n", p); mylog("PGAPI_ColAttr: TABLE_NAME = '%s'\n", p);
break; break;
case SQL_COLUMN_TYPE: case SQL_COLUMN_TYPE: /* == SQL_DESC_CONCISE_TYPE */
value = pgtype_to_sqltype(stmt, field_type); value = pgtype_to_sqltype(stmt, field_type);
break; break;
case SQL_COLUMN_TYPE_NAME: case SQL_COLUMN_TYPE_NAME: /* == SQL_DESC_TYPE_NAME */
p = pgtype_to_name(stmt, field_type); p = pgtype_to_name(stmt, field_type);
break; break;
case SQL_COLUMN_UNSIGNED: case SQL_COLUMN_UNSIGNED: /* == SQL_DESC_UNSINGED */
value = pgtype_unsigned(stmt, field_type); value = pgtype_unsigned(stmt, field_type);
if (value == -1) /* non-numeric becomes TRUE (ODBC Doc) */ if (value == -1) /* non-numeric becomes TRUE (ODBC Doc) */
value = TRUE; value = TRUE;
break; break;
case SQL_COLUMN_UPDATABLE: case SQL_COLUMN_UPDATABLE: /* == SQL_DESC_UPDATABLE */
/* /*
* Neither Access or Borland care about this. * Neither Access or Borland care about this.
...@@ -604,6 +659,60 @@ PGAPI_ColAttributes( ...@@ -604,6 +659,60 @@ PGAPI_ColAttributes(
mylog("PGAPI_ColAttr: UPDATEABLE = %d\n", value); mylog("PGAPI_ColAttr: UPDATEABLE = %d\n", value);
break; break;
#if (ODBCVER >= 0x0300)
case SQL_DESC_BASE_COLUMN_NAME:
p = fi ? fi->name : QR_get_fieldname(SC_get_Curres(stmt), col_idx);
mylog("PGAPI_ColAttr: BASE_COLUMN_NAME = '%s'\n", p);
break;
case SQL_DESC_BASE_TABLE_NAME: /* the same as TABLE_NAME ok ? */
p = fi && (fi->ti) ? fi->ti->name : "";
mylog("PGAPI_ColAttr: BASE_TABLE_NAME = '%s'\n", p);
break;
case SQL_DESC_LENGTH: /* different from SQL_COLUMN_LENGTH */
value = fi ? fi->length : pgtype_length(stmt, field_type, col_idx, unknown_sizes);
mylog("PGAPI_ColAttributes: col %d, length = %d\n", col_idx, value);
break;
case SQL_DESC_OCTET_LENGTH:
value = fi ? fi->length : pgtype_length(stmt, field_type, col_idx, unknown_sizes);
mylog("PGAPI_ColAttributes: col %d, octet_length = %d\n", col_idx, value);
break;
case SQL_DESC_PRECISION: /* different from SQL_COLUMN_PRECISION */
value = fi ? fi->precision : pgtype_precision(stmt, field_type, col_idx, unknown_sizes);
mylog("PGAPI_ColAttributes: col %d, desc_precision = %d\n", col_idx, value);
break;
case SQL_DESC_SCALE: /* different from SQL_COLUMN_SCALE */
value = pgtype_scale(stmt, field_type, col_idx);
break;
case SQL_DESC_LOCAL_TYPE_NAME:
p = pgtype_to_name(stmt, field_type);
break;
case SQL_DESC_TYPE:
value = pgtype_to_sqltype(stmt, field_type);
switch (value)
{
case SQL_TYPE_DATE:
case SQL_TYPE_TIME:
case SQL_TYPE_TIMESTAMP:
value = SQL_DATETIME;
break;
}
break;
case SQL_DESC_LITERAL_PREFIX:
case SQL_DESC_LITERAL_SUFFIX:
case SQL_DESC_NUM_PREC_RADIX:
case SQL_DESC_UNNAMED:
#endif /* ODBCVER */
default:
stmt->errornumber = STMT_INVALID_OPTION_IDENTIFIER;
stmt->errormsg = "ColAttribute for this type not implemented yet";
SC_log_error(func, "", stmt);
return SQL_ERROR;
} }
result = SQL_SUCCESS; result = SQL_SUCCESS;
...@@ -614,6 +723,14 @@ PGAPI_ColAttributes( ...@@ -614,6 +723,14 @@ PGAPI_ColAttributes(
if (rgbDesc) if (rgbDesc)
{ {
#ifdef UNICODE_SUPPORT
if (conn->unicode)
{
len = utf8_to_ucs2(p, len, (SQLWCHAR *) rgbDesc, cbDescMax / 2);
len *= 2;
}
else
#endif /* UNICODE_SUPPORT */
strncpy_null((char *) rgbDesc, p, (size_t) cbDescMax); strncpy_null((char *) rgbDesc, p, (size_t) cbDescMax);
if (len >= cbDescMax) if (len >= cbDescMax)
...@@ -667,7 +784,7 @@ PGAPI_GetData( ...@@ -667,7 +784,7 @@ PGAPI_GetData(
return SQL_INVALID_HANDLE; return SQL_INVALID_HANDLE;
} }
ci = &(SC_get_conn(stmt)->connInfo); ci = &(SC_get_conn(stmt)->connInfo);
res = stmt->result; res = SC_get_Curres(stmt);
if (STMT_EXECUTING == stmt->status) if (STMT_EXECUTING == stmt->status)
{ {
...@@ -834,7 +951,7 @@ PGAPI_Fetch( ...@@ -834,7 +951,7 @@ PGAPI_Fetch(
StatementClass *stmt = (StatementClass *) hstmt; StatementClass *stmt = (StatementClass *) hstmt;
QResultClass *res; QResultClass *res;
mylog("PGAPI_Fetch: stmt = %u, stmt->result= %u\n", stmt, stmt->result); mylog("PGAPI_Fetch: stmt = %u, stmt->result= %u\n", stmt, SC_get_Curres(stmt));
if (!stmt) if (!stmt)
{ {
...@@ -844,7 +961,7 @@ PGAPI_Fetch( ...@@ -844,7 +961,7 @@ PGAPI_Fetch(
SC_clear_error(stmt); SC_clear_error(stmt);
if (!(res = stmt->result)) if (!(res = SC_get_Curres(stmt)))
{ {
stmt->errormsg = "Null statement result in PGAPI_Fetch."; stmt->errormsg = "Null statement result in PGAPI_Fetch.";
stmt->errornumber = STMT_SEQUENCE_ERROR; stmt->errornumber = STMT_SEQUENCE_ERROR;
...@@ -935,7 +1052,7 @@ PGAPI_ExtendedFetch( ...@@ -935,7 +1052,7 @@ PGAPI_ExtendedFetch(
SC_clear_error(stmt); SC_clear_error(stmt);
if (!(res = stmt->result)) if (!(res = SC_get_Curres(stmt)))
{ {
stmt->errormsg = "Null statement result in PGAPI_ExtendedFetch."; stmt->errormsg = "Null statement result in PGAPI_ExtendedFetch.";
stmt->errornumber = STMT_SEQUENCE_ERROR; stmt->errornumber = STMT_SEQUENCE_ERROR;
...@@ -1214,6 +1331,15 @@ RETCODE SQL_API ...@@ -1214,6 +1331,15 @@ RETCODE SQL_API
PGAPI_MoreResults( PGAPI_MoreResults(
HSTMT hstmt) HSTMT hstmt)
{ {
const char *func = "PGAPI_MoreResults";
StatementClass *stmt = (StatementClass *) hstmt;
QResultClass *res;
mylog("%s: entering...\n", func);
if (stmt && (res = SC_get_Curres(stmt)))
SC_get_Curres(stmt) = res->next;
if (SC_get_Curres(stmt))
return SQL_SUCCESS;
return SQL_NO_DATA_FOUND; return SQL_NO_DATA_FOUND;
} }
...@@ -1243,12 +1369,7 @@ positioned_load(StatementClass *stmt, BOOL latest, int res_cols, UInt4 oid, cons ...@@ -1243,12 +1369,7 @@ positioned_load(StatementClass *stmt, BOOL latest, int res_cols, UInt4 oid, cons
} }
sprintf(selstr, "%s oid = %u", selstr, oid), sprintf(selstr, "%s oid = %u", selstr, oid),
mylog("selstr=%s\n", selstr); mylog("selstr=%s\n", selstr);
qres = CC_send_query(SC_get_conn(stmt), selstr, NULL); qres = CC_send_query(SC_get_conn(stmt), selstr, NULL, TRUE);
if (qres && QR_aborted(qres))
{
QR_Destructor(qres);
qres = (QResultClass *) 0;
}
return qres; return qres;
} }
...@@ -1270,7 +1391,7 @@ SC_pos_reload(StatementClass *stmt, UWORD irow, UWORD *count) ...@@ -1270,7 +1391,7 @@ SC_pos_reload(StatementClass *stmt, UWORD irow, UWORD *count)
rcnt = 0; rcnt = 0;
if (count) if (count)
*count = 0; *count = 0;
if (!(res = stmt->result)) if (!(res = SC_get_Curres(stmt)))
return SQL_ERROR; return SQL_ERROR;
if (!stmt->ti) if (!stmt->ti)
parse_statement(stmt); /* not preferable */ parse_statement(stmt); /* not preferable */
...@@ -1339,7 +1460,7 @@ SC_pos_newload(StatementClass *stmt, UInt4 oid, const char *tidval) ...@@ -1339,7 +1460,7 @@ SC_pos_newload(StatementClass *stmt, UInt4 oid, const char *tidval)
RETCODE ret = SQL_ERROR; RETCODE ret = SQL_ERROR;
mylog("positioned new fi=%x ti=%x\n", stmt->fi, stmt->ti); mylog("positioned new fi=%x ti=%x\n", stmt->fi, stmt->ti);
if (!(res = stmt->result)) if (!(res = SC_get_Curres(stmt)))
return SQL_ERROR; return SQL_ERROR;
if (!stmt->ti) if (!stmt->ti)
parse_statement(stmt); /* not preferable */ parse_statement(stmt); /* not preferable */
...@@ -1401,6 +1522,41 @@ SC_pos_newload(StatementClass *stmt, UInt4 oid, const char *tidval) ...@@ -1401,6 +1522,41 @@ SC_pos_newload(StatementClass *stmt, UInt4 oid, const char *tidval)
return ret; return ret;
} }
static RETCODE SQL_API
irow_update(RETCODE ret, StatementClass *stmt, UWORD irow)
{
if (ret != SQL_ERROR)
{
int updcnt;
const char *cmdstr = QR_get_command(SC_get_Curres(stmt));
if (cmdstr &&
sscanf(cmdstr, "UPDATE %d", &updcnt) == 1)
{
if (updcnt == 1)
SC_pos_reload(stmt, irow, (UWORD *) 0);
else if (updcnt == 0)
{
stmt->errornumber = STMT_ROW_VERSION_CHANGED;
stmt->errormsg = "the content was changed before updation";
ret = SQL_ERROR;
if (stmt->options.cursor_type == SQL_CURSOR_KEYSET_DRIVEN)
SC_pos_reload(stmt, irow, (UWORD *) 0);
}
else
ret = SQL_ERROR;
stmt->currTuple = stmt->rowset_start + irow;
}
else
ret = SQL_ERROR;
if (ret == SQL_ERROR && stmt->errornumber == 0)
{
stmt->errornumber = STMT_ERROR_TAKEN_FROM_BACKEND;
stmt->errormsg = "SetPos update return error";
}
}
return ret;
}
RETCODE SQL_API RETCODE SQL_API
SC_pos_update(StatementClass *stmt, SC_pos_update(StatementClass *stmt,
UWORD irow) UWORD irow)
...@@ -1419,8 +1575,8 @@ SC_pos_update(StatementClass *stmt, ...@@ -1419,8 +1575,8 @@ SC_pos_update(StatementClass *stmt,
UInt4 offset; UInt4 offset;
Int4 *used; Int4 *used;
mylog("POS UPDATE %d+%d fi=%x ti=%x\n", irow, stmt->result->base, stmt->fi, stmt->ti); mylog("POS UPDATE %d+%d fi=%x ti=%x\n", irow, SC_get_Curres(stmt)->base, stmt->fi, stmt->ti);
if (!(res = stmt->result)) if (!(res = SC_get_Curres(stmt)))
return SQL_ERROR; return SQL_ERROR;
if (!stmt->ti) if (!stmt->ti)
parse_statement(stmt); /* not preferable */ parse_statement(stmt); /* not preferable */
...@@ -1510,40 +1666,12 @@ SC_pos_update(StatementClass *stmt, ...@@ -1510,40 +1666,12 @@ SC_pos_update(StatementClass *stmt,
stmt->errormsg = "SetPos with data_at_exec not yet supported"; stmt->errormsg = "SetPos with data_at_exec not yet supported";
ret = SQL_ERROR; ret = SQL_ERROR;
} }
if (ret != SQL_ERROR) ret = irow_update(ret, qstmt, irow);
{
int updcnt;
const char *cmdstr = QR_get_command(qstmt->result);
if (cmdstr &&
sscanf(cmdstr, "UPDATE %d", &updcnt) == 1)
{
if (updcnt == 1)
SC_pos_reload(stmt, irow, (UWORD *) 0);
else if (updcnt == 0)
{
stmt->errornumber = STMT_ROW_VERSION_CHANGED;
stmt->errormsg = "the content was changed before updation";
ret = SQL_ERROR;
if (stmt->options.cursor_type == SQL_CURSOR_KEYSET_DRIVEN)
SC_pos_reload(stmt, irow, (UWORD *) 0);
}
else
ret = SQL_ERROR;
stmt->currTuple = stmt->rowset_start + irow;
}
else
ret = SQL_ERROR;
if (ret == SQL_ERROR && stmt->errornumber == 0)
{
stmt->errornumber = STMT_ERROR_TAKEN_FROM_BACKEND;
stmt->errormsg = "SetPos update return error";
}
}
PGAPI_FreeStmt(hstmt, SQL_DROP); PGAPI_FreeStmt(hstmt, SQL_DROP);
} }
else else
ret = SQL_SUCCESS_WITH_INFO; ret = SQL_SUCCESS_WITH_INFO;
#if (ODBCVER >= 0x0300)
if (stmt->options.rowStatusArray) if (stmt->options.rowStatusArray)
{ {
switch (ret) switch (ret)
...@@ -1556,6 +1684,7 @@ SC_pos_update(StatementClass *stmt, ...@@ -1556,6 +1684,7 @@ SC_pos_update(StatementClass *stmt,
break; break;
} }
} }
#endif /* ODBCVER */
return ret; return ret;
} }
...@@ -1573,7 +1702,7 @@ SC_pos_delete(StatementClass *stmt, ...@@ -1573,7 +1702,7 @@ SC_pos_delete(StatementClass *stmt,
char *oidval; char *oidval;
mylog("POS DELETE fi=%x ti=%x\n", stmt->fi, stmt->ti); mylog("POS DELETE fi=%x ti=%x\n", stmt->fi, stmt->ti);
if (!(res = stmt->result)) if (!(res = SC_get_Curres(stmt)))
return SQL_ERROR; return SQL_ERROR;
if (!stmt->ti) if (!stmt->ti)
parse_statement(stmt); /* not preferable */ parse_statement(stmt); /* not preferable */
...@@ -1591,11 +1720,11 @@ SC_pos_delete(StatementClass *stmt, ...@@ -1591,11 +1720,11 @@ SC_pos_delete(StatementClass *stmt,
} }
sprintf(dltstr, "delete from \"%s\" where ctid = '%s' and oid = %s", sprintf(dltstr, "delete from \"%s\" where ctid = '%s' and oid = %s",
stmt->ti[0]->name, stmt->ti[0]->name,
QR_get_value_backend_row(stmt->result, global_ridx, res_cols - 2), QR_get_value_backend_row(SC_get_Curres(stmt), global_ridx, res_cols - 2),
oidval); oidval);
mylog("dltstr=%s\n", dltstr); mylog("dltstr=%s\n", dltstr);
qres = CC_send_query(SC_get_conn(stmt), dltstr, NULL); qres = CC_send_query(SC_get_conn(stmt), dltstr, NULL, TRUE);
if (qres && QR_command_successful(qres)) if (qres && QR_command_successful(qres))
{ {
int dltcnt; int dltcnt;
...@@ -1630,6 +1759,7 @@ SC_pos_delete(StatementClass *stmt, ...@@ -1630,6 +1759,7 @@ SC_pos_delete(StatementClass *stmt,
} }
if (qres) if (qres)
QR_Destructor(qres); QR_Destructor(qres);
#if (ODBCVER >= 0x0300)
if (stmt->options.rowStatusArray) if (stmt->options.rowStatusArray)
{ {
switch (ret) switch (ret)
...@@ -1642,6 +1772,40 @@ SC_pos_delete(StatementClass *stmt, ...@@ -1642,6 +1772,40 @@ SC_pos_delete(StatementClass *stmt,
break; break;
} }
} }
#endif /* ODBCVER */
return ret;
}
static RETCODE SQL_API
irow_insert(RETCODE ret, StatementClass *stmt, int addpos)
{
if (ret != SQL_ERROR)
{
int addcnt;
UInt4 oid;
const char *cmdstr = QR_get_command(SC_get_Curres(stmt));
if (cmdstr &&
sscanf(cmdstr, "INSERT %u %d", &oid, &addcnt) == 2 &&
addcnt == 1)
{
SC_pos_newload(stmt, oid, NULL);
if (stmt->bookmark.buffer)
{
char buf[32];
sprintf(buf, "%ld", addpos);
copy_and_convert_field(stmt, 0, buf,
SQL_C_ULONG, stmt->bookmark.buffer,
0, stmt->bookmark.used);
}
}
else
{
stmt->errornumber = STMT_ERROR_TAKEN_FROM_BACKEND;
stmt->errormsg = "SetPos insert return error";
}
}
return ret; return ret;
} }
RETCODE SQL_API RETCODE SQL_API
...@@ -1661,7 +1825,7 @@ SC_pos_add(StatementClass *stmt, ...@@ -1661,7 +1825,7 @@ SC_pos_add(StatementClass *stmt,
Int4 *used; Int4 *used;
mylog("POS ADD fi=%x ti=%x\n", stmt->fi, stmt->ti); mylog("POS ADD fi=%x ti=%x\n", stmt->fi, stmt->ti);
if (!(res = stmt->result)) if (!(res = SC_get_Curres(stmt)))
return SQL_ERROR; return SQL_ERROR;
if (!stmt->ti) if (!stmt->ti)
parse_statement(stmt); /* not preferable */ parse_statement(stmt); /* not preferable */
...@@ -1721,50 +1885,24 @@ SC_pos_add(StatementClass *stmt, ...@@ -1721,50 +1885,24 @@ SC_pos_add(StatementClass *stmt,
mylog("addstr=%s\n", addstr); mylog("addstr=%s\n", addstr);
qstmt->exec_start_row = qstmt->exec_end_row = irow; qstmt->exec_start_row = qstmt->exec_end_row = irow;
ret = PGAPI_ExecDirect(hstmt, addstr, strlen(addstr)); ret = PGAPI_ExecDirect(hstmt, addstr, strlen(addstr));
if (ret == SQL_NEED_DATA) /* must be fixed */
{
stmt->options.scroll_concurrency = SQL_CONCUR_READ_ONLY;
stmt->errornumber = STMT_INVALID_CURSOR_STATE_ERROR;
stmt->errormsg = "SetPos with data_at_exec not yet supported";
ret = SQL_ERROR;
}
if (ret == SQL_ERROR) if (ret == SQL_ERROR)
{ {
stmt->errornumber = qstmt->errornumber; stmt->errornumber = qstmt->errornumber;
stmt->errormsg = qstmt->errormsg; stmt->errormsg = qstmt->errormsg;
} }
else else if (ret == SQL_NEED_DATA) /* must be fixed */
{ {
int addcnt; stmt->options.scroll_concurrency = SQL_CONCUR_READ_ONLY;
UInt4 oid; stmt->errornumber = STMT_INVALID_CURSOR_STATE_ERROR;
const char *cmdstr = QR_get_command(qstmt->result); stmt->errormsg = "SetPos with data_at_exec not yet supported";
ret = SQL_ERROR;
if (cmdstr &&
sscanf(cmdstr, "INSERT %u %d", &oid, &addcnt) == 2 &&
addcnt == 1)
{
SC_pos_newload(stmt, oid, NULL);
if (stmt->bookmark.buffer)
{
char buf[32];
sprintf(buf, "%ld", res->fcount);
copy_and_convert_field(stmt, 0, buf,
SQL_C_ULONG, stmt->bookmark.buffer,
0, stmt->bookmark.used);
}
}
else
{
stmt->errornumber = STMT_ERROR_TAKEN_FROM_BACKEND;
stmt->errormsg = "SetPos insert return error";
ret = SQL_ERROR;
}
} }
ret = irow_insert(ret, qstmt, res->fcount);
} }
else else
ret = SQL_SUCCESS_WITH_INFO; ret = SQL_SUCCESS_WITH_INFO;
PGAPI_FreeStmt(hstmt, SQL_DROP); PGAPI_FreeStmt(hstmt, SQL_DROP);
#if (ODBCVER >= 0x0300)
if (stmt->options.rowStatusArray) if (stmt->options.rowStatusArray)
{ {
switch (ret) switch (ret)
...@@ -1777,6 +1915,8 @@ SC_pos_add(StatementClass *stmt, ...@@ -1777,6 +1915,8 @@ SC_pos_add(StatementClass *stmt,
break; break;
} }
} }
#endif /* ODBCVER */
return ret; return ret;
} }
...@@ -1823,7 +1963,7 @@ PGAPI_SetPos( ...@@ -1823,7 +1963,7 @@ PGAPI_SetPos(
return SQL_ERROR; return SQL_ERROR;
} }
if (!(res = stmt->result)) if (!(res = SC_get_Curres(stmt)))
{ {
stmt->errormsg = "Null statement result in PGAPI_SetPos."; stmt->errormsg = "Null statement result in PGAPI_SetPos.";
stmt->errornumber = STMT_SEQUENCE_ERROR; stmt->errornumber = STMT_SEQUENCE_ERROR;
......
...@@ -90,7 +90,6 @@ ConfigDSN(HWND hwnd, ...@@ -90,7 +90,6 @@ ConfigDSN(HWND hwnd,
if (!hglbAttr) if (!hglbAttr)
return FALSE; return FALSE;
lpsetupdlg = (LPSETUPDLG) GlobalLock(hglbAttr); lpsetupdlg = (LPSETUPDLG) GlobalLock(hglbAttr);
/* Parse attribute string */ /* Parse attribute string */
if (lpszAttributes) if (lpszAttributes)
ParseAttributes(lpszAttributes, lpsetupdlg); ParseAttributes(lpszAttributes, lpsetupdlg);
...@@ -339,7 +338,7 @@ ParseAttributes(LPCSTR lpszAttributes, LPSETUPDLG lpsetupdlg) ...@@ -339,7 +338,7 @@ ParseAttributes(LPCSTR lpszAttributes, LPSETUPDLG lpsetupdlg)
int cbKey; int cbKey;
char value[MAXPGPATH]; char value[MAXPGPATH];
memset(&lpsetupdlg->ci, 0, sizeof(ConnInfo)); CC_conninfo_init(&(lpsetupdlg->ci));
for (lpsz = lpszAttributes; *lpsz; lpsz++) for (lpsz = lpszAttributes; *lpsz; lpsz++)
{ {
......
...@@ -159,10 +159,10 @@ PGAPI_FreeStmt(HSTMT hstmt, ...@@ -159,10 +159,10 @@ PGAPI_FreeStmt(HSTMT hstmt,
} }
/* Free any cursors and discard any result info */ /* Free any cursors and discard any result info */
if (stmt->result) if (SC_get_Result(stmt))
{ {
QR_Destructor(stmt->result); QR_Destructor(SC_get_Result(stmt));
stmt->result = NULL; SC_set_Result(stmt, NULL);
} }
} }
...@@ -230,6 +230,7 @@ SC_Constructor(void) ...@@ -230,6 +230,7 @@ SC_Constructor(void)
rv->hdbc = NULL; /* no connection associated yet */ rv->hdbc = NULL; /* no connection associated yet */
rv->phstmt = NULL; rv->phstmt = NULL;
rv->result = NULL; rv->result = NULL;
rv->curres = NULL;
rv->manual_result = FALSE; rv->manual_result = FALSE;
rv->prepare = FALSE; rv->prepare = FALSE;
rv->status = STMT_ALLOCATED; rv->status = STMT_ALLOCATED;
...@@ -238,7 +239,6 @@ SC_Constructor(void) ...@@ -238,7 +239,6 @@ SC_Constructor(void)
rv->errormsg = NULL; rv->errormsg = NULL;
rv->errornumber = 0; rv->errornumber = 0;
rv->errormsg_created = FALSE; rv->errormsg_created = FALSE;
rv->errormsg_malloced = FALSE;
rv->statement = NULL; rv->statement = NULL;
rv->stmt_with_params = NULL; rv->stmt_with_params = NULL;
...@@ -292,7 +292,9 @@ SC_Constructor(void) ...@@ -292,7 +292,9 @@ SC_Constructor(void)
char char
SC_Destructor(StatementClass *self) SC_Destructor(StatementClass *self)
{ {
mylog("SC_Destructor: self=%u, self->result=%u, self->hdbc=%u\n", self, self->result, self->hdbc); QResultClass *res = SC_get_Result(self);
mylog("SC_Destructor: self=%u, self->result=%u, self->hdbc=%u\n", self, res, self->hdbc);
SC_clear_error(self); SC_clear_error(self);
if (STMT_EXECUTING == self->status) if (STMT_EXECUTING == self->status)
{ {
...@@ -301,12 +303,12 @@ SC_Destructor(StatementClass *self) ...@@ -301,12 +303,12 @@ SC_Destructor(StatementClass *self)
return FALSE; return FALSE;
} }
if (self->result) if (res)
{ {
if (!self->hdbc) if (!self->hdbc)
self->result->conn = NULL; /* prevent any dbase activity */ res->conn = NULL; /* prevent any dbase activity */
QR_Destructor(self->result); QR_Destructor(res);
} }
if (self->statement) if (self->statement)
...@@ -442,6 +444,7 @@ char ...@@ -442,6 +444,7 @@ char
SC_recycle_statement(StatementClass *self) SC_recycle_statement(StatementClass *self)
{ {
ConnectionClass *conn; ConnectionClass *conn;
QResultClass *res;
mylog("recycle statement: self= %u\n", self); mylog("recycle statement: self= %u\n", self);
...@@ -514,10 +517,10 @@ SC_recycle_statement(StatementClass *self) ...@@ -514,10 +517,10 @@ SC_recycle_statement(StatementClass *self)
self->parse_status = STMT_PARSE_NONE; self->parse_status = STMT_PARSE_NONE;
/* Free any cursors */ /* Free any cursors */
if (self->result) if (res = SC_get_Result(self), res)
{ {
QR_Destructor(self->result); QR_Destructor(res);
self->result = NULL; SC_set_Result(self, NULL);
} }
self->inaccurate_result = FALSE; self->inaccurate_result = FALSE;
...@@ -533,12 +536,9 @@ SC_recycle_statement(StatementClass *self) ...@@ -533,12 +536,9 @@ SC_recycle_statement(StatementClass *self)
self->bind_row = 0; self->bind_row = 0;
self->last_fetch_count = 0; self->last_fetch_count = 0;
if (self->errormsg_malloced && self->errormsg)
free(self->errormsg);
self->errormsg = NULL; self->errormsg = NULL;
self->errornumber = 0; self->errornumber = 0;
self->errormsg_created = FALSE; self->errormsg_created = FALSE;
self->errormsg_malloced = FALSE;
self->lobj_fd = -1; self->lobj_fd = -1;
...@@ -583,8 +583,8 @@ SC_pre_execute(StatementClass *self) ...@@ -583,8 +583,8 @@ SC_pre_execute(StatementClass *self)
} }
if (!SC_is_pre_executable(self)) if (!SC_is_pre_executable(self))
{ {
self->result = QR_Constructor(); SC_set_Result(self, QR_Constructor());
QR_set_status(self->result, PGRES_TUPLES_OK); QR_set_status(SC_get_Result(self), PGRES_TUPLES_OK);
self->inaccurate_result = TRUE; self->inaccurate_result = TRUE;
self->status = STMT_PREMATURE; self->status = STMT_PREMATURE;
} }
...@@ -617,12 +617,11 @@ SC_unbind_cols(StatementClass *self) ...@@ -617,12 +617,11 @@ SC_unbind_cols(StatementClass *self)
void void
SC_clear_error(StatementClass *self) SC_clear_error(StatementClass *self)
{ {
if (self->errormsg_malloced && self->errormsg)
free(self->errormsg);
self->errornumber = 0; self->errornumber = 0;
self->errormsg = NULL; self->errormsg = NULL;
self->errormsg_created = FALSE; self->errormsg_created = FALSE;
self->errormsg_malloced = FALSE; self->errorpos = 0;
self->error_recsize = -1;
} }
...@@ -633,7 +632,7 @@ SC_clear_error(StatementClass *self) ...@@ -633,7 +632,7 @@ SC_clear_error(StatementClass *self)
char * char *
SC_create_errormsg(StatementClass *self) SC_create_errormsg(StatementClass *self)
{ {
QResultClass *res = self->result; QResultClass *res = SC_get_Curres(self);
ConnectionClass *conn = self->hdbc; ConnectionClass *conn = self->hdbc;
int pos; int pos;
static char msg[4096]; static char msg[4096];
...@@ -642,10 +641,21 @@ SC_create_errormsg(StatementClass *self) ...@@ -642,10 +641,21 @@ SC_create_errormsg(StatementClass *self)
if (res && res->message) if (res && res->message)
strcpy(msg, res->message); strcpy(msg, res->message);
else if (self->errormsg) else if (self->errormsg)
strcpy(msg, self->errormsg); strcpy(msg, self->errormsg);
if (!msg[0] && res && QR_get_notice(res))
{
char *notice = QR_get_notice(res);
int len = strlen(notice);
if (len < sizeof(msg))
{
memcpy(msg, notice, len);
msg[len] = '\0';
}
else
return notice;
}
if (conn) if (conn)
{ {
SocketClass *sock = conn->sock; SocketClass *sock = conn->sock;
...@@ -653,7 +663,7 @@ SC_create_errormsg(StatementClass *self) ...@@ -653,7 +663,7 @@ SC_create_errormsg(StatementClass *self)
if (conn->errormsg && conn->errormsg[0] != '\0') if (conn->errormsg && conn->errormsg[0] != '\0')
{ {
pos = strlen(msg); pos = strlen(msg);
sprintf(&msg[pos], ";\n%s", conn->errormsg); /*sprintf(&msg[pos], ";\n%s", conn->errormsg);*/
} }
if (sock && sock->errormsg && sock->errormsg[0] != '\0') if (sock && sock->errormsg && sock->errormsg[0] != '\0')
...@@ -662,9 +672,6 @@ SC_create_errormsg(StatementClass *self) ...@@ -662,9 +672,6 @@ SC_create_errormsg(StatementClass *self)
sprintf(&msg[pos], ";\n%s", sock->errormsg); sprintf(&msg[pos], ";\n%s", sock->errormsg);
} }
} }
if (!msg[0] && res && QR_get_notice(res))
return QR_get_notice(res);
return msg; return msg;
} }
...@@ -679,18 +686,17 @@ SC_get_error(StatementClass *self, int *number, char **message) ...@@ -679,18 +686,17 @@ SC_get_error(StatementClass *self, int *number, char **message)
{ {
self->errormsg = SC_create_errormsg(self); self->errormsg = SC_create_errormsg(self);
self->errormsg_created = TRUE; self->errormsg_created = TRUE;
self->errorpos = 0;
self->error_recsize = -1;
} }
if (self->errornumber) if (self->errornumber)
{ {
*number = self->errornumber; *number = self->errornumber;
*message = self->errormsg; *message = self->errormsg;
if (!self->errormsg_malloced)
self->errormsg = NULL;
} }
rv = (self->errornumber != 0); rv = (self->errornumber != 0);
self->errornumber = 0;
return rv; return rv;
} }
...@@ -712,7 +718,7 @@ RETCODE ...@@ -712,7 +718,7 @@ RETCODE
SC_fetch(StatementClass *self) SC_fetch(StatementClass *self)
{ {
static char *func = "SC_fetch"; static char *func = "SC_fetch";
QResultClass *res = self->result; QResultClass *res = SC_get_Curres(self);
int retval, int retval,
result; result;
...@@ -901,6 +907,7 @@ SC_execute(StatementClass *self) ...@@ -901,6 +907,7 @@ SC_execute(StatementClass *self)
static char *func = "SC_execute"; static char *func = "SC_execute";
ConnectionClass *conn; ConnectionClass *conn;
char was_ok, was_nonfatal; char was_ok, was_nonfatal;
QResultClass *res = NULL;
Int2 oldstatus, Int2 oldstatus,
numcols; numcols;
QueryInfo qi; QueryInfo qi;
...@@ -952,12 +959,12 @@ SC_execute(StatementClass *self) ...@@ -952,12 +959,12 @@ SC_execute(StatementClass *self)
mylog(" Sending SELECT statement on stmt=%u, cursor_name='%s'\n", self, self->cursor_name); mylog(" Sending SELECT statement on stmt=%u, cursor_name='%s'\n", self, self->cursor_name);
/* send the declare/select */ /* send the declare/select */
self->result = CC_send_query(conn, self->stmt_with_params, NULL); res = CC_send_query(conn, self->stmt_with_params, NULL, TRUE);
if (SC_is_fetchcursor(self) && self->result != NULL && if (SC_is_fetchcursor(self) && res != NULL &&
QR_command_successful(self->result)) QR_command_successful(res))
{ {
QR_Destructor(self->result); QR_Destructor(res);
/* /*
* That worked, so now send the fetch to start getting data * That worked, so now send the fetch to start getting data
...@@ -976,7 +983,7 @@ SC_execute(StatementClass *self) ...@@ -976,7 +983,7 @@ SC_execute(StatementClass *self)
*/ */
sprintf(fetch, "fetch %d in %s", qi.row_size, self->cursor_name); sprintf(fetch, "fetch %d in %s", qi.row_size, self->cursor_name);
self->result = CC_send_query(conn, fetch, &qi); res = CC_send_query(conn, fetch, &qi, FALSE);
} }
mylog(" done sending the query:\n"); mylog(" done sending the query:\n");
} }
...@@ -984,7 +991,7 @@ SC_execute(StatementClass *self) ...@@ -984,7 +991,7 @@ SC_execute(StatementClass *self)
{ {
/* not a SELECT statement so don't use a cursor */ /* not a SELECT statement so don't use a cursor */
mylog(" it's NOT a select statement: stmt=%u\n", self); mylog(" it's NOT a select statement: stmt=%u\n", self);
self->result = CC_send_query(conn, self->stmt_with_params, NULL); res = CC_send_query(conn, self->stmt_with_params, NULL, FALSE);
/* /*
* We shouldn't send COMMIT. Postgres backend does the autocommit * We shouldn't send COMMIT. Postgres backend does the autocommit
...@@ -1003,10 +1010,10 @@ SC_execute(StatementClass *self) ...@@ -1003,10 +1010,10 @@ SC_execute(StatementClass *self)
self->status = STMT_FINISHED; self->status = STMT_FINISHED;
/* Check the status of the result */ /* Check the status of the result */
if (self->result) if (res)
{ {
was_ok = QR_command_successful(self->result); was_ok = QR_command_successful(res);
was_nonfatal = QR_command_nonfatal(self->result); was_nonfatal = QR_command_nonfatal(res);
if (was_ok) if (was_ok)
self->errornumber = STMT_OK; self->errornumber = STMT_OK;
...@@ -1018,24 +1025,30 @@ SC_execute(StatementClass *self) ...@@ -1018,24 +1025,30 @@ SC_execute(StatementClass *self)
self->current_col = -1; self->current_col = -1;
self->rowset_start = -1; self->rowset_start = -1;
/* see if the query did return any result columns */ /* issue "ABORT" when query aborted */
numcols = QR_NumResultCols(self->result); if (QR_get_aborted(res))
/* now allocate the array to hold the binding info */
if (numcols > 0)
{ {
extend_bindings(self, numcols); if (!self->internal)
if (self->bindings == NULL) CC_abort(conn);
}
else
{
/* see if the query did return any result columns */
numcols = QR_NumResultCols(res);
/* now allocate the array to hold the binding info */
if (numcols > 0)
{ {
self->errornumber = STMT_NO_MEMORY_ERROR; extend_bindings(self, numcols);
self->errormsg = "Could not get enough free memory to store the binding information"; if (self->bindings == NULL)
SC_log_error(func, "", self); {
return SQL_ERROR; QR_Destructor(res);
self->errornumber = STMT_NO_MEMORY_ERROR;
self->errormsg = "Could not get enough free memory to store the binding information";
SC_log_error(func, "", self);
return SQL_ERROR;
}
} }
} }
/* issue "ABORT" when query aborted */
if (QR_get_aborted(self->result) && !self->internal)
CC_abort(conn);
} }
else else
{ {
...@@ -1061,6 +1074,15 @@ SC_execute(StatementClass *self) ...@@ -1061,6 +1074,15 @@ SC_execute(StatementClass *self)
if (!self->internal) if (!self->internal)
CC_abort(conn); CC_abort(conn);
} }
if (!SC_get_Result(self))
SC_set_Result(self, res);
else
{
QResultClass *last;
for (last = SC_get_Result(self); last->next; last = last->next)
;
last->next = res;
}
if (self->statement_type == STMT_TYPE_PROCCALL && if (self->statement_type == STMT_TYPE_PROCCALL &&
(self->errornumber == STMT_OK || (self->errornumber == STMT_OK ||
...@@ -1095,7 +1117,8 @@ SC_execute(StatementClass *self) ...@@ -1095,7 +1117,8 @@ SC_execute(StatementClass *self)
return SQL_SUCCESS_WITH_INFO; return SQL_SUCCESS_WITH_INFO;
else else
{ {
self->errormsg = "Error while executing the query"; if (!self->errormsg || !self->errormsg[0])
self->errormsg = "Error while executing the query";
SC_log_error(func, "", self); SC_log_error(func, "", self);
return SQL_ERROR; return SQL_ERROR;
} }
...@@ -1103,17 +1126,19 @@ SC_execute(StatementClass *self) ...@@ -1103,17 +1126,19 @@ SC_execute(StatementClass *self)
void void
SC_log_error(char *func, char *desc, StatementClass *self) SC_log_error(const char *func, const char *desc, const StatementClass *self)
{ {
#ifdef PRN_NULLCHECK #ifdef PRN_NULLCHECK
#define nullcheck(a) (a ? a : "(NULL)") #define nullcheck(a) (a ? a : "(NULL)")
#endif #endif
if (self) if (self)
{ {
QResultClass *res = SC_get_Result(self);
qlog("STATEMENT ERROR: func=%s, desc='%s', errnum=%d, errmsg='%s'\n", func, desc, self->errornumber, nullcheck(self->errormsg)); qlog("STATEMENT ERROR: func=%s, desc='%s', errnum=%d, errmsg='%s'\n", func, desc, self->errornumber, nullcheck(self->errormsg));
mylog("STATEMENT ERROR: func=%s, desc='%s', errnum=%d, errmsg='%s'\n", func, desc, self->errornumber, nullcheck(self->errormsg)); mylog("STATEMENT ERROR: func=%s, desc='%s', errnum=%d, errmsg='%s'\n", func, desc, self->errornumber, nullcheck(self->errormsg));
qlog(" ------------------------------------------------------------\n"); qlog(" ------------------------------------------------------------\n");
qlog(" hdbc=%u, stmt=%u, result=%u\n", self->hdbc, self, self->result); qlog(" hdbc=%u, stmt=%u, result=%u\n", self->hdbc, self, res);
qlog(" manual_result=%d, prepare=%d, internal=%d\n", self->manual_result, self->prepare, self->internal); qlog(" manual_result=%d, prepare=%d, internal=%d\n", self->manual_result, self->prepare, self->internal);
qlog(" bindings=%u, bindings_allocated=%d\n", self->bindings, self->bindings_allocated); qlog(" bindings=%u, bindings_allocated=%d\n", self->bindings, self->bindings_allocated);
qlog(" parameters=%u, parameters_allocated=%d\n", self->parameters, self->parameters_allocated); qlog(" parameters=%u, parameters_allocated=%d\n", self->parameters, self->parameters_allocated);
...@@ -1126,10 +1151,8 @@ SC_log_error(char *func, char *desc, StatementClass *self) ...@@ -1126,10 +1151,8 @@ SC_log_error(char *func, char *desc, StatementClass *self)
qlog(" ----------------QResult Info -------------------------------\n"); qlog(" ----------------QResult Info -------------------------------\n");
if (self->result) if (res)
{ {
QResultClass *res = self->result;
qlog(" fields=%u, manual_tuples=%u, backend_tuples=%u, tupleField=%d, conn=%u\n", res->fields, res->manual_tuples, res->backend_tuples, res->tupleField, res->conn); qlog(" fields=%u, manual_tuples=%u, backend_tuples=%u, tupleField=%d, conn=%u\n", res->fields, res->manual_tuples, res->backend_tuples, res->tupleField, res->conn);
qlog(" fetch_count=%d, fcount=%d, num_fields=%d, cursor='%s'\n", res->fetch_count, res->fcount, res->num_fields, nullcheck(res->cursor)); qlog(" fetch_count=%d, fcount=%d, num_fields=%d, cursor='%s'\n", res->fetch_count, res->fcount, res->num_fields, nullcheck(res->cursor));
qlog(" message='%s', command='%s', notice='%s'\n", nullcheck(res->message), nullcheck(res->command), nullcheck(res->notice)); qlog(" message='%s', command='%s', notice='%s'\n", nullcheck(res->message), nullcheck(res->command), nullcheck(res->notice));
...@@ -1140,6 +1163,9 @@ SC_log_error(char *func, char *desc, StatementClass *self) ...@@ -1140,6 +1163,9 @@ SC_log_error(char *func, char *desc, StatementClass *self)
CC_log_error(func, desc, self->hdbc); CC_log_error(func, desc, self->hdbc);
} }
else else
{
qlog("INVALID STATEMENT HANDLE ERROR: func=%s, desc='%s'\n", func, desc); qlog("INVALID STATEMENT HANDLE ERROR: func=%s, desc='%s'\n", func, desc);
mylog("INVALID STATEMENT HANDLE ERROR: func=%s, desc='%s'\n", func, desc);
}
#undef PRN_NULLCHECK #undef PRN_NULLCHECK
} }
...@@ -103,7 +103,7 @@ enum ...@@ -103,7 +103,7 @@ enum
STMT_PARSE_NONE = 0, STMT_PARSE_NONE = 0,
STMT_PARSE_COMPLETE, STMT_PARSE_COMPLETE,
STMT_PARSE_INCOMPLETE, STMT_PARSE_INCOMPLETE,
STMT_PARSE_FATAL STMT_PARSE_FATAL,
}; };
/* Result style */ /* Result style */
...@@ -111,7 +111,7 @@ enum ...@@ -111,7 +111,7 @@ enum
{ {
STMT_FETCH_NONE = 0, STMT_FETCH_NONE = 0,
STMT_FETCH_NORMAL, STMT_FETCH_NORMAL,
STMT_FETCH_EXTENDED STMT_FETCH_EXTENDED,
}; };
typedef struct typedef struct
...@@ -147,6 +147,7 @@ struct StatementClass_ ...@@ -147,6 +147,7 @@ struct StatementClass_
ConnectionClass *hdbc; /* pointer to ConnectionClass this ConnectionClass *hdbc; /* pointer to ConnectionClass this
* statement belongs to */ * statement belongs to */
QResultClass *result; /* result of the current statement */ QResultClass *result; /* result of the current statement */
QResultClass *curres; /* the current result in the chain */
HSTMT FAR *phstmt; HSTMT FAR *phstmt;
StatementOptions options; StatementOptions options;
...@@ -215,14 +216,15 @@ struct StatementClass_ ...@@ -215,14 +216,15 @@ struct StatementClass_
char pre_executing; /* This statement is prematurely executing */ char pre_executing; /* This statement is prematurely executing */
char inaccurate_result; /* Current status is PREMATURE but char inaccurate_result; /* Current status is PREMATURE but
* result is inaccurate */ * result is inaccurate */
char errormsg_malloced; /* Current error message is
* malloed (not in a static
* variable) ? */
char miscinfo; char miscinfo;
SWORD errorpos;
SWORD error_recsize;
}; };
#define SC_get_conn(a) (a->hdbc) #define SC_get_conn(a) (a->hdbc)
#define SC_get_Result(a) (a->result); #define SC_set_Result(a, b) (a->result = a->curres = b)
#define SC_get_Result(a) (a->result)
#define SC_get_Curres(a) (a->curres)
/* options for SC_free_params() */ /* options for SC_free_params() */
#define STMT_FREE_PARAMS_ALL 0 #define STMT_FREE_PARAMS_ALL 0
...@@ -252,7 +254,7 @@ char *SC_create_errormsg(StatementClass *self); ...@@ -252,7 +254,7 @@ char *SC_create_errormsg(StatementClass *self);
RETCODE SC_execute(StatementClass *self); RETCODE SC_execute(StatementClass *self);
RETCODE SC_fetch(StatementClass *self); RETCODE SC_fetch(StatementClass *self);
void SC_free_params(StatementClass *self, char option); void SC_free_params(StatementClass *self, char option);
void SC_log_error(char *func, char *desc, StatementClass *self); void SC_log_error(const char *func, const char *desc, const StatementClass *self);
unsigned long SC_get_bookmark(StatementClass *self); unsigned long SC_get_bookmark(StatementClass *self);
#endif #endif
...@@ -31,7 +31,7 @@ CFG=Release ...@@ -31,7 +31,7 @@ CFG=Release
!MESSAGE "Release" (Win32 Release DLL) !MESSAGE "Release" (Win32 Release DLL)
!MESSAGE "Debug" (Win32 Debug DLL) !MESSAGE "Debug" (Win32 Debug DLL)
!MESSAGE "MultibyteRelease" (Win32 Release DLL with Multibyte support) !MESSAGE "MultibyteRelease" (Win32 Release DLL with Multibyte support)
!MESSAGE "MultibyteDebug" (Win32 Release DLL with Multibyte support) !MESSAGE "MultibyteDebug" (Win32 Debug DLL with Multibyte support)
!MESSAGE !MESSAGE
!ERROR An invalid configuration was specified. !ERROR An invalid configuration was specified.
!ENDIF !ENDIF
...@@ -46,13 +46,15 @@ NULL=nul ...@@ -46,13 +46,15 @@ NULL=nul
!IF "$(CFG)" == "MultibyteRelease" !IF "$(CFG)" == "MultibyteRelease"
OUTDIR=.\MultibyteRelease OUTDIR=.\MultibyteRelease
OUTDIRBIN=.\MultibyteRelease
INTDIR=.\MultibyteRelease INTDIR=.\MultibyteRelease
!ELSE !ELSE
OUTDIR=.\Release OUTDIR=.\Release
OUTDIRBIN=.\Release
INTDIR=.\Release INTDIR=.\Release
!ENDIF !ENDIF
ALL : "$(OUTDIR)\psqlodbc.dll" ALL : "$(OUTDIRBIN)\psqlodbc.dll"
CLEAN : CLEAN :
...@@ -64,7 +66,6 @@ CLEAN : ...@@ -64,7 +66,6 @@ CLEAN :
-@erase "$(INTDIR)\drvconn.obj" -@erase "$(INTDIR)\drvconn.obj"
-@erase "$(INTDIR)\environ.obj" -@erase "$(INTDIR)\environ.obj"
-@erase "$(INTDIR)\execute.obj" -@erase "$(INTDIR)\execute.obj"
-@erase "$(INTDIR)\gpps.obj"
-@erase "$(INTDIR)\info.obj" -@erase "$(INTDIR)\info.obj"
-@erase "$(INTDIR)\lobj.obj" -@erase "$(INTDIR)\lobj.obj"
-@erase "$(INTDIR)\win_md5.obj" -@erase "$(INTDIR)\win_md5.obj"
...@@ -139,7 +140,7 @@ BSC32_FLAGS=/nologo /o"$(OUTDIR)\psqlodbc.bsc" ...@@ -139,7 +140,7 @@ BSC32_FLAGS=/nologo /o"$(OUTDIR)\psqlodbc.bsc"
BSC32_SBRS= \ BSC32_SBRS= \
LINK32=link.exe LINK32=link.exe
LINK32_FLAGS=kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib wsock32.lib /nologo /dll /incremental:no /pdb:"$(OUTDIR)\psqlodbc.pdb" /machine:I386 /def:"psqlodbc_win32.def" /out:"$(OUTDIR)\psqlodbc.dll" /implib:"$(OUTDIR)\psqlodbc.lib" LINK32_FLAGS=kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib wsock32.lib /nologo /dll /incremental:no /pdb:"$(OUTDIR)\psqlodbc.pdb" /machine:I386 /def:"psqlodbc_win32.def" /out:"$(OUTDIRBIN)\psqlodbc.dll" /implib:"$(OUTDIR)\psqlodbc.lib"
DEF_FILE= "psqlodbc_win32.def" DEF_FILE= "psqlodbc_win32.def"
LINK32_OBJS= \ LINK32_OBJS= \
"$(INTDIR)\bind.obj" \ "$(INTDIR)\bind.obj" \
...@@ -150,7 +151,6 @@ LINK32_OBJS= \ ...@@ -150,7 +151,6 @@ LINK32_OBJS= \
"$(INTDIR)\drvconn.obj" \ "$(INTDIR)\drvconn.obj" \
"$(INTDIR)\environ.obj" \ "$(INTDIR)\environ.obj" \
"$(INTDIR)\execute.obj" \ "$(INTDIR)\execute.obj" \
"$(INTDIR)\gpps.obj" \
"$(INTDIR)\info.obj" \ "$(INTDIR)\info.obj" \
"$(INTDIR)\lobj.obj" \ "$(INTDIR)\lobj.obj" \
"$(INTDIR)\win_md5.obj" \ "$(INTDIR)\win_md5.obj" \
...@@ -172,7 +172,7 @@ LINK32_OBJS= \ ...@@ -172,7 +172,7 @@ LINK32_OBJS= \
"$(INTDIR)\odbcapi.obj" \ "$(INTDIR)\odbcapi.obj" \
"$(INTDIR)\psqlodbc.res" "$(INTDIR)\psqlodbc.res"
"$(OUTDIR)\psqlodbc.dll" : "$(OUTDIR)" $(DEF_FILE) $(LINK32_OBJS) "$(OUTDIRBIN)\psqlodbc.dll" : "$(OUTDIR)" $(DEF_FILE) $(LINK32_OBJS)
$(LINK32) @<< $(LINK32) @<<
$(LINK32_FLAGS) $(LINK32_OBJS) $(LINK32_FLAGS) $(LINK32_OBJS)
<< <<
...@@ -199,7 +199,6 @@ CLEAN : ...@@ -199,7 +199,6 @@ CLEAN :
-@erase "$(INTDIR)\drvconn.obj" -@erase "$(INTDIR)\drvconn.obj"
-@erase "$(INTDIR)\environ.obj" -@erase "$(INTDIR)\environ.obj"
-@erase "$(INTDIR)\execute.obj" -@erase "$(INTDIR)\execute.obj"
-@erase "$(INTDIR)\gpps.obj"
-@erase "$(INTDIR)\info.obj" -@erase "$(INTDIR)\info.obj"
-@erase "$(INTDIR)\lobj.obj" -@erase "$(INTDIR)\lobj.obj"
-@erase "$(INTDIR)\win_md5.obj" -@erase "$(INTDIR)\win_md5.obj"
...@@ -288,7 +287,6 @@ LINK32_OBJS= \ ...@@ -288,7 +287,6 @@ LINK32_OBJS= \
"$(INTDIR)\drvconn.obj" \ "$(INTDIR)\drvconn.obj" \
"$(INTDIR)\environ.obj" \ "$(INTDIR)\environ.obj" \
"$(INTDIR)\execute.obj" \ "$(INTDIR)\execute.obj" \
"$(INTDIR)\gpps.obj" \
"$(INTDIR)\info.obj" \ "$(INTDIR)\info.obj" \
"$(INTDIR)\lobj.obj" \ "$(INTDIR)\lobj.obj" \
"$(INTDIR)\win_md5.obj" "$(INTDIR)\win_md5.obj"
...@@ -367,12 +365,6 @@ SOURCE=execute.c ...@@ -367,12 +365,6 @@ SOURCE=execute.c
$(CPP) $(CPP_PROJ) $(SOURCE) $(CPP) $(CPP_PROJ) $(SOURCE)
SOURCE=gpps.c
"$(INTDIR)\gpps.obj" : $(SOURCE) "$(INTDIR)"
$(CPP) $(CPP_PROJ) $(SOURCE)
SOURCE=info.c SOURCE=info.c
"$(INTDIR)\info.obj" : $(SOURCE) "$(INTDIR)" "$(INTDIR)\info.obj" : $(SOURCE) "$(INTDIR)"
......
...@@ -88,6 +88,7 @@ CLEAN : ...@@ -88,6 +88,7 @@ CLEAN :
-@erase "$(INTDIR)\tuplelist.obj" -@erase "$(INTDIR)\tuplelist.obj"
-@erase "$(INTDIR)\odbcapi.obj" -@erase "$(INTDIR)\odbcapi.obj"
-@erase "$(INTDIR)\odbcapi30.obj" -@erase "$(INTDIR)\odbcapi30.obj"
-@erase "$(INTDIR)\pgapi30.obj"
-@erase "$(INTDIR)\vc60.idb" -@erase "$(INTDIR)\vc60.idb"
-@erase "$(OUTDIR)\psqlodbc30.dll" -@erase "$(OUTDIR)\psqlodbc30.dll"
-@erase "$(OUTDIR)\psqlodbc.exp" -@erase "$(OUTDIR)\psqlodbc.exp"
...@@ -174,6 +175,7 @@ LINK32_OBJS= \ ...@@ -174,6 +175,7 @@ LINK32_OBJS= \
"$(INTDIR)\tuplelist.obj" \ "$(INTDIR)\tuplelist.obj" \
"$(INTDIR)\odbcapi.obj" \ "$(INTDIR)\odbcapi.obj" \
"$(INTDIR)\odbcapi30.obj" \ "$(INTDIR)\odbcapi30.obj" \
"$(INTDIR)\pgapi30.obj" \
"$(INTDIR)\psqlodbc.res" "$(INTDIR)\psqlodbc.res"
"$(OUTDIRBIN)\psqlodbc30.dll" : "$(OUTDIR)" $(DEF_FILE) $(LINK32_OBJS) "$(OUTDIRBIN)\psqlodbc30.dll" : "$(OUTDIR)" $(DEF_FILE) $(LINK32_OBJS)
...@@ -225,6 +227,7 @@ CLEAN : ...@@ -225,6 +227,7 @@ CLEAN :
-@erase "$(INTDIR)\tuplelist.obj" -@erase "$(INTDIR)\tuplelist.obj"
-@erase "$(INTDIR)\odbcapi.obj" -@erase "$(INTDIR)\odbcapi.obj"
-@erase "$(INTDIR)\odbcapi30.obj" -@erase "$(INTDIR)\odbcapi30.obj"
-@erase "$(INTDIR)\pgapi30.obj"
-@erase "$(INTDIR)\vc60.idb" -@erase "$(INTDIR)\vc60.idb"
-@erase "$(INTDIR)\vc60.pdb" -@erase "$(INTDIR)\vc60.pdb"
-@erase "$(OUTDIR)\psqlodbc30.dll" -@erase "$(OUTDIR)\psqlodbc30.dll"
...@@ -314,6 +317,7 @@ LINK32_OBJS= \ ...@@ -314,6 +317,7 @@ LINK32_OBJS= \
"$(INTDIR)\tuplelist.obj" \ "$(INTDIR)\tuplelist.obj" \
"$(INTDIR)\odbcapi.obj" \ "$(INTDIR)\odbcapi.obj" \
"$(INTDIR)\odbcapi30.obj" \ "$(INTDIR)\odbcapi30.obj" \
"$(INTDIR)\pgapi30.obj" \
"$(INTDIR)\psqlodbc.res" "$(INTDIR)\psqlodbc.res"
"$(OUTDIR)\psqlodbc30.dll" : "$(OUTDIR)" $(DEF_FILE) $(LINK32_OBJS) "$(OUTDIR)\psqlodbc30.dll" : "$(OUTDIR)" $(DEF_FILE) $(LINK32_OBJS)
...@@ -513,7 +517,10 @@ SOURCE=odbcapi30.c ...@@ -513,7 +517,10 @@ SOURCE=odbcapi30.c
"$(INTDIR)\odbcapi30.obj" : $(SOURCE) "$(INTDIR)" "$(INTDIR)\odbcapi30.obj" : $(SOURCE) "$(INTDIR)"
$(CPP) $(CPP_PROJ) $(SOURCE) $(CPP) $(CPP_PROJ) $(SOURCE)
SOURCE=pgcapi30.c
"$(INTDIR)\pgcapi30.obj" : $(SOURCE) "$(INTDIR)"
$(CPP) $(CPP_PROJ) $(SOURCE)
!ENDIF !ENDIF
#
# File: win32_30w.mak
#
# Description: psqlodbc30 Unicode version Makefile for Win32.
#
# Configurations: Unicode30Debug, Unicode30
# Build Types: ALL, CLEAN
# Usage: NMAKE /f win32_30.mak CFG=[Unicode30 | Unicode30Debug] [ALL | CLEAN]
#
# Comments: Created by Dave Page, 2001-02-12
#
!MESSAGE Building the PostgreSQL Unicode 3.0 Driver for Win32...
!MESSAGE
!IF "$(CFG)" == ""
CFG=Unicode30
!MESSAGE No configuration specified. Defaulting to Unicode30.
!MESSAGE
!ENDIF
!IF "$(CFG)" != "Unicode30" && "$(CFG)" != "Unicode30Debug"
!MESSAGE Invalid configuration "$(CFG)" specified.
!MESSAGE You can specify a configuration when running NMAKE
!MESSAGE by defining the macro CFG on the command line. For example:
!MESSAGE
!MESSAGE NMAKE /f win32_30.mak CFG=[Unicode30 | Unicode30Debug] [ALL | CLEAN]
!MESSAGE
!MESSAGE Possible choices for configuration are:
!MESSAGE
!MESSAGE "Unicode30" (Win32 Release DLL)
!MESSAGE "Unicode30Debug" (Win32 Debug DLL)
!MESSAGE
!ERROR An invalid configuration was specified.
!ENDIF
!IF "$(OS)" == "Windows_NT"
NULL=
!ELSE
NULL=nul
!ENDIF
!IF "$(CFG)" == "Unicode30"
OUTDIR=.\Unicode30
OUTDIRBIN=.\Unicode30
INTDIR=.\Unicode30
ALL : "$(OUTDIRBIN)\psqlodbc30.dll"
CLEAN :
-@erase "$(INTDIR)\bind.obj"
-@erase "$(INTDIR)\columninfo.obj"
-@erase "$(INTDIR)\connection.obj"
-@erase "$(INTDIR)\convert.obj"
-@erase "$(INTDIR)\dlg_specific.obj"
-@erase "$(INTDIR)\drvconn.obj"
-@erase "$(INTDIR)\environ.obj"
-@erase "$(INTDIR)\execute.obj"
-@erase "$(INTDIR)\info.obj"
-@erase "$(INTDIR)\info30.obj"
-@erase "$(INTDIR)\lobj.obj"
-@erase "$(INTDIR)\win_md5.obj"
-@erase "$(INTDIR)\misc.obj"
-@erase "$(INTDIR)\pgapi30.obj"
-@erase "$(INTDIR)\multibyte.obj"
-@erase "$(INTDIR)\odbcapiw.obj"
-@erase "$(INTDIR)\odbcapi30w.obj"
-@erase "$(INTDIR)\win_unicode.obj"
-@erase "$(INTDIR)\options.obj"
-@erase "$(INTDIR)\parse.obj"
-@erase "$(INTDIR)\pgtypes.obj"
-@erase "$(INTDIR)\psqlodbc.obj"
-@erase "$(INTDIR)\psqlodbc.res"
-@erase "$(INTDIR)\qresult.obj"
-@erase "$(INTDIR)\results.obj"
-@erase "$(INTDIR)\setup.obj"
-@erase "$(INTDIR)\socket.obj"
-@erase "$(INTDIR)\statement.obj"
-@erase "$(INTDIR)\tuple.obj"
-@erase "$(INTDIR)\tuplelist.obj"
-@erase "$(INTDIR)\odbcapi.obj"
-@erase "$(INTDIR)\odbcapi30.obj"
-@erase "$(INTDIR)\vc60.idb"
-@erase "$(OUTDIR)\psqlodbc30.dll"
-@erase "$(OUTDIR)\psqlodbc.exp"
-@erase "$(OUTDIR)\psqlodbc.lib"
"$(OUTDIR)" :
if not exist "$(OUTDIR)/$(NULL)" mkdir "$(OUTDIR)"
CPP=cl.exe
CPP_PROJ=/nologo /MT /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "PSQLODBC_EXPORTS" /D "ODBCVER=0x0300" /D "MULTIBYTE" /D "UNICODE_SUPPORT" /D "DRIVER_CURSOR_IMPLEMENT" /Fp"$(INTDIR)\psqlodbc.pch" /YX /Fo"$(INTDIR)\\" /Fd"$(INTDIR)\\" /FD /c
.c{$(INTDIR)}.obj::
$(CPP) @<<
$(CPP_PROJ) $<
<<
.cpp{$(INTDIR)}.obj::
$(CPP) @<<
$(CPP_PROJ) $<
<<
.cxx{$(INTDIR)}.obj::
$(CPP) @<<
$(CPP_PROJ) $<
<<
.c{$(INTDIR)}.sbr::
$(CPP) @<<
$(CPP_PROJ) $<
<<
.cpp{$(INTDIR)}.sbr::
$(CPP) @<<
$(CPP_PROJ) $<
<<
.cxx{$(INTDIR)}.sbr::
$(CPP) @<<
$(CPP_PROJ) $<
<<
MTL=midl.exe
MTL_PROJ=/nologo /D "NDEBUG" /mktyplib203 /win32
RSC=rc.exe
RSC_PROJ=/l 0x809 /fo"$(INTDIR)\psqlodbc.res" /d "NDEBUG"
BSC32=bscmake.exe
BSC32_FLAGS=/nologo /o"$(OUTDIR)\psqlodbc.bsc"
BSC32_SBRS= \
LINK32=link.exe
LINK32_FLAGS=kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib wsock32.lib /nologo /dll /incremental:no /pdb:"$(OUTDIR)\psqlodbc.pdb" /machine:I386 /def:"psqlodbc_api30w.def" /out:"$(OUTDIRBIN)\psqlodbc30.dll" /implib:"$(OUTDIR)\psqlodbc.lib"
DEF_FILE= "psqlodbc_api30w.def"
LINK32_OBJS= \
"$(INTDIR)\bind.obj" \
"$(INTDIR)\columninfo.obj" \
"$(INTDIR)\connection.obj" \
"$(INTDIR)\convert.obj" \
"$(INTDIR)\dlg_specific.obj" \
"$(INTDIR)\drvconn.obj" \
"$(INTDIR)\environ.obj" \
"$(INTDIR)\execute.obj" \
"$(INTDIR)\info.obj" \
"$(INTDIR)\info30.obj" \
"$(INTDIR)\lobj.obj" \
"$(INTDIR)\win_md5.obj" \
"$(INTDIR)\misc.obj" \
"$(INTDIR)\pgapi30.obj" \
"$(INTDIR)\multibyte.obj" \
"$(INTDIR)\odbcapiw.obj" \
"$(INTDIR)\odbcapi30w.obj" \
"$(INTDIR)\win_unicode.obj" \
"$(INTDIR)\options.obj" \
"$(INTDIR)\parse.obj" \
"$(INTDIR)\pgtypes.obj" \
"$(INTDIR)\psqlodbc.obj" \
"$(INTDIR)\qresult.obj" \
"$(INTDIR)\results.obj" \
"$(INTDIR)\setup.obj" \
"$(INTDIR)\socket.obj" \
"$(INTDIR)\statement.obj" \
"$(INTDIR)\tuple.obj" \
"$(INTDIR)\tuplelist.obj" \
"$(INTDIR)\odbcapi.obj" \
"$(INTDIR)\odbcapi30.obj" \
"$(INTDIR)\psqlodbc.res"
"$(OUTDIRBIN)\psqlodbc30.dll" : "$(OUTDIR)" $(DEF_FILE) $(LINK32_OBJS)
$(LINK32) @<<
$(LINK32_FLAGS) $(LINK32_OBJS)
<<
!ELSEIF "$(CFG)" == "Unicode30Debug"
ALL : "$(OUTDIR)\psqlodbc30.dll"
CLEAN :
-@erase "$(INTDIR)\bind.obj"
-@erase "$(INTDIR)\columninfo.obj"
-@erase "$(INTDIR)\connection.obj"
-@erase "$(INTDIR)\convert.obj"
-@erase "$(INTDIR)\dlg_specific.obj"
-@erase "$(INTDIR)\drvconn.obj"
-@erase "$(INTDIR)\environ.obj"
-@erase "$(INTDIR)\execute.obj"
-@erase "$(INTDIR)\info.obj"
-@erase "$(INTDIR)\info30.obj"
-@erase "$(INTDIR)\lobj.obj"
-@erase "$(INTDIR)\win_md5.obj"
-@erase "$(INTDIR)\misc.obj"
-@erase "$(INTDIR)\pgapi30.obj"
-@erase "$(INTDIR)\multibyte.obj"
-@erase "$(INTDIR)\odbcapiw.obj"
-@erase "$(INTDIR)\odbcapi30w.obj"
-@erase "$(INTDIR)\win_unicode.obj"
-@erase "$(INTDIR)\options.obj"
-@erase "$(INTDIR)\parse.obj"
-@erase "$(INTDIR)\pgtypes.obj"
-@erase "$(INTDIR)\psqlodbc.obj"
-@erase "$(INTDIR)\psqlodbc.res"
-@erase "$(INTDIR)\qresult.obj"
-@erase "$(INTDIR)\results.obj"
-@erase "$(INTDIR)\setup.obj"
-@erase "$(INTDIR)\socket.obj"
-@erase "$(INTDIR)\statement.obj"
-@erase "$(INTDIR)\tuple.obj"
-@erase "$(INTDIR)\tuplelist.obj"
-@erase "$(INTDIR)\odbcapi.obj"
-@erase "$(INTDIR)\odbcapi30.obj"
-@erase "$(INTDIR)\vc60.idb"
-@erase "$(INTDIR)\vc60.pdb"
-@erase "$(OUTDIR)\psqlodbc30.dll"
-@erase "$(OUTDIR)\psqlodbc.exp"
-@erase "$(OUTDIR)\psqlodbc.ilk"
-@erase "$(OUTDIR)\psqlodbc.lib"
-@erase "$(OUTDIR)\psqlodbc.pdb"
"$(OUTDIR)" :
if not exist "$(OUTDIR)/$(NULL)" mkdir "$(OUTDIR)"
CPP=cl.exe
CPP_PROJ=/nologo /MTd /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "PSQLODBC_EXPORTS" /D "ODBCVER=0x0300" /D "MULTIBYTE" /D "UNICODE_SUPPORT" /D "DRIVER_CURSOR_IMPLEMENT" /Fp"$(INTDIR)\psqlodbc.pch" /YX /Fo"$(INTDIR)\\" /Fd"$(INTDIR)\\" /FD /GZ /c
.c{$(INTDIR)}.obj::
$(CPP) @<<
$(CPP_PROJ) $<
<<
.cpp{$(INTDIR)}.obj::
$(CPP) @<<
$(CPP_PROJ) $<
<<
.cxx{$(INTDIR)}.obj::
$(CPP) @<<
$(CPP_PROJ) $<
<<
.c{$(INTDIR)}.sbr::
$(CPP) @<<
$(CPP_PROJ) $<
<<
.cpp{$(INTDIR)}.sbr::
$(CPP) @<<
$(CPP_PROJ) $<
<<
.cxx{$(INTDIR)}.sbr::
$(CPP) @<<
$(CPP_PROJ) $<
<<
MTL=midl.exe
MTL_PROJ=/nologo /D "_DEBUG" /mktyplib203 /win32
RSC=rc.exe
RSC_PROJ=/l 0x809 /fo"$(INTDIR)\psqlodbc.res" /d "_DEBUG"
BSC32=bscmake.exe
BSC32_FLAGS=/nologo /o"$(OUTDIR)\psqlodbc.bsc"
BSC32_SBRS= \
LINK32=link.exe
LINK32_FLAGS=kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib wsock32.lib /nologo /dll /incremental:yes /pdb:"$(OUTDIR)\psqlodbc.pdb" /debug /machine:I386 /def:"psqlodbc_api30w.def" /out:"$(OUTDIR)\psqlodbc30.dll" /implib:"$(OUTDIR)\psqlodbc.lib" /pdbtype:sept
DEF_FILE= "psqlodbc_api30w.def"
LINK32_OBJS= \
"$(INTDIR)\bind.obj" \
"$(INTDIR)\columninfo.obj" \
"$(INTDIR)\connection.obj" \
"$(INTDIR)\convert.obj" \
"$(INTDIR)\dlg_specific.obj" \
"$(INTDIR)\drvconn.obj" \
"$(INTDIR)\environ.obj" \
"$(INTDIR)\execute.obj" \
"$(INTDIR)\info.obj" \
"$(INTDIR)\info30.obj" \
"$(INTDIR)\lobj.obj" \
"$(INTDIR)\win_md5.obj"
"$(INTDIR)\misc.obj" \
"$(INTDIR)\pgapi30.obj" \
"$(INTDIR)\multibyte.obj" \
"$(INTDIR)\odbcapiw.obj" \
"$(INTDIR)\odbcapi30w.obj" \
"$(INTDIR)\win_unicode.obj" \
"$(INTDIR)\options.obj" \
"$(INTDIR)\parse.obj" \
"$(INTDIR)\pgtypes.obj" \
"$(INTDIR)\psqlodbc.obj" \
"$(INTDIR)\qresult.obj" \
"$(INTDIR)\results.obj" \
"$(INTDIR)\setup.obj" \
"$(INTDIR)\socket.obj" \
"$(INTDIR)\statement.obj" \
"$(INTDIR)\tuple.obj" \
"$(INTDIR)\tuplelist.obj" \
"$(INTDIR)\odbcapi.obj" \
"$(INTDIR)\odbcapi30.obj" \
"$(INTDIR)\psqlodbc.res"
"$(OUTDIR)\psqlodbc30.dll" : "$(OUTDIR)" $(DEF_FILE) $(LINK32_OBJS)
$(LINK32) @<<
$(LINK32_FLAGS) $(LINK32_OBJS)
<<
!ENDIF
!IF "$(CFG)" == "Unicode30" || "$(CFG)" == "Unicode30Debug"
SOURCE=bind.c
"$(INTDIR)\bind.obj" : $(SOURCE) "$(INTDIR)"
$(CPP) $(CPP_PROJ) $(SOURCE)
SOURCE=columninfo.c
"$(INTDIR)\columninfo.obj" : $(SOURCE) "$(INTDIR)"
$(CPP) $(CPP_PROJ) $(SOURCE)
SOURCE=connection.c
"$(INTDIR)\connection.obj" : $(SOURCE) "$(INTDIR)"
$(CPP) $(CPP_PROJ) $(SOURCE)
SOURCE=convert.c
"$(INTDIR)\convert.obj" : $(SOURCE) "$(INTDIR)"
$(CPP) $(CPP_PROJ) $(SOURCE)
SOURCE=dlg_specific.c
"$(INTDIR)\dlg_specific.obj" : $(SOURCE) "$(INTDIR)"
$(CPP) $(CPP_PROJ) $(SOURCE)
SOURCE=drvconn.c
"$(INTDIR)\drvconn.obj" : $(SOURCE) "$(INTDIR)"
$(CPP) $(CPP_PROJ) $(SOURCE)
SOURCE=environ.c
"$(INTDIR)\environ.obj" : $(SOURCE) "$(INTDIR)"
$(CPP) $(CPP_PROJ) $(SOURCE)
SOURCE=execute.c
"$(INTDIR)\execute.obj" : $(SOURCE) "$(INTDIR)"
$(CPP) $(CPP_PROJ) $(SOURCE)
SOURCE=info.c
"$(INTDIR)\info.obj" : $(SOURCE) "$(INTDIR)"
$(CPP) $(CPP_PROJ) $(SOURCE)
SOURCE=info30.c
"$(INTDIR)\info30.obj" : $(SOURCE) "$(INTDIR)"
$(CPP) $(CPP_PROJ) $(SOURCE)
SOURCE=lobj.c
"$(INTDIR)\lobj.obj" : $(SOURCE) "$(INTDIR)"
$(CPP) $(CPP_PROJ) $(SOURCE)
SOURCE=misc.c
"$(INTDIR)\misc.obj" : $(SOURCE) "$(INTDIR)"
$(CPP) $(CPP_PROJ) $(SOURCE)
SOURCE=multibyte.c
"$(INTDIR)\multibyte.obj" : $(SOURCE) "$(INTDIR)"
$(CPP) $(CPP_PROJ) $(SOURCE)
SOURCE=odbcapiw.c
"$(INTDIR)\odbcapiw.obj" : $(SOURCE) "$(INTDIR)"
$(CPP) $(CPP_PROJ) $(SOURCE)
SOURCE=pgapi30.c
"$(INTDIR)\pgapi30.obj" : $(SOURCE) "$(INTDIR)"
$(CPP) $(CPP_PROJ) $(SOURCE)
SOURCE=odbcapi30w.c
"$(INTDIR)\odbcapi30w.obj" : $(SOURCE) "$(INTDIR)"
$(CPP) $(CPP_PROJ) $(SOURCE)
SOURCE=win_unicode.c
"$(INTDIR)\win_unicode.obj" : $(SOURCE) "$(INTDIR)"
$(CPP) $(CPP_PROJ) $(SOURCE)
SOURCE=options.c
"$(INTDIR)\options.obj" : $(SOURCE) "$(INTDIR)"
$(CPP) $(CPP_PROJ) $(SOURCE)
SOURCE=parse.c
"$(INTDIR)\parse.obj" : $(SOURCE) "$(INTDIR)"
$(CPP) $(CPP_PROJ) $(SOURCE)
SOURCE=pgtypes.c
"$(INTDIR)\pgtypes.obj" : $(SOURCE) "$(INTDIR)"
$(CPP) $(CPP_PROJ) $(SOURCE)
SOURCE=psqlodbc.c
"$(INTDIR)\psqlodbc.obj" : $(SOURCE) "$(INTDIR)"
$(CPP) $(CPP_PROJ) $(SOURCE)
SOURCE=psqlodbc.rc
!IF "$(CFG)" == "Unicode30"
"$(INTDIR)\psqlodbc.res" : $(SOURCE) "$(INTDIR)"
$(RSC) /l 0x809 /fo"$(INTDIR)\psqlodbc.res" /d "NDEBUG" /d "MULTIBYTE" $(SOURCE)
!ENDIF
!IF "$(CFG)" == "Unicode30Debug"
"$(INTDIR)\psqlodbc.res" : $(SOURCE) "$(INTDIR)"
$(RSC) /l 0x809 /fo"$(INTDIR)\psqlodbc.res" /d "_DEBUG" $(SOURCE)
!ENDIF
SOURCE=qresult.c
"$(INTDIR)\qresult.obj" : $(SOURCE) "$(INTDIR)"
$(CPP) $(CPP_PROJ) $(SOURCE)
SOURCE=results.c
"$(INTDIR)\results.obj" : $(SOURCE) "$(INTDIR)"
$(CPP) $(CPP_PROJ) $(SOURCE)
SOURCE=setup.c
"$(INTDIR)\setup.obj" : $(SOURCE) "$(INTDIR)"
$(CPP) $(CPP_PROJ) $(SOURCE)
SOURCE=socket.c
"$(INTDIR)\socket.obj" : $(SOURCE) "$(INTDIR)"
$(CPP) $(CPP_PROJ) $(SOURCE)
SOURCE=statement.c
"$(INTDIR)\statement.obj" : $(SOURCE) "$(INTDIR)"
$(CPP) $(CPP_PROJ) $(SOURCE)
SOURCE=tuple.c
"$(INTDIR)\tuple.obj" : $(SOURCE) "$(INTDIR)"
$(CPP) $(CPP_PROJ) $(SOURCE)
SOURCE=tuplelist.c
"$(INTDIR)\tuplelist.obj" : $(SOURCE) "$(INTDIR)"
$(CPP) $(CPP_PROJ) $(SOURCE)
SOURCE=win_md5.c
"$(INTDIR)\win_md5.obj" : $(SOURCE) "$(INTDIR)"
$(CPP) $(CPP_PROJ) $(SOURCE)
SOURCE=odbcapi.c
"$(INTDIR)\odbcapi.obj" : $(SOURCE) "$(INTDIR)"
$(CPP) $(CPP_PROJ) $(SOURCE)
SOURCE=odbcapi30.c
"$(INTDIR)\odbcapi30.obj" : $(SOURCE) "$(INTDIR)"
$(CPP) $(CPP_PROJ) $(SOURCE)
!ENDIF
#
# File: win32w.mak
#
# Description: psqlodbc Unicode version Makefile for Win32.
#
# Configurations: UnicodeDebug, Unicode
# Build Types: ALL, CLEAN
# Usage: NMAKE /f win32w.mak CFG=[Unicode | UnicodeDebug] [ALL | CLEAN]
#
# Comments: Created by Dave Page, 2001-02-12
#
!MESSAGE Building the PostgreSQL Unicode Driver for Win32...
!MESSAGE
!IF "$(CFG)" == ""
CFG=Unicode
!MESSAGE No configuration specified. Defaulting to Unicode.
!MESSAGE
!ENDIF
!IF "$(CFG)" != "Unicode" && "$(CFG)" != "UnicodeDebug"
!MESSAGE Invalid configuration "$(CFG)" specified.
!MESSAGE You can specify a configuration when running NMAKE
!MESSAGE by defining the macro CFG on the command line. For example:
!MESSAGE
!MESSAGE NMAKE /f win32w.mak CFG=[Unicode | UnicodeDebug] [ALL | CLEAN]
!MESSAGE
!MESSAGE Possible choices for configuration are:
!MESSAGE
!MESSAGE "Unicode" (Win32 Release DLL)
!MESSAGE "UnicodeDebug" (Win32 Debug DLL)
!MESSAGE
!ERROR An invalid configuration was specified.
!ENDIF
!IF "$(OS)" == "Windows_NT"
NULL=
!ELSE
NULL=nul
!ENDIF
!IF "$(CFG)" == "Unicode"
OUTDIR=.\Unicode
OUTDIRBIN=.\Unicode
INTDIR=.\Unicode
ALL : "$(OUTDIRBIN)\psqlodbc.dll"
CLEAN :
-@erase "$(INTDIR)\bind.obj"
-@erase "$(INTDIR)\columninfo.obj"
-@erase "$(INTDIR)\connection.obj"
-@erase "$(INTDIR)\convert.obj"
-@erase "$(INTDIR)\dlg_specific.obj"
-@erase "$(INTDIR)\drvconn.obj"
-@erase "$(INTDIR)\environ.obj"
-@erase "$(INTDIR)\execute.obj"
-@erase "$(INTDIR)\info.obj"
-@erase "$(INTDIR)\lobj.obj"
-@erase "$(INTDIR)\win_md5.obj"
-@erase "$(INTDIR)\misc.obj"
-@erase "$(INTDIR)\multibyte.obj"
-@erase "$(INTDIR)\odbcapiw.obj"
-@erase "$(INTDIR)\odbcapi25w.obj"
-@erase "$(INTDIR)\win_unicode.obj"
-@erase "$(INTDIR)\options.obj"
-@erase "$(INTDIR)\parse.obj"
-@erase "$(INTDIR)\pgtypes.obj"
-@erase "$(INTDIR)\psqlodbc.obj"
-@erase "$(INTDIR)\psqlodbc.res"
-@erase "$(INTDIR)\qresult.obj"
-@erase "$(INTDIR)\results.obj"
-@erase "$(INTDIR)\setup.obj"
-@erase "$(INTDIR)\socket.obj"
-@erase "$(INTDIR)\statement.obj"
-@erase "$(INTDIR)\tuple.obj"
-@erase "$(INTDIR)\tuplelist.obj"
-@erase "$(INTDIR)\odbcapi.obj"
-@erase "$(INTDIR)\vc60.idb"
-@erase "$(OUTDIR)\psqlodbc.dll"
-@erase "$(OUTDIR)\psqlodbc.exp"
-@erase "$(OUTDIR)\psqlodbc.lib"
"$(OUTDIR)" :
if not exist "$(OUTDIR)/$(NULL)" mkdir "$(OUTDIR)"
CPP=cl.exe
CPP_PROJ=/nologo /MT /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "PSQLODBC_EXPORTS" /D "ODBCVER=0x0250" /D "MULTIBYTE" /D "UNICODE_SUPPORT" /D "DRIVER_CURSOR_IMPLEMENT" /Fp"$(INTDIR)\psqlodbc.pch" /YX /Fo"$(INTDIR)\\" /Fd"$(INTDIR)\\" /FD /c
.c{$(INTDIR)}.obj::
$(CPP) @<<
$(CPP_PROJ) $<
<<
.cpp{$(INTDIR)}.obj::
$(CPP) @<<
$(CPP_PROJ) $<
<<
.cxx{$(INTDIR)}.obj::
$(CPP) @<<
$(CPP_PROJ) $<
<<
.c{$(INTDIR)}.sbr::
$(CPP) @<<
$(CPP_PROJ) $<
<<
.cpp{$(INTDIR)}.sbr::
$(CPP) @<<
$(CPP_PROJ) $<
<<
.cxx{$(INTDIR)}.sbr::
$(CPP) @<<
$(CPP_PROJ) $<
<<
MTL=midl.exe
MTL_PROJ=/nologo /D "NDEBUG" /mktyplib203 /win32
RSC=rc.exe
RSC_PROJ=/l 0x809 /fo"$(INTDIR)\psqlodbc.res" /d "NDEBUG"
BSC32=bscmake.exe
BSC32_FLAGS=/nologo /o"$(OUTDIR)\psqlodbc.bsc"
BSC32_SBRS= \
LINK32=link.exe
LINK32_FLAGS=kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib wsock32.lib /nologo /dll /incremental:no /pdb:"$(OUTDIR)\psqlodbc.pdb" /machine:I386 /def:"psqlodbc_apiw.def" /out:"$(OUTDIRBIN)\psqlodbc.dll" /implib:"$(OUTDIR)\psqlodbc.lib"
DEF_FILE= "psqlodbc_apiw.def"
LINK32_OBJS= \
"$(INTDIR)\bind.obj" \
"$(INTDIR)\columninfo.obj" \
"$(INTDIR)\connection.obj" \
"$(INTDIR)\convert.obj" \
"$(INTDIR)\dlg_specific.obj" \
"$(INTDIR)\drvconn.obj" \
"$(INTDIR)\environ.obj" \
"$(INTDIR)\execute.obj" \
"$(INTDIR)\info.obj" \
"$(INTDIR)\lobj.obj" \
"$(INTDIR)\win_md5.obj" \
"$(INTDIR)\misc.obj" \
"$(INTDIR)\multibyte.obj" \
"$(INTDIR)\odbcapiw.obj" \
"$(INTDIR)\odbcapi25w.obj" \
"$(INTDIR)\win_unicode.obj" \
"$(INTDIR)\options.obj" \
"$(INTDIR)\parse.obj" \
"$(INTDIR)\pgtypes.obj" \
"$(INTDIR)\psqlodbc.obj" \
"$(INTDIR)\qresult.obj" \
"$(INTDIR)\results.obj" \
"$(INTDIR)\setup.obj" \
"$(INTDIR)\socket.obj" \
"$(INTDIR)\statement.obj" \
"$(INTDIR)\tuple.obj" \
"$(INTDIR)\tuplelist.obj" \
"$(INTDIR)\odbcapi.obj" \
"$(INTDIR)\psqlodbc.res"
"$(OUTDIRBIN)\psqlodbc.dll" : "$(OUTDIR)" $(DEF_FILE) $(LINK32_OBJS)
$(LINK32) @<<
$(LINK32_FLAGS) $(LINK32_OBJS)
<<
!ELSEIF "$(CFG)" == "UnicodeDebug"
ALL : "$(OUTDIR)\psqlodbc.dll"
CLEAN :
-@erase "$(INTDIR)\bind.obj"
-@erase "$(INTDIR)\columninfo.obj"
-@erase "$(INTDIR)\connection.obj"
-@erase "$(INTDIR)\convert.obj"
-@erase "$(INTDIR)\dlg_specific.obj"
-@erase "$(INTDIR)\drvconn.obj"
-@erase "$(INTDIR)\environ.obj"
-@erase "$(INTDIR)\execute.obj"
-@erase "$(INTDIR)\info.obj"
-@erase "$(INTDIR)\lobj.obj"
-@erase "$(INTDIR)\win_md5.obj"
-@erase "$(INTDIR)\misc.obj"
-@erase "$(INTDIR)\multibyte.obj"
-@erase "$(INTDIR)\odbcapiw.obj"
-@erase "$(INTDIR)\odbcapi25w.obj"
-@erase "$(INTDIR)\win_unicode.obj"
-@erase "$(INTDIR)\options.obj"
-@erase "$(INTDIR)\parse.obj"
-@erase "$(INTDIR)\pgtypes.obj"
-@erase "$(INTDIR)\psqlodbc.obj"
-@erase "$(INTDIR)\psqlodbc.res"
-@erase "$(INTDIR)\qresult.obj"
-@erase "$(INTDIR)\results.obj"
-@erase "$(INTDIR)\setup.obj"
-@erase "$(INTDIR)\socket.obj"
-@erase "$(INTDIR)\statement.obj"
-@erase "$(INTDIR)\tuple.obj"
-@erase "$(INTDIR)\tuplelist.obj"
-@erase "$(INTDIR)\odbcapi.obj"
-@erase "$(INTDIR)\vc60.idb"
-@erase "$(INTDIR)\vc60.pdb"
-@erase "$(OUTDIR)\psqlodbc.dll"
-@erase "$(OUTDIR)\psqlodbc.exp"
-@erase "$(OUTDIR)\psqlodbc.ilk"
-@erase "$(OUTDIR)\psqlodbc.lib"
-@erase "$(OUTDIR)\psqlodbc.pdb"
"$(OUTDIR)" :
if not exist "$(OUTDIR)/$(NULL)" mkdir "$(OUTDIR)"
CPP=cl.exe
CPP_PROJ=/nologo /MTd /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "PSQLODBC_EXPORTS" /D "ODBCVER=0x0250" /D "MULTIBYTE" /D "UNICODE_SUPPORT" /D "DRIVER_CURSOR_IMPLEMENT" /Fp"$(INTDIR)\psqlodbc.pch" /YX /Fo"$(INTDIR)\\" /Fd"$(INTDIR)\\" /FD /GZ /c
.c{$(INTDIR)}.obj::
$(CPP) @<<
$(CPP_PROJ) $<
<<
.cpp{$(INTDIR)}.obj::
$(CPP) @<<
$(CPP_PROJ) $<
<<
.cxx{$(INTDIR)}.obj::
$(CPP) @<<
$(CPP_PROJ) $<
<<
.c{$(INTDIR)}.sbr::
$(CPP) @<<
$(CPP_PROJ) $<
<<
.cpp{$(INTDIR)}.sbr::
$(CPP) @<<
$(CPP_PROJ) $<
<<
.cxx{$(INTDIR)}.sbr::
$(CPP) @<<
$(CPP_PROJ) $<
<<
MTL=midl.exe
MTL_PROJ=/nologo /D "_DEBUG" /mktyplib203 /win32
RSC=rc.exe
RSC_PROJ=/l 0x809 /fo"$(INTDIR)\psqlodbc.res" /d "_DEBUG"
BSC32=bscmake.exe
BSC32_FLAGS=/nologo /o"$(OUTDIR)\psqlodbc.bsc"
BSC32_SBRS= \
LINK32=link.exe
LINK32_FLAGS=kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib wsock32.lib /nologo /dll /incremental:yes /pdb:"$(OUTDIR)\psqlodbc.pdb" /debug /machine:I386 /def:"psqlodbc_apiw.def" /out:"$(OUTDIR)\psqlodbc.dll" /implib:"$(OUTDIR)\psqlodbc.lib" /pdbtype:sept
DEF_FILE= "psqlodbc_apiw.def"
LINK32_OBJS= \
"$(INTDIR)\bind.obj" \
"$(INTDIR)\columninfo.obj" \
"$(INTDIR)\connection.obj" \
"$(INTDIR)\convert.obj" \
"$(INTDIR)\dlg_specific.obj" \
"$(INTDIR)\drvconn.obj" \
"$(INTDIR)\environ.obj" \
"$(INTDIR)\execute.obj" \
"$(INTDIR)\info.obj" \
"$(INTDIR)\lobj.obj" \
"$(INTDIR)\win_md5.obj"
"$(INTDIR)\misc.obj" \
"$(INTDIR)\multibyte.obj" \
"$(INTDIR)\odbcapiw.obj" \
"$(INTDIR)\odbcapi25w.obj" \
"$(INTDIR)\win_unicode.obj" \
"$(INTDIR)\options.obj" \
"$(INTDIR)\parse.obj" \
"$(INTDIR)\pgtypes.obj" \
"$(INTDIR)\psqlodbc.obj" \
"$(INTDIR)\qresult.obj" \
"$(INTDIR)\results.obj" \
"$(INTDIR)\setup.obj" \
"$(INTDIR)\socket.obj" \
"$(INTDIR)\statement.obj" \
"$(INTDIR)\tuple.obj" \
"$(INTDIR)\tuplelist.obj" \
"$(INTDIR)\odbcapi.obj" \
"$(INTDIR)\psqlodbc.res"
"$(OUTDIR)\psqlodbc.dll" : "$(OUTDIR)" $(DEF_FILE) $(LINK32_OBJS)
$(LINK32) @<<
$(LINK32_FLAGS) $(LINK32_OBJS)
<<
!ENDIF
!IF "$(CFG)" == "Unicode" || "$(CFG)" == "UnicodeDebug"
SOURCE=bind.c
"$(INTDIR)\bind.obj" : $(SOURCE) "$(INTDIR)"
$(CPP) $(CPP_PROJ) $(SOURCE)
SOURCE=columninfo.c
"$(INTDIR)\columninfo.obj" : $(SOURCE) "$(INTDIR)"
$(CPP) $(CPP_PROJ) $(SOURCE)
SOURCE=connection.c
"$(INTDIR)\connection.obj" : $(SOURCE) "$(INTDIR)"
$(CPP) $(CPP_PROJ) $(SOURCE)
SOURCE=convert.c
"$(INTDIR)\convert.obj" : $(SOURCE) "$(INTDIR)"
$(CPP) $(CPP_PROJ) $(SOURCE)
SOURCE=dlg_specific.c
"$(INTDIR)\dlg_specific.obj" : $(SOURCE) "$(INTDIR)"
$(CPP) $(CPP_PROJ) $(SOURCE)
SOURCE=drvconn.c
"$(INTDIR)\drvconn.obj" : $(SOURCE) "$(INTDIR)"
$(CPP) $(CPP_PROJ) $(SOURCE)
SOURCE=environ.c
"$(INTDIR)\environ.obj" : $(SOURCE) "$(INTDIR)"
$(CPP) $(CPP_PROJ) $(SOURCE)
SOURCE=execute.c
"$(INTDIR)\execute.obj" : $(SOURCE) "$(INTDIR)"
$(CPP) $(CPP_PROJ) $(SOURCE)
SOURCE=info.c
"$(INTDIR)\info.obj" : $(SOURCE) "$(INTDIR)"
$(CPP) $(CPP_PROJ) $(SOURCE)
SOURCE=lobj.c
"$(INTDIR)\lobj.obj" : $(SOURCE) "$(INTDIR)"
$(CPP) $(CPP_PROJ) $(SOURCE)
SOURCE=misc.c
"$(INTDIR)\misc.obj" : $(SOURCE) "$(INTDIR)"
$(CPP) $(CPP_PROJ) $(SOURCE)
SOURCE=multibyte.c
"$(INTDIR)\multibyte.obj" : $(SOURCE) "$(INTDIR)"
$(CPP) $(CPP_PROJ) $(SOURCE)
SOURCE=odbcapiw.c
"$(INTDIR)\odbcapiw.obj" : $(SOURCE) "$(INTDIR)"
$(CPP) $(CPP_PROJ) $(SOURCE)
SOURCE=odbcapi25w.c
"$(INTDIR)\odbcapi25w.obj" : $(SOURCE) "$(INTDIR)"
$(CPP) $(CPP_PROJ) $(SOURCE)
SOURCE=win_unicode.c
"$(INTDIR)\win_unicode.obj" : $(SOURCE) "$(INTDIR)"
$(CPP) $(CPP_PROJ) $(SOURCE)
SOURCE=options.c
"$(INTDIR)\options.obj" : $(SOURCE) "$(INTDIR)"
$(CPP) $(CPP_PROJ) $(SOURCE)
SOURCE=parse.c
"$(INTDIR)\parse.obj" : $(SOURCE) "$(INTDIR)"
$(CPP) $(CPP_PROJ) $(SOURCE)
SOURCE=pgtypes.c
"$(INTDIR)\pgtypes.obj" : $(SOURCE) "$(INTDIR)"
$(CPP) $(CPP_PROJ) $(SOURCE)
SOURCE=psqlodbc.c
"$(INTDIR)\psqlodbc.obj" : $(SOURCE) "$(INTDIR)"
$(CPP) $(CPP_PROJ) $(SOURCE)
SOURCE=psqlodbc.rc
!IF "$(CFG)" == "Unicode"
"$(INTDIR)\psqlodbc.res" : $(SOURCE) "$(INTDIR)"
$(RSC) /l 0x809 /fo"$(INTDIR)\psqlodbc.res" /d "NDEBUG" /d "MULTIBYTE" $(SOURCE)
!ENDIF
!IF "$(CFG)" == "UnicodeDebug"
"$(INTDIR)\psqlodbc.res" : $(SOURCE) "$(INTDIR)"
$(RSC) /l 0x809 /fo"$(INTDIR)\psqlodbc.res" /d "_DEBUG" $(SOURCE)
!ENDIF
SOURCE=qresult.c
"$(INTDIR)\qresult.obj" : $(SOURCE) "$(INTDIR)"
$(CPP) $(CPP_PROJ) $(SOURCE)
SOURCE=results.c
"$(INTDIR)\results.obj" : $(SOURCE) "$(INTDIR)"
$(CPP) $(CPP_PROJ) $(SOURCE)
SOURCE=setup.c
"$(INTDIR)\setup.obj" : $(SOURCE) "$(INTDIR)"
$(CPP) $(CPP_PROJ) $(SOURCE)
SOURCE=socket.c
"$(INTDIR)\socket.obj" : $(SOURCE) "$(INTDIR)"
$(CPP) $(CPP_PROJ) $(SOURCE)
SOURCE=statement.c
"$(INTDIR)\statement.obj" : $(SOURCE) "$(INTDIR)"
$(CPP) $(CPP_PROJ) $(SOURCE)
SOURCE=tuple.c
"$(INTDIR)\tuple.obj" : $(SOURCE) "$(INTDIR)"
$(CPP) $(CPP_PROJ) $(SOURCE)
SOURCE=tuplelist.c
"$(INTDIR)\tuplelist.obj" : $(SOURCE) "$(INTDIR)"
$(CPP) $(CPP_PROJ) $(SOURCE)
SOURCE=win_md5.c
"$(INTDIR)\win_md5.obj" : $(SOURCE) "$(INTDIR)"
$(CPP) $(CPP_PROJ) $(SOURCE)
SOURCE=odbcapi.c
"$(INTDIR)\odbcapi.obj" : $(SOURCE) "$(INTDIR)"
$(CPP) $(CPP_PROJ) $(SOURCE)
!ENDIF
...@@ -20,6 +20,13 @@ ...@@ -20,6 +20,13 @@
#define byte3_mask2 0x0fc0 #define byte3_mask2 0x0fc0
#define byte3_mask3 0x003f #define byte3_mask3 0x003f
UInt4 ucs2strlen(const SQLWCHAR *ucs2str)
{
UInt4 len;
for (len = 0; ucs2str[len]; len++)
;
return len;
}
char *ucs2_to_utf8(const SQLWCHAR *ucs2str, Int4 ilen, UInt4 *olen) char *ucs2_to_utf8(const SQLWCHAR *ucs2str, Int4 ilen, UInt4 *olen)
{ {
char * utf8str; char * utf8str;
...@@ -28,24 +35,21 @@ char *ucs2_to_utf8(const SQLWCHAR *ucs2str, Int4 ilen, UInt4 *olen) ...@@ -28,24 +35,21 @@ char *ucs2_to_utf8(const SQLWCHAR *ucs2str, Int4 ilen, UInt4 *olen)
if (!ucs2str) if (!ucs2str)
return NULL; return NULL;
if (ilen < 0) if (ilen < 0)
{ ilen = ucs2strlen(ucs2str);
for (ilen = 0; ucs2str[ilen]; ilen++)
;
}
/*mylog(" newlen=%d", ilen);*/ /*mylog(" newlen=%d", ilen);*/
utf8str = (char *) malloc(ilen * 3 + 1); utf8str = (char *) malloc(ilen * 3 + 1);
if (utf8str) if (utf8str)
{ {
int i, len = 0; int i, len = 0;
Int2 byte2code; UInt2 byte2code;
Int4 byte4code; Int4 byte4code;
const SQLWCHAR *wstr; const SQLWCHAR *wstr;
for (i = 0, wstr = ucs2str; i < ilen; i++, wstr++) for (i = 0, wstr = ucs2str; i < ilen; i++, wstr++)
{ {
if (!*wstr) if (!*wstr)
break; break;
else if (iswascii(*wstr)) else if (0 == (*wstr & 0xff80))
utf8str[len++] = (char) *wstr; utf8str[len++] = (char) *wstr;
else if ((*wstr & byte3check) == 0) else if ((*wstr & byte3check) == 0)
{ {
...@@ -66,7 +70,8 @@ char *ucs2_to_utf8(const SQLWCHAR *ucs2str, Int4 ilen, UInt4 *olen) ...@@ -66,7 +70,8 @@ char *ucs2_to_utf8(const SQLWCHAR *ucs2str, Int4 ilen, UInt4 *olen)
} }
} }
utf8str[len] = '\0'; utf8str[len] = '\0';
*olen = len; if (olen)
*olen = len;
} }
/*mylog(" olen=%d %s\n", *olen, utf8str ? utf8str : "");*/ /*mylog(" olen=%d %s\n", *olen, utf8str ? utf8str : "");*/
return utf8str; return utf8str;
...@@ -109,7 +114,7 @@ UInt4 utf8_to_ucs2(const char *utf8str, Int4 ilen, SQLWCHAR *ucs2str, UInt4 bufc ...@@ -109,7 +114,7 @@ UInt4 utf8_to_ucs2(const char *utf8str, Int4 ilen, SQLWCHAR *ucs2str, UInt4 bufc
{ {
wcode = ((((UInt4) *str) & byte3_m1) << 12) | wcode = ((((UInt4) *str) & byte3_m1) << 12) |
((((UInt4) str[1]) & byte3_m2) << 6) | ((((UInt4) str[1]) & byte3_m2) << 6) |
((UInt4) str[2]) & byte3_m3; (((UInt4) str[2]) & byte3_m3);
ucs2str[ocount] = (SQLWCHAR) wcode; ucs2str[ocount] = (SQLWCHAR) wcode;
} }
ocount++; ocount++;
...@@ -121,7 +126,7 @@ UInt4 utf8_to_ucs2(const char *utf8str, Int4 ilen, SQLWCHAR *ucs2str, UInt4 bufc ...@@ -121,7 +126,7 @@ UInt4 utf8_to_ucs2(const char *utf8str, Int4 ilen, SQLWCHAR *ucs2str, UInt4 bufc
if (ocount < bufcount) if (ocount < bufcount)
{ {
wcode = ((((UInt4) *str) & byte2_m1) << 6) | wcode = ((((UInt4) *str) & byte2_m1) << 6) |
((UInt4) str[1]) & byte2_m2; (((UInt4) str[1]) & byte2_m2);
ucs2str[ocount] = (SQLWCHAR) wcode; ucs2str[ocount] = (SQLWCHAR) wcode;
} }
ocount++; ocount++;
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment