mirror of
https://github.com/postgres/postgres.git
synced 2025-07-28 23:42:10 +03:00
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:
@ -14,6 +14,10 @@
|
|||||||
*/
|
*/
|
||||||
/* Multibyte support Eiji Tokuya 2001-03-15 */
|
/* Multibyte support Eiji Tokuya 2001-03-15 */
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <ctype.h>
|
||||||
|
|
||||||
#include "connection.h"
|
#include "connection.h"
|
||||||
|
|
||||||
#include "environ.h"
|
#include "environ.h"
|
||||||
@ -27,9 +31,6 @@
|
|||||||
#include "multibyte.h"
|
#include "multibyte.h"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#include <stdio.h>
|
|
||||||
#include <string.h>
|
|
||||||
|
|
||||||
#ifdef WIN32
|
#ifdef WIN32
|
||||||
#include <odbcinst.h>
|
#include <odbcinst.h>
|
||||||
#endif
|
#endif
|
||||||
@ -277,6 +278,10 @@ memcpy(&(rv->connInfo.drivers), &globals, sizeof(globals));
|
|||||||
rv->pg_version_number = .0;
|
rv->pg_version_number = .0;
|
||||||
rv->pg_version_major = 0;
|
rv->pg_version_major = 0;
|
||||||
rv->pg_version_minor = 0;
|
rv->pg_version_minor = 0;
|
||||||
|
#ifdef MULTIBYTE
|
||||||
|
rv->client_encoding = NULL;
|
||||||
|
rv->server_encoding = NULL;
|
||||||
|
#endif /* MULTIBYTE */
|
||||||
|
|
||||||
|
|
||||||
/* Initialize statement options to defaults */
|
/* Initialize statement options to defaults */
|
||||||
@ -302,6 +307,12 @@ CC_Destructor(ConnectionClass *self)
|
|||||||
|
|
||||||
mylog("after CC_Cleanup\n");
|
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 */
|
/* Free up statement holders */
|
||||||
if (self->stmts)
|
if (self->stmts)
|
||||||
{
|
{
|
||||||
@ -510,6 +521,9 @@ CC_connect(ConnectionClass *self, char do_password)
|
|||||||
char msgbuffer[ERROR_MSG_LENGTH];
|
char msgbuffer[ERROR_MSG_LENGTH];
|
||||||
char salt[5];
|
char salt[5];
|
||||||
static char *func = "CC_connect";
|
static char *func = "CC_connect";
|
||||||
|
#ifdef MULTIBYTE
|
||||||
|
char *encoding;
|
||||||
|
#endif /* MULTIBYTE */
|
||||||
|
|
||||||
mylog("%s: entering...\n", func);
|
mylog("%s: entering...\n", func);
|
||||||
|
|
||||||
@ -537,7 +551,9 @@ CC_connect(ConnectionClass *self, char do_password)
|
|||||||
ci->drivers.bools_as_char);
|
ci->drivers.bools_as_char);
|
||||||
|
|
||||||
#ifdef MULTIBYTE
|
#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",
|
qlog(" extra_systable_prefixes='%s', conn_settings='%s' conn_encoding='%s'\n",
|
||||||
ci->drivers.extra_systable_prefixes,
|
ci->drivers.extra_systable_prefixes,
|
||||||
ci->drivers.conn_settings,
|
ci->drivers.conn_settings,
|
||||||
@ -1041,7 +1057,6 @@ CC_send_query(ConnectionClass *self, char *query, QueryInfo *qi)
|
|||||||
CC_set_no_trans(self);
|
CC_set_no_trans(self);
|
||||||
ReadyToReturn = TRUE;
|
ReadyToReturn = TRUE;
|
||||||
retres = NULL;
|
retres = NULL;
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@ -1059,6 +1074,7 @@ CC_send_query(ConnectionClass *self, char *query, QueryInfo *qi)
|
|||||||
QR_set_status(res, PGRES_COMMAND_OK);
|
QR_set_status(res, PGRES_COMMAND_OK);
|
||||||
QR_set_command(res, cmdbuffer);
|
QR_set_command(res, cmdbuffer);
|
||||||
query_completed = TRUE;
|
query_completed = TRUE;
|
||||||
|
mylog("send_query: returning res = %u\n", res);
|
||||||
if (!before_64)
|
if (!before_64)
|
||||||
break;
|
break;
|
||||||
/*
|
/*
|
||||||
@ -1069,71 +1085,14 @@ CC_send_query(ConnectionClass *self, char *query, QueryInfo *qi)
|
|||||||
* an 'I' is received
|
* an 'I' is received
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
|
||||||
if (empty_reqs == 0)
|
if (empty_reqs == 0)
|
||||||
{
|
{
|
||||||
SOCK_put_string(sock, "Q ");
|
SOCK_put_string(sock, "Q ");
|
||||||
SOCK_flush_output(sock);
|
SOCK_flush_output(sock);
|
||||||
empty_reqs++;
|
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) */
|
case 'Z': /* Backend is ready for new query (6.4) */
|
||||||
if (empty_reqs == 0)
|
if (empty_reqs == 0)
|
||||||
{
|
{
|
||||||
|
@ -274,6 +274,10 @@ struct ConnectionClass_
|
|||||||
float pg_version_number;
|
float pg_version_number;
|
||||||
Int2 pg_version_major;
|
Int2 pg_version_major;
|
||||||
Int2 pg_version_minor;
|
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
|
RETCODE SQL_API
|
||||||
PGAPI_ForeignKeys(
|
PGAPI_ForeignKeys(
|
||||||
HSTMT hstmt,
|
HSTMT hstmt,
|
||||||
@ -2698,10 +2872,14 @@ PGAPI_ForeignKeys(
|
|||||||
del_rule[MAX_TABLE_LEN];
|
del_rule[MAX_TABLE_LEN];
|
||||||
char pk_table_needed[MAX_TABLE_LEN + 1];
|
char pk_table_needed[MAX_TABLE_LEN + 1];
|
||||||
char fk_table_needed[MAX_TABLE_LEN + 1];
|
char fk_table_needed[MAX_TABLE_LEN + 1];
|
||||||
char *pkey_ptr,
|
char *pkey_ptr, *pkey_text,
|
||||||
*fkey_ptr,
|
*fkey_ptr, *fkey_text,
|
||||||
*pk_table,
|
*pk_table, *pkt_text,
|
||||||
*fk_table;
|
*fk_table, *fkt_text;
|
||||||
|
#ifdef MULTIBYTE
|
||||||
|
BOOL pkey_alloced, fkey_alloced, pkt_alloced, fkt_alloced;
|
||||||
|
ConnectionClass *conn;
|
||||||
|
#endif /* MULTIBYTE */
|
||||||
int i,
|
int i,
|
||||||
j,
|
j,
|
||||||
k,
|
k,
|
||||||
@ -2795,6 +2973,10 @@ PGAPI_ForeignKeys(
|
|||||||
make_string(szPkTableName, cbPkTableName, pk_table_needed);
|
make_string(szPkTableName, cbPkTableName, pk_table_needed);
|
||||||
make_string(szFkTableName, cbFkTableName, fk_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
|
* Case #2 -- Get the foreign keys in the specified table (fktab) that
|
||||||
* refer to the primary keys of other table(s).
|
* refer to the primary keys of other table(s).
|
||||||
@ -2954,18 +3136,24 @@ PGAPI_ForeignKeys(
|
|||||||
for (k = 0; k < 2; k++)
|
for (k = 0; k < 2; k++)
|
||||||
pk_table += strlen(pk_table) + 1;
|
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 there is a pk table specified, then check it. */
|
||||||
if (pk_table_needed[0] != '\0')
|
if (pk_table_needed[0] != '\0')
|
||||||
{
|
{
|
||||||
/* If it doesn't match, then continue */
|
/* 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);
|
result = PGAPI_Fetch(htbl_stmt);
|
||||||
continue;
|
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)
|
if (keyresult != SQL_SUCCESS)
|
||||||
{
|
{
|
||||||
stmt->errornumber = STMT_NO_MEMORY_ERROR;
|
stmt->errornumber = STMT_NO_MEMORY_ERROR;
|
||||||
@ -2975,8 +3163,6 @@ PGAPI_ForeignKeys(
|
|||||||
return SQL_ERROR;
|
return SQL_ERROR;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Check that the key listed is the primary key */
|
|
||||||
keyresult = PGAPI_Fetch(hpkey_stmt);
|
|
||||||
|
|
||||||
/* Get to first primary key */
|
/* Get to first primary key */
|
||||||
pkey_ptr = trig_args;
|
pkey_ptr = trig_args;
|
||||||
@ -2985,17 +3171,32 @@ PGAPI_ForeignKeys(
|
|||||||
|
|
||||||
for (k = 0; k < num_keys; k++)
|
for (k = 0; k < num_keys; k++)
|
||||||
{
|
{
|
||||||
mylog("%s: pkey_ptr='%s', pkey='%s'\n", func, pkey_ptr, pkey);
|
/* Check that the key listed is the primary key */
|
||||||
if (keyresult != SQL_SUCCESS || strcmp(pkey_ptr, pkey))
|
keyresult = PGAPI_Fetch(hpkey_stmt);
|
||||||
|
if (keyresult != SQL_SUCCESS)
|
||||||
{
|
{
|
||||||
num_keys = 0;
|
num_keys = 0;
|
||||||
break;
|
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 */
|
/* Get to next primary key */
|
||||||
for (k = 0; k < 2; k++)
|
for (k = 0; k < 2; k++)
|
||||||
pkey_ptr += strlen(pkey_ptr) + 1;
|
pkey_ptr += strlen(pkey_ptr) + 1;
|
||||||
|
|
||||||
keyresult = PGAPI_Fetch(hpkey_stmt);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Set to first fk column */
|
/* Set to first fk column */
|
||||||
@ -3045,17 +3246,24 @@ PGAPI_ForeignKeys(
|
|||||||
{
|
{
|
||||||
row = (TupleNode *) malloc(sizeof(TupleNode) + (result_cols - 1) *sizeof(TupleField));
|
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_null(&row->tuple[0]);
|
||||||
set_tuplefield_string(&row->tuple[1], "");
|
set_tuplefield_string(&row->tuple[1], "");
|
||||||
set_tuplefield_string(&row->tuple[2], pk_table);
|
set_tuplefield_string(&row->tuple[2], pkt_text);
|
||||||
set_tuplefield_string(&row->tuple[3], pkey_ptr);
|
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_null(&row->tuple[4]);
|
||||||
set_tuplefield_string(&row->tuple[5], "");
|
set_tuplefield_string(&row->tuple[5], "");
|
||||||
set_tuplefield_string(&row->tuple[6], fk_table_needed);
|
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);
|
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));
|
set_tuplefield_int2(&row->tuple[8], (Int2) (k + 1));
|
||||||
@ -3069,7 +3277,14 @@ PGAPI_ForeignKeys(
|
|||||||
#endif /* ODBCVER >= 0x0300 */
|
#endif /* ODBCVER >= 0x0300 */
|
||||||
|
|
||||||
QR_add_tuple(stmt->result, row);
|
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 */
|
/* next primary/foreign key */
|
||||||
for (i = 0; i < 2; i++)
|
for (i = 0; i < 2; i++)
|
||||||
{
|
{
|
||||||
@ -3077,6 +3292,11 @@ PGAPI_ForeignKeys(
|
|||||||
pkey_ptr += strlen(pkey_ptr) + 1;
|
pkey_ptr += strlen(pkey_ptr) + 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
#ifdef MULTIBYTE
|
||||||
|
if (pkt_alloced)
|
||||||
|
free(pkt_text);
|
||||||
|
pkt_alloced = FALSE;
|
||||||
|
#endif /* MULTIBYTE */
|
||||||
|
|
||||||
result = PGAPI_Fetch(htbl_stmt);
|
result = PGAPI_Fetch(htbl_stmt);
|
||||||
}
|
}
|
||||||
@ -3257,6 +3477,12 @@ PGAPI_ForeignKeys(
|
|||||||
/* Get to first foreign table */
|
/* Get to first foreign table */
|
||||||
fk_table = trig_args;
|
fk_table = trig_args;
|
||||||
fk_table += strlen(fk_table) + 1;
|
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 */
|
/* Get to first foreign key */
|
||||||
fkey_ptr = trig_args;
|
fkey_ptr = trig_args;
|
||||||
@ -3265,21 +3491,28 @@ PGAPI_ForeignKeys(
|
|||||||
|
|
||||||
for (k = 0; k < num_keys; k++)
|
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));
|
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_null(&row->tuple[0]);
|
||||||
set_tuplefield_string(&row->tuple[1], "");
|
set_tuplefield_string(&row->tuple[1], "");
|
||||||
set_tuplefield_string(&row->tuple[2], pk_table_needed);
|
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_null(&row->tuple[4]);
|
||||||
set_tuplefield_string(&row->tuple[5], "");
|
set_tuplefield_string(&row->tuple[5], "");
|
||||||
set_tuplefield_string(&row->tuple[6], fk_table);
|
set_tuplefield_string(&row->tuple[6], fkt_text);
|
||||||
set_tuplefield_string(&row->tuple[7], fkey_ptr);
|
set_tuplefield_string(&row->tuple[7], fkey_text);
|
||||||
|
|
||||||
set_tuplefield_int2(&row->tuple[8], (Int2) (k + 1));
|
set_tuplefield_int2(&row->tuple[8], (Int2) (k + 1));
|
||||||
|
|
||||||
@ -3298,6 +3531,14 @@ PGAPI_ForeignKeys(
|
|||||||
#endif /* ODBCVER >= 0x0300 */
|
#endif /* ODBCVER >= 0x0300 */
|
||||||
|
|
||||||
QR_add_tuple(stmt->result, row);
|
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 */
|
/* next primary/foreign key */
|
||||||
for (j = 0; j < 2; j++)
|
for (j = 0; j < 2; j++)
|
||||||
@ -3306,6 +3547,11 @@ PGAPI_ForeignKeys(
|
|||||||
fkey_ptr += strlen(fkey_ptr) + 1;
|
fkey_ptr += strlen(fkey_ptr) + 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
#ifdef MULTIBYTE
|
||||||
|
if (fkt_alloced)
|
||||||
|
free(fkt_text);
|
||||||
|
fkt_alloced = FALSE;
|
||||||
|
#endif /* MULTIBYTE */
|
||||||
result = PGAPI_Fetch(htbl_stmt);
|
result = PGAPI_Fetch(htbl_stmt);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -3317,6 +3563,16 @@ PGAPI_ForeignKeys(
|
|||||||
PGAPI_FreeStmt(htbl_stmt, SQL_DROP);
|
PGAPI_FreeStmt(htbl_stmt, SQL_DROP);
|
||||||
return SQL_ERROR;
|
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);
|
PGAPI_FreeStmt(htbl_stmt, SQL_DROP);
|
||||||
|
|
||||||
|
@ -227,12 +227,17 @@ QR_set_field_info(stmt->result, 13, "FIELD_TYPE", PG_TYPE_INT4, 4);
|
|||||||
void
|
void
|
||||||
getColInfo(COL_INFO *col_info, FIELD_INFO *fi, int k)
|
getColInfo(COL_INFO *col_info, FIELD_INFO *fi, int k)
|
||||||
{
|
{
|
||||||
|
char *str;
|
||||||
if (fi->name[0] == '\0')
|
if (fi->name[0] == '\0')
|
||||||
strcpy(fi->name, QR_get_value_manual(col_info->result, k, 3));
|
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->type = atoi(QR_get_value_manual(col_info->result, k, 13));
|
||||||
fi->precision = atoi(QR_get_value_manual(col_info->result, k, 6));
|
fi->precision = atoi(QR_get_value_manual(col_info->result, k, 6));
|
||||||
fi->length = atoi(QR_get_value_manual(col_info->result, k, 7));
|
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->nullable = atoi(QR_get_value_manual(col_info->result, k, 10));
|
||||||
fi->display_size = atoi(QR_get_value_manual(col_info->result, k, 12));
|
fi->display_size = atoi(QR_get_value_manual(col_info->result, k, 12));
|
||||||
}
|
}
|
||||||
|
@ -199,7 +199,7 @@ PGAPI_DescribeCol(
|
|||||||
QResultClass *res;
|
QResultClass *res;
|
||||||
char *col_name = NULL;
|
char *col_name = NULL;
|
||||||
Int4 fieldtype = 0;
|
Int4 fieldtype = 0;
|
||||||
int precision = 0;
|
int precision = 0, scale = 0;
|
||||||
ConnInfo *ci;
|
ConnInfo *ci;
|
||||||
char parse_ok;
|
char parse_ok;
|
||||||
char buf[255];
|
char buf[255];
|
||||||
@ -250,6 +250,7 @@ PGAPI_DescribeCol(
|
|||||||
fieldtype = stmt->fi[icol]->type;
|
fieldtype = stmt->fi[icol]->type;
|
||||||
col_name = stmt->fi[icol]->name;
|
col_name = stmt->fi[icol]->name;
|
||||||
precision = stmt->fi[icol]->precision;
|
precision = stmt->fi[icol]->precision;
|
||||||
|
scale = stmt->fi[icol]->scale;
|
||||||
|
|
||||||
mylog("PARSE: fieldtype=%d, col_name='%s', precision=%d\n", fieldtype, col_name, precision);
|
mylog("PARSE: fieldtype=%d, col_name='%s', precision=%d\n", fieldtype, col_name, precision);
|
||||||
if (fieldtype > 0)
|
if (fieldtype > 0)
|
||||||
@ -292,6 +293,7 @@ PGAPI_DescribeCol(
|
|||||||
|
|
||||||
/* atoi(ci->unknown_sizes) */
|
/* atoi(ci->unknown_sizes) */
|
||||||
precision = pgtype_precision(stmt, fieldtype, icol, ci->drivers.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);
|
mylog("describeCol: col %d fieldname = '%s'\n", icol, col_name);
|
||||||
@ -348,10 +350,7 @@ PGAPI_DescribeCol(
|
|||||||
*/
|
*/
|
||||||
if (pibScale)
|
if (pibScale)
|
||||||
{
|
{
|
||||||
Int2 scale;
|
if (scale < 0)
|
||||||
|
|
||||||
scale = pgtype_scale(stmt, fieldtype, icol);
|
|
||||||
if (scale == -1)
|
|
||||||
scale = 0;
|
scale = 0;
|
||||||
|
|
||||||
*pibScale = scale;
|
*pibScale = scale;
|
||||||
|
@ -131,6 +131,7 @@ typedef struct
|
|||||||
{
|
{
|
||||||
TABLE_INFO *ti; /* resolve to explicit table names */
|
TABLE_INFO *ti; /* resolve to explicit table names */
|
||||||
int precision;
|
int precision;
|
||||||
|
int scale;
|
||||||
int display_size;
|
int display_size;
|
||||||
int length;
|
int length;
|
||||||
int type;
|
int type;
|
||||||
|
Reference in New Issue
Block a user