Location via proxy:   [ UP ]  
[Report a bug]   [Manage cookies]                
Skip to content

Commit 0b96c6f

Browse files
author
Thomas G. Lockhart
committed
Change form of query which used "DISTINCT ON" to help support primary keys.
We still have an internal limit in the ODBC code of 8 columns per key, but this should lay the groundwork for resolving that. Includes reformulated query from Tom Lane.
1 parent 8d7dc6f commit 0b96c6f

File tree

2 files changed

+83
-28
lines changed

2 files changed

+83
-28
lines changed

src/interfaces/odbc/convert.c

Lines changed: 36 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -110,16 +110,16 @@ int
110110
copy_and_convert_field(StatementClass *stmt, Int4 field_type, void *value, Int2 fCType,
111111
PTR rgbValue, SDWORD cbValueMax, SDWORD *pcbValue)
112112
{
113-
Int4 len = 0, copy_len = 0;
114-
SIMPLE_TIME st;
115-
time_t t = time(NULL);
116-
struct tm *tim;
117-
int pcbValueOffset, rgbValueOffset;
118-
char *rgbValueBindRow, *ptr;
119-
int bind_row = stmt->bind_row;
120-
int bind_size = stmt->options.bind_size;
121-
int result = COPY_OK;
122-
char tempBuf[TEXT_FIELD_SIZE+5];
113+
Int4 len = 0, copy_len = 0;
114+
SIMPLE_TIME st;
115+
time_t t = time(NULL);
116+
struct tm *tim;
117+
int pcbValueOffset, rgbValueOffset;
118+
char *rgbValueBindRow, *ptr;
119+
int bind_row = stmt->bind_row;
120+
int bind_size = stmt->options.bind_size;
121+
int result = COPY_OK;
122+
char tempBuf[TEXT_FIELD_SIZE+5];
123123

124124
/* rgbValueOffset is *ONLY* for character and binary data */
125125
/* pcbValueOffset is for computing any pcbValue location */
@@ -211,11 +211,35 @@ char tempBuf[TEXT_FIELD_SIZE+5];
211211

212212
/* This is for internal use by SQLStatistics() */
213213
case PG_TYPE_INT2VECTOR: {
214+
int nval, i;
215+
char *vp;
214216
// this is an array of eight integers
215217
short *short_array = (short *) ( (char *) rgbValue + rgbValueOffset);
216218

217219
len = 16;
220+
vp = value;
221+
nval = 0;
222+
for (i = 0; i < 8; i++)
223+
{
224+
if (sscanf(vp, "%hd", &short_array[i]) != 1)
225+
break;
226+
227+
nval++;
228+
229+
/* skip the current token */
230+
while ((*vp != '\0') && (! isspace(*vp))) vp++;
231+
/* and skip the space to the next token */
232+
while ((*vp != '\0') && (isspace(*vp))) vp++;
233+
if (*vp == '\0')
234+
break;
235+
}
218236

237+
for (i = nval; i < 8; i++)
238+
{
239+
short_array[i] = 0;
240+
}
241+
242+
#if 0
219243
sscanf(value, "%hd %hd %hd %hd %hd %hd %hd %hd",
220244
&short_array[0],
221245
&short_array[1],
@@ -225,13 +249,14 @@ char tempBuf[TEXT_FIELD_SIZE+5];
225249
&short_array[5],
226250
&short_array[6],
227251
&short_array[7]);
252+
#endif
228253

229254
/* There is no corresponding fCType for this. */
230255
if(pcbValue)
231256
*(SDWORD *) ((char *) pcbValue + pcbValueOffset) = len;
232257

233258
return COPY_OK; /* dont go any further or the data will be trashed */
234-
}
259+
}
235260

236261
/* This is a large object OID, which is used to store LONGVARBINARY objects. */
237262
case PG_TYPE_LO:

src/interfaces/odbc/info.c

