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.
* Classes: BindInfoClass, ParameterInfoClass
*
* API functions: SQLBindParameter, SQLBindCol, SQLDescribeParam, SQLNumParams,
- * SQLParamOptions(NI)
+ * SQLParamOptions
*
* Comments: See "notice.txt" for copyright and license information.
*-------
mylog("%s: entering... %d %x\n", func, crow, pirow);
- if (crow == 1) /* temporary solution and must be
- * rewritten later */
- {
- 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;
+ stmt->options.paramset_size = crow;
+ stmt->options.param_processed_ptr = pirow;
+ return SQL_SUCCESS;
}
return SQL_ERROR;
}
- *phdbc = (HDBC) conn;
+ if (phdbc)
+ *phdbc = (HDBC) conn;
return SQL_SUCCESS;
}
}
+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
*/
rv->status = CONN_NOT_CONNECTED;
rv->transact_status = CONN_IN_AUTOCOMMIT; /* autocommit by default */
- memset(&rv->connInfo, 0, sizeof(ConnInfo));
-#ifdef DRIVER_CURSOR_IMPLEMENT
- rv->connInfo.updatable_cursors = 1;
-#endif /* DRIVER_CURSOR_IMPLEMENT */
- memcpy(&(rv->connInfo.drivers), &globals, sizeof(globals));
+ CC_conninfo_init(&(rv->connInfo));
rv->sock = SOCK_Constructor(rv);
if (!rv->sock)
return NULL;
rv->pg_version_major = 0;
rv->pg_version_minor = 0;
rv->ms_jet = 0;
+ rv->unicode = 0;
#ifdef MULTIBYTE
rv->client_encoding = NULL;
rv->server_encoding = NULL;
for (i = 0; i < self->num_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++;
}
char ret = TRUE;
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");
if (res != NULL)
{
- ret = (!QR_aborted(res) && QR_command_successful(res));
+ ret = QR_command_successful(res);
QR_Destructor(res);
if (ret)
CC_set_in_trans(self);
}
else
- ret = FALSE;
+ return FALSE;
}
return ret;
char ret = FALSE;
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");
CC_set_no_trans(self);
QR_Destructor(res);
}
else
- ret = FALSE;
+ return FALSE;
}
return ret;
{
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");
CC_set_no_trans(self);
self->status = CONN_NOT_CONNECTED;
self->transact_status = CONN_IN_AUTOCOMMIT;
- memset(&self->connInfo, 0, sizeof(ConnInfo));
-#ifdef DRIVER_CURSOR_IMPLEMENT
- self->connInfo.updatable_cursors = 1;
-#endif /* DRIVER_CURSOR_IMPLEMENT */
- memcpy(&(self->connInfo.drivers), &globals, sizeof(globals));
+ CC_conninfo_init(&(self->connInfo));
#ifdef MULTIBYTE
if (self->client_encoding)
free(self->client_encoding);
{
free(pwd1);
return 1;
- }
+ }
if (!(pwd2 = malloc(MD5_PASSWD_LEN + 1)))
{
free(pwd1);
return 1;
- }
+ }
if (!EncryptMD5(pwd1 + strlen("md5"), salt, 4, pwd2))
{
free(pwd2);
SOCK_put_n_char(sock, pwd2, strlen(pwd2) + 1);
SOCK_flush_output(sock);
free(pwd2);
- return 0;
+ return 0;
}
char
ConnInfo *ci = &(self->connInfo);
int areq = -1;
int beresp;
- char msgbuffer[ERROR_MSG_LENGTH];
+ static char msgbuffer[ERROR_MSG_LENGTH];
char salt[5];
static char *func = "CC_connect";
if (encoding && strcmp(encoding, "OTHER"))
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",
ci->drivers.extra_systable_prefixes,
ci->drivers.conn_settings,
encoding ? encoding : "");
#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.conn_settings,
- ci->protocol);
+ ci->drivers.conn_settings);
#endif
if (self->status != CONN_NOT_CONNECTED)
*/
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)
{
mylog("got no result from the empty query. (probably database does not exist)\n");
* function instead.
*/
CC_send_settings(self);
- CC_lookup_lo(self); /* a hack to get the oid of our large
- * object oid type */
-#ifdef MULTIBYTE\r
- CC_lookup_characterset(self);\r
-#endif\r
- CC_lookup_pg_version(self); /* Get PostgreSQL version for SQLGetInfo
- * use */
+ CC_lookup_lo(self); /* a hack to get the oid of
+ our large object oid type */
+ 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 */
self->status = CONN_CONNECTED;
* 'declare cursor C3326857 for ...' and 'fetch 100 in C3326857' statements.
*/
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,
- *res = NULL,
- *retres = NULL;
+ *cmdres = NULL,
+ *retres = NULL,
+ *res = NULL;
char swallow,
*wq;
int id;
empty_reqs;
BOOL msg_truncated,
ReadyToReturn,
- tuples_return = FALSE,
query_completed = FALSE,
before_64 = PG_VERSION_LT(self, 6.4),
+ aborted = FALSE,
used_passed_result_object = FALSE;
/* ERROR_MSG_LENGTH is suffcient */
;
if (*wq == '\0')
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)
{
/* what type of message is coming now ? */
{
mylog("send_query: ok - 'C' - %s\n", cmdbuffer);
- if (res == NULL) /* allow for "show" style info */
- res = QR_Constructor();
+ if (query_completed) /* allow for "show" style notices */
+ {
+ res->next = QR_Constructor();
+ res = res->next;
+ }
mylog("send_query: setting cmdbuffer = '%s'\n", cmdbuffer);
- /* Only save the first command */
if (QR_command_successful(res))
QR_set_status(res, PGRES_COMMAND_OK);
QR_set_command(res, cmdbuffer);
if (empty_reqs == 0)
{
ReadyToReturn = TRUE;
- if (res && QR_get_aborted(res))
- retres = res;
- else if (tuples_return)
- retres = result_in;
- else if (query_completed)
- retres = res;
+ if (aborted || query_completed)
+ retres = cmdres;
else
ReadyToReturn = FALSE;
}
break;
- case 'N': /* INFO, NOTICE, WARNING */
+ case 'N': /* NOTICE: */
msg_truncated = SOCK_get_string(sock, cmdbuffer, ERROR_MSG_LENGTH);
- if (!res)
- res = QR_Constructor();
if (QR_command_successful(res))
QR_set_status(res, PGRES_NONFATAL_ERROR);
QR_set_notice(res, cmdbuffer); /* will dup this string */
-#ifdef MULTIBYTE\r
- if (strstr(cmdbuffer,"encoding is"))\r
- {\r
- if (strstr(cmdbuffer,"Current client encoding is"))\r
- strcpy(PG_CCSS, cmdbuffer + 36);\r
- if (strstr(cmdbuffer,"Current server encoding is"))\r
- strcpy(PG_SCSS, cmdbuffer + 36);\r
- mylog("~~~ WARNING: '%s'\n", cmdbuffer);\r
- qlog("WARNING from backend during send_query: '%s'\n ClientEncoding = %s\n ServerEncoding = %s\n", cmdbuffer, PG_CCSS, PG_SCSS);\r
-\r
- }\r
- else\r
- {\r
-\r
- mylog("~~~ WARNING: '%s'\n", cmdbuffer);\r
- qlog("WARNING from backend during send_query: '%s'\n", cmdbuffer);\r
- }\r
-#else\r
- mylog("~~~ WARNING: '%s'\n", cmdbuffer);\r
- qlog("WARNING from backend during send_query: '%s'\n", cmdbuffer);\r
-#endif
+ mylog("~~~ NOTICE: '%s'\n", cmdbuffer);
+ qlog("NOTICE from backend during send_query: '%s'\n", cmdbuffer);
while (msg_truncated)
msg_truncated = SOCK_get_string(sock, cmdbuffer, ERROR_MSG_LENGTH);
case 'I': /* The server sends an empty query */
/* There is a closing '\0' following the 'I', so we eat it */
swallow = SOCK_get_char(sock);
- if (!res)
- res = QR_Constructor();
if ((swallow != '\0') || SOCK_get_errcode(sock) != 0)
{
self->errornumber = CONNECTION_BACKEND_CRAZY;
self->errormsg = "Unexpected protocol character from backend (send_query - I)";
QR_set_status(res, PGRES_FATAL_ERROR);
ReadyToReturn = TRUE;
- retres = res;
+ retres = cmdres;
break;
}
else
qlog("ERROR from backend during send_query: '%s'\n", self->errormsg);
/* We should report that an error occured. Zoltan */
- if (!res)
- res = QR_Constructor();
if (!strncmp(self->errormsg, "FATAL", 5))
{
self->errornumber = CONNECTION_SERVER_REPORTED_WARNING;
QR_set_status(res, PGRES_FATAL_ERROR);
QR_set_aborted(res, TRUE);
+ aborted = TRUE;
while (msg_truncated)
msg_truncated = SOCK_get_string(sock, cmdbuffer, ERROR_MSG_LENGTH);
SOCK_get_string(sock, msgbuffer, ERROR_MSG_LENGTH);
break;
case 'T': /* Tuple results start here */
- result_in = qi ? qi->result_in : NULL;
-
- if (result_in == NULL)
+ if (query_completed)
{
- result_in = QR_Constructor();
- mylog("send_query: 'T' no result_in: res = %u\n", result_in);
- if (!result_in)
+ res->next = QR_Constructor();
+ mylog("send_query: 'T' no result_in: res = %u\n", res->next);
+ if (!res->next)
{
self->errornumber = CONNECTION_COULD_NOT_RECEIVE;
self->errormsg = "Could not create result info in send_query.";
retres = NULL;
break;
}
+ res = res->next;
if (qi)
- QR_set_cache_size(result_in, qi->row_size);
-
- if (!QR_fetch_tuples(result_in, self, qi ? qi->cursor : NULL))
+ QR_set_cache_size(res, qi->row_size);
+ }
+ if (!used_passed_result_object)
+ {
+ if (!QR_fetch_tuples(res, self, qi ? qi->cursor : NULL))
{
self->errornumber = CONNECTION_COULD_NOT_RECEIVE;
- self->errormsg = QR_get_message(result_in);
+ self->errormsg = QR_get_message(res);
ReadyToReturn = TRUE;
retres = NULL;
break;
}
+ query_completed = TRUE;
}
else
{ /* next fetch, so reuse an existing result */
- used_passed_result_object = TRUE;
/*
* called from QR_next_tuple and must return
* immediately.
*/
ReadyToReturn = TRUE;
- if (!QR_fetch_tuples(result_in, NULL, NULL))
+ if (!QR_fetch_tuples(res, NULL, NULL))
{
self->errornumber = CONNECTION_COULD_NOT_RECEIVE;
- self->errormsg = QR_get_message(result_in);
+ self->errormsg = QR_get_message(res);
retres = NULL;
break;
}
- retres = result_in;
+ retres = cmdres;
}
-
- tuples_return = TRUE;
break;
case 'D': /* Copy in command began successfully */
- if (!res)
- res = QR_Constructor();
- if (QR_command_successful(res))
- QR_set_status(res, PGRES_COPY_IN);
+ if (query_completed)
+ {
+ res->next = QR_Constructor();
+ res = res->next;
+ }
+ QR_set_status(res, PGRES_COPY_IN);
ReadyToReturn = TRUE;
- retres = res;
+ retres = cmdres;
break;
case 'B': /* Copy out command began successfully */
- if (!res)
- res = QR_Constructor();
- if (QR_command_successful(res))
- QR_set_status(res, PGRES_COPY_OUT);
+ if (query_completed)
+ {
+ res->next = QR_Constructor();
+ res = res->next;
+ }
+ QR_set_status(res, PGRES_COPY_OUT);
ReadyToReturn = TRUE;
- retres = res;
+ retres = cmdres;
break;
default:
self->errornumber = CONNECTION_BACKEND_CRAZY;
*/
if (before_64)
{
- if (empty_reqs == 0 && (query_completed || tuples_return))
+ if (empty_reqs == 0 && query_completed)
break;
}
}
* Break before being ready to return.
*/
if (!ReadyToReturn)
- {
- if (res && QR_get_aborted(res))
- retres = res;
- else if (tuples_return)
- retres = result_in;
- else
- retres = res;
- }
+ retres = cmdres;
/*
- * set notice message to result_in.
+ * Cleanup garbage results before returning.
*/
- if (result_in && res && retres == result_in)
- {
- if (QR_command_successful(result_in))
- QR_set_status(result_in, QR_get_status(res));
- QR_set_notice(result_in, QR_get_notice(res));
- }
-
+ if (cmdres && retres != cmdres && !used_passed_result_object)
+ QR_Destructor(cmdres);
/*
- * Cleanup garbage results before returning.
+ * Cleanup the aborted result if specified
*/
- if (res && retres != res)
- QR_Destructor(res);
- if (result_in && retres != result_in)
+ if (retres)
{
- if (!used_passed_result_object)
- QR_Destructor(result_in);
+ if (aborted)
+ {
+ 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;
}
SOCK_get_string(sock, msgbuffer, ERROR_MSG_LENGTH);
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
* reading */
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
#define nullcheck(a) (a ? a : "(NULL)")
}
}
else
+{
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
}
char focus_password;
char disallow_premature;
char updatable_cursors;
+ char lf_conversion;
+ char true_is_minus1;
GLOBAL_VALUES drivers; /* moved from driver's option */
} ConnInfo;
char *client_encoding;
char *server_encoding;
#endif /* MULTIBYTE */
+ int ccsc;
};
/* prototypes */
ConnectionClass *CC_Constructor(void);
+void CC_conninfo_init(ConnInfo *conninfo);
char CC_Destructor(ConnectionClass *self);
int CC_cursor_count(ConnectionClass *self);
char CC_cleanup(ConnectionClass *self);
char CC_add_statement(ConnectionClass *self, StatementClass *stmt);
char CC_remove_statement(ConnectionClass *self, StatementClass *stmt);
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);
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);
void CC_lookup_lo(ConnectionClass *conn);
void CC_lookup_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);
#endif
int bind_row = stmt->bind_row;
int bind_size = stmt->options.bind_size;
int result = COPY_OK;
- BOOL changed;
+ BOOL changed, true_is_minus1 = FALSE;
const char *neut_str = value;
char midtemp[2][32];
int mtemp_cnt = 0;
static BindInfoClass sbic;
BindInfoClass *pbic;
+#ifdef UNICODE_SUPPORT
+ BOOL wchanged = FALSE;
+#endif /* UNICODE_SUPPORT */
if (stmt->current_col >= 0)
{
char *s;
s = midtemp[mtemp_cnt];
- strcpy(s, (char *) value);
- if (s[0] == 'f' || s[0] == 'F' || s[0] == 'n' || s[0] == 'N' || s[0] == '0')
- s[0] = '0';
- else
- s[0] = '1';
- s[1] = '\0';
+ switch (((char *)value)[0])
+ {
+ case 'f':
+ case 'F':
+ case 'n':
+ 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];
mtemp_cnt++;
-
}
break;
rgbValueBindRow = (char *) rgbValue + rgbValueOffset;
+#ifdef UNICODE_SUPPORT
+ if (fCType == SQL_C_CHAR || fCType == SQL_C_WCHAR)
+#else
if (fCType == SQL_C_CHAR)
+#endif /* UNICODE_SUPPORT */
{
/* Special character formatting as required */
break;
case PG_TYPE_BOOL:
- len = 1;
+ len = strlen(neut_str);
if (cbValueMax > len)
{
strcpy(rgbValueBindRow, neut_str);
pbic = &stmt->bindings[stmt->current_col];
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 */
- len = convert_linefeeds(neut_str, NULL, 0, &changed);
+ len = convert_linefeeds(neut_str, NULL, 0, lf_conv, &changed);
if (cbValueMax == 0) /* just returns length
* info */
{
pbic->ttlbuf = realloc(pbic->ttlbuf, 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;
}
else
mylog(" SQL_C_CHAR, default: len = %d, cbValueMax = %d, rgbValueBindRow = '%s'\n", len, cbValueMax, rgbValueBindRow);
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
*/
#define CVT_SPECIAL_CHARS(buf, used) \
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; \
\
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; \
} while (0)
}
#ifdef MULTIBYTE
-#define my_strchr(s1,c1) multibyte_strchr(s1,c1)
+#define my_strchr(conn, s1,c1) pg_mbschr(conn->ccsc, s1,c1)
#else
-#define my_strchr(s1,c1) strchr(s1,c1)
+#define my_strchr(conn, s1,c1) strchr(s1,c1)
#endif
/*
* This function inserts parameters into an SQL statements.
time_t t = time(NULL);
struct tm *tim;
SDWORD used;
- char *buffer,
- *buf;
+ char *buffer, *buf, *allocbuf;
BOOL in_quote = FALSE,
in_dquote = FALSE,
in_escape = FALSE;
BOOL prev_token_end;
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;
+ BOOL lf_conv = ci->lf_conversion;
+#ifdef MULTIBYTE
+ encoded_str encstr;
+#endif /* MULTIBYTE */
#ifdef DRIVER_CURSOR_IMPLEMENT
BOOL search_from_pos = FALSE;
}
param_number = -1;
#ifdef MULTIBYTE
- multibyte_init();
+ make_encoded_str(&encstr, conn, old_statement);
#endif
for (opos = 0; opos < oldstmtlen; opos++)
{
- oldchar = old_statement[opos];
#ifdef MULTIBYTE
- if (multibyte_char_check(oldchar) != 0)
+ oldchar = encoded_byte_check(&encstr, opos);
+ if (ENCODE_STATUS(encstr) != 0)
{
CVT_APPEND_CHAR(oldchar);
continue;
/*
* From here we are guaranteed to handle a 1-byte character.
*/
+#else
+ oldchar = old_statement[opos];
#endif
if (in_escape) /* escape check */
* nor a double quote.
*/
/* 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')
continue;
}
opos += lit_call_len;
CVT_APPEND_STR("SELECT ");
- if (my_strchr(&old_statement[opos], '('))
+ if (my_strchr(conn, &old_statement[opos], '('))
proc_no_param = FALSE;
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->errornumber = STMT_EXEC_ERROR;
if (param_ctype == SQL_C_DEFAULT)
param_ctype = sqltype_to_default_ctype(param_sqltype);
- buf = NULL;
+ allocbuf = buf = NULL;
param_string[0] = '\0';
cbuf[0] = '\0';
buf = buffer;
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:
sprintf(param_string, "%.15g",
*((SDOUBLE *) buffer));
case SQL_CHAR:
case SQL_VARCHAR:
case SQL_LONGVARCHAR:
+#ifdef UNICODE_SUPPORT
+ case SQL_WCHAR:
+ case SQL_WVARCHAR:
+ case SQL_WLONGVARCHAR:
+#endif /* UNICODE_SUPPORT */
CVT_APPEND_CHAR('\''); /* Open Quote */
tmp[0] = '\'';
/* Time zone stuff is unreliable */
stime2timestamp(&st, tmp + 1, USE_ZONE, PG_VERSION_GE(conn, 7.2));
- strcat(tmp, "'");
+ strcat(tmp, "'::timestamp");
CVT_APPEND_STR(tmp);
break;
}
+#ifdef UNICODE_SUPPORT
+ if (allocbuf)
+ free(allocbuf);
+#endif /* UNICODE_SUPPORT */
} /* end, for */
/* make sure new_statement is always null-terminated */
while ((*valptr != '\0') && isspace((unsigned char) *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);
return CONVERT_ESCAPE_ERROR;
const char *valptr;
char buf[1024];
BOOL in_quote, in_dquote, in_escape, leadingSpace;
+#ifdef MULTIBYTE
+ encoded_str encstr;
+#endif /* MULTIBYTE */
buf[sizeof(buf)-1] = '\0';
innerParenthesis = 0;
in_quote = in_dquote = in_escape = leadingSpace = FALSE;
param_count = 0;
#ifdef MULTIBYTE
- multibyte_init();
+ make_encoded_str(&encstr, conn, value);
#endif /* MULTIBYTE */
/* begin with outer '(' */
for (stop = FALSE, valptr = value, ipos = count = 0; *valptr != '\0'; ipos++, valptr++)
return CONVERT_ESCAPE_OVERFLOW;
}
#ifdef MULTIBYTE
- if (multibyte_char_check(*valptr) != 0)
+ encoded_byte_check(&encstr, ipos);
+ if (ENCODE_STATUS(encstr) != 0)
{
result[count++] = *valptr;
continue;
/* Change linefeed to carriage-return/linefeed */
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,
out = 0;
*changed = FALSE;
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 */
if (i > 0 && si[i - 1] == '\r')
* Plus, escape any special characters.
*/
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,
out = 0,
max;
char *p = NULL;
+#ifdef MULTIBYTE
+ encoded_str encstr;
+#endif
if (used == SQL_NTS)
p[0] = '\0';
}
#ifdef MULTIBYTE
- multibyte_init();
+ encoded_str_constr(&encstr, ccsc, si);
#endif
for (i = 0; i < max && si[i]; i++)
{
#ifdef MULTIBYTE
- if (multibyte_char_check(si[i]) != 0)
+ encoded_nextchar(&encstr);
+ if (ENCODE_STATUS(encstr) != 0)
{
if (p)
p[out] = si[i];
continue;
}
#endif
- if (si[i] == '\r' && si[i + 1] == '\n')
+ if (convlf && si[i] == '\r' && si[i + 1] == '\n')
continue;
else if (si[i] == '\'' || si[i] == '\\')
{
/* convert_escape results */
#define CONVERT_ESCAPE_OK 0
#define CONVERT_ESCAPE_OVERFLOW 1
-#define CONVERT_ESCAPE_ERROR 2
+#define CONVERT_ESCAPE_ERROR -1
typedef struct
{
int *npos, int *stsize, const char **val_resume);
BOOL convert_money(const char *s, char *sout, size_t soutmax);
char parse_datetime(char *buf, SIMPLE_TIME *st);
-int convert_linefeeds(const char *s, char *dst, size_t max, BOOL *changed);
-int convert_special_chars(const char *si, char *dst, int used);
+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, BOOL convlf,int ccsc);
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);
CheckDlgButton(hdlg, DRV_OPTIMIZER, comval->disable_optimizer);
CheckDlgButton(hdlg, DRV_KSQO, comval->ksqo);
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);
EnableWindow(GetDlgItem(hdlg, DRV_READONLY), enable);
CheckDlgButton(hdlg, DRV_USEDECLAREFETCH, comval->use_declarefetch);
CheckDlgButton(hdlg, DS_ROWVERSIONING, atoi(ci->row_versioning));
CheckDlgButton(hdlg, DS_SHOWSYSTEMTABLES, atoi(ci->show_system_tables));
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));
sprintf(ci->row_versioning, "%d", IsDlgButtonChecked(hdlg, DS_ROWVERSIONING));
ci->disallow_premature = IsDlgButtonChecked(hdlg, DS_DISALLOWPREMATURE);
+ ci->lf_conversion = IsDlgButtonChecked(hdlg, DS_LFCONVERSION);
+ ci->true_is_minus1 = IsDlgButtonChecked(hdlg, DS_TRUEISMINUS1);
/* OID Options */
sprintf(ci->fake_oid_index, "%d", IsDlgButtonChecked(hdlg, DS_FAKEOIDINDEX));
hlen = strlen(connect_string);
if (!abbrev)
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,
+ INI_PROTOCOL,
ci->protocol,
+ INI_FAKEOIDINDEX,
ci->fake_oid_index,
+ INI_SHOWOIDCOLUMN,
ci->show_oid_column,
+ INI_ROWVERSIONING,
ci->row_versioning,
+ INI_SHOWSYSTEMTABLES,
ci->show_system_tables,
+ INI_CONNSETTINGS,
encoded_conn_settings,
+ INI_FETCH,
ci->drivers.fetch_max,
+ INI_SOCKET,
ci->drivers.socket_buffersize,
+ INI_UNKNOWNSIZES,
ci->drivers.unknown_sizes,
+ INI_MAXVARCHARSIZE,
ci->drivers.max_varchar_size,
+ INI_MAXLONGVARCHARSIZE,
ci->drivers.max_longvarchar_size,
+ INI_DEBUG,
ci->drivers.debug,
+ INI_COMMLOG,
ci->drivers.commlog,
+ INI_OPTIMIZER,
ci->drivers.disable_optimizer,
+ INI_KSQO,
ci->drivers.ksqo,
+ INI_USEDECLAREFETCH,
ci->drivers.use_declarefetch,
+ INI_TEXTASLONGVARCHAR,
ci->drivers.text_as_longvarchar,
+ INI_UNKNOWNSASLONGVARCHAR,
ci->drivers.unknowns_as_longvarchar,
+ INI_BOOLSASCHAR,
ci->drivers.bools_as_char,
+ INI_PARSE,
ci->drivers.parse,
+ INI_CANCELASFREESTMT,
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 ? */
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],
- ";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",
- ci->onlyread,
- ci->protocol,
- ci->fake_oid_index,
- ci->show_oid_column,
- ci->row_versioning,
- ci->show_system_tables,
+ ";A6=%s;A7=%d;A8=%d;B0=%d;B1=%d;C2=%s;CX=%02x%x",
encoded_conn_settings,
ci->drivers.fetch_max,
ci->drivers.socket_buffersize,
- ci->drivers.unknown_sizes,
ci->drivers.max_varchar_size,
ci->drivers.max_longvarchar_size,
- ci->drivers.debug,
- ci->drivers.commlog,
- ci->drivers.disable_optimizer,
- 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);
+ ci->drivers.extra_systable_prefixes,
+ EFFECTIVE_BIT_COUNT,
+ flag);
+ }
}
+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
copyAttributes(ConnInfo *ci, const char *attribute, const char *value)
{
ci->disallow_premature = atoi(value);
else if (stricmp(attribute, INI_UPDATABLECURSORS) == 0 || stricmp(attribute, "C4") == 0)
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);
}
if (ci->row_versioning[0] == '\0')
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;
}
if (ci->translation_option[0] == '\0' || overwrite)
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);
- 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);
- 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 */
INI_UPDATABLECURSORS,
temp,
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);
}
#define INI_TRANSLATIONOPTION "TranslationOption"
#define INI_DISALLOWPREMATURE "DisallowPremature"
#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 */
#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 */
void getCommonDefaults(const char *section, const char *filename, ConnInfo *ci);
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;
}
*equals;
char *strtok_arg;
- memset(ci, 0, sizeof(ConnInfo));
-#ifdef DRIVER_CURSOR_IMPLEMENT
- ci->updatable_cursors = 1;
-#endif /* DRIVER_CURSOR_IMPLEMENT */
+ CC_conninfo_init(ci);
our_connect_string = strdup(connect_string);
strtok_arg = our_connect_string;
}
+#define DRVMNGRDIV 511
/* Returns the next SQL error information. */
RETCODE SQL_API
-PGAPI_Error(
- HENV henv,
- HDBC hdbc,
- HSTMT hstmt,
+PGAPI_StmtError( HSTMT hstmt,
+ SWORD RecNumber,
UCHAR FAR * szSqlState,
SDWORD FAR * pfNativeError,
UCHAR FAR * szErrorMsg,
SWORD cbErrorMsgMax,
- SWORD FAR * pcbErrorMsg)
+ SWORD FAR * pcbErrorMsg,
+ UWORD flag)
{
- char *msg;
- int status;
- BOOL once_again = FALSE;
- SWORD msglen;
+ /* CC: return an error of a hstmt */
+ StatementClass *stmt = (StatementClass *) hstmt;
+ char *msg;
+ 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)
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))
- {
- mylog("SC_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 = (SWORD) strlen(msg);
- if (NULL != pcbErrorMsg)
- {
- *pcbErrorMsg = msglen;
- if (cbErrorMsgMax == 0)
- once_again = TRUE;
- else if (msglen >= cbErrorMsgMax)
- {
- once_again = TRUE;
- *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);
- }
+ if (!SC_get_error(stmt, &status, &msg) || NULL == msg || !msg[0])
+ {
+ mylog("SC_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;
+ }
+ mylog("SC_get_error: status = %d, msg = #%s#\n", status, msg);
+ msglen = (SWORD) strlen(msg);
+ /*
+ * Even though an application specifies a larger error message
+ * buffer, the driver manager changes it silently.
+ * Therefore we divide the error message into ...
+ */
+ if (stmt->error_recsize < 0)
+ {
+ if (cbErrorMsgMax > 0)
+ stmt->error_recsize = cbErrorMsgMax - 1; /* apply the first request */
else
- {
- if (NULL != szSqlState)
- strcpy(szSqlState, "00000");
- if (NULL != pcbErrorMsg)
- *pcbErrorMsg = 0;
- if ((NULL != szErrorMsg) && (cbErrorMsgMax > 0))
- szErrorMsg[0] = '\0';
+ stmt->error_recsize = DRVMNGRDIV;
+ }
+ if (RecNumber < 0)
+ {
+ if (0 == stmt->errorpos)
+ RecNumber = 1;
+ 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;
-
- stmt->errornumber = status;
- if (cbErrorMsgMax > 0)
- outlen = *pcbErrorMsg;
- else
- outlen = 0;
- if (!stmt->errormsg_malloced || !stmt->errormsg)
- {
- stmt->errormsg = malloc(msglen - outlen + 1);
- stmt->errormsg_malloced = TRUE;
- }
- memmove(stmt->errormsg, msg + outlen, msglen - outlen + 1);
+ /* 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;
}
- 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);
- if (cbErrorMsgMax == 0)
- return SQL_SUCCESS_WITH_INFO;
- else
- return SQL_SUCCESS;
}
- else if (SQL_NULL_HDBC != hdbc)
- {
- ConnectionClass *conn = (ConnectionClass *) hdbc;
-
- 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';
+ if (wrtlen == 0)
+ return SQL_SUCCESS_WITH_INFO;
+ else
+ return SQL_SUCCESS;
+}
- 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)
- {
- conn->errornumber = status;
- return SQL_SUCCESS_WITH_INFO;
- }
- else
- return SQL_SUCCESS;
+ if (RecNumber != 1)
+ return SQL_NO_DATA_FOUND;
+ if (cbErrorMsgMax < 0)
+ return SQL_ERROR;
+ if (!CC_get_error(conn, &status, &msg) || NULL == msg)
+ {
+ 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))
- {
- 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)
+ switch (status)
{
- if (NULL != szSqlState)
- strcpy(szSqlState, "00000");
- if (NULL != pcbErrorMsg)
- *pcbErrorMsg = 0;
- if ((NULL != szErrorMsg) && (cbErrorMsgMax > 0))
- szErrorMsg[0] = '\0';
-
- return SQL_NO_DATA_FOUND;
+ 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;
}
+ if (once_again)
+ {
+ conn->errornumber = status;
+ return SQL_SUCCESS_WITH_INFO;
+ }
+ else
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)
- *pcbErrorMsg = 0;
+ *pcbErrorMsg = (SWORD) strlen(msg);
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
*/
{
rv->errormsg = 0;
rv->errornumber = 0;
+ rv->flag = 0;
}
return rv;
struct EnvironmentClass_
{
char *errormsg;
- int errornumber;
+ int errornumber;
+ Int4 flag;
};
/* Environment prototypes */
char EN_remove_connection(EnvironmentClass *self, ConnectionClass *conn);
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
if (stmt->status == STMT_FINISHED)
{
mylog("%s: recycling statement (should have been done by app)...\n", func);
+/******** Is this really NEEDED ? ******/
SC_recycle_statement(stmt);
}
{
if (stmt->options.param_processed_ptr)
*stmt->options.param_processed_ptr = 0;
+ SC_recycle_statement(stmt);
}
next_param_row:
}
/* we are now in a transaction */
CC_set_in_trans(conn);
- stmt->result = res = CC_send_query(conn, stmt->stmt_with_params, NULL);
- if (!res || QR_aborted(res))
+ res = CC_send_query(conn, stmt->stmt_with_params, NULL, TRUE);
+ if (!res)
{
CC_abort(conn);
stmt->errornumber = STMT_EXEC_ERROR;
stmt->errormsg = "Handle prepare 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);
- else if (!in_trans && begin_included)
- CC_set_no_trans(conn);
- }
- stmt->status = STMT_FINISHED;
- return SQL_SUCCESS;
+ if (issued_begin)
+ CC_commit(conn);
+ else if (!in_trans && begin_included)
+ CC_set_no_trans(conn);
}
+ stmt->status = STMT_FINISHED;
+ return SQL_SUCCESS;
}
else
return SQL_SUCCESS;
{
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);
if (!res)
/* commit transaction if needed */
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->errornumber = STMT_EXEC_ERROR;
}
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 */
if (cbValue == SQL_NTS)
{
}
else
{
- Int2 ctype = current_param->CType;
-
- if (ctype == SQL_C_DEFAULT)
- ctype = sqltype_to_default_ctype(current_param->SQLType);
+#ifdef UNICODE_SUPPORT
+ if (ctype == SQL_C_CHAR || ctype == SQL_C_BINARY || ctype == SQL_C_WCHAR)
+#else
if (ctype == SQL_C_CHAR || ctype == SQL_C_BINARY)
+#endif /* UNICODE_SUPPORT */
{
current_param->EXEC_buffer = malloc(cbValue + 1);
if (!current_param->EXEC_buffer)
}
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);
- if (!buffer)
- {
- stmt->errornumber = STMT_NO_MEMORY_ERROR;
- stmt->errormsg = "Out of memory in PGAPI_PutData (3)";
- SC_log_error(func, "", stmt);
- 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;
+#ifdef UNICODE_SUPPORT
+ if (SQL_C_WCHAR == ctype)
+ old_pos = 2 * ucs2strlen((SQLWCHAR *) buffer);
+ else
+#endif /* UNICODE_SUPPORT */
+ old_pos = strlen(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;
mylog(" cbValue = %d, old_pos = %d, *used = %d\n", cbValue, old_pos, *current_param->EXEC_used);
* SQLTables, SQLColumns, SQLStatistics, SQLSpecialColumns,
* SQLPrimaryKeys, SQLForeignKeys,
* SQLProcedureColumns(NI), SQLProcedures,
- * SQLTablePrivileges(NI), SQLColumnPrivileges(NI)
+ * SQLTablePrivileges, SQLColumnPrivileges(NI)
*
* Comments: See "notice.txt" for copyright and license information.
*--------
case SQL_FETCH_DIRECTION: /* ODBC 1.0 */
len = 4;
- value = ci->drivers.use_declarefetch ? (SQL_FD_FETCH_NEXT) : (SQL_FD_FETCH_NEXT |
- SQL_FD_FETCH_FIRST |
- SQL_FD_FETCH_LAST |
- SQL_FD_FETCH_PRIOR |
- SQL_FD_FETCH_ABSOLUTE |
- SQL_FD_FETCH_RELATIVE |
- SQL_FD_FETCH_BOOKMARK);
+ value = ci->drivers.use_declarefetch ? (SQL_FD_FETCH_NEXT) :
+ (SQL_FD_FETCH_NEXT |
+ SQL_FD_FETCH_FIRST |
+ SQL_FD_FETCH_LAST |
+ SQL_FD_FETCH_PRIOR |
+ SQL_FD_FETCH_ABSOLUTE |
+ SQL_FD_FETCH_RELATIVE |
+ SQL_FD_FETCH_BOOKMARK);
break;
case SQL_FILE_USAGE: /* ODBC 2.0 */
/* unrecognized key */
conn->errormsg = "Unrecognized key passed to PGAPI_GetInfo.";
conn->errornumber = CONN_NOT_IMPLEMENTED_ERROR;
- CC_log_error(func, "", conn);
return SQL_ERROR;
}
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);
if (len >= cbInfoValueMax)
{
result = SQL_SUCCESS_WITH_INFO;
- conn->errornumber = STMT_TRUNCATED;
+ conn->errornumber = CONN_TRUNCATED;
conn->errormsg = "The buffer was too small for tthe InfoValue.";
}
}
{
static char *func = "PGAPI_GetTypeInfo";
StatementClass *stmt = (StatementClass *) hstmt;
+ QResultClass *res;
TupleNode *row;
int i;
}
stmt->manual_result = TRUE;
- stmt->result = QR_Constructor();
- if (!stmt->result)
+ if (res = QR_Constructor(), !res)
{
SC_log_error(func, "Error creating result.", stmt);
return SQL_ERROR;
}
+ SC_set_Result(stmt, res);
extend_bindings(stmt, 15);
- QR_set_num_fields(stmt->result, 15);
- QR_set_field_info(stmt->result, 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(stmt->result, 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(stmt->result, 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(stmt->result, 6, "NULLABLE", PG_TYPE_INT2, 2);
- QR_set_field_info(stmt->result, 7, "CASE_SENSITIVE", PG_TYPE_INT2, 2);
- QR_set_field_info(stmt->result, 8, "SEARCHABLE", PG_TYPE_INT2, 2);
- QR_set_field_info(stmt->result, 9, "UNSIGNED_ATTRIBUTE", PG_TYPE_INT2, 2);
- QR_set_field_info(stmt->result, 10, "MONEY", PG_TYPE_INT2, 2);
- QR_set_field_info(stmt->result, 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(stmt->result, 13, "MINIMUM_SCALE", PG_TYPE_INT2, 2);
- QR_set_field_info(stmt->result, 14, "MAXIMUM_SCALE", PG_TYPE_INT2, 2);
+ QR_set_num_fields(res, 15);
+ QR_set_field_info(res, 0, "TYPE_NAME", PG_TYPE_TEXT, MAX_INFO_STRING);
+ QR_set_field_info(res, 1, "DATA_TYPE", PG_TYPE_INT2, 2);
+ QR_set_field_info(res, 2, "PRECISION", PG_TYPE_INT4, 4);
+ QR_set_field_info(res, 3, "LITERAL_PREFIX", PG_TYPE_TEXT, MAX_INFO_STRING);
+ QR_set_field_info(res, 4, "LITERAL_SUFFIX", PG_TYPE_TEXT, MAX_INFO_STRING);
+ QR_set_field_info(res, 5, "CREATE_PARAMS", PG_TYPE_TEXT, MAX_INFO_STRING);
+ QR_set_field_info(res, 6, "NULLABLE", PG_TYPE_INT2, 2);
+ QR_set_field_info(res, 7, "CASE_SENSITIVE", PG_TYPE_INT2, 2);
+ QR_set_field_info(res, 8, "SEARCHABLE", PG_TYPE_INT2, 2);
+ QR_set_field_info(res, 9, "UNSIGNED_ATTRIBUTE", PG_TYPE_INT2, 2);
+ QR_set_field_info(res, 10, "MONEY", PG_TYPE_INT2, 2);
+ QR_set_field_info(res, 11, "AUTO_INCREMENT", PG_TYPE_INT2, 2);
+ QR_set_field_info(res, 12, "LOCAL_TYPE_NAME", PG_TYPE_TEXT, MAX_INFO_STRING);
+ QR_set_field_info(res, 13, "MINIMUM_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])
{
set_nullfield_int2(&row->tuple[13], 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);
}
}
pfExists[SQL_API_SQLMORERESULTS] = TRUE;
pfExists[SQL_API_SQLNATIVESQL] = TRUE;
pfExists[SQL_API_SQLNUMPARAMS] = TRUE;
- pfExists[SQL_API_SQLPARAMOPTIONS] = FALSE;
+ pfExists[SQL_API_SQLPARAMOPTIONS] = TRUE;
pfExists[SQL_API_SQLPRIMARYKEYS] = TRUE;
pfExists[SQL_API_SQLPROCEDURECOLUMNS] = FALSE;
if (PG_VERSION_LT(conn, 6.5))
pfExists[SQL_API_SQLPROCEDURES] = TRUE;
pfExists[SQL_API_SQLSETPOS] = TRUE;
pfExists[SQL_API_SQLSETSCROLLOPTIONS] = TRUE; /* odbc 1.0 */
- pfExists[SQL_API_SQLTABLEPRIVILEGES] = FALSE;
+ pfExists[SQL_API_SQLTABLEPRIVILEGES] = TRUE;
}
}
else
*pfExists = TRUE;
break;
case SQL_API_SQLPARAMOPTIONS:
- *pfExists = FALSE;
+ *pfExists = TRUE;
break;
case SQL_API_SQLPRIMARYKEYS:
*pfExists = TRUE;
*pfExists = TRUE;
break; /* odbc 1.0 */
case SQL_API_SQLTABLEPRIVILEGES:
- *pfExists = FALSE;
+ *pfExists = TRUE;
break;
}
}
static char *func = "PGAPI_Tables";
StatementClass *stmt = (StatementClass *) hstmt;
StatementClass *tbl_stmt;
+ QResultClass *res;
TupleNode *row;
HSTMT htbl_stmt;
RETCODE result;
return SQL_ERROR;
}
- stmt->result = QR_Constructor();
- if (!stmt->result)
+ if (res = QR_Constructor(), !res)
{
stmt->errormsg = "Couldn't allocate memory for PGAPI_Tables result.";
stmt->errornumber = STMT_NO_MEMORY_ERROR;
PGAPI_FreeStmt(htbl_stmt, SQL_DROP);
return SQL_ERROR;
}
+ SC_set_Result(stmt, res);
/* the binding structure for a statement is not set up until */
extend_bindings(stmt, 5);
/* set the field names */
- QR_set_num_fields(stmt->result, 5);
- QR_set_field_info(stmt->result, 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(stmt->result, 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(stmt->result, 4, "REMARKS", PG_TYPE_TEXT, 254);
+ QR_set_num_fields(res, 5);
+ QR_set_field_info(res, 0, "TABLE_QUALIFIER", PG_TYPE_TEXT, MAX_INFO_STRING);
+ QR_set_field_info(res, 1, "TABLE_OWNER", PG_TYPE_TEXT, MAX_INFO_STRING);
+ QR_set_field_info(res, 2, "TABLE_NAME", PG_TYPE_TEXT, MAX_INFO_STRING);
+ QR_set_field_info(res, 3, "TABLE_TYPE", PG_TYPE_TEXT, MAX_INFO_STRING);
+ QR_set_field_info(res, 4, "REMARKS", PG_TYPE_TEXT, 254);
/* add the tuples */
result = PGAPI_Fetch(htbl_stmt);
row = (TupleNode *) malloc(sizeof(TupleNode) + (5 - 1) *sizeof(TupleField));
/*set_tuplefield_string(&row->tuple[0], "");*/
+ /*set_tuplefield_string(&row->tuple[0], "cat0");*/
set_tuplefield_null(&row->tuple[0]);
/*
set_tuplefield_null(&row->tuple[1]);
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[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);
}
* PostgreSQL needs 2 '\\' to escape '_' and '%'.
*/
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;
const char *in;
BOOL escape_in = FALSE;
+#ifdef MULTIBYTE
+ encoded_str encstr;
+#endif
if (srclen == SQL_NULL_DATA)
{
if (srclen <= 0)
return STRCPY_FAIL;
#ifdef MULTIBYTE
- multibyte_init();
+ encoded_str_constr(&encstr, ccsc, src);
#endif
for (i = 0, in = src, outlen = 0; i < srclen && outlen < dst_len; i++, in++)
{
#ifdef MULTIBYTE
- if (multibyte_char_check(*in) != 0)
+ encoded_nextchar(&encstr);
+ if (ENCODE_STATUS(encstr) != 0)
{
dest[outlen++] = *in;
continue;
{
static char *func = "PGAPI_Columns";
StatementClass *stmt = (StatementClass *) hstmt;
+ QResultClass *res;
TupleNode *row;
HSTMT hcol_stmt;
StatementClass *col_stmt;
table_name[MAX_INFO_STRING],
field_name[MAX_INFO_STRING],
field_type_name[MAX_INFO_STRING];
- Int2 field_number,
+ Int2 field_number, sqltype,
result_cols,
scale;
Int4 field_type,
char esc_table_name[MAX_TABLE_LEN * 2];
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 u.usename like '%.*s'", szTableOwner, cbTableOwner);
my_strcat(columns_query, " and a.attname like '%.*s'", szColumnName, cbColumnName);
return SQL_ERROR;
}
- stmt->result = QR_Constructor();
- if (!stmt->result)
+ if (res = QR_Constructor(), !res)
{
stmt->errormsg = "Couldn't allocate memory for PGAPI_Columns result.";
stmt->errornumber = STMT_NO_MEMORY_ERROR;
PGAPI_FreeStmt(hcol_stmt, SQL_DROP);
return SQL_ERROR;
}
+ SC_set_Result(stmt, res);
/* the binding structure for a statement is not set up until */
extend_bindings(stmt, result_cols);
/* set the field names */
- QR_set_num_fields(stmt->result, result_cols);
- QR_set_field_info(stmt->result, 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(stmt->result, 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(stmt->result, 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(stmt->result, 6, "PRECISION", PG_TYPE_INT4, 4);
- QR_set_field_info(stmt->result, 7, "LENGTH", PG_TYPE_INT4, 4);
- QR_set_field_info(stmt->result, 8, "SCALE", PG_TYPE_INT2, 2);
- QR_set_field_info(stmt->result, 9, "RADIX", PG_TYPE_INT2, 2);
- QR_set_field_info(stmt->result, 10, "NULLABLE", PG_TYPE_INT2, 2);
- QR_set_field_info(stmt->result, 11, "REMARKS", PG_TYPE_TEXT, 254);
+ QR_set_num_fields(res, result_cols);
+ QR_set_field_info(res, 0, "TABLE_QUALIFIER", PG_TYPE_TEXT, MAX_INFO_STRING);
+ QR_set_field_info(res, 1, "TABLE_OWNER", PG_TYPE_TEXT, MAX_INFO_STRING);
+ QR_set_field_info(res, 2, "TABLE_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(res, 4, "DATA_TYPE", PG_TYPE_INT2, 2);
+ QR_set_field_info(res, 5, "TYPE_NAME", PG_TYPE_TEXT, MAX_INFO_STRING);
+ QR_set_field_info(res, 6, "PRECISION", PG_TYPE_INT4, 4);
+ QR_set_field_info(res, 7, "LENGTH", PG_TYPE_INT4, 4);
+ QR_set_field_info(res, 8, "SCALE", PG_TYPE_INT2, 2);
+ QR_set_field_info(res, 9, "RADIX", PG_TYPE_INT2, 2);
+ QR_set_field_info(res, 10, "NULLABLE", PG_TYPE_INT2, 2);
+ QR_set_field_info(res, 11, "REMARKS", PG_TYPE_TEXT, 254);
/* User defined fields */
- QR_set_field_info(stmt->result, 12, "DISPLAY_SIZE", PG_TYPE_INT4, 4);
- QR_set_field_info(stmt->result, 13, "FIELD_TYPE", PG_TYPE_INT4, 4);
+#if (ODBCVER >= 0x0300)
+ 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);
set_tuplefield_string(&row->tuple[1], "");
set_tuplefield_string(&row->tuple[2], table_name);
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_int4(&row->tuple[7], pgtype_length(stmt, the_type, PG_STATIC, PG_STATIC));
set_tuplefield_int2(&row->tuple[10], SQL_NO_NULLS);
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[13], the_type);
+#endif /* ODBCVER */
- QR_add_tuple(stmt->result, row);
+ QR_add_tuple(res, row);
}
}
set_tuplefield_string(&row->tuple[1], "");
set_tuplefield_string(&row->tuple[2], table_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);
*----------
*/
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;
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_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);
+#endif /* ODBCVER */
- QR_add_tuple(stmt->result, row);
+ QR_add_tuple(res, row);
result = PGAPI_Fetch(hcol_stmt);
set_tuplefield_int4(&row->tuple[12], pgtype_display_size(stmt, the_type, PG_STATIC, PG_STATIC));
set_tuplefield_int4(&row->tuple[13], the_type);
- QR_add_tuple(stmt->result, row);
+ QR_add_tuple(res, row);
}
/*
static char *func = "PGAPI_SpecialColumns";
TupleNode *row;
StatementClass *stmt = (StatementClass *) hstmt;
+ QResultClass *res;
ConnInfo *ci;
HSTMT hcol_stmt;
StatementClass *col_stmt;
result = PGAPI_Fetch(hcol_stmt);
PGAPI_FreeStmt(hcol_stmt, SQL_DROP);
- stmt->result = QR_Constructor();
+ res = QR_Constructor();
+ SC_set_Result(stmt, res);
extend_bindings(stmt, 8);
- QR_set_num_fields(stmt->result, 8);
- QR_set_field_info(stmt->result, 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(stmt->result, 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(stmt->result, 4, "PRECISION", PG_TYPE_INT4, 4);
- QR_set_field_info(stmt->result, 5, "LENGTH", PG_TYPE_INT4, 4);
- QR_set_field_info(stmt->result, 6, "SCALE", PG_TYPE_INT2, 2);
- QR_set_field_info(stmt->result, 7, "PSEUDO_COLUMN", PG_TYPE_INT2, 2);
+ QR_set_num_fields(res, 8);
+ QR_set_field_info(res, 0, "SCOPE", PG_TYPE_INT2, 2);
+ QR_set_field_info(res, 1, "COLUMN_NAME", PG_TYPE_TEXT, MAX_INFO_STRING);
+ QR_set_field_info(res, 2, "DATA_TYPE", PG_TYPE_INT2, 2);
+ QR_set_field_info(res, 3, "TYPE_NAME", PG_TYPE_TEXT, MAX_INFO_STRING);
+ QR_set_field_info(res, 4, "PRECISION", PG_TYPE_INT4, 4);
+ QR_set_field_info(res, 5, "LENGTH", PG_TYPE_INT4, 4);
+ QR_set_field_info(res, 6, "SCALE", PG_TYPE_INT2, 2);
+ QR_set_field_info(res, 7, "PSEUDO_COLUMN", PG_TYPE_INT2, 2);
if (relhasrules[0] != '1')
{
set_tuplefield_int2(&row->tuple[6], pgtype_scale(stmt, PG_TYPE_OID, PG_STATIC));
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)
set_tuplefield_int2(&row->tuple[6], pgtype_scale(stmt, the_type, PG_STATIC));
set_tuplefield_int2(&row->tuple[7], SQL_PC_PSEUDO);
- QR_add_tuple(stmt->result, row);
+ QR_add_tuple(res, row);
}
}
}
{
static char *func = "PGAPI_Statistics";
StatementClass *stmt = (StatementClass *) hstmt;
+ QResultClass *res;
char index_query[INFO_INQUIRY_LEN];
HSTMT hindx_stmt;
RETCODE result;
ci = &(SC_get_conn(stmt)->connInfo);
- stmt->result = QR_Constructor();
- if (!stmt->result)
+ if (res = QR_Constructor(), !res)
{
stmt->errormsg = "Couldn't allocate memory for PGAPI_Statistics result.";
stmt->errornumber = STMT_NO_MEMORY_ERROR;
SC_log_error(func, "", stmt);
return SQL_ERROR;
}
+ SC_set_Result(stmt, res);
/* the binding structure for a statement is not set up until */
extend_bindings(stmt, 13);
/* set the field names */
- QR_set_num_fields(stmt->result, 13);
- QR_set_field_info(stmt->result, 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(stmt->result, 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(stmt->result, 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(stmt->result, 6, "TYPE", PG_TYPE_INT2, 2);
- QR_set_field_info(stmt->result, 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(stmt->result, 9, "COLLATION", PG_TYPE_CHAR, 1);
- QR_set_field_info(stmt->result, 10, "CARDINALITY", PG_TYPE_INT4, 4);
- QR_set_field_info(stmt->result, 11, "PAGES", PG_TYPE_INT4, 4);
- QR_set_field_info(stmt->result, 12, "FILTER_CONDITION", PG_TYPE_TEXT, MAX_INFO_STRING);
+ QR_set_num_fields(res, 13);
+ QR_set_field_info(res, 0, "TABLE_QUALIFIER", PG_TYPE_TEXT, MAX_INFO_STRING);
+ QR_set_field_info(res, 1, "TABLE_OWNER", PG_TYPE_TEXT, MAX_INFO_STRING);
+ QR_set_field_info(res, 2, "TABLE_NAME", PG_TYPE_TEXT, MAX_INFO_STRING);
+ QR_set_field_info(res, 3, "NON_UNIQUE", PG_TYPE_INT2, 2);
+ QR_set_field_info(res, 4, "INDEX_QUALIFIER", PG_TYPE_TEXT, MAX_INFO_STRING);
+ QR_set_field_info(res, 5, "INDEX_NAME", PG_TYPE_TEXT, MAX_INFO_STRING);
+ QR_set_field_info(res, 6, "TYPE", PG_TYPE_INT2, 2);
+ QR_set_field_info(res, 7, "SEQ_IN_INDEX", PG_TYPE_INT2, 2);
+ QR_set_field_info(res, 8, "COLUMN_NAME", PG_TYPE_TEXT, MAX_INFO_STRING);
+ QR_set_field_info(res, 9, "COLLATION", PG_TYPE_CHAR, 1);
+ QR_set_field_info(res, 10, "CARDINALITY", PG_TYPE_INT4, 4);
+ QR_set_field_info(res, 11, "PAGES", PG_TYPE_INT4, 4);
+ 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
set_tuplefield_null(&row->tuple[11]);
set_tuplefield_null(&row->tuple[12]);
- QR_add_tuple(stmt->result, row);
+ QR_add_tuple(res, row);
}
result = PGAPI_Fetch(hindx_stmt);
set_tuplefield_null(&row->tuple[11]);
set_tuplefield_null(&row->tuple[12]);
- QR_add_tuple(stmt->result, row);
+ QR_add_tuple(res, row);
i++;
}
}
SWORD cbColumnName)
{
static char *func = "PGAPI_ColumnPrivileges";
+ StatementClass *stmt = (StatementClass *) hstmt;
mylog("%s: entering...\n", func);
/* 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;
}
{
static char *func = "PGAPI_PrimaryKeys";
StatementClass *stmt = (StatementClass *) hstmt;
+ QResultClass *res;
ConnectionClass *conn;
TupleNode *row;
RETCODE result;
stmt->manual_result = TRUE;
stmt->errormsg_created = TRUE;
- stmt->result = QR_Constructor();
- if (!stmt->result)
+ if (res = QR_Constructor(), !res)
{
stmt->errormsg = "Couldn't allocate memory for PGAPI_PrimaryKeys result.";
stmt->errornumber = STMT_NO_MEMORY_ERROR;
SC_log_error(func, "", stmt);
return SQL_ERROR;
}
+ SC_set_Result(stmt, res);
/* the binding structure for a statement is not set up until */
extend_bindings(stmt, result_cols);
/* set the field names */
- QR_set_num_fields(stmt->result, result_cols);
- QR_set_field_info(stmt->result, 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(stmt->result, 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(stmt->result, 4, "KEY_SEQ", PG_TYPE_INT2, 2);
- QR_set_field_info(stmt->result, 5, "PK_NAME", PG_TYPE_TEXT, MAX_INFO_STRING);
+ QR_set_num_fields(res, result_cols);
+ QR_set_field_info(res, 0, "TABLE_QUALIFIER", PG_TYPE_TEXT, MAX_INFO_STRING);
+ QR_set_field_info(res, 1, "TABLE_OWNER", PG_TYPE_TEXT, MAX_INFO_STRING);
+ QR_set_field_info(res, 2, "TABLE_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(res, 4, "KEY_SEQ", PG_TYPE_INT2, 2);
+ QR_set_field_info(res, 5, "PK_NAME", PG_TYPE_TEXT, MAX_INFO_STRING);
result = PGAPI_AllocStmt(stmt->hdbc, &htbl_stmt);
set_tuplefield_int2(&row->tuple[4], (Int2) (++seq));
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);
return ret;
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)
conn->server_encoding = strdup(QR_get_value_backend_row(res, 0, 0));
if (!conn->server_encoding)
return ret;
sprintf(query, "SET CLIENT_ENCODING TO '%s'", conn->server_encoding);
- if (res = CC_send_query(conn, query, NULL), res)
- {
- bError = QR_get_aborted(res);
- QR_Destructor(res);
- }
- else
- bError = TRUE;
+ bError = (CC_send_query(conn, query, NULL, TRUE) == NULL);
if (!bError && continueExec)
{
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)
strcpy(saveoid, QR_get_value_backend_row(res, 0, 0));
else
- {
continueExec = FALSE;
- bError = QR_get_aborted(res);
- }
QR_Destructor(res);
}
else
}
/* restore the client encoding */
sprintf(query, "SET CLIENT_ENCODING TO '%s'", conn->client_encoding);
- if (res = CC_send_query(conn, query, NULL), res)
- {
- bError = QR_get_aborted(res);
- QR_Destructor(res);
- }
- else
- bError = TRUE;
+ bError = (CC_send_query(conn, query, NULL, TRUE) == NULL);
if (bError || !continueExec)
return ret;
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)
{
return ret;
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)
conn->server_encoding = strdup(QR_get_value_backend_row(res, 0, 0));
if (!conn->server_encoding)
return ret;
sprintf(query, "SET CLIENT_ENCODING TO '%s'", conn->server_encoding);
- if (res = CC_send_query(conn, query, NULL), res)
- {
- bError = QR_get_aborted(res);
- QR_Destructor(res);
- }
- else
- bError = TRUE;
+ bError = (CC_send_query(conn, query, NULL, TRUE) == NULL);
if (!bError && continueExec)
{
sprintf(query, "select attrelid, attnum from pg_class, pg_attribute "
"where relname = '%s' and attrelid = pg_class.oid "
"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)
{
strcpy(saveattnum, QR_get_value_backend_row(res, 0, 1));
}
else
- {
continueExec = FALSE;
- bError = QR_get_aborted(res);
- }
QR_Destructor(res);
}
else
}
/* restore the cleint encoding */
sprintf(query, "SET CLIENT_ENCODING TO '%s'", conn->client_encoding);
- if (res = CC_send_query(conn, query, NULL), res)
- {
- bError = QR_get_aborted(res);
- QR_Destructor(res);
- }
- else
- bError = TRUE;
+ bError = (CC_send_query(conn, query, NULL, TRUE) == NULL);
if (bError || !continueExec)
return ret;
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)
{
{
static char *func = "PGAPI_ForeignKeys";
StatementClass *stmt = (StatementClass *) hstmt;
+ QResultClass *res;
TupleNode *row;
HSTMT htbl_stmt,
hpkey_stmt;
stmt->manual_result = TRUE;
stmt->errormsg_created = TRUE;
- stmt->result = QR_Constructor();
- if (!stmt->result)
+ if (res = QR_Constructor(), !res)
{
stmt->errormsg = "Couldn't allocate memory for PGAPI_ForeignKeys result.";
stmt->errornumber = STMT_NO_MEMORY_ERROR;
SC_log_error(func, "", stmt);
return SQL_ERROR;
}
+ SC_set_Result(stmt, res);
/* the binding structure for a statement is not set up until */
extend_bindings(stmt, result_cols);
/* set the field names */
- QR_set_num_fields(stmt->result, result_cols);
- QR_set_field_info(stmt->result, 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(stmt->result, 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(stmt->result, 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(stmt->result, 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(stmt->result, 8, "KEY_SEQ", PG_TYPE_INT2, 2);
- QR_set_field_info(stmt->result, 9, "UPDATE_RULE", PG_TYPE_INT2, 2);
- QR_set_field_info(stmt->result, 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(stmt->result, 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_num_fields(res, result_cols);
+ QR_set_field_info(res, 0, "PKTABLE_QUALIFIER", PG_TYPE_TEXT, MAX_INFO_STRING);
+ QR_set_field_info(res, 1, "PKTABLE_OWNER", PG_TYPE_TEXT, MAX_INFO_STRING);
+ QR_set_field_info(res, 2, "PKTABLE_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(res, 4, "FKTABLE_QUALIFIER", PG_TYPE_TEXT, MAX_INFO_STRING);
+ QR_set_field_info(res, 5, "FKTABLE_OWNER", PG_TYPE_TEXT, MAX_INFO_STRING);
+ QR_set_field_info(res, 6, "FKTABLE_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(res, 8, "KEY_SEQ", PG_TYPE_INT2, 2);
+ QR_set_field_info(res, 9, "UPDATE_RULE", PG_TYPE_INT2, 2);
+ QR_set_field_info(res, 10, "DELETE_RULE", PG_TYPE_INT2, 2);
+ QR_set_field_info(res, 11, "FK_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(res, 13, "TRIGGER_NAME", PG_TYPE_TEXT, MAX_INFO_STRING);
#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 */
/*
set_tuplefield_int2(&row->tuple[14], defer_type);
#endif /* ODBCVER >= 0x0300 */
- QR_add_tuple(stmt->result, row);
+ QR_add_tuple(res, row);
#ifdef MULTIBYTE
if (fkey_alloced)
free(fkey_text);
set_tuplefield_int2(&row->tuple[14], defer_type);
#endif /* ODBCVER >= 0x0300 */
- QR_add_tuple(stmt->result, row);
+ QR_add_tuple(res, row);
#ifdef MULTIBYTE
if (pkey_alloced)
free(pkey_text);
SWORD cbColumnName)
{
static char *func = "PGAPI_ProcedureColumns";
+ StatementClass *stmt = (StatementClass *) hstmt;
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;
}
{
stmt->errornumber = STMT_NOT_IMPLEMENTED_ERROR;
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;
}
if (!SC_recycle_statement(stmt))
" 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);
- res = CC_send_query(conn, proc_query, NULL);
- if (!res || QR_aborted(res))
+ if (res = CC_send_query(conn, proc_query, NULL, TRUE), !res)
{
- if (res)
- QR_Destructor(res);
stmt->errornumber = STMT_EXEC_ERROR;
stmt->errormsg = "PGAPI_Procedures query error";
return SQL_ERROR;
}
- stmt->result = res;
+ SC_set_Result(stmt, res);
/*
* also, things need to think that this statement is finished so the
}
+#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
PGAPI_TablePrivileges(
HSTMT hstmt,
UCHAR FAR * szTableOwner,
SWORD cbTableOwner,
UCHAR FAR * szTableName,
- SWORD cbTableName)
+ SWORD cbTableName,
+ UWORD flag)
{
StatementClass *stmt = (StatementClass *) hstmt;
static char *func = "PGAPI_TablePrivileges";
+ ConnectionClass *conn = SC_get_conn(stmt);
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);
+ if (!SC_recycle_statement(stmt))
+ return SQL_ERROR;
/*
* a statement is actually executed, so we'll have to do this
/* set the field names */
stmt->manual_result = TRUE;
- stmt->result = QR_Constructor();
- QR_set_num_fields(stmt->result, result_cols);
- QR_set_field_info(stmt->result, 0, "TABLE_CAT", PG_TYPE_TEXT, MAX_INFO_STRING);
- QR_set_field_info(stmt->result, 1, "TABLE_SCHEM", 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(stmt->result, 3, "GRANTOR", PG_TYPE_TEXT, MAX_INFO_STRING);
- QR_set_field_info(stmt->result, 4, "GRANTEE", PG_TYPE_TEXT, MAX_INFO_STRING);
- QR_set_field_info(stmt->result, 5, "PRIVILEGE", PG_TYPE_TEXT, MAX_INFO_STRING);
- QR_set_field_info(stmt->result, 6, "IS_GRANTABLE", PG_TYPE_TEXT, MAX_INFO_STRING);
-
- SC_log_error(func, "Function not implemented", (StatementClass *) hstmt);
- return SQL_ERROR;
+ res = QR_Constructor();
+ SC_set_Result(stmt, res);
+ QR_set_num_fields(res, result_cols);
+ QR_set_field_info(res, 0, "TABLE_CAT", PG_TYPE_TEXT, MAX_INFO_STRING);
+ QR_set_field_info(res, 1, "TABLE_SCHEM", PG_TYPE_TEXT, MAX_INFO_STRING);
+ QR_set_field_info(res, 2, "TABLE_NAME", PG_TYPE_TEXT, MAX_INFO_STRING);
+ QR_set_field_info(res, 3, "GRANTOR", PG_TYPE_TEXT, MAX_INFO_STRING);
+ QR_set_field_info(res, 4, "GRANTEE", 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);
+
+ /*
+ * 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;
}
{
static char *func = "PGAPI_GetInfo30";
ConnectionClass *conn = (ConnectionClass *) hdbc;
+ ConnInfo *ci = &(conn->connInfo);
char *p = NULL;
int len = 0,
value = 0;
| SQL_CA1_RELATIVE | SQL_CA1_BOOKMARK
| SQL_CA1_LOCK_NO_CHANGE | SQL_CA1_POS_POSITION
| SQL_CA1_POS_UPDATE | SQL_CA1_POS_DELETE
- | SQL_CA1_POS_REFRESH
- /* | SQL_CA1_BULK_ADD
+ | SQL_CA1_POS_REFRESH;
+ if (ci->drivers.lie)
+ value |=
+ ( SQL_CA1_BULK_ADD
| SQL_CA1_BULK_UPDATE_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;
case SQL_KEYSET_CURSOR_ATTRIBUTES2:
len = 4;
- value = SQL_CA2_OPT_ROWVER_CONCURRENCY |
- SQL_CA2_SENSITIVITY_ADDITIONS |
- SQL_CA2_SENSITIVITY_DELETIONS |
- SQL_CA2_SENSITIVITY_UPDATES;
+ value = SQL_CA2_OPT_ROWVER_CONCURRENCY
+ | SQL_CA2_SENSITIVITY_ADDITIONS
+ | SQL_CA2_SENSITIVITY_DELETIONS
+ | 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;
case SQL_STATIC_CURSOR_ATTRIBUTES1:
len = 4;
- value = SQL_CA1_NEXT | SQL_CA1_ABSOLUTE |
- SQL_CA1_RELATIVE | SQL_CA1_BOOKMARK |
- SQL_CA1_LOCK_NO_CHANGE | SQL_CA1_POS_POSITION |
- SQL_CA1_POS_UPDATE | SQL_CA1_POS_DELETE |
- SQL_CA1_POS_REFRESH;
+ value = SQL_CA1_NEXT | SQL_CA1_ABSOLUTE
+ | SQL_CA1_RELATIVE | SQL_CA1_BOOKMARK
+ | SQL_CA1_LOCK_NO_CHANGE | SQL_CA1_POS_POSITION
+ | SQL_CA1_POS_UPDATE | SQL_CA1_POS_DELETE
+ | SQL_CA1_POS_REFRESH;
break;
case SQL_STATIC_CURSOR_ATTRIBUTES2:
len = 4;
- value = SQL_CA2_OPT_ROWVER_CONCURRENCY |
- SQL_CA2_SENSITIVITY_ADDITIONS |
- SQL_CA2_SENSITIVITY_DELETIONS |
- SQL_CA2_SENSITIVITY_UPDATES;
+ value = SQL_CA2_OPT_ROWVER_CONCURRENCY
+ | SQL_CA2_SENSITIVITY_ADDITIONS
+ | SQL_CA2_SENSITIVITY_DELETIONS
+ | SQL_CA2_SENSITIVITY_UPDATES;
break;
case SQL_ODBC_INTERFACE_CONFORMANCE:
break;
case SQL_BATCH_ROW_COUNT:
len = 4;
- value = SQL_BRC_ROLLED_UP | SQL_BRC_EXPLICIT;
+ value = SQL_BRC_EXPLICIT;
break;
case SQL_BATCH_SUPPORT:
len = 4;
- value = SQL_BS_ROW_COUNT_EXPLICIT;
+ value = SQL_BS_SELECT_EXPLICIT | SQL_BS_ROW_COUNT_EXPLICIT;
break;
case SQL_CATALOG_NAME:
len = 0;
len = 4;
value = SQL_DT_DROP_TABLE;
if (PG_VERSION_GT(conn, 7.2)) /* hopefully */
- value |= SQL_DT_RESTRICT | SQL_DT_CASCADE;
+ value |= (SQL_DT_RESTRICT | SQL_DT_CASCADE);
break;
case SQL_DROP_TRANSLATION:
len = 4;
len = 4;
value = SQL_DV_DROP_VIEW;
if (PG_VERSION_GT(conn, 7.2)) /* hopefully */
- value |= SQL_DV_RESTRICT | SQL_DV_CASCADE;
+ value |= (SQL_DV_RESTRICT | SQL_DV_CASCADE);
break;
case SQL_INDEX_KEYWORDS:
len = 4;
break;
case SQL_PARAM_ARRAY_ROW_COUNTS:
len = 4;
- value = SQL_PARC_NO_BATCH;
+ value = SQL_PARC_BATCH;
break;
case SQL_PARAM_ARRAY_SELECTS:
len = 4;
- value = SQL_PAS_NO_SELECT;
+ value = SQL_PAS_BATCH;
break;
case SQL_SQL_CONFORMANCE:
len = 4;
return SQL_ERROR;
}
result = SQL_SUCCESS;
+ mylog("%s: p='%s', len=%d, value=%d, cbMax=%d\n", func, p ? p : "<NULL>", len, value, cbInfoValueMax);
if (p)
{
/* char/binary data */
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);
if (len >= cbInfoValueMax)
#include "psqlodbc.h"
#include <stdio.h>
-#include <stdlib.h>
#include <stdarg.h>
#include <string.h>
#define MYLOGDIR "c:"
#endif
extern void mylog(char *fmt,...);
+#define inolog mylog /* for really temporary debug */
#else
#ifndef WIN32
#include <stdio.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[] =
{
{ "SQL_ASCII", SQL_ASCII },
int
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++)
{
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);
}
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++)
{
if (CS_Table[i].code == characterset_code)
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;
unsigned char *s;
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))
break;
else
}
int
-pg_mbslen(const unsigned char *string)
+pg_mbslen(int csc, const unsigned char *string)
{
unsigned char *s;
int len, cs_stat;
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)
len++;
}
}
unsigned char *
-pg_mbsinc(const unsigned char *current )
+pg_mbsinc(int csc, const unsigned char *current )
{
int mb_stat = 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)
mb_stat = 1;
return ((unsigned char *) current + mb_stat);
return NULL;
}
-void
-CC_lookup_characterset(ConnectionClass *self)
+static char *
+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;
- StatementClass *stmt;
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);
if ((result != SQL_SUCCESS) && (result != SQL_SUCCESS_WITH_INFO))
- return;
- stmt = (StatementClass *) hstmt;
+ return encstr;
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);
- return;
+ char sqlState[8], errormsg[128], enc[32];
+
+ 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);
- if ((result != SQL_SUCCESS) && (result != SQL_SUCCESS_WITH_INFO))
- return;
- stmt = (StatementClass *) hstmt;
+ PGAPI_FreeStmt(hstmt, SQL_DROP);
+ return encstr;
+}
- result = PGAPI_ExecDirect(hstmt, "Show Server_Encoding", SQL_NTS);
- if ((result != SQL_SUCCESS) && (result != SQL_SUCCESS_WITH_INFO))
+void
+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);
- return;
+ self->ccsc = SQL_ASCII;
+ self->client_encoding = NULL;
}
+}
- strcpy(PG_SCSS , pg_CS_name(PG_SCSC = pg_CS_code(PG_SCSS)));
- strcpy(PG_CCSS , pg_CS_name(PG_CCSC = pg_CS_code(PG_CCSS)));
+void encoded_str_constr(encoded_str *encstr, int ccsc, const char *str)
+{
+ 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;
}
*
*/
#include "psqlodbc.h"
+#include "qresult.h"
/* PostgreSQL client encoding */
#define SQL_ASCII 0 /* SQL/ASCII */
#define EUC_JP 1 /* EUC for Japanese */
#define EUC_CN 2 /* EUC for Chinese */
#define EUC_KR 3 /* EUC for Korean */
-#define EUC_TW 4 /* EUC for Taiwan */\r
+#define EUC_TW 4 /* EUC for Taiwan */
#define JOHAB 5
#define UTF8 6 /* Unicode UTF-8 */
#define MULE_INTERNAL 7 /* Mule internal code */
#define LATIN6 13 /* ISO-8859 Latin 6 */
#define LATIN7 14 /* ISO-8859 Latin 7 */
#define LATIN8 15 /* ISO-8859 Latin 8 */
-#define LATIN9 16 /* ISO-8859 Latin 9 */\r
-#define LATIN10 17 /* ISO-8859 Latin 10 */\r
-#define WIN1256 18 /* Arabic Windows */\r
-#define TCVN 19 /* Vietnamese Windows */\r
-#define WIN874 20 /* Thai Windows */\r
-#define KOI8R 21 /* KOI8-R/U */\r
+#define LATIN9 16 /* ISO-8859 Latin 9 */
+#define LATIN10 17 /* ISO-8859 Latin 10 */
+#define WIN1256 18 /* Arabic Windows */
+#define TCVN 19 /* Vietnamese Windows */
+#define WIN874 20 /* Thai Windows */
+#define KOI8R 21 /* KOI8-R/U */
#define WIN1251 22 /* windows-1251 */
#define ALT 23 /* Alternativny Variant (MS-DOS CP866) */
-#define ISO_8859_5 24 /* ISO-8859-5 */\r
-#define ISO_8859_6 25 /* ISO-8859-6 */\r
-#define ISO_8859_7 26 /* ISO-8859-7 */\r
-#define ISO_8859_8 27 /* ISO-8859-8 */\r
-\r
+#define ISO_8859_5 24 /* ISO-8859-5 */
+#define ISO_8859_6 25 /* ISO-8859-6 */
+#define ISO_8859_7 26 /* ISO-8859-7 */
+#define ISO_8859_8 27 /* ISO-8859-8 */
+
#define SJIS 28 /* Shift JIS */
-#define BIG5 29 /* Big5 */\r
-#define GBK 30 /* GBK */\r
-#define UHC 31 /* UHC */\r
-#define WIN1250 32 /* windows-1250 */\r
-#define OTHER -1\r
-\r
-#define MAX_CHARACTERSET_NAME 24\r
-#define MAX_CHARACTER_LEN 6\r
+#define BIG5 29 /* Big5 */
+#define GBK 30 /* GBK */
+#define UHC 31 /* UHC */
+#define WIN1250 32 /* windows-1250 */
+#define OTHER -1
+
+#define MAX_CHARACTERSET_NAME 24
+#define MAX_CHARACTER_LEN 6
-/* OLD Type */\r
+/* OLD Type */
// extern int multibyte_client_encoding; /* Multibyte client encoding. */
// extern int multibyte_status; /* Multibyte charcter status. */
//
// void multibyte_init(void);
// unsigned char *check_client_encoding(unsigned char *sql_string);
// int multibyte_char_check(unsigned char s);
-// unsigned char *multibyte_strchr(const unsigned char *string, unsigned int c);\r
-\r
-/* New Type */\r
-\r
-extern int PG_CCST; /* Client Character StaTus */\r
-\r
-extern int PG_SCSC; /* Server Character Set (Code) */\r
-extern int PG_CCSC; /* Client Character Set (Code) */\r
-extern unsigned char *PG_SCSS; /* Server Character Set (String) */\r
-extern unsigned char *PG_CCSS; /* Client Character Set (String) */\r
-\r
-extern void CC_lookup_characterset(ConnectionClass *self);\r
-\r
-extern int pg_CS_stat(int stat,unsigned int charcter,int characterset_code);\r
-extern int pg_CS_code(const unsigned char *stat_string);\r
-extern unsigned char *pg_CS_name(const int code);\r
-\r
-typedef struct pg_CS\r
-{\r
- unsigned char *name;\r
- int code;\r
-}pg_CS;\r
-extern pg_CS CS_Table[];\r
-\r
-extern int pg_mbslen(const unsigned char *string);\r
-extern unsigned char *pg_mbschr(const unsigned char *string, unsigned int character);\r
-extern unsigned char *pg_mbsinc( const unsigned char *current );\r
-\r
-/* Old Type Compatible */\r
-#define multibyte_init() (PG_CCST = 0)\r
-#define multibyte_char_check(X) pg_CS_stat(PG_CCST, (unsigned int) X, PG_CCSC)\r
-#define multibyte_strchr(X,Y) pg_mbschr(X,Y)\r
-#define check_client_encoding(X) pg_CS_name(PG_CCSC = pg_CS_code(X))\r
+// unsigned char *multibyte_strchr(const unsigned char *string, unsigned int c);
+
+/* New Type */
+
+extern void CC_lookup_characterset(ConnectionClass *self);
+
+extern int pg_CS_stat(int stat,unsigned int charcter,int characterset_code);
+extern int pg_CS_code(const unsigned char *stat_string);
+extern unsigned char *pg_CS_name(int code);
+
+typedef struct pg_CS
+{
+ unsigned char *name;
+ int code;
+}pg_CS;
+extern int pg_mbslen(int ccsc, const unsigned char *string);
+extern unsigned char *pg_mbschr(int ccsc, const unsigned char *string, unsigned int character);
+extern unsigned char *pg_mbsinc(int ccsc, const unsigned char *current );
+
+/* Old Type Compatible */
+typedef struct
+{
+ int ccsc;
+ const char *encstr;
+ int pos;
+ int ccst;
+} encoded_str;
+#define ENCODE_STATUS(enc) ((enc).ccst)
+
+void encoded_str_constr(encoded_str *encstr, int ccsc, const char *str);
+#define make_encoded_str(encstr, conn, str) encoded_str_constr(encstr, conn->ccsc, str)
+extern int encoded_nextchar(encoded_str *encstr);
+extern int encoded_byte_check(encoded_str *encstr, int abspos);
+#define check_client_encoding(X) pg_CS_name(pg_CS_code(X))
{
mylog("[SQLError]");
return PGAPI_Error(EnvironmentHandle, ConnectionHandle, StatementHandle,
- Sqlstate, NativeError, MessageText, BufferLength, TextLength);
+ Sqlstate, NativeError, MessageText, BufferLength,
+ TextLength);
}
RETCODE SQL_API
SQLUSMALLINT InfoType, PTR InfoValue,
SQLSMALLINT BufferLength, SQLSMALLINT *StringLength)
{
-#if (ODBCVER >= 0x0300)
RETCODE ret;
+ ConnectionClass *conn = (ConnectionClass *) ConnectionHandle;
+ CC_clear_error(conn);
+#if (ODBCVER >= 0x0300)
mylog("[SQLGetInfo(30)]");
if ((ret = PGAPI_GetInfo(ConnectionHandle, InfoType, InfoValue,
BufferLength, StringLength)) == SQL_ERROR)
{
if (((ConnectionClass *) ConnectionHandle)->driver_version >= 0x0300)
- return PGAPI_GetInfo30(ConnectionHandle, InfoType, InfoValue,
+ {
+ CC_clear_error(conn);
+ ret = PGAPI_GetInfo30(ConnectionHandle, InfoType, InfoValue,
BufferLength, StringLength);
+ }
}
- return ret;
+ if (SQL_ERROR == ret)
+ CC_log_error("SQLGetInfo30", "", conn);
#else
mylog("[SQLGetInfo]");
- return PGAPI_GetInfo(ConnectionHandle, InfoType, InfoValue,
- BufferLength, StringLength);
+ if (ret = PGAPI_GetInfo(ConnectionHandle, InfoType, InfoValue,
+ BufferLength, StringLength), SQL_ERROR == ret)
+ CC_log_error("PGAPI_GetInfo", "", conn);
#endif
+ return ret;
}
RETCODE SQL_API
{
mylog("[SQLTablePrivileges]");
return PGAPI_TablePrivileges(hstmt, szCatalogName, cbCatalogName,
- szSchemaName, cbSchemaName, szTableName, cbTableName);
+ szSchemaName, cbSchemaName, szTableName, cbTableName, 0);
}
RETCODE SQL_API
SQLSMALLINT *TextLength)
{
RETCODE ret;
- SWORD tlen;
+ SWORD tlen, buflen;
char *qst = NULL, *mtxt = NULL;
mylog("[SQLErrorW]");
if (Sqlstate)
qst = malloc(8);
- if (MessageText)
- mtxt = malloc(BufferLength);
+ buflen = 0;
+ if (MessageText && BufferLength > 0)
+ {
+ buflen = BufferLength * 3 + 1;
+ mtxt = malloc(buflen);
+ }
ret = PGAPI_Error(EnvironmentHandle, ConnectionHandle, StatementHandle,
- qst, NativeError, mtxt, BufferLength, &tlen);
+ qst, NativeError, mtxt, buflen, &tlen);
if (qst)
utf8_to_ucs2(qst, strlen(qst), Sqlstate, 5);
if (TextLength)
*TextLength = utf8_to_ucs2(mtxt, tlen, MessageText, BufferLength);
free(qst);
- free(mtxt);
+ if (mtxt)
+ free(mtxt);
return ret;
}
SQLUSMALLINT Option, SQLUINTEGER Value)
{
mylog("[SQLSetConnectionOptionW]");
+if (!ConnectionHandle) return SQL_ERROR;
((ConnectionClass *) ConnectionHandle)->unicode = 1;
return PGAPI_SetConnectOption(ConnectionHandle, Option, Value);
}
default:
break;
}
- return SQL_ERROR; /* SQLSTATE HY092 ("Invalid
- * attribute/option identifier") */
-
+ return SQL_ERROR;
}
/* SQLExtendedFetch -> SQLFetchScroll */
SQLINTEGER *NativeError, SQLCHAR *MessageText,
SQLSMALLINT BufferLength, SQLSMALLINT *TextLength)
{
- RETCODE ret;
-
mylog("[[SQLGetDiagRec]]\n");
- switch (HandleType)
- {
- 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;
+ return PGAPI_GetDiagRec(HandleType, Handle, RecNumber, Sqlstate,
+ NativeError, MessageText, BufferLength, TextLength);
}
/* new function */
*((unsigned int *) Value) = SQL_CP_RELAXED_MATCH;
break;
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;
case SQL_ATTR_OUTPUT_NTS:
*((unsigned int *) Value) = SQL_TRUE;
SQLSMALLINT FieldIdentifier, PTR Value, SQLINTEGER BufferLength)
{
RETCODE ret = SQL_SUCCESS;
+ PTR tptr;
switch (FieldIdentifier)
{
case SQL_DESC_ARRAY_SIZE:
case SQL_DESC_BIND_TYPE:
stmt->options.bind_size = (SQLUINTEGER) Value;
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;
stmt->errornumber = STMT_INVALID_OPTION_IDENTIFIER;
+ stmt->errormsg = "not implemedted yet";
}
return ret;
}
case SQL_DESC_BIND_TYPE:
stmt->options.param_bind_type = (SQLUINTEGER) Value;
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;
stmt->errornumber = STMT_INVALID_OPTION_IDENTIFIER;
}
HSTMT hstmt;
SQLUINTEGER descType;
StatementClass *stmt;
+ static const char *func = "SQLSetDescField";
+
mylog("[[SQLSetDescField]] h=%u rec=%d field=%d val=%x\n", DescriptorHandle, RecNumber, FieldIdentifier, Value);
hstmt = statementHandleFromDescHandle(DescriptorHandle, &descType);
mylog("stmt=%x type=%d\n", hstmt, descType);
break;
default:ret = SQL_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;
}
PTR Data, SQLINTEGER *StringLength,
SQLINTEGER *Indicator)
{
+ const char *func = "SQLSetDescField";
+
mylog("[[SQLSetDescRec]]\n");
mylog("Error not implemented\n");
return SQL_ERROR;
return SQL_SUCCESS;
case SQL_ATTR_ODBC_VERSION:
if ((SQLUINTEGER) Value == SQL_OV_ODBC2)
- return SQL_SUCCESS;
+ EN_set_odbc2(env);
+ else
+ EN_set_odbc3(env);
+ return SQL_SUCCESS;
break;
case SQL_ATTR_OUTPUT_NTS:
if ((SQLUINTEGER) Value == SQL_TRUE)
* case SQL_ATTR_PREDICATE_PTR: case
* 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->errormsg = "Unsupported statement option (Set)";
SC_log_error(func, "", stmt);
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 */
stmt->options.bookmark_ptr = Value;
break;
+ case SQL_ATTR_PARAM_BIND_OFFSET_PTR: /* 17 */
+ stmt->options.param_offset_ptr = (SQLUINTEGER *) Value;
+ break;
case SQL_ATTR_PARAM_BIND_TYPE: /* 18 */
stmt->options.param_bind_type = (SQLUINTEGER) Value;
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 */
stmt->options.param_processed_ptr = (SQLUINTEGER *) Value;
break;
case SQL_ATTR_PARAMSET_SIZE: /* 22 */
stmt->options.paramset_size = (SQLUINTEGER) Value;
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 */
stmt->options.rowStatusArray = (SQLUSMALLINT *) Value;
-
break;
case SQL_ATTR_ROWS_FETCHED_PTR: /* 26 */
stmt->options.rowsFetched = (SQLUINTEGER *) Value;
-
break;
case SQL_ATTR_ROW_ARRAY_SIZE: /* 27 */
stmt->options.rowset_size = (SQLUINTEGER) Value;
-
break;
default:
return PGAPI_SetStmtOption(StatementHandle, (UWORD) Attribute, (UDWORD) Value);
RETCODE SQL_API
PGAPI_GetFunctions30(HDBC hdbc, UWORD fFunction, UWORD FAR * pfExists)
{
- ConnectionClass *conn = (ConnectionClass *) hdbc;
+ ConnectionClass *conn = (ConnectionClass *) hdbc;
ConnInfo *ci = &(conn->connInfo);
if (fFunction != SQL_API_ODBC3_ALL_FUNCTIONS)
SQL_FUNC_ESET(pfExists, SQL_API_SQLPARAMDATA); /* 48 */
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_SQLSPECIALCOLUMNS); /* 52 */
+ SQL_FUNC_ESET(pfExists, SQL_API_SQLSPECIALCOLUMNS); /* 52 */
SQL_FUNC_ESET(pfExists, SQL_API_SQLSTATISTICS); /* 53 */
SQL_FUNC_ESET(pfExists, SQL_API_SQLTABLES); /* 54 */
SQL_FUNC_ESET(pfExists, SQL_API_SQLBROWSECONNECT); /* 55 */
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_SQLDESCRIBEPARAM); /* 58 */
/* SQL_FUNC_ESET(pfExists, SQL_API_SQLEXTENDEDFETCH); 59 deprecated */
/* SQL_FUNC_ESET(pfExists, SQL_API_SQLPARAMOPTIONS); 64 deprecated */
SQL_FUNC_ESET(pfExists, SQL_API_SQLPRIMARYKEYS); /* 65 */
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_SQLSETPOS); /* 68 */
- SQL_FUNC_ESET(pfExists, SQL_API_SQLSETSCROLLOPTIONS); /* 69 deprecated */
- if (ci->drivers.lie)
- SQL_FUNC_ESET(pfExists, SQL_API_SQLTABLEPRIVILEGES); /* 70 not implemented yet */
+ /* SQL_FUNC_ESET(pfExists, SQL_API_SQLSETSCROLLOPTIONS); 69 deprecated */
+ SQL_FUNC_ESET(pfExists, SQL_API_SQLTABLEPRIVILEGES); /* 70 */
/* SQL_FUNC_ESET(pfExists, SQL_API_SQLDRIVERS); */ /* 71 */
SQL_FUNC_ESET(pfExists, SQL_API_SQLBINDPARAMETER); /* 72 */
if (ci->drivers.lie)
{
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_SQLGETDIAGREC); /* 1011 */
SQL_FUNC_ESET(pfExists, SQL_API_SQLSETCONNECTATTR); /* 1016 */
SQL_FUNC_ESET(pfExists, SQL_API_SQLSETDESCFIELD); /* 1017 */
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_SQLSETSTMTATTR); /* 1020 */
SQL_FUNC_ESET(pfExists, SQL_API_SQLFETCHSCROLL); /* 1021 */
SQLSMALLINT *pcbErrorMsg)
{
RETCODE ret;
- SWORD tlen;
- char *qst = NULL, *mtxt = NULL;
+ SWORD buflen, tlen;
+ char *qstr = NULL, *mtxt = NULL;
mylog("[SQLGetDiagRecW]");
if (szSqlState)
- qst = malloc(8);
- if (szErrorMsg)
- mtxt = malloc(cbErrorMsgMax);
- ret = PGAPI_GetDiagRec(fHandleType, handle, iRecord, qst,
- pfNativeError, mtxt, cbErrorMsgMax, &tlen);
- if (qst)
- utf8_to_ucs2(qst, strlen(qst), szSqlState, 5);
- if (pcbErrorMsg)
- *pcbErrorMsg = utf8_to_ucs2(mtxt, tlen, szErrorMsg, cbErrorMsgMax);
- free(qst);
- free(mtxt);
+ qstr = malloc(8);
+ buflen = 0;
+ if (szErrorMsg && cbErrorMsgMax > 0)
+ {
+ buflen = cbErrorMsgMax;
+ mtxt = malloc(buflen);
+ }
+ ret = PGAPI_GetDiagRec(fHandleType, handle, iRecord, qstr,
+ pfNativeError, mtxt, buflen, &tlen);
+ if (ret == SQL_SUCCESS || ret == SQL_SUCCESS_WITH_INFO)
+ {
+ 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;
}
SQLPrepareW, SQLPrimaryKeysW, SQLProcedureColumnsW,
SQLProceduresW, SQLSetCursorNameW,
SQLSpecialColumnsW, SQLStatisticsW, SQLTablesW,
- SQLTablePrivilegesW
+ SQLTablePrivilegesW, SQLGetTypeInfoW
*-------
*/
ret = PGAPI_DriverConnect(hdbc, hwnd, szIn, (SWORD) inlen,
szOut, cbConnStrOutMax, &olen, fDriverCompletion);
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);
if (szIn);
free(szIn);
ret = PGAPI_BrowseConnect(hdbc, szIn, (SWORD) inlen,
szOut, cbConnStrOutMax, &olen);
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);
if (szIn);
free(szIn);
SQLSMALLINT *DecimalDigits, SQLSMALLINT *Nullable)
{
RETCODE ret;
- SWORD nmlen;
+ SWORD buflen, nmlen;
char *clName;
mylog("[SQLDescribeColW]");
- clName = malloc(BufferLength);
+ buflen = BufferLength * 3 + 1;
+ clName = malloc(buflen);
ret = PGAPI_DescribeCol(StatementHandle, ColumnNumber,
- clName, BufferLength, &nmlen,
- DataType, ColumnSize, DecimalDigits, Nullable);
- *NameLength = utf8_to_ucs2(clName, nmlen, ColumnName, BufferLength);
+ clName, buflen, &nmlen, DataType, ColumnSize,
+ DecimalDigits, Nullable);
+ 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);
return ret;
}
{
RETCODE ret;
char *crName;
- SWORD clen;
+ SWORD clen, buflen;
mylog("[SQLGetCursorNameW]");
- crName = malloc(BufferLength);
- ret = PGAPI_GetCursorName(StatementHandle, crName, BufferLength,
- &clen);
- *NameLength = utf8_to_ucs2(crName, (Int4) clen, CursorName, BufferLength);
+ buflen = BufferLength * 3 + 1;
+ crName = malloc(buflen);
+ ret = PGAPI_GetCursorName(StatementHandle, crName, buflen, &clen);
+ 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);
return ret;
}
SQLUSMALLINT InfoType, PTR InfoValue,
SQLSMALLINT BufferLength, SQLSMALLINT *StringLength)
{
+ ConnectionClass *conn = (ConnectionClass *) ConnectionHandle;
RETCODE ret;
- ((ConnectionClass *) ConnectionHandle)->unicode = 1;
+
+ conn->unicode = 1;
+ CC_clear_error(conn);
#if (ODBCVER >= 0x0300)
mylog("[SQLGetInfoW(30)]");
if ((ret = PGAPI_GetInfo(ConnectionHandle, InfoType, InfoValue,
BufferLength, StringLength)) == SQL_ERROR)
{
- if (((ConnectionClass *) ConnectionHandle)->driver_version >= 0x0300)
- return PGAPI_GetInfo30(ConnectionHandle, InfoType, InfoValue,
+ if (conn->driver_version >= 0x0300)
+ {
+ CC_clear_error(conn);
+ ret = PGAPI_GetInfo30(ConnectionHandle, InfoType, InfoValue,
BufferLength, StringLength);
+ }
}
- return ret;
+ if (SQL_ERROR == ret)
+ CC_log_error("SQLGetInfoW(30)", "", conn);
#else
mylog("[SQLGetInfoW]");
- return PGAPI_GetInfo(ConnectionHandle, InfoType, InfoValue,
+ ret = PGAPI_GetInfo(ConnectionHandle, InfoType, InfoValue,
BufferLength, StringLength);
+ if (SQL_ERROR == ret)
+ CC_log_error("SQLGetInfoW", "", conn);
#endif
+ return ret;
}
RETCODE SQL_API SQLPrepareW(HSTMT StatementHandle,
RETCODE ret;
char *szIn, *szOut;
UInt4 slen;
- SQLINTEGER olen;
+ SQLINTEGER buflen, olen;
mylog("[SQLNativeSqlW]");
((ConnectionClass *) hdbc)->unicode = 1;
szIn = ucs2_to_utf8(szSqlStrIn, cbSqlStrIn, &slen);
- szOut = malloc(cbSqlStrMax);
+ buflen = 3 * cbSqlStrMax + 1;
+ szOut = malloc(buflen);
ret = PGAPI_NativeSql(hdbc, szIn, (SQLINTEGER) slen,
- szOut, cbSqlStrMax, &olen);
+ szOut, buflen, &olen);
if (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);
return ret;
}
free(tbName);
return ret;
}
+
+RETCODE SQL_API SQLGetTypeInfoW(
+ SQLHSTMT StatementHandle,
+ SQLSMALLINT DataType)
+{
+ return PGAPI_GetTypeInfo(StatementHandle, DataType);
+}
break;
case SQL_AUTOCOMMIT:
- if (vParam == SQL_AUTOCOMMIT_ON && CC_is_in_autocommit(conn))
+ if (vParam == SQL_AUTOCOMMIT_ON && CC_is_in_trans(conn))
break;
- else if (vParam == SQL_AUTOCOMMIT_OFF && !CC_is_in_autocommit(conn))
+ else if (vParam == SQL_AUTOCOMMIT_OFF && !CC_is_in_trans(conn))
break;
if (CC_is_in_trans(conn))
CC_commit(conn);
+
mylog("PGAPI_SetConnectOption: AUTOCOMMIT: transact_status=%d, vparam=%d\n", conn->transact_status, vParam);
switch (vParam)
sprintf(option, "fOption=%d, vParam=%ld", fOption, 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->ms_jet = 1;
return SQL_SUCCESS;
case SQL_CURRENT_QUALIFIER: /* don't use qualifiers */
if (pvParam)
- strcpy(pvParam, "");
+ ((char *) pvParam)[0] = ((char *) pvParam)[1] = '\0';
break;
case SQL_GET_BOOKMARK:
case SQL_ROW_NUMBER:
- res = stmt->result;
+ res = SC_get_Curres(stmt);
if (stmt->manual_result || !ci->drivers.use_declarefetch)
{
#define TAB_INCR 8
#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);
+#endif /* MULTIBYTE */
void getColInfo(COL_INFO *col_info, FIELD_INFO *fi, int k);
char searchColInfo(COL_INFO *col_info, FIELD_INFO *fi);
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 out = 0;
char qc,
in_escape = FALSE;
+#ifdef MULTIBYTE
+ encoded_str encstr;
+#endif
if (smax <= 1)
return NULL;
if (numeric)
*numeric = FALSE;
+#ifdef MULTIBYTE
+ encoded_str_constr(&encstr, ccsc, &s[i]);
+#endif
/* get the next token */
- while (!isspace((unsigned char) s[i]) && s[i] != ',' &&
- s[i] != '\0' && out != smax)
+ while (s[i] != '\0' && out < smax)
{
#ifdef MULTIBYTE
- if (multibyte_char_check(s[i]) != 0)
+ encoded_nextchar(&encstr);
+ if (ENCODE_STATUS(encstr) != 0)
{
token[out++] = s[i++];
continue;
}
#endif
+ if (isspace((unsigned char) s[i]) || s[i] == ',')
+ break;
/* Handle quoted stuff */
if (out == 0 && (s[i] == '\"' || s[i] == '\''))
{
while (s[i] != '\0' && out != smax)
{
#ifdef MULTIBYTE
- if (multibyte_char_check(s[i]) != 0)
+ encoded_nextchar(&encstr);
+ if (ENCODE_STATUS(encstr) != 0)
{
token[out++] = s[i++];
continue;
#if 0
-QR_set_num_fields(stmt->result, 14);
-QR_set_field_info(stmt->result, 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(stmt->result, 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(stmt->result, 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(stmt->result, 6, "PRECISION", PG_TYPE_INT4, 4);
-QR_set_field_info(stmt->result, 7, "LENGTH", PG_TYPE_INT4, 4);
-QR_set_field_info(stmt->result, 8, "SCALE", PG_TYPE_INT2, 2);
-QR_set_field_info(stmt->result, 9, "RADIX", PG_TYPE_INT2, 2);
-QR_set_field_info(stmt->result, 10, "NULLABLE", PG_TYPE_INT2, 2);
-QR_set_field_info(stmt->result, 11, "REMARKS", PG_TYPE_TEXT, 254);
+QR_set_num_fields(SC_get_Curres(stmt), 14);
+QR_set_field_info(SC_get_Curres(stmt), 0, "TABLE_QUALIFIER", 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(SC_get_Curres(stmt), 2, "TABLE_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(SC_get_Curres(stmt), 4, "DATA_TYPE", PG_TYPE_INT2, 2);
+QR_set_field_info(SC_get_Curres(stmt), 5, "TYPE_NAME", PG_TYPE_TEXT, MAX_INFO_STRING);
+QR_set_field_info(SC_get_Curres(stmt), 6, "PRECISION", PG_TYPE_INT4, 4);
+QR_set_field_info(SC_get_Curres(stmt), 7, "LENGTH", PG_TYPE_INT4, 4);
+QR_set_field_info(SC_get_Curres(stmt), 8, "SCALE", PG_TYPE_INT2, 2);
+QR_set_field_info(SC_get_Curres(stmt), 9, "RADIX", PG_TYPE_INT2, 2);
+QR_set_field_info(SC_get_Curres(stmt), 10, "NULLABLE", PG_TYPE_INT2, 2);
+QR_set_field_info(SC_get_Curres(stmt), 11, "REMARKS", PG_TYPE_TEXT, 254);
/* User defined fields */
-QR_set_field_info(stmt->result, 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), 12, "DISPLAY_SIZE", PG_TYPE_INT4, 4);
+QR_set_field_info(SC_get_Curres(stmt), 13, "FIELD_TYPE", PG_TYPE_INT4, 4);
#endif
void
stmt->ntab = 0;
#ifdef MULTIBYTE
- multibyte_init();
-#endif
+ while (pptr = ptr, (ptr = getNextToken(conn->ccsc, pptr, token, sizeof(token), &delim, "e, &dquote, &numeric)) != NULL)
+#else
while (pptr = ptr, (ptr = getNextToken(pptr, token, sizeof(token), &delim, "e, &dquote, &numeric)) != NULL)
+#endif
{
unquoted = !(quote || dquote);
if (!dquote)
{
char *ptr;
+#ifdef MULTIBYTE
+ encoded_str encstr;
+ make_encoded_str(&encstr, conn, ti[stmt->ntab]->name);
+#endif /* MULTIBYTE */
/* lower case table name */
for (ptr = ti[stmt->ntab]->name; *ptr; ptr++)
{
#ifdef MULTIBYTE
- if ((unsigned char) *ptr >= 0x80)
+ encoded_nextchar(&encstr);
+ if (ENCODE_STATUS(encstr) != 0)
ptr++;
else
#endif /* MULTIBYTE */
* structure
*/
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
* make sure that the statement doesn't free it
*/
- col_stmt->result = NULL;
+ SC_set_Result(col_stmt, NULL);
conn->ntables++;
RETCODE ret;
static const char *func = "PGAPI_GetDiagRec";
- mylog("%s entering ", func);
+ mylog("%s entering rec=%d", func, RecNumber);
switch (HandleType)
{
case SQL_HANDLE_ENV:
- ret = PGAPI_Error(Handle, NULL, NULL, Sqlstate, NativeError,
- MessageText, BufferLength, TextLength);
+ ret = PGAPI_EnvError(Handle, RecNumber, Sqlstate,
+ NativeError, MessageText,
+ BufferLength, TextLength, 0);
break;
case SQL_HANDLE_DBC:
- ret = PGAPI_Error(NULL, Handle, NULL, Sqlstate, NativeError,
- MessageText, BufferLength, TextLength);
+ ret = PGAPI_ConnectError(Handle, RecNumber, Sqlstate,
+ NativeError, MessageText, BufferLength,
+ TextLength, 0);
break;
case SQL_HANDLE_STMT:
- ret = PGAPI_Error(NULL, NULL, Handle, Sqlstate, NativeError,
- MessageText, BufferLength, TextLength);
+ ret = PGAPI_StmtError(Handle, RecNumber, Sqlstate,
+ NativeError, MessageText, BufferLength,
+ TextLength, 0);
break;
default:
ret = SQL_ERROR;
}
- if (ret == SQL_SUCCESS_WITH_INFO &&
- BufferLength == 0 &&
- *TextLength)
- {
- SQLSMALLINT BufferLength = *TextLength + 4;
- SQLCHAR *MessageText = malloc(BufferLength);
+ mylog("%s exiting %d\n", func, ret);
+ return ret;
+}
+
+RETCODE SQL_API
+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,
- NativeError, MessageText, BufferLength,
- TextLength);
- free(MessageText);
+ mylog("%s entering rec=%d", func, RecNumber);
+ switch (HandleType)
+ {
+ 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;
}
case SQL_ATTR_CONNECTION_TIMEOUT:
case SQL_ATTR_METADATA_ID:
conn->errornumber = STMT_INVALID_OPTION_IDENTIFIER;
- conn->errormsg = "Unsupported connection option (Set)";
+ conn->errormsg = "Unsupported connect attribute (Get)";
return SQL_ERROR;
}
return PGAPI_GetConnectOption(ConnectionHandle, (UWORD) Attribute, Value);
case SQL_ATTR_CONNECTION_TIMEOUT:
case SQL_ATTR_METADATA_ID:
conn->errornumber = STMT_INVALID_OPTION_IDENTIFIER;
- conn->errormsg = "Unsupported connection option (Set)";
+ conn->errormsg = "Unsupported connect attribute (Set)";
return SQL_ERROR;
}
return PGAPI_SetConnectOption(ConnectionHandle, (UWORD) Attribute, (UDWORD) Value);
#include <string.h>
#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,
HDBC FAR * ConnectionHandle);
SQLCHAR *Sqlstate, SQLINTEGER *NativeError,
SQLCHAR *MessageText, SQLSMALLINT BufferLength,
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,
SQLCHAR *StatementText, SQLINTEGER TextLength);
RETCODE SQL_API PGAPI_Execute(HSTMT StatementHandle);
SQLCHAR *szSchemaName,
SQLSMALLINT cbSchemaName,
SQLCHAR *szTableName,
- SQLSMALLINT cbTableName);
+ SQLSMALLINT cbTableName,
+ UWORD flag);
RETCODE SQL_API PGAPI_BindParameter(
HSTMT hstmt,
SQLUSMALLINT ipar,
SDWORD crowKeyset,
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__ */
#include "dlg_specific.h"
#include "statement.h"
#include "connection.h"
+#include "environ.h"
#include "qresult.h"
SQL_TINYINT,
SQL_VARBINARY,
SQL_VARCHAR,
+#ifdef UNICODE_SUPPORT
+ SQL_WCHAR,
+ SQL_WVARCHAR,
+ SQL_WLONGVARCHAR,
+#endif /* UNICODE_SUPPORT */
0
};
+#if (ODBCVER >= 0x0300) && defined(OBDCINT64)
+#define ALLOWED_C_BIGINT SQL_C_SBIGINT
+#else
+#define ALLOWED_C_BIGINT SQL_C_CHAR
+#endif
Int4
sqltype_to_pgtype(StatementClass *stmt, SWORD fSqlType)
{
Int4 pgType;
- ConnInfo *ci = &(SC_get_conn(stmt)->connInfo);
+ ConnectionClass *conn = SC_get_conn(stmt);
+ ConnInfo *ci = &(conn->connInfo);
switch (fSqlType)
{
pgType = PG_TYPE_BPCHAR;
break;
+#ifdef UNICODE_SUPPORT
+ case SQL_WCHAR:
+ pgType = PG_TYPE_BPCHAR;
+ break;
+#endif /* UNICODE_SUPPORT */
+
case SQL_BIT:
pgType = ci->drivers.bools_as_char ? PG_TYPE_CHAR : PG_TYPE_BOOL;
break;
case SQL_DATE:
+#if (ODBCVER >= 0x0300)
+ case SQL_TYPE_DATE:
+#endif /* ODBCVER */
pgType = PG_TYPE_DATE;
break;
pgType = ci->drivers.text_as_longvarchar ? PG_TYPE_TEXT : PG_TYPE_VARCHAR;
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:
pgType = PG_TYPE_FLOAT4;
break;
break;
case SQL_TIME:
+#if (ODBCVER >= 0x0300)
+ case SQL_TYPE_TIME:
+#endif /* ODBCVER */
pgType = PG_TYPE_TIME;
break;
case SQL_TIMESTAMP:
+#if (ODBCVER >= 0x0300)
+ case SQL_TYPE_TIMESTAMP:
+#endif /* ODBCVER */
pgType = PG_TYPE_DATETIME;
break;
pgType = PG_TYPE_VARCHAR;
break;
+#if UNICODE_SUPPORT
+ case SQL_WVARCHAR:
+ pgType = PG_TYPE_VARCHAR;
+ break;
+#endif /* UNICODE_SUPPORT */
+
default:
pgType = 0; /* ??? */
break;
Int2
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)
{
case PG_TYPE_NAME:
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:
return SQL_CHAR;
case PG_TYPE_TEXT:
return ci->drivers.text_as_longvarchar ? SQL_LONGVARCHAR : SQL_VARCHAR;
+#endif /* UNICODE_SUPPORT */
case PG_TYPE_BYTEA:
return SQL_VARBINARY;
/* Change this to SQL_BIGINT for ODBC v3 bjm 2001-01-23 */
case PG_TYPE_INT8:
#if (ODBCVER >= 0x0300)
- return SQL_BIGINT;
-#else
- return SQL_CHAR;
+ if (!conn->ms_jet)
+ return SQL_BIGINT;
#endif /* ODBCVER */
+ return SQL_CHAR;
case PG_TYPE_NUMERIC:
return SQL_NUMERIC;
case PG_TYPE_FLOAT8:
return SQL_FLOAT;
case PG_TYPE_DATE:
+#if (ODBCVER >= 0x0300)
+ if (EN_is_odbc3(env))
+ return SQL_TYPE_DATE;
+#endif /* ODBCVER */
return SQL_DATE;
case PG_TYPE_TIME:
+#if (ODBCVER >= 0x0300)
+ if (EN_is_odbc3(env))
+ return SQL_TYPE_TIME;
+#endif /* ODBCVER */
return SQL_TIME;
case PG_TYPE_ABSTIME:
case PG_TYPE_DATETIME:
case PG_TYPE_TIMESTAMP:
+#if (ODBCVER >= 0x0300)
+ if (EN_is_odbc3(env))
+ return SQL_TYPE_TIMESTAMP;
+#endif /* ODBCVER */
return SQL_TIMESTAMP;
case PG_TYPE_MONEY:
return SQL_FLOAT;
Int2
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)
{
case PG_TYPE_INT8:
#if (ODBCVER >= 0x0300)
- return SQL_C_SBIGINT;
-#else
+ if (!conn->ms_jet)
+ return ALLOWED_C_BIGINT;
+#endif /* ODBCVER */
return SQL_C_CHAR;
-#endif
case PG_TYPE_NUMERIC:
return SQL_C_CHAR;
case PG_TYPE_INT2:
return SQL_C_DOUBLE;
case PG_TYPE_DATE:
#if (ODBCVER >= 0x0300)
- return SQL_C_TYPE_DATE;
-#else
- return SQL_C_DATE;
+ if (EN_is_odbc3(env))
+ return SQL_C_TYPE_DATE;
#endif /* ODBCVER */
+ return SQL_C_DATE;
case PG_TYPE_TIME:
#if (ODBCVER >= 0x0300)
- return SQL_C_TYPE_TIME;
-#else
- return SQL_C_TIME;
+ if (EN_is_odbc3(env))
+ return SQL_C_TYPE_TIME;
#endif /* ODBCVER */
+ return SQL_C_TIME;
case PG_TYPE_ABSTIME:
case PG_TYPE_DATETIME:
case PG_TYPE_TIMESTAMP:
#if (ODBCVER >= 0x0300)
- return SQL_C_TYPE_TIMESTAMP;
-#else
- return SQL_C_TIMESTAMP;
+ if (EN_is_odbc3(env))
+ return SQL_C_TYPE_TIMESTAMP;
#endif /* ODBCVER */
+ return SQL_C_TIMESTAMP;
case PG_TYPE_MONEY:
return SQL_C_FLOAT;
case PG_TYPE_BOOL:
return SQL_C_BINARY;
case PG_TYPE_LO:
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:
/* hack until permanent type is available */
if (col < 0)
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
if (col < 0)
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
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 (PG_VERSION_GE(SC_get_conn(stmt), 7.1))
else
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)
return maxsize;
- result = SC_get_Result(stmt);
+ result = SC_get_Curres(stmt);
/*
* Manual Result Sets -- use assigned column width (i.e., from
if (QR_get_atttypmod(result, col) > -1)
return QR_get_atttypmod(result, col);
+ /* The type is really unknown */
if (type == PG_TYPE_BPCHAR || handle_unknown_size_as == UNKNOWNS_AS_LONGEST)
{
p = QR_get_display_size(result, col);
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;
- else
- return p;
+ else /* handle_unknown_size_as == DONT_KNOW */
+ return -1;
+
}
static Int2
if (PG_VERSION_LT(conn, 7.2))
return 0;
- result = SC_get_Result(stmt);
+ result = SC_get_Curres(stmt);
/*
* Manual Result Sets -- use assigned column width (i.e., from
fixed = 8;
break;
case PG_TYPE_TIME_WITH_TMZONE:
- if (USE_ZONE)
- fixed = 11;
- else
- fixed = 8;
+ fixed = 11;
break;
case PG_TYPE_TIMESTAMP_NO_TMZONE:
fixed = 19;
return getTimestampPrecision(stmt, type, col);
case PG_TYPE_BOOL:
- return 1;
+ {
+ BOOL true_is_minus1 = FALSE;
+ return true_is_minus1 ? 2 : 1;
+ }
case PG_TYPE_LO:
return SQL_NO_TOTAL;
Int4
pgtype_length(StatementClass *stmt, Int4 type, int col, int handle_unknown_size_as)
{
+ ConnectionClass *conn = SC_get_conn(stmt);
+
switch (type)
{
case PG_TYPE_INT2:
/* Character types (and NUMERIC) use the default precision */
case PG_TYPE_VARCHAR:
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
/* after 7.2 */
- if (PG_VERSION_GE(SC_get_conn(stmt), 7.2))
- return 3 * pgtype_precision(stmt, type, col, handle_unknown_size_as);
+ if (PG_VERSION_GE(conn, 7.2))
+ coef = 3;
else
-#else
- /* CR -> CR/LF */
- return 2 * pgtype_precision(stmt, type, col, handle_unknown_size_as);
#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:
return pgtype_precision(stmt, type, col, handle_unknown_size_as);
}
case PG_TYPE_NUMERIC:
case PG_TYPE_DATE:
- case PG_TYPE_TIME:
case PG_TYPE_TIME_WITH_TMZONE:
+ case PG_TYPE_TIME:
case PG_TYPE_ABSTIME:
case PG_TYPE_DATETIME:
case PG_TYPE_TIMESTAMP:
#else
return SQL_C_CHAR;
case SQL_BIGINT:
- return SQL_C_SBIGINT;
+ return ALLOWED_C_BIGINT;
#endif
+#ifdef UNICODE_SUPPORT
+ case SQL_WCHAR:
+ case SQL_WVARCHAR:
+ case SQL_WLONGVARCHAR:
+ return SQL_C_WCHAR;
+#endif /* UNICODE_SUPPORT */
+
case SQL_BIT:
return SQL_C_BIT;
return SQL_C_BINARY;
case SQL_DATE:
-#if (ODBCVER >= 0x0300)
- return SQL_C_TYPE_DATE;
-#else
return SQL_C_DATE;
-#endif /* ODBCVER */
case SQL_TIME:
-#if (ODBCVER >= 0x0300)
- return SQL_C_TYPE_TIME;
-#else
return SQL_C_TIME;
-#endif /* ODBCVER */
case SQL_TIMESTAMP:
+ return SQL_C_TIMESTAMP;
+
#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;
-#else
- return SQL_C_TIMESTAMP;
#endif /* ODBCVER */
default:
case SQL_C_BINARY:
case SQL_C_CHAR:
+ case SQL_C_WCHAR:
return 0;
default: /* should never happen */
*
* 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 $
*
*/
#define DBMS_NAME "PostgreSQL"
#endif /* ODBCVER */
-#define POSTGRESDRIVERVERSION "07.01.0010"
+#define POSTGRESDRIVERVERSION "07.01.0011"
#ifdef WIN32
#if (ODBCVER >= 0x0300)
#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_
void *debug_alloc(size_t);
void *debug_realloc(void *, size_t);
BS_NOTIFY | WS_TABSTOP,247,205,40,10
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
CAPTION "Advanced Options (DataSource)"
FONT 10, "Terminal"
BS_AUTOCHECKBOX | WS_TABSTOP,45,28,88,10
CONTROL "Disallow &Premature",DS_DISALLOWPREMATURE,"Button",
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 |
- WS_GROUP,53,54,47,10
+ WS_GROUP,53,69,47,10
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,
- 187,54,26,10
- GROUPBOX "OID Options",IDC_STATIC,43,74,180,25
+ 187,69,26,10
+ GROUPBOX "OID Options",IDC_STATIC,43,89,180,25
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 |
- WS_GROUP | WS_TABSTOP,161,85,55,10
- LTEXT "Connect &Settings:",IDC_STATIC,10,105,35,25
- EDITTEXT DS_CONNSETTINGS,50,105,200,20,ES_MULTILINE |
+ WS_GROUP | WS_TABSTOP,161,100,55,10
+ LTEXT "Connect &Settings:",IDC_STATIC,10,120,35,25
+ EDITTEXT DS_CONNSETTINGS,50,120,200,20,ES_MULTILINE |
ES_AUTOVSCROLL | ES_AUTOHSCROLL | ES_WANTRETURN
- DEFPUSHBUTTON "OK",IDOK,71,135,50,14,WS_GROUP
- PUSHBUTTON "Cancel",IDCANCEL,146,135,50,14
+ DEFPUSHBUTTON "OK",IDOK,71,150,50,14,WS_GROUP
+ PUSHBUTTON "Cancel",IDCANCEL,146,150,50,14
END
#else
DLG_CONFIG DIALOG DISCARDABLE 65, 43, 292, 116
BS_NOTIFY | WS_TABSTOP,233,224,40,10
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
CAPTION "Advanced Options (DataSource)"
FONT 8, "MS Sans Serif"
BS_AUTOCHECKBOX | WS_TABSTOP,25,25,85,10
CONTROL "Disallow &Premature",DS_DISALLOWPREMATURE,"Button",
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,
- 50,35,10
+ 65,35,10
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,
- 130,50,26,10
- GROUPBOX "OID Options",IDC_STATIC,15,70,180,25
+ 130,65,26,10
+ GROUPBOX "OID Options",IDC_STATIC,15,86,180,25
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 |
- WS_GROUP | WS_TABSTOP,115,81,51,10
- RTEXT "Connect &Settings:",IDC_STATIC,10,105,35,25
- EDITTEXT DS_CONNSETTINGS,50,105,200,20,ES_MULTILINE |
+ WS_GROUP | WS_TABSTOP,115,96,51,10
+ RTEXT "Connect &Settings:",IDC_STATIC,10,120,35,25
+ EDITTEXT DS_CONNSETTINGS,50,120,200,20,ES_MULTILINE |
ES_AUTOVSCROLL | ES_AUTOHSCROLL | ES_WANTRETURN
- DEFPUSHBUTTON "OK",IDOK,71,135,50,14,WS_GROUP
- PUSHBUTTON "Cancel",IDCANCEL,146,135,50,14
+ DEFPUSHBUTTON "OK",IDOK,71,150,50,14,WS_GROUP
+ PUSHBUTTON "Cancel",IDCANCEL,146,150,50,14
END
#endif
//
VS_VERSION_INFO VERSIONINFO
- FILEVERSION 7,1,0,10
- PRODUCTVERSION 7,1,0,10
+ FILEVERSION 7,1,0,11
+ PRODUCTVERSION 7,1,0,11
FILEFLAGSMASK 0x3L
#ifdef _DEBUG
FILEFLAGS 0x1L
VALUE "CompanyName", "Insight Distribution Systems\0"
#endif
VALUE "FileDescription", "PostgreSQL Driver\0"
- VALUE "FileVersion", " 07.01.0010\0"
+ VALUE "FileVersion", " 07.01.0011\0"
VALUE "InternalName", "psqlodbc\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 "OriginalFilename", "psqlodbc.dll\0"
VALUE "PrivateBuild", "\0"
VALUE "ProductName", "Microsoft Open Database Connectivity\0"
- VALUE "ProductVersion", " 07.01.0010\0"
+ VALUE "ProductVersion", " 07.01.0011\0"
VALUE "SpecialBuild", "\0"
END
END
--- /dev/null
+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
--- /dev/null
+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
rv->command = NULL;
rv->notice = NULL;
rv->conn = NULL;
+ rv->next = NULL;
rv->inTuples = FALSE;
rv->fcount = 0;
rv->fetch_count = 0;
/* Free notice info (this is from strdup()) */
if (self->notice)
free(self->notice);
+ /* Destruct the result object in the chain */
+ if (self->next)
+ QR_Destructor(self->next);
free(self);
if (self->cursor)
free(self->cursor);
+ self->cursor = NULL;
if (fetch_cursor)
{
sprintf(buf, "close %s", self->cursor);
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->currTuple = -1;
qi.row_size = self->cache_size;
qi.result_in = self;
qi.cursor = NULL;
- res = CC_send_query(self->conn, fetch, &qi);
- if (res == NULL || QR_get_aborted(res))
+ res = CC_send_query(self->conn, fetch, &qi, TRUE);
+ if (res == NULL)
{
self->status = PGRES_FATAL_ERROR;
QR_set_message(self, "Error fetching next group.");
- if (res)
- QR_Destructor(res);
return FALSE;
}
self->inTuples = TRUE;
*/
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;
}
TupleListClass *manual_tuples; /* manual result tuple list */
ConnectionClass *conn; /* the connection this result is using
* (backend) */
+ QResultClass *next; /* the following result class */
/* Stuff for declare/fetch tuples */
int count_allocated; /* m(re)alloced count */
#define DRV_OR_DSN 1059\r
#define DRV_DEBUG 1060\r
#define DS_DISALLOWPREMATURE 1061\r
+#define DS_LFCONVERSION 1062\r
+#define DS_TRUEISMINUS1 1063\r
\r
/* Next default values for new objects\r */
/*\r */
*
* API functions: SQLRowCount, SQLNumResultCols, SQLDescribeCol,
* SQLColAttributes, SQLGetData, SQLFetch, SQLExtendedFetch,
- * SQLMoreResults(NI), SQLSetPos, SQLSetScrollOptions(NI),
+ * SQLMoreResults, SQLSetPos, SQLSetScrollOptions(NI),
* SQLSetCursorName, SQLGetCursorName
*
* Comments: See "notice.txt" for copyright and license information.
*ptr;
ConnInfo *ci;
+ mylog("%s: entering...\n", func);
if (!stmt)
{
SC_log_error(func, "", NULL);
{
if (stmt->status == STMT_FINISHED)
{
- res = SC_get_Result(stmt);
+ res = SC_get_Curres(stmt);
if (res && pcrow)
{
}
else
{
- res = SC_get_Result(stmt);
+ res = SC_get_Curres(stmt);
if (res && pcrow)
{
msg = QR_get_command(res);
char parse_ok;
ConnInfo *ci;
+ mylog("%s: entering...\n", func);
if (!stmt)
{
SC_log_error(func, "", NULL);
if (!parse_ok)
{
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);
if ((!result) || ((stmt->status != STMT_FINISHED) && (stmt->status != STMT_PREMATURE)))
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
* driver manager.
{
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);
if ((NULL == res) || ((stmt->status != STMT_FINISHED) && (stmt->status != STMT_PREMATURE)))
if (pcbColName)
*pcbColName = len;
- if (szColName)
+ if (szColName && cbColNameMax > 0)
{
strncpy_null(szColName, col_name, cbColNameMax);
{
static char *func = "PGAPI_ColAttributes";
StatementClass *stmt = (StatementClass *) hstmt;
- Int4 field_type = 0;
- ConnInfo *ci;
+ Int4 col_idx, field_type = 0;
+ ConnectionClass *conn;
+ ConnInfo *ci;
int unknown_sizes;
int cols = 0;
char parse_ok;
RETCODE result;
- char *p = NULL;
+ const char *p = NULL;
int len = 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)
{
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
* 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); */
unknown_sizes = ci->drivers.unknown_sizes;
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->errormsg = "Invalid column number in ColAttributes.";
SC_log_error(func, "", stmt);
return SQL_ERROR;
}
- field_type = stmt->fi[icol]->type;
+ field_type = stmt->fi[col_idx]->type;
if (field_type > 0)
parse_ok = TRUE;
}
}
- if (!parse_ok)
+ if (parse_ok)
+ fi = stmt->fi[col_idx];
+ else
{
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->errornumber = STMT_SEQUENCE_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
* in this case.
*/
+#if (ODBCVER >= 0x0300)
+ if (fDescType == SQL_DESC_COUNT)
+#else
if (fDescType == SQL_COLUMN_COUNT)
+#endif /* ODBCVER */
{
if (pfDesc)
*pfDesc = cols;
return SQL_SUCCESS;
}
- if (icol >= cols)
+ if (col_idx >= cols)
{
stmt->errornumber = STMT_INVALID_COLUMN_NUMBER_ERROR;
stmt->errormsg = "Invalid column number in ColAttributes.";
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)
{
- case SQL_COLUMN_AUTO_INCREMENT:
+ case SQL_COLUMN_AUTO_INCREMENT: /* == SQL_DESC_AUTO_UNIQUE_VALUE */
value = pgtype_auto_increment(stmt, field_type);
if (value == -1) /* non-numeric becomes FALSE (ODBC Doc) */
value = FALSE;
break;
- case SQL_COLUMN_CASE_SENSITIVE:
+ case SQL_COLUMN_CASE_SENSITIVE: /* == SQL_DESC_CASE_SENSITIVE */
value = pgtype_case_sensitive(stmt, field_type);
break;
*
* case SQL_COLUMN_COUNT:
*/
- case SQL_COLUMN_DISPLAY_SIZE:
- value = (parse_ok) ? stmt->fi[icol]->display_size : pgtype_display_size(stmt, field_type, icol, unknown_sizes);
+ case SQL_COLUMN_DISPLAY_SIZE: /* == SQL_DESC_DISPLAY_SIZE */
+ 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;
- case SQL_COLUMN_LABEL:
- if (parse_ok && stmt->fi[icol]->alias[0] != '\0')
+ case SQL_COLUMN_LABEL: /* == SQL_DESC_LABEL */
+ if (fi && fi->alias[0] != '\0')
{
- p = stmt->fi[icol]->alias;
+ p = fi->alias;
mylog("PGAPI_ColAttr: COLUMN_LABEL = '%s'\n", p);
break;
}
/* otherwise same as column name -- FALL THROUGH!!! */
+#if (ODBCVER >= 0x0300)
+ case SQL_DESC_NAME:
+#else
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);
break;
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;
- case SQL_COLUMN_MONEY:
+ case SQL_COLUMN_MONEY: /* == SQL_DESC_FIXED_PREC_SCALE */
value = pgtype_money(stmt, field_type);
break;
+#if (ODBCVER >= 0x0300)
+ case SQL_DESC_NULLABLE:
+#else
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;
- case SQL_COLUMN_OWNER_NAME:
+ case SQL_COLUMN_OWNER_NAME: /* == SQL_DESC_SCHEMA_NAME */
p = "";
break;
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;
- case SQL_COLUMN_QUALIFIER_NAME:
+ case SQL_COLUMN_QUALIFIER_NAME: /* == SQL_DESC_CATALOG_NAME */
p = "";
break;
case SQL_COLUMN_SCALE:
- value = pgtype_scale(stmt, field_type, icol);
+ value = pgtype_scale(stmt, field_type, col_idx);
break;
- case SQL_COLUMN_SEARCHABLE:
+ case SQL_COLUMN_SEARCHABLE: /* SQL_DESC_SEARCHABLE */
value = pgtype_searchable(stmt, field_type);
break;
- case SQL_COLUMN_TABLE_NAME:
- p = (parse_ok && stmt->fi[icol]->ti) ? stmt->fi[icol]->ti->name : "";
+ case SQL_COLUMN_TABLE_NAME: /* == SQL_DESC_TABLE_NAME */
+ p = fi && (fi->ti) ? fi->ti->name : "";
mylog("PGAPI_ColAttr: TABLE_NAME = '%s'\n", p);
break;
- case SQL_COLUMN_TYPE:
+ case SQL_COLUMN_TYPE: /* == SQL_DESC_CONCISE_TYPE */
value = pgtype_to_sqltype(stmt, field_type);
break;
- case SQL_COLUMN_TYPE_NAME:
+ case SQL_COLUMN_TYPE_NAME: /* == SQL_DESC_TYPE_NAME */
p = pgtype_to_name(stmt, field_type);
break;
- case SQL_COLUMN_UNSIGNED:
+ case SQL_COLUMN_UNSIGNED: /* == SQL_DESC_UNSINGED */
value = pgtype_unsigned(stmt, field_type);
if (value == -1) /* non-numeric becomes TRUE (ODBC Doc) */
value = TRUE;
break;
- case SQL_COLUMN_UPDATABLE:
+ case SQL_COLUMN_UPDATABLE: /* == SQL_DESC_UPDATABLE */
/*
* Neither Access or Borland care about this.
mylog("PGAPI_ColAttr: UPDATEABLE = %d\n", value);
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;
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);
if (len >= cbDescMax)
return SQL_INVALID_HANDLE;
}
ci = &(SC_get_conn(stmt)->connInfo);
- res = stmt->result;
+ res = SC_get_Curres(stmt);
if (STMT_EXECUTING == stmt->status)
{
StatementClass *stmt = (StatementClass *) hstmt;
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)
{
SC_clear_error(stmt);
- if (!(res = stmt->result))
+ if (!(res = SC_get_Curres(stmt)))
{
stmt->errormsg = "Null statement result in PGAPI_Fetch.";
stmt->errornumber = STMT_SEQUENCE_ERROR;
SC_clear_error(stmt);
- if (!(res = stmt->result))
+ if (!(res = SC_get_Curres(stmt)))
{
stmt->errormsg = "Null statement result in PGAPI_ExtendedFetch.";
stmt->errornumber = STMT_SEQUENCE_ERROR;
PGAPI_MoreResults(
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;
}
}
sprintf(selstr, "%s oid = %u", selstr, oid),
mylog("selstr=%s\n", selstr);
- qres = CC_send_query(SC_get_conn(stmt), selstr, NULL);
- if (qres && QR_aborted(qres))
- {
- QR_Destructor(qres);
- qres = (QResultClass *) 0;
- }
+ qres = CC_send_query(SC_get_conn(stmt), selstr, NULL, TRUE);
return qres;
}
rcnt = 0;
if (count)
*count = 0;
- if (!(res = stmt->result))
+ if (!(res = SC_get_Curres(stmt)))
return SQL_ERROR;
if (!stmt->ti)
parse_statement(stmt); /* not preferable */
RETCODE ret = SQL_ERROR;
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;
if (!stmt->ti)
parse_statement(stmt); /* not preferable */
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
SC_pos_update(StatementClass *stmt,
UWORD irow)
UInt4 offset;
Int4 *used;
- mylog("POS UPDATE %d+%d fi=%x ti=%x\n", irow, stmt->result->base, stmt->fi, stmt->ti);
- if (!(res = stmt->result))
+ mylog("POS UPDATE %d+%d fi=%x ti=%x\n", irow, SC_get_Curres(stmt)->base, stmt->fi, stmt->ti);
+ if (!(res = SC_get_Curres(stmt)))
return SQL_ERROR;
if (!stmt->ti)
parse_statement(stmt); /* not preferable */
stmt->errormsg = "SetPos with data_at_exec not yet supported";
ret = SQL_ERROR;
}
- if (ret != SQL_ERROR)
- {
- 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";
- }
- }
+ ret = irow_update(ret, qstmt, irow);
PGAPI_FreeStmt(hstmt, SQL_DROP);
}
else
ret = SQL_SUCCESS_WITH_INFO;
+#if (ODBCVER >= 0x0300)
if (stmt->options.rowStatusArray)
{
switch (ret)
break;
}
}
+#endif /* ODBCVER */
return ret;
}
char *oidval;
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;
if (!stmt->ti)
parse_statement(stmt); /* not preferable */
}
sprintf(dltstr, "delete from \"%s\" where ctid = '%s' and oid = %s",
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);
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))
{
int dltcnt;
}
if (qres)
QR_Destructor(qres);
+#if (ODBCVER >= 0x0300)
if (stmt->options.rowStatusArray)
{
switch (ret)
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;
}
RETCODE SQL_API
Int4 *used;
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;
if (!stmt->ti)
parse_statement(stmt); /* not preferable */
mylog("addstr=%s\n", addstr);
qstmt->exec_start_row = qstmt->exec_end_row = irow;
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)
{
stmt->errornumber = qstmt->errornumber;
stmt->errormsg = qstmt->errormsg;
}
- else
+ else if (ret == SQL_NEED_DATA) /* must be fixed */
{
- int addcnt;
- UInt4 oid;
- const char *cmdstr = QR_get_command(qstmt->result);
-
- 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;
- }
+ 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;
}
+ ret = irow_insert(ret, qstmt, res->fcount);
}
else
ret = SQL_SUCCESS_WITH_INFO;
PGAPI_FreeStmt(hstmt, SQL_DROP);
+#if (ODBCVER >= 0x0300)
if (stmt->options.rowStatusArray)
{
switch (ret)
break;
}
}
+#endif /* ODBCVER */
+
return ret;
}
return SQL_ERROR;
}
- if (!(res = stmt->result))
+ if (!(res = SC_get_Curres(stmt)))
{
stmt->errormsg = "Null statement result in PGAPI_SetPos.";
stmt->errornumber = STMT_SEQUENCE_ERROR;
if (!hglbAttr)
return FALSE;
lpsetupdlg = (LPSETUPDLG) GlobalLock(hglbAttr);
-
/* Parse attribute string */
if (lpszAttributes)
ParseAttributes(lpszAttributes, lpsetupdlg);
int cbKey;
char value[MAXPGPATH];
- memset(&lpsetupdlg->ci, 0, sizeof(ConnInfo));
+ CC_conninfo_init(&(lpsetupdlg->ci));
for (lpsz = lpszAttributes; *lpsz; lpsz++)
{
}
/* Free any cursors and discard any result info */
- if (stmt->result)
+ if (SC_get_Result(stmt))
{
- QR_Destructor(stmt->result);
- stmt->result = NULL;
+ QR_Destructor(SC_get_Result(stmt));
+ SC_set_Result(stmt, NULL);
}
}
rv->hdbc = NULL; /* no connection associated yet */
rv->phstmt = NULL;
rv->result = NULL;
+ rv->curres = NULL;
rv->manual_result = FALSE;
rv->prepare = FALSE;
rv->status = STMT_ALLOCATED;
rv->errormsg = NULL;
rv->errornumber = 0;
rv->errormsg_created = FALSE;
- rv->errormsg_malloced = FALSE;
rv->statement = NULL;
rv->stmt_with_params = NULL;
char
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);
if (STMT_EXECUTING == self->status)
{
return FALSE;
}
- if (self->result)
+ if (res)
{
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)
SC_recycle_statement(StatementClass *self)
{
ConnectionClass *conn;
+ QResultClass *res;
mylog("recycle statement: self= %u\n", self);
self->parse_status = STMT_PARSE_NONE;
/* Free any cursors */
- if (self->result)
+ if (res = SC_get_Result(self), res)
{
- QR_Destructor(self->result);
- self->result = NULL;
+ QR_Destructor(res);
+ SC_set_Result(self, NULL);
}
self->inaccurate_result = FALSE;
self->bind_row = 0;
self->last_fetch_count = 0;
- if (self->errormsg_malloced && self->errormsg)
- free(self->errormsg);
self->errormsg = NULL;
self->errornumber = 0;
self->errormsg_created = FALSE;
- self->errormsg_malloced = FALSE;
self->lobj_fd = -1;
}
if (!SC_is_pre_executable(self))
{
- self->result = QR_Constructor();
- QR_set_status(self->result, PGRES_TUPLES_OK);
+ SC_set_Result(self, QR_Constructor());
+ QR_set_status(SC_get_Result(self), PGRES_TUPLES_OK);
self->inaccurate_result = TRUE;
self->status = STMT_PREMATURE;
}
void
SC_clear_error(StatementClass *self)
{
- if (self->errormsg_malloced && self->errormsg)
- free(self->errormsg);
self->errornumber = 0;
self->errormsg = NULL;
self->errormsg_created = FALSE;
- self->errormsg_malloced = FALSE;
+ self->errorpos = 0;
+ self->error_recsize = -1;
}
char *
SC_create_errormsg(StatementClass *self)
{
- QResultClass *res = self->result;
+ QResultClass *res = SC_get_Curres(self);
ConnectionClass *conn = self->hdbc;
int pos;
static char msg[4096];
if (res && res->message)
strcpy(msg, res->message);
-
else if (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)
{
SocketClass *sock = conn->sock;
if (conn->errormsg && conn->errormsg[0] != '\0')
{
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')
sprintf(&msg[pos], ";\n%s", sock->errormsg);
}
}
- if (!msg[0] && res && QR_get_notice(res))
- return QR_get_notice(res);
-
return msg;
}
{
self->errormsg = SC_create_errormsg(self);
self->errormsg_created = TRUE;
+ self->errorpos = 0;
+ self->error_recsize = -1;
}
if (self->errornumber)
{
*number = self->errornumber;
*message = self->errormsg;
- if (!self->errormsg_malloced)
- self->errormsg = NULL;
}
rv = (self->errornumber != 0);
- self->errornumber = 0;
return rv;
}
SC_fetch(StatementClass *self)
{
static char *func = "SC_fetch";
- QResultClass *res = self->result;
+ QResultClass *res = SC_get_Curres(self);
int retval,
result;
static char *func = "SC_execute";
ConnectionClass *conn;
char was_ok, was_nonfatal;
+ QResultClass *res = NULL;
Int2 oldstatus,
numcols;
QueryInfo qi;
mylog(" Sending SELECT statement on stmt=%u, cursor_name='%s'\n", self, self->cursor_name);
/* 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 &&
- QR_command_successful(self->result))
+ if (SC_is_fetchcursor(self) && res != NULL &&
+ QR_command_successful(res))
{
- QR_Destructor(self->result);
+ QR_Destructor(res);
/*
* That worked, so now send the fetch to start getting data
*/
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");
}
{
/* not a SELECT statement so don't use a cursor */
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
self->status = STMT_FINISHED;
/* Check the status of the result */
- if (self->result)
+ if (res)
{
- was_ok = QR_command_successful(self->result);
- was_nonfatal = QR_command_nonfatal(self->result);
+ was_ok = QR_command_successful(res);
+ was_nonfatal = QR_command_nonfatal(res);
if (was_ok)
self->errornumber = STMT_OK;
self->current_col = -1;
self->rowset_start = -1;
- /* see if the query did return any result columns */
- numcols = QR_NumResultCols(self->result);
-
- /* now allocate the array to hold the binding info */
- if (numcols > 0)
+ /* issue "ABORT" when query aborted */
+ if (QR_get_aborted(res))
{
- extend_bindings(self, numcols);
- if (self->bindings == NULL)
+ if (!self->internal)
+ 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;
- self->errormsg = "Could not get enough free memory to store the binding information";
- SC_log_error(func, "", self);
- return SQL_ERROR;
+ extend_bindings(self, numcols);
+ if (self->bindings == NULL)
+ {
+ 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
{
if (!self->internal)
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 &&
(self->errornumber == STMT_OK ||
return SQL_SUCCESS_WITH_INFO;
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);
return SQL_ERROR;
}
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
#define nullcheck(a) (a ? a : "(NULL)")
#endif
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));
mylog("STATEMENT ERROR: func=%s, desc='%s', errnum=%d, errmsg='%s'\n", func, desc, self->errornumber, nullcheck(self->errormsg));
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(" bindings=%u, bindings_allocated=%d\n", self->bindings, self->bindings_allocated);
qlog(" parameters=%u, parameters_allocated=%d\n", self->parameters, self->parameters_allocated);
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(" 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));
CC_log_error(func, desc, self->hdbc);
}
else
+ {
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
}
STMT_PARSE_NONE = 0,
STMT_PARSE_COMPLETE,
STMT_PARSE_INCOMPLETE,
- STMT_PARSE_FATAL
+ STMT_PARSE_FATAL,
};
/* Result style */
{
STMT_FETCH_NONE = 0,
STMT_FETCH_NORMAL,
- STMT_FETCH_EXTENDED
+ STMT_FETCH_EXTENDED,
};
typedef struct
ConnectionClass *hdbc; /* pointer to ConnectionClass this
* statement belongs to */
QResultClass *result; /* result of the current statement */
+ QResultClass *curres; /* the current result in the chain */
HSTMT FAR *phstmt;
StatementOptions options;
char pre_executing; /* This statement is prematurely executing */
char inaccurate_result; /* Current status is PREMATURE but
* result is inaccurate */
- char errormsg_malloced; /* Current error message is
- * malloed (not in a static
- * variable) ? */
char miscinfo;
+ SWORD errorpos;
+ SWORD error_recsize;
};
#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() */
#define STMT_FREE_PARAMS_ALL 0
RETCODE SC_execute(StatementClass *self);
RETCODE SC_fetch(StatementClass *self);
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);
#endif
!MESSAGE "Release" (Win32 Release DLL)
!MESSAGE "Debug" (Win32 Debug DLL)
!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
!ERROR An invalid configuration was specified.
!ENDIF
!IF "$(CFG)" == "MultibyteRelease"
OUTDIR=.\MultibyteRelease
+OUTDIRBIN=.\MultibyteRelease
INTDIR=.\MultibyteRelease
!ELSE
OUTDIR=.\Release
+OUTDIRBIN=.\Release
INTDIR=.\Release
!ENDIF
-ALL : "$(OUTDIR)\psqlodbc.dll"
+ALL : "$(OUTDIRBIN)\psqlodbc.dll"
CLEAN :
-@erase "$(INTDIR)\drvconn.obj"
-@erase "$(INTDIR)\environ.obj"
-@erase "$(INTDIR)\execute.obj"
- -@erase "$(INTDIR)\gpps.obj"
-@erase "$(INTDIR)\info.obj"
-@erase "$(INTDIR)\lobj.obj"
-@erase "$(INTDIR)\win_md5.obj"
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_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"
LINK32_OBJS= \
"$(INTDIR)\bind.obj" \
"$(INTDIR)\drvconn.obj" \
"$(INTDIR)\environ.obj" \
"$(INTDIR)\execute.obj" \
- "$(INTDIR)\gpps.obj" \
"$(INTDIR)\info.obj" \
"$(INTDIR)\lobj.obj" \
"$(INTDIR)\win_md5.obj" \
"$(INTDIR)\odbcapi.obj" \
"$(INTDIR)\psqlodbc.res"
-"$(OUTDIR)\psqlodbc.dll" : "$(OUTDIR)" $(DEF_FILE) $(LINK32_OBJS)
+"$(OUTDIRBIN)\psqlodbc.dll" : "$(OUTDIR)" $(DEF_FILE) $(LINK32_OBJS)
$(LINK32) @<<
$(LINK32_FLAGS) $(LINK32_OBJS)
<<
-@erase "$(INTDIR)\drvconn.obj"
-@erase "$(INTDIR)\environ.obj"
-@erase "$(INTDIR)\execute.obj"
- -@erase "$(INTDIR)\gpps.obj"
-@erase "$(INTDIR)\info.obj"
-@erase "$(INTDIR)\lobj.obj"
-@erase "$(INTDIR)\win_md5.obj"
"$(INTDIR)\drvconn.obj" \
"$(INTDIR)\environ.obj" \
"$(INTDIR)\execute.obj" \
- "$(INTDIR)\gpps.obj" \
"$(INTDIR)\info.obj" \
"$(INTDIR)\lobj.obj" \
"$(INTDIR)\win_md5.obj"
$(CPP) $(CPP_PROJ) $(SOURCE)
-SOURCE=gpps.c
-
-"$(INTDIR)\gpps.obj" : $(SOURCE) "$(INTDIR)"
- $(CPP) $(CPP_PROJ) $(SOURCE)
-
-
SOURCE=info.c
"$(INTDIR)\info.obj" : $(SOURCE) "$(INTDIR)"
-@erase "$(INTDIR)\tuplelist.obj"
-@erase "$(INTDIR)\odbcapi.obj"
-@erase "$(INTDIR)\odbcapi30.obj"
+ -@erase "$(INTDIR)\pgapi30.obj"
-@erase "$(INTDIR)\vc60.idb"
-@erase "$(OUTDIR)\psqlodbc30.dll"
-@erase "$(OUTDIR)\psqlodbc.exp"
"$(INTDIR)\tuplelist.obj" \
"$(INTDIR)\odbcapi.obj" \
"$(INTDIR)\odbcapi30.obj" \
+ "$(INTDIR)\pgapi30.obj" \
"$(INTDIR)\psqlodbc.res"
"$(OUTDIRBIN)\psqlodbc30.dll" : "$(OUTDIR)" $(DEF_FILE) $(LINK32_OBJS)
-@erase "$(INTDIR)\tuplelist.obj"
-@erase "$(INTDIR)\odbcapi.obj"
-@erase "$(INTDIR)\odbcapi30.obj"
+ -@erase "$(INTDIR)\pgapi30.obj"
-@erase "$(INTDIR)\vc60.idb"
-@erase "$(INTDIR)\vc60.pdb"
-@erase "$(OUTDIR)\psqlodbc30.dll"
"$(INTDIR)\tuplelist.obj" \
"$(INTDIR)\odbcapi.obj" \
"$(INTDIR)\odbcapi30.obj" \
+ "$(INTDIR)\pgapi30.obj" \
"$(INTDIR)\psqlodbc.res"
"$(OUTDIR)\psqlodbc30.dll" : "$(OUTDIR)" $(DEF_FILE) $(LINK32_OBJS)
"$(INTDIR)\odbcapi30.obj" : $(SOURCE) "$(INTDIR)"
$(CPP) $(CPP_PROJ) $(SOURCE)
+SOURCE=pgcapi30.c
+"$(INTDIR)\pgcapi30.obj" : $(SOURCE) "$(INTDIR)"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
!ENDIF
--- /dev/null
+#
+# 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
--- /dev/null
+#
+# 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
#define byte3_mask2 0x0fc0
#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 * utf8str;
if (!ucs2str)
return NULL;
if (ilen < 0)
- {
- for (ilen = 0; ucs2str[ilen]; ilen++)
- ;
- }
+ ilen = ucs2strlen(ucs2str);
/*mylog(" newlen=%d", ilen);*/
utf8str = (char *) malloc(ilen * 3 + 1);
if (utf8str)
{
int i, len = 0;
- Int2 byte2code;
- Int4 byte4code;
-
+ UInt2 byte2code;
+ Int4 byte4code;
const SQLWCHAR *wstr;
+
for (i = 0, wstr = ucs2str; i < ilen; i++, wstr++)
{
if (!*wstr)
break;
- else if (iswascii(*wstr))
+ else if (0 == (*wstr & 0xff80))
utf8str[len++] = (char) *wstr;
else if ((*wstr & byte3check) == 0)
{
}
}
utf8str[len] = '\0';
- *olen = len;
+ if (olen)
+ *olen = len;
}
/*mylog(" olen=%d %s\n", *olen, utf8str ? utf8str : "");*/
return utf8str;
{
wcode = ((((UInt4) *str) & byte3_m1) << 12) |
((((UInt4) str[1]) & byte3_m2) << 6) |
- ((UInt4) str[2]) & byte3_m3;
+ (((UInt4) str[2]) & byte3_m3);
ucs2str[ocount] = (SQLWCHAR) wcode;
}
ocount++;
if (ocount < bufcount)
{
wcode = ((((UInt4) *str) & byte2_m1) << 6) |
- ((UInt4) str[1]) & byte2_m2;
+ (((UInt4) str[1]) & byte2_m2);
ucs2str[ocount] = (SQLWCHAR) wcode;
}
ocount++;