1) Fix SQLForeignKeys() in multibyte mode.
2) Fix a bug with NUMERIC scale in case of Parse statement option. 3) Remove a no longer needed loop in CC_send_query(). Hiroshi Inoue
This commit is contained in:
parent
531126c854
commit
9abd055405
@ -14,6 +14,10 @@
|
||||
*/
|
||||
/* Multibyte support Eiji Tokuya 2001-03-15 */
|
||||
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <ctype.h>
|
||||
|
||||
#include "connection.h"
|
||||
|
||||
#include "environ.h"
|
||||
@ -27,9 +31,6 @@
|
||||
#include "multibyte.h"
|
||||
#endif
|
||||
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
|
||||
#ifdef WIN32
|
||||
#include <odbcinst.h>
|
||||
#endif
|
||||
@ -277,6 +278,10 @@ memcpy(&(rv->connInfo.drivers), &globals, sizeof(globals));
|
||||
rv->pg_version_number = .0;
|
||||
rv->pg_version_major = 0;
|
||||
rv->pg_version_minor = 0;
|
||||
#ifdef MULTIBYTE
|
||||
rv->client_encoding = NULL;
|
||||
rv->server_encoding = NULL;
|
||||
#endif /* MULTIBYTE */
|
||||
|
||||
|
||||
/* Initialize statement options to defaults */
|
||||
@ -302,6 +307,12 @@ CC_Destructor(ConnectionClass *self)
|
||||
|
||||
mylog("after CC_Cleanup\n");
|
||||
|
||||
#ifdef MULTIBYTE
|
||||
if (self->client_encoding)
|
||||
free(self->client_encoding);
|
||||
if (self->server_encoding)
|
||||
free(self->server_encoding);
|
||||
#endif /* MULTIBYTE */
|
||||
/* Free up statement holders */
|
||||
if (self->stmts)
|
||||
{
|
||||
@ -510,6 +521,9 @@ CC_connect(ConnectionClass *self, char do_password)
|
||||
char msgbuffer[ERROR_MSG_LENGTH];
|
||||
char salt[5];
|
||||
static char *func = "CC_connect";
|
||||
#ifdef MULTIBYTE
|
||||
char *encoding;
|
||||
#endif /* MULTIBYTE */
|
||||
|
||||
mylog("%s: entering...\n", func);
|
||||
|
||||
@ -537,7 +551,9 @@ CC_connect(ConnectionClass *self, char do_password)
|
||||
ci->drivers.bools_as_char);
|
||||
|
||||
#ifdef MULTIBYTE
|
||||
check_client_encoding(ci->drivers.conn_settings);
|
||||
encoding = check_client_encoding(ci->drivers.conn_settings);
|
||||
if (encoding && strcmp(encoding, "OTHER"))
|
||||
self->client_encoding = strdup(encoding);
|
||||
qlog(" extra_systable_prefixes='%s', conn_settings='%s' conn_encoding='%s'\n",
|
||||
ci->drivers.extra_systable_prefixes,
|
||||
ci->drivers.conn_settings,
|
||||
@ -1041,7 +1057,6 @@ CC_send_query(ConnectionClass *self, char *query, QueryInfo *qi)
|
||||
CC_set_no_trans(self);
|
||||
ReadyToReturn = TRUE;
|
||||
retres = NULL;
|
||||
break;
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -1059,6 +1074,7 @@ CC_send_query(ConnectionClass *self, char *query, QueryInfo *qi)
|
||||
QR_set_status(res, PGRES_COMMAND_OK);
|
||||
QR_set_command(res, cmdbuffer);
|
||||
query_completed = TRUE;
|
||||
mylog("send_query: returning res = %u\n", res);
|
||||
if (!before_64)
|
||||
break;
|
||||
/*
|
||||
@ -1069,71 +1085,14 @@ CC_send_query(ConnectionClass *self, char *query, QueryInfo *qi)
|
||||
* an 'I' is received
|
||||
*/
|
||||
|
||||
|
||||
if (empty_reqs == 0)
|
||||
{
|
||||
SOCK_put_string(sock, "Q ");
|
||||
SOCK_flush_output(sock);
|
||||
empty_reqs++;
|
||||
}
|
||||
break;
|
||||
|
||||
while (!clear)
|
||||
{
|
||||
id = SOCK_get_char(sock);
|
||||
mylog("got clear id = '%c'\n", id);
|
||||
switch (id)
|
||||
{
|
||||
case 'I':
|
||||
(void) SOCK_get_char(sock);
|
||||
clear = TRUE;
|
||||
break;
|
||||
case 'Z':
|
||||
break;
|
||||
case 'C':
|
||||
SOCK_get_string(sock, cmdbuffer, ERROR_MSG_LENGTH);
|
||||
qlog("Command response: '%s'\n", cmdbuffer);
|
||||
break;
|
||||
case 'N':
|
||||
msg_truncated = SOCK_get_string(sock, cmdbuffer, ERROR_MSG_LENGTH);
|
||||
if (QR_command_successful(res))
|
||||
QR_set_status(res, PGRES_NONFATAL_ERROR);
|
||||
QR_set_notice(res, cmdbuffer); /* will dup this string */
|
||||
qlog("NOTICE from backend during clear: '%s'\n", cmdbuffer);
|
||||
while (msg_truncated)
|
||||
msg_truncated = SOCK_get_string(sock, cmdbuffer, ERROR_MSG_LENGTH);
|
||||
break;
|
||||
case 'E':
|
||||
msg_truncated = SOCK_get_string(sock, msgbuffer, ERROR_MSG_LENGTH);
|
||||
mylog("ERROR from backend during clear: '%s'\n", msgbuffer);
|
||||
qlog("ERROR from backend during clear: '%s'\n", msgbuffer);
|
||||
|
||||
/*
|
||||
* We must report this type of error as
|
||||
* well (practically for reference
|
||||
* integrity violation error reporting,
|
||||
* from PostgreSQL 7.0). (Zoltan Kovacs,
|
||||
* 04/26/2000)
|
||||
*/
|
||||
self->errormsg = msgbuffer;
|
||||
if (!strncmp(self->errormsg, "FATAL", 5))
|
||||
{
|
||||
self->errornumber = CONNECTION_SERVER_REPORTED_ERROR;
|
||||
CC_set_no_trans(self);
|
||||
}
|
||||
else
|
||||
self->errornumber = CONNECTION_SERVER_REPORTED_WARNING;
|
||||
QR_set_status(res, PGRES_FATAL_ERROR);
|
||||
QR_set_aborted(res, TRUE);
|
||||
while (msg_truncated)
|
||||
msg_truncated = SOCK_get_string(sock, cmdbuffer, ERROR_MSG_LENGTH);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
mylog("send_query: returning res = %u\n", res);
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case 'Z': /* Backend is ready for new query (6.4) */
|
||||
if (empty_reqs == 0)
|
||||
{
|
||||
|
@ -274,6 +274,10 @@ struct ConnectionClass_
|
||||
float pg_version_number;
|
||||
Int2 pg_version_major;
|
||||
Int2 pg_version_minor;
|
||||
#ifdef MULTIBYTE
|
||||
char *client_encoding;
|
||||
char *server_encoding;
|
||||
#endif /* MULTIBYTE */
|
||||
};
|
||||
|
||||
|
||||
|
@ -2666,6 +2666,180 @@ PGAPI_PrimaryKeys(
|
||||
}
|
||||
|
||||
|
||||
#ifdef MULTIBYTE
|
||||
/*
|
||||
* Multibyte support stuff for SQLForeignKeys().
|
||||
* There may be much more effective way in the
|
||||
* future version. The way is very forcive currently.
|
||||
*/
|
||||
static BOOL isMultibyte(const unsigned char *str)
|
||||
{
|
||||
for (; *str; str++)
|
||||
{
|
||||
if (*str >= 0x80)
|
||||
return TRUE;
|
||||
}
|
||||
return FALSE;
|
||||
}
|
||||
static char *getClientTableName(ConnectionClass *conn, char *serverTableName, BOOL *nameAlloced)
|
||||
{
|
||||
char query[1024], saveoid[24], *ret = serverTableName;
|
||||
BOOL continueExec = TRUE, bError = FALSE;
|
||||
QResultClass *res;
|
||||
|
||||
*nameAlloced = FALSE;
|
||||
if (!conn->client_encoding || !isMultibyte(serverTableName))
|
||||
return ret;
|
||||
if (!conn->server_encoding)
|
||||
{
|
||||
if (res = CC_send_query(conn, "select getdatabaseencoding()", NULL), res)
|
||||
{
|
||||
if (QR_get_num_tuples(res) > 0)
|
||||
conn->server_encoding = strdup(QR_get_value_backend_row(res, 0, 0));
|
||||
QR_Destructor(res);
|
||||
}
|
||||
}
|
||||
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;
|
||||
if (!bError && continueExec)
|
||||
{
|
||||
sprintf(query, "select OID from pg_class where relname = '%s'", serverTableName);
|
||||
if (res = CC_send_query(conn, query, NULL), 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
|
||||
bError = TRUE;
|
||||
}
|
||||
continueExec = (continueExec && !bError);
|
||||
if (bError && CC_is_in_trans(conn))
|
||||
{
|
||||
if (res = CC_send_query(conn, "abort", NULL), res)
|
||||
QR_Destructor(res);
|
||||
CC_set_no_trans(conn);
|
||||
bError = FALSE;
|
||||
}
|
||||
/* 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;
|
||||
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 (QR_get_num_tuples(res) > 0)
|
||||
{
|
||||
ret = strdup(QR_get_value_backend_row(res, 0, 0));
|
||||
*nameAlloced = TRUE;
|
||||
}
|
||||
QR_Destructor(res);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
static char *getClientColumnName(ConnectionClass *conn, const char *serverTableName, char *serverColumnName, BOOL *nameAlloced)
|
||||
{
|
||||
char query[1024], saveattrelid[24], saveattnum[16], *ret = serverColumnName;
|
||||
BOOL continueExec = TRUE, bError = FALSE;
|
||||
QResultClass *res;
|
||||
|
||||
*nameAlloced = FALSE;
|
||||
if (!conn->client_encoding || !isMultibyte(serverColumnName))
|
||||
return ret;
|
||||
if (!conn->server_encoding)
|
||||
{
|
||||
if (res = CC_send_query(conn, "select getdatabaseencoding()", NULL), res)
|
||||
{
|
||||
if (QR_get_num_tuples(res) > 0)
|
||||
conn->server_encoding = strdup(QR_get_value_backend_row(res, 0, 0));
|
||||
QR_Destructor(res);
|
||||
}
|
||||
}
|
||||
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;
|
||||
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 (QR_get_num_tuples(res) > 0)
|
||||
{
|
||||
strcpy(saveattrelid, QR_get_value_backend_row(res, 0, 0));
|
||||
strcpy(saveattnum, QR_get_value_backend_row(res, 0, 1));
|
||||
}
|
||||
else
|
||||
{
|
||||
continueExec = FALSE;
|
||||
bError = QR_get_aborted(res);
|
||||
}
|
||||
QR_Destructor(res);
|
||||
}
|
||||
else
|
||||
bError = TRUE;
|
||||
}
|
||||
continueExec = (continueExec && !bError);
|
||||
if (bError && CC_is_in_trans(conn))
|
||||
{
|
||||
if (res = CC_send_query(conn, "abort", NULL), res)
|
||||
QR_Destructor(res);
|
||||
CC_set_no_trans(conn);
|
||||
bError = FALSE;
|
||||
}
|
||||
/* 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;
|
||||
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 (QR_get_num_tuples(res) > 0)
|
||||
{
|
||||
ret = strdup(QR_get_value_backend_row(res, 0, 0));
|
||||
*nameAlloced = TRUE;
|
||||
}
|
||||
QR_Destructor(res);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
#endif /* MULTIBYTE */
|
||||
|
||||
RETCODE SQL_API
|
||||
PGAPI_ForeignKeys(
|
||||
HSTMT hstmt,
|
||||
@ -2698,10 +2872,14 @@ PGAPI_ForeignKeys(
|
||||
del_rule[MAX_TABLE_LEN];
|
||||
char pk_table_needed[MAX_TABLE_LEN + 1];
|
||||
char fk_table_needed[MAX_TABLE_LEN + 1];
|
||||
char *pkey_ptr,
|
||||
*fkey_ptr,
|
||||
*pk_table,
|
||||
*fk_table;
|
||||
char *pkey_ptr, *pkey_text,
|
||||
*fkey_ptr, *fkey_text,
|
||||
*pk_table, *pkt_text,
|
||||
*fk_table, *fkt_text;
|
||||
#ifdef MULTIBYTE
|
||||
BOOL pkey_alloced, fkey_alloced, pkt_alloced, fkt_alloced;
|
||||
ConnectionClass *conn;
|
||||
#endif /* MULTIBYTE */
|
||||
int i,
|
||||
j,
|
||||
k,
|
||||
@ -2795,6 +2973,10 @@ PGAPI_ForeignKeys(
|
||||
make_string(szPkTableName, cbPkTableName, pk_table_needed);
|
||||
make_string(szFkTableName, cbFkTableName, fk_table_needed);
|
||||
|
||||
#ifdef MULTIBYTE
|
||||
pkey_alloced = fkey_alloced = pkt_alloced = fkt_alloced = FALSE;
|
||||
conn = SC_get_conn(stmt);
|
||||
#endif /* MULTIBYTE */
|
||||
/*
|
||||
* Case #2 -- Get the foreign keys in the specified table (fktab) that
|
||||
* refer to the primary keys of other table(s).
|
||||
@ -2954,18 +3136,24 @@ PGAPI_ForeignKeys(
|
||||
for (k = 0; k < 2; k++)
|
||||
pk_table += strlen(pk_table) + 1;
|
||||
|
||||
#ifdef MULTIBYTE
|
||||
fk_table = trig_args + strlen(trig_args) + 1;
|
||||
pkt_text = getClientTableName(conn, pk_table, &pkt_alloced);
|
||||
#else
|
||||
pkt_text = pk_table;
|
||||
#endif /* MULTIBYTE */
|
||||
/* If there is a pk table specified, then check it. */
|
||||
if (pk_table_needed[0] != '\0')
|
||||
{
|
||||
/* If it doesn't match, then continue */
|
||||
if (strcmp(pk_table, pk_table_needed))
|
||||
if (strcmp(pkt_text, pk_table_needed))
|
||||
{
|
||||
result = PGAPI_Fetch(htbl_stmt);
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
keyresult = PGAPI_PrimaryKeys(hpkey_stmt, NULL, 0, NULL, 0, pk_table, SQL_NTS);
|
||||
keyresult = PGAPI_PrimaryKeys(hpkey_stmt, NULL, 0, NULL, 0, pkt_text, SQL_NTS);
|
||||
if (keyresult != SQL_SUCCESS)
|
||||
{
|
||||
stmt->errornumber = STMT_NO_MEMORY_ERROR;
|
||||
@ -2975,8 +3163,6 @@ PGAPI_ForeignKeys(
|
||||
return SQL_ERROR;
|
||||
}
|
||||
|
||||
/* Check that the key listed is the primary key */
|
||||
keyresult = PGAPI_Fetch(hpkey_stmt);
|
||||
|
||||
/* Get to first primary key */
|
||||
pkey_ptr = trig_args;
|
||||
@ -2985,17 +3171,32 @@ PGAPI_ForeignKeys(
|
||||
|
||||
for (k = 0; k < num_keys; k++)
|
||||
{
|
||||
mylog("%s: pkey_ptr='%s', pkey='%s'\n", func, pkey_ptr, pkey);
|
||||
if (keyresult != SQL_SUCCESS || strcmp(pkey_ptr, pkey))
|
||||
/* Check that the key listed is the primary key */
|
||||
keyresult = PGAPI_Fetch(hpkey_stmt);
|
||||
if (keyresult != SQL_SUCCESS)
|
||||
{
|
||||
num_keys = 0;
|
||||
break;
|
||||
}
|
||||
#ifdef MULTIBYTE
|
||||
pkey_text = getClientColumnName(conn, pk_table, pkey_ptr, &pkey_alloced);
|
||||
#else
|
||||
pkey_text = pkey_ptr;
|
||||
#endif /* MULTIBYTE */
|
||||
mylog("%s: pkey_ptr='%s', pkey='%s'\n", func, pkey_text, pkey);
|
||||
if (strcmp(pkey_text, pkey))
|
||||
{
|
||||
num_keys = 0;
|
||||
break;
|
||||
}
|
||||
#ifdef MULTIBYTE
|
||||
if (pkey_alloced)
|
||||
free(pkey_text);
|
||||
#endif /* MULTIBYTE */
|
||||
/* Get to next primary key */
|
||||
for (k = 0; k < 2; k++)
|
||||
pkey_ptr += strlen(pkey_ptr) + 1;
|
||||
|
||||
keyresult = PGAPI_Fetch(hpkey_stmt);
|
||||
}
|
||||
|
||||
/* Set to first fk column */
|
||||
@ -3045,17 +3246,24 @@ PGAPI_ForeignKeys(
|
||||
{
|
||||
row = (TupleNode *) malloc(sizeof(TupleNode) + (result_cols - 1) *sizeof(TupleField));
|
||||
|
||||
mylog("%s: pk_table = '%s', pkey_ptr = '%s'\n", func, pk_table, pkey_ptr);
|
||||
#ifdef MULTIBYTE
|
||||
pkey_text = getClientColumnName(conn, pk_table, pkey_ptr, &pkey_alloced);
|
||||
fkey_text = getClientColumnName(conn, fk_table, fkey_ptr, &fkey_alloced);
|
||||
#else
|
||||
pkey_text = pkey_ptr;
|
||||
fkey_text = fkey_ptr;
|
||||
#endif /* MULTIBYTE */
|
||||
mylog("%s: pk_table = '%s', pkey_ptr = '%s'\n", func, pkt_text, pkey_text);
|
||||
set_tuplefield_null(&row->tuple[0]);
|
||||
set_tuplefield_string(&row->tuple[1], "");
|
||||
set_tuplefield_string(&row->tuple[2], pk_table);
|
||||
set_tuplefield_string(&row->tuple[3], pkey_ptr);
|
||||
set_tuplefield_string(&row->tuple[2], pkt_text);
|
||||
set_tuplefield_string(&row->tuple[3], pkey_text);
|
||||
|
||||
mylog("%s: fk_table_needed = '%s', fkey_ptr = '%s'\n", func, fk_table_needed, fkey_ptr);
|
||||
mylog("%s: fk_table_needed = '%s', fkey_ptr = '%s'\n", func, fk_table_needed, fkey_text);
|
||||
set_tuplefield_null(&row->tuple[4]);
|
||||
set_tuplefield_string(&row->tuple[5], "");
|
||||
set_tuplefield_string(&row->tuple[6], fk_table_needed);
|
||||
set_tuplefield_string(&row->tuple[7], fkey_ptr);
|
||||
set_tuplefield_string(&row->tuple[7], fkey_text);
|
||||
|
||||
mylog("%s: upd_rule_type = '%i', del_rule_type = '%i'\n, trig_name = '%s'", func, upd_rule_type, del_rule_type, trig_args);
|
||||
set_tuplefield_int2(&row->tuple[8], (Int2) (k + 1));
|
||||
@ -3069,7 +3277,14 @@ PGAPI_ForeignKeys(
|
||||
#endif /* ODBCVER >= 0x0300 */
|
||||
|
||||
QR_add_tuple(stmt->result, row);
|
||||
|
||||
#ifdef MULTIBYTE
|
||||
if (fkey_alloced)
|
||||
free(fkey_text);
|
||||
fkey_alloced = FALSE;
|
||||
if (pkey_alloced)
|
||||
free(pkey_text);
|
||||
pkey_alloced = FALSE;
|
||||
#endif /* MULTIBYTE */
|
||||
/* next primary/foreign key */
|
||||
for (i = 0; i < 2; i++)
|
||||
{
|
||||
@ -3077,6 +3292,11 @@ PGAPI_ForeignKeys(
|
||||
pkey_ptr += strlen(pkey_ptr) + 1;
|
||||
}
|
||||
}
|
||||
#ifdef MULTIBYTE
|
||||
if (pkt_alloced)
|
||||
free(pkt_text);
|
||||
pkt_alloced = FALSE;
|
||||
#endif /* MULTIBYTE */
|
||||
|
||||
result = PGAPI_Fetch(htbl_stmt);
|
||||
}
|
||||
@ -3257,6 +3477,12 @@ PGAPI_ForeignKeys(
|
||||
/* Get to first foreign table */
|
||||
fk_table = trig_args;
|
||||
fk_table += strlen(fk_table) + 1;
|
||||
#ifdef MULTIBYTE
|
||||
pk_table = fk_table + strlen(fk_table) + 1;
|
||||
fkt_text = getClientTableName(conn, fk_table, &fkt_alloced);
|
||||
#else
|
||||
fkt_text = fk_table;
|
||||
#endif /* MULTIBYTE */
|
||||
|
||||
/* Get to first foreign key */
|
||||
fkey_ptr = trig_args;
|
||||
@ -3265,21 +3491,28 @@ PGAPI_ForeignKeys(
|
||||
|
||||
for (k = 0; k < num_keys; k++)
|
||||
{
|
||||
mylog("pkey_ptr = '%s', fk_table = '%s', fkey_ptr = '%s'\n", pkey_ptr, fk_table, fkey_ptr);
|
||||
#ifdef MULTIBYTE
|
||||
pkey_text = getClientColumnName(conn, pk_table, pkey_ptr, &pkey_alloced);
|
||||
fkey_text = getClientColumnName(conn, fk_table, fkey_ptr, &fkey_alloced);
|
||||
#else
|
||||
pkey_text = pkey_ptr;
|
||||
fkey_text = fkey_ptr;
|
||||
#endif /* MULTIBYTE */
|
||||
mylog("pkey_ptr = '%s', fk_table = '%s', fkey_ptr = '%s'\n", pkey_text, fkt_text, fkey_text);
|
||||
|
||||
row = (TupleNode *) malloc(sizeof(TupleNode) + (result_cols - 1) *sizeof(TupleField));
|
||||
|
||||
mylog("pk_table_needed = '%s', pkey_ptr = '%s'\n", pk_table_needed, pkey_ptr);
|
||||
mylog("pk_table_needed = '%s', pkey_ptr = '%s'\n", pk_table_needed, pkey_text);
|
||||
set_tuplefield_null(&row->tuple[0]);
|
||||
set_tuplefield_string(&row->tuple[1], "");
|
||||
set_tuplefield_string(&row->tuple[2], pk_table_needed);
|
||||
set_tuplefield_string(&row->tuple[3], pkey_ptr);
|
||||
set_tuplefield_string(&row->tuple[3], pkey_text);
|
||||
|
||||
mylog("fk_table = '%s', fkey_ptr = '%s'\n", fk_table, fkey_ptr);
|
||||
mylog("fk_table = '%s', fkey_ptr = '%s'\n", fkt_text, fkey_text);
|
||||
set_tuplefield_null(&row->tuple[4]);
|
||||
set_tuplefield_string(&row->tuple[5], "");
|
||||
set_tuplefield_string(&row->tuple[6], fk_table);
|
||||
set_tuplefield_string(&row->tuple[7], fkey_ptr);
|
||||
set_tuplefield_string(&row->tuple[6], fkt_text);
|
||||
set_tuplefield_string(&row->tuple[7], fkey_text);
|
||||
|
||||
set_tuplefield_int2(&row->tuple[8], (Int2) (k + 1));
|
||||
|
||||
@ -3298,6 +3531,14 @@ PGAPI_ForeignKeys(
|
||||
#endif /* ODBCVER >= 0x0300 */
|
||||
|
||||
QR_add_tuple(stmt->result, row);
|
||||
#ifdef MULTIBYTE
|
||||
if (pkey_alloced)
|
||||
free(pkey_text);
|
||||
pkey_alloced = FALSE;
|
||||
if (fkey_alloced)
|
||||
free(fkey_text);
|
||||
fkey_alloced = FALSE;
|
||||
#endif /* MULTIBYTE */
|
||||
|
||||
/* next primary/foreign key */
|
||||
for (j = 0; j < 2; j++)
|
||||
@ -3306,6 +3547,11 @@ PGAPI_ForeignKeys(
|
||||
fkey_ptr += strlen(fkey_ptr) + 1;
|
||||
}
|
||||
}
|
||||
#ifdef MULTIBYTE
|
||||
if (fkt_alloced)
|
||||
free(fkt_text);
|
||||
fkt_alloced = FALSE;
|
||||
#endif /* MULTIBYTE */
|
||||
result = PGAPI_Fetch(htbl_stmt);
|
||||
}
|
||||
}
|
||||
@ -3317,6 +3563,16 @@ PGAPI_ForeignKeys(
|
||||
PGAPI_FreeStmt(htbl_stmt, SQL_DROP);
|
||||
return SQL_ERROR;
|
||||
}
|
||||
#ifdef MULTIBYTE
|
||||
if (pkt_alloced)
|
||||
free(pkt_text);
|
||||
if (pkey_alloced)
|
||||
free(pkey_text);
|
||||
if (fkt_alloced)
|
||||
free(fkt_text);
|
||||
if (fkey_alloced)
|
||||
free(fkey_text);
|
||||
#endif /* MULTIBYTE */
|
||||
|
||||
PGAPI_FreeStmt(htbl_stmt, SQL_DROP);
|
||||
|
||||
|
@ -227,12 +227,17 @@ QR_set_field_info(stmt->result, 13, "FIELD_TYPE", PG_TYPE_INT4, 4);
|
||||
void
|
||||
getColInfo(COL_INFO *col_info, FIELD_INFO *fi, int k)
|
||||
{
|
||||
char *str;
|
||||
if (fi->name[0] == '\0')
|
||||
strcpy(fi->name, QR_get_value_manual(col_info->result, k, 3));
|
||||
|
||||
fi->type = atoi(QR_get_value_manual(col_info->result, k, 13));
|
||||
fi->precision = atoi(QR_get_value_manual(col_info->result, k, 6));
|
||||
fi->length = atoi(QR_get_value_manual(col_info->result, k, 7));
|
||||
if (str = QR_get_value_manual(col_info->result, k, 8), str)
|
||||
fi->scale = atoi(str);
|
||||
else
|
||||
fi->scale = -1;
|
||||
fi->nullable = atoi(QR_get_value_manual(col_info->result, k, 10));
|
||||
fi->display_size = atoi(QR_get_value_manual(col_info->result, k, 12));
|
||||
}
|
||||
|
@ -199,7 +199,7 @@ PGAPI_DescribeCol(
|
||||
QResultClass *res;
|
||||
char *col_name = NULL;
|
||||
Int4 fieldtype = 0;
|
||||
int precision = 0;
|
||||
int precision = 0, scale = 0;
|
||||
ConnInfo *ci;
|
||||
char parse_ok;
|
||||
char buf[255];
|
||||
@ -250,6 +250,7 @@ PGAPI_DescribeCol(
|
||||
fieldtype = stmt->fi[icol]->type;
|
||||
col_name = stmt->fi[icol]->name;
|
||||
precision = stmt->fi[icol]->precision;
|
||||
scale = stmt->fi[icol]->scale;
|
||||
|
||||
mylog("PARSE: fieldtype=%d, col_name='%s', precision=%d\n", fieldtype, col_name, precision);
|
||||
if (fieldtype > 0)
|
||||
@ -292,6 +293,7 @@ PGAPI_DescribeCol(
|
||||
|
||||
/* atoi(ci->unknown_sizes) */
|
||||
precision = pgtype_precision(stmt, fieldtype, icol, ci->drivers.unknown_sizes);
|
||||
scale = pgtype_scale(stmt, fieldtype, icol);
|
||||
}
|
||||
|
||||
mylog("describeCol: col %d fieldname = '%s'\n", icol, col_name);
|
||||
@ -348,10 +350,7 @@ PGAPI_DescribeCol(
|
||||
*/
|
||||
if (pibScale)
|
||||
{
|
||||
Int2 scale;
|
||||
|
||||
scale = pgtype_scale(stmt, fieldtype, icol);
|
||||
if (scale == -1)
|
||||
if (scale < 0)
|
||||
scale = 0;
|
||||
|
||||
*pibScale = scale;
|
||||
|
@ -131,6 +131,7 @@ typedef struct
|
||||
{
|
||||
TABLE_INFO *ti; /* resolve to explicit table names */
|
||||
int precision;
|
||||
int scale;
|
||||
int display_size;
|
||||
int length;
|
||||
int type;
|
||||
|
Loading…
x
Reference in New Issue
Block a user