mirror of
				https://github.com/postgres/postgres.git
				synced 2025-11-03 09:13:20 +03:00 
			
		
		
		
	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.
This commit is contained in:
		@@ -211,11 +211,35 @@ char tempBuf[TEXT_FIELD_SIZE+5];
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
	/* This is for internal use by SQLStatistics() */
 | 
						/* This is for internal use by SQLStatistics() */
 | 
				
			||||||
	case PG_TYPE_INT2VECTOR: {
 | 
						case PG_TYPE_INT2VECTOR: {
 | 
				
			||||||
 | 
							int nval, i;
 | 
				
			||||||
 | 
							char *vp;
 | 
				
			||||||
		// this is an array of eight integers
 | 
							// this is an array of eight integers
 | 
				
			||||||
		short *short_array = (short *) ( (char *) rgbValue + rgbValueOffset);
 | 
							short *short_array = (short *) ( (char *) rgbValue + rgbValueOffset);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		len = 16;
 | 
							len = 16;
 | 
				
			||||||
 | 
							vp = value;
 | 
				
			||||||
 | 
							nval = 0;
 | 
				
			||||||
 | 
							for (i = 0; i < 8; i++)
 | 
				
			||||||
 | 
							{
 | 
				
			||||||
 | 
								if (sscanf(vp, "%hd", &short_array[i]) != 1)
 | 
				
			||||||
 | 
									break;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								nval++;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								/* skip the current token */
 | 
				
			||||||
 | 
								while ((*vp != '\0') && (! isspace(*vp))) vp++;
 | 
				
			||||||
 | 
								/* and skip the space to the next token */
 | 
				
			||||||
 | 
								while ((*vp != '\0') && (isspace(*vp))) vp++;
 | 
				
			||||||
 | 
								if (*vp == '\0')
 | 
				
			||||||
 | 
									break;
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							for (i = nval; i < 8; i++)
 | 
				
			||||||
 | 
							{
 | 
				
			||||||
 | 
								short_array[i] = 0;
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#if 0
 | 
				
			||||||
		sscanf(value, "%hd %hd %hd %hd %hd %hd %hd %hd",
 | 
							sscanf(value, "%hd %hd %hd %hd %hd %hd %hd %hd",
 | 
				
			||||||
			&short_array[0],
 | 
								&short_array[0],
 | 
				
			||||||
			&short_array[1],
 | 
								&short_array[1],
 | 
				
			||||||
@@ -225,6 +249,7 @@ char tempBuf[TEXT_FIELD_SIZE+5];
 | 
				
			|||||||
			&short_array[5],
 | 
								&short_array[5],
 | 
				
			||||||
			&short_array[6],
 | 
								&short_array[6],
 | 
				
			||||||
			&short_array[7]);
 | 
								&short_array[7]);
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		/*  There is no corresponding fCType for this. */
 | 
							/*  There is no corresponding fCType for this. */
 | 
				
			||||||
		if(pcbValue)
 | 
							if(pcbValue)
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -1201,9 +1201,11 @@ ConnInfo *ci;
 | 
				
			|||||||
	// **********************************************************************
 | 
						// **********************************************************************
 | 
				
			||||||
	//	Create the query to find out the columns (Note: pre 6.3 did not have the atttypmod field)
 | 
						//	Create the query to find out the columns (Note: pre 6.3 did not have the atttypmod field)
 | 
				
			||||||
	// **********************************************************************
 | 
						// **********************************************************************
 | 
				
			||||||
	sprintf(columns_query, "select u.usename, c.relname, a.attname, a.atttypid,t.typname, a.attnum, a.attlen, %s, a.attnotnull, c.relhasrules "
 | 
						sprintf(columns_query, "select u.usename, c.relname, a.attname, a.atttypid"
 | 
				
			||||||
		"from pg_user u, pg_class c, pg_attribute a, pg_type t where "
 | 
								", t.typname, a.attnum, a.attlen, %s, a.attnotnull, c.relhasrules"
 | 
				
			||||||
		"int4out(u.usesysid) = int4out(c.relowner) and c.oid= a.attrelid and a.atttypid = t.oid and (a.attnum > 0)",
 | 
								" from pg_user u, pg_class c, pg_attribute a, pg_type t"
 | 
				
			||||||
 | 
								" where u.usesysid = c.relowner"
 | 
				
			||||||
 | 
								" and c.oid= a.attrelid and a.atttypid = t.oid and (a.attnum > 0)",
 | 
				
			||||||
			PROTOCOL_62(ci) ? "a.attlen" : "a.atttypmod");
 | 
								PROTOCOL_62(ci) ? "a.attlen" : "a.atttypmod");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	my_strcat(columns_query, " and c.relname like '%.*s'", szTableName, cbTableName);
 | 
						my_strcat(columns_query, " and c.relname like '%.*s'", szTableName, cbTableName);
 | 
				
			||||||
@@ -1593,7 +1595,7 @@ mylog("%s: entering...stmt=%u\n", func, stmt);
 | 
				
			|||||||
	// **********************************************************************
 | 
						// **********************************************************************
 | 
				
			||||||
	sprintf(columns_query, "select c.relhasrules "
 | 
						sprintf(columns_query, "select c.relhasrules "
 | 
				
			||||||
		"from pg_user u, pg_class c where "
 | 
							"from pg_user u, pg_class c where "
 | 
				
			||||||
		"int4out(u.usesysid) = int4out(c.relowner) ");
 | 
							"u.usesysid = c.relowner");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	my_strcat(columns_query, " and c.relname like '%.*s'", szTableName, cbTableName);
 | 
						my_strcat(columns_query, " and c.relname like '%.*s'", szTableName, cbTableName);
 | 
				
			||||||
	my_strcat(columns_query, " and u.usename like '%.*s'", szTableOwner, cbTableOwner);
 | 
						my_strcat(columns_query, " and u.usename like '%.*s'", szTableOwner, cbTableOwner);
 | 
				
			||||||
@@ -1848,8 +1850,11 @@ mylog("%s: entering...stmt=%u\n", func, stmt);
 | 
				
			|||||||
    }
 | 
					    }
 | 
				
			||||||
	indx_stmt = (StatementClass *) hindx_stmt;
 | 
						indx_stmt = (StatementClass *) hindx_stmt;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	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", 
 | 
						sprintf(index_query, "select c.relname, i.indkey, i.indisunique"
 | 
				
			||||||
		table_name);
 | 
								", 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", table_name);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    result = SQLExecDirect(hindx_stmt, index_query, strlen(index_query));
 | 
					    result = SQLExecDirect(hindx_stmt, index_query, strlen(index_query));
 | 
				
			||||||
    if((result != SQL_SUCCESS) && (result != SQL_SUCCESS_WITH_INFO)) {
 | 
					    if((result != SQL_SUCCESS) && (result != SQL_SUCCESS_WITH_INFO)) {
 | 
				
			||||||
@@ -2061,7 +2066,9 @@ static char *func="SQLColumnPrivileges";
 | 
				
			|||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/* SQLPrimaryKeys()
 | 
				
			||||||
 | 
					 * Retrieve the primary key columns for the specified table.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
RETCODE SQL_API SQLPrimaryKeys(
 | 
					RETCODE SQL_API SQLPrimaryKeys(
 | 
				
			||||||
                               HSTMT         hstmt,
 | 
					                               HSTMT         hstmt,
 | 
				
			||||||
                               UCHAR FAR *   szTableQualifier,
 | 
					                               UCHAR FAR *   szTableQualifier,
 | 
				
			||||||
@@ -2135,7 +2142,23 @@ Int2 result_cols;
 | 
				
			|||||||
		return SQL_ERROR;
 | 
							return SQL_ERROR;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#if 0
 | 
				
			||||||
	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);
 | 
						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);
 | 
				
			||||||
 | 
					#else
 | 
				
			||||||
 | 
						/* Simplified query to remove assumptions about
 | 
				
			||||||
 | 
						 * number of possible index columns.
 | 
				
			||||||
 | 
						 * Courtesy of Tom Lane - thomas 2000-03-21
 | 
				
			||||||
 | 
						 */
 | 
				
			||||||
 | 
						sprintf(tables_query, "select ta.attname, ia.attnum"
 | 
				
			||||||
 | 
								" from pg_attribute ta, pg_attribute ia, pg_class c, pg_index i"
 | 
				
			||||||
 | 
								" where c.relname = '%s_pkey'"
 | 
				
			||||||
 | 
								" AND c.oid = i.indexrelid"
 | 
				
			||||||
 | 
								" AND ia.attrelid = i.indexrelid"
 | 
				
			||||||
 | 
								" AND ta.attrelid = i.indrelid"
 | 
				
			||||||
 | 
								" AND ta.attnum = i.indkey[ia.attnum-1]"
 | 
				
			||||||
 | 
								" order by ia.attnum", pktab);
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	mylog("SQLPrimaryKeys: tables_query='%s'\n", tables_query);
 | 
						mylog("SQLPrimaryKeys: tables_query='%s'\n", tables_query);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -2166,11 +2189,11 @@ Int2 result_cols;
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
        set_tuplefield_null(&row->tuple[0]);
 | 
					        set_tuplefield_null(&row->tuple[0]);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        // I have to hide the table owner from Access, otherwise it
 | 
							/* I have to hide the table owner from Access, otherwise it
 | 
				
			||||||
        // insists on referring to the table as 'owner.table'.
 | 
							 * insists on referring to the table as 'owner.table'.
 | 
				
			||||||
        // (this is valid according to the ODBC SQL grammar, but
 | 
							 * (this is valid according to the ODBC SQL grammar, but
 | 
				
			||||||
        // Postgres won't support it.)
 | 
							 * Postgres won't support it.)
 | 
				
			||||||
 | 
							 */
 | 
				
			||||||
        set_tuplefield_string(&row->tuple[1], "");
 | 
					        set_tuplefield_string(&row->tuple[1], "");
 | 
				
			||||||
        set_tuplefield_string(&row->tuple[2], pktab);
 | 
					        set_tuplefield_string(&row->tuple[2], pktab);
 | 
				
			||||||
        set_tuplefield_string(&row->tuple[3], attname);
 | 
					        set_tuplefield_string(&row->tuple[3], attname);
 | 
				
			||||||
@@ -2312,7 +2335,10 @@ Int2 result_cols;
 | 
				
			|||||||
	*/
 | 
						*/
 | 
				
			||||||
	if (fktab[0] != '\0') {
 | 
						if (fktab[0] != '\0') {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		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'",
 | 
							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'",
 | 
				
			||||||
				fktab);
 | 
									fktab);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		result = SQLExecDirect(htbl_stmt, tables_query, strlen(tables_query));
 | 
							result = SQLExecDirect(htbl_stmt, tables_query, strlen(tables_query));
 | 
				
			||||||
@@ -2487,7 +2513,11 @@ Int2 result_cols;
 | 
				
			|||||||
	*/
 | 
						*/
 | 
				
			||||||
    else if (pktab[0] != '\0') {
 | 
					    else if (pktab[0] != '\0') {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		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'",
 | 
							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'",
 | 
				
			||||||
				pktab);
 | 
									pktab);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		result = SQLExecDirect(htbl_stmt, tables_query, strlen(tables_query));
 | 
							result = SQLExecDirect(htbl_stmt, tables_query, strlen(tables_query));
 | 
				
			||||||
 
 | 
				
			|||||||
		Reference in New Issue
	
	Block a user