Lines changed: 47 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -1201,10 +1201,12 @@ ConnInfo *ci;
12011201
// **********************************************************************
12021202
// Create the query to find out the columns (Note: pre 6.3 did not have the atttypmod field)
12031203
// **********************************************************************
1204-
sprintf(columns_query, "select u.usename, c.relname, a.attname, a.atttypid,t.typname, a.attnum, a.attlen, %s, a.attnotnull, c.relhasrules "
1205-
"from pg_user u, pg_class c, pg_attribute a, pg_type t where "
1206-
"int4out(u.usesysid) = int4out(c.relowner) and c.oid= a.attrelid and a.atttypid = t.oid and (a.attnum > 0)",
1207-
PROTOCOL_62(ci) ? "a.attlen" : "a.atttypmod");
1204+
sprintf(columns_query, "select u.usename, c.relname, a.attname, a.atttypid"
1205+
", t.typname, a.attnum, a.attlen, %s, a.attnotnull, c.relhasrules"
1206+
" from pg_user u, pg_class c, pg_attribute a, pg_type t"
1207+
" where u.usesysid = c.relowner"
1208+
" and c.oid= a.attrelid and a.atttypid = t.oid and (a.attnum > 0)",
1209+
PROTOCOL_62(ci) ? "a.attlen" : "a.atttypmod");
12081210

12091211
my_strcat(columns_query, " and c.relname like '%.*s'", szTableName, cbTableName);
12101212
my_strcat(columns_query, " and u.usename like '%.*s'", szTableOwner, cbTableOwner);
@@ -1593,7 +1595,7 @@ mylog("%s: entering...stmt=%u\n", func, stmt);
15931595
// **********************************************************************
15941596
sprintf(columns_query, "select c.relhasrules "
15951597
"from pg_user u, pg_class c where "
1596-
"int4out(u.usesysid) = int4out(c.relowner) ");
1598+
"u.usesysid = c.relowner");
15971599

15981600
my_strcat(columns_query, " and c.relname like '%.*s'", szTableName, cbTableName);
15991601
my_strcat(columns_query, " and u.usename like '%.*s'", szTableOwner, cbTableOwner);
@@ -1848,8 +1850,11 @@ mylog("%s: entering...stmt=%u\n", func, stmt);
18481850
}
18491851
indx_stmt = (StatementClass *) hindx_stmt;
18501852

1851-
sprintf(index_query, "select c.relname, i.indkey, i.indisunique, i.indisclustered, c.relhasrules from pg_index i, pg_class c, pg_class d where c.oid = i.indexrelid and d.relname = '%s' and d.oid = i.indrelid",
1852-
table_name);
1853+
sprintf(index_query, "select c.relname, i.indkey, i.indisunique"
1854+
", i.indisclustered, c.relhasrules"
1855+
" from pg_index i, pg_class c, pg_class d"
1856+
" where c.oid = i.indexrelid and d.relname = '%s'"
1857+
" and d.oid = i.indrelid", table_name);
18531858

18541859
result = SQLExecDirect(hindx_stmt, index_query, strlen(index_query));
18551860
if((result != SQL_SUCCESS) && (result != SQL_SUCCESS_WITH_INFO)) {
@@ -2061,7 +2066,9 @@ static char *func="SQLColumnPrivileges";
20612066
}
20622067

20632068

2064-
2069+
/* SQLPrimaryKeys()
2070+
* Retrieve the primary key columns for the specified table.
2071+
*/
20652072
RETCODE SQL_API SQLPrimaryKeys(
20662073
HSTMT hstmt,
20672074
UCHAR FAR * szTableQualifier,
@@ -2135,7 +2142,23 @@ Int2 result_cols;
21352142
return SQL_ERROR;
21362143
}
21372144

2145+
#if 0
21382146
sprintf(tables_query, "select distinct on (attnum) a2.attname, a2.attnum from pg_attribute a1, pg_attribute a2, pg_class c, pg_index i where c.relname = '%s_pkey' AND c.oid = i.indexrelid AND a1.attrelid = c.oid AND a2.attrelid = c.oid AND (i.indkey[0] = a1.attnum OR i.indkey[1] = a1.attnum OR i.indkey[2] = a1.attnum OR i.indkey[3] = a1.attnum OR i.indkey[4] = a1.attnum OR i.indkey[5] = a1.attnum OR i.indkey[6] = a1.attnum OR i.indkey[7] = a1.attnum) order by a2.attnum", pktab);
2147+
#else
2148+
/* Simplified query to remove assumptions about
2149+
* number of possible index columns.
2150+
* Courtesy of Tom Lane - thomas 2000-03-21
2151+
*/
2152+
sprintf(tables_query, "select ta.attname, ia.attnum"
2153+
" from pg_attribute ta, pg_attribute ia, pg_class c, pg_index i"
2154+
" where c.relname = '%s_pkey'"
2155+
" AND c.oid = i.indexrelid"
2156+
" AND ia.attrelid = i.indexrelid"
2157+
" AND ta.attrelid = i.indrelid"
2158+
" AND ta.attnum = i.indkey[ia.attnum-1]"
2159+
" order by ia.attnum", pktab);
2160+
#endif
2161+
21392162

21402163
mylog("SQLPrimaryKeys: tables_query='%s'\n", tables_query);
21412164

@@ -2166,11 +2189,11 @@ Int2 result_cols;
21662189

21672190
set_tuplefield_null(&row->tuple[0]);
21682191

2169-
// I have to hide the table owner from Access, otherwise it
2170-
// insists on referring to the table as 'owner.table'.
2171-
// (this is valid according to the ODBC SQL grammar, but
2172-
// Postgres won't support it.)
2173-
2192+
/* I have to hide the table owner from Access, otherwise it
2193+
* insists on referring to the table as 'owner.table'.
2194+
* (this is valid according to the ODBC SQL grammar, but
2195+
* Postgres won't support it.)
2196+
*/
21742197
set_tuplefield_string(&row->tuple[1], "");
21752198
set_tuplefield_string(&row->tuple[2], pktab);
21762199
set_tuplefield_string(&row->tuple[3], attname);
@@ -2312,8 +2335,11 @@ Int2 result_cols;
23122335
*/
23132336
if (fktab[0] != '\0') {
23142337

2315-
sprintf(tables_query, "select pg_trigger.tgargs, pg_trigger.tgnargs, pg_trigger.tgname from pg_proc, pg_trigger, pg_class where pg_proc.oid = pg_trigger.tgfoid and pg_trigger.tgrelid = pg_class.oid AND pg_proc.proname = 'check_primary_key' AND pg_class.relname = '%s'",
2316-
fktab);
2338+
sprintf(tables_query, "select pg_trigger.tgargs, pg_trigger.tgnargs, pg_trigger.tgname"
2339+
" from pg_proc, pg_trigger, pg_class"
2340+
" where pg_proc.oid = pg_trigger.tgfoid and pg_trigger.tgrelid = pg_class.oid"
2341+
" AND pg_proc.proname = 'check_primary_key' AND pg_class.relname = '%s'",
2342+
fktab);
23172343

23182344
result = SQLExecDirect(htbl_stmt, tables_query, strlen(tables_query));
23192345
if((result != SQL_SUCCESS) && (result != SQL_SUCCESS_WITH_INFO)) {
@@ -2487,8 +2513,12 @@ Int2 result_cols;
24872513
*/
24882514
else if (pktab[0] != '\0') {
24892515

2490-
sprintf(tables_query, "select pg_trigger.tgargs, pg_trigger.tgnargs, pg_trigger.tgtype, pg_trigger.tgname from pg_proc, pg_trigger, pg_class where pg_proc.oid = pg_trigger.tgfoid and pg_trigger.tgrelid = pg_class.oid AND pg_proc.proname = 'check_foreign_key' AND pg_class.relname = '%s'",
2491-
pktab);
2516+
sprintf(tables_query, "select pg_trigger.tgargs, pg_trigger.tgnargs"
2517+
", pg_trigger.tgtype, pg_trigger.tgname"
2518+
" from pg_proc, pg_trigger, pg_class"
2519+
" where pg_proc.oid = pg_trigger.tgfoid and pg_trigger.tgrelid = pg_class.oid"
2520+
" AND pg_proc.proname = 'check_foreign_key' AND pg_class.relname = '%s'",
2521+
pktab);
24922522

24932523
result = SQLExecDirect(htbl_stmt, tables_query, strlen(tables_query));
24942524
if((result != SQL_SUCCESS) && (result != SQL_SUCCESS_WITH_INFO)) {

0 commit comments

Comments
 (0)