summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTom Lane2010-06-15 20:29:01 +0000
committerTom Lane2010-06-15 20:29:01 +0000
commitc0989c67fa8fcc53f8475bbc918e330588628cff (patch)
tree42432e90967bebf04b5c1b5829ac2f370eef3d3d
parent77a4c51af80819c3bcd581d9237f5c47e68393a6 (diff)
Change the interpretation of the primary_key_attnums parameter of
dblink_build_sql_insert() and related functions. Now the column numbers are treated as logical not physical column numbers. This will provide saner behavior in the presence of dropped columns; furthermore, if we ever get around to allowing rearrangement of logical column ordering, the original definition would become nearly untenable from a usability standpoint. Per recent discussion of dblink's handling of dropped columns. Not back-patched for fear of breaking existing applications.
-rw-r--r--contrib/dblink/dblink.c32
-rw-r--r--contrib/dblink/expected/dblink.out6
-rw-r--r--contrib/dblink/sql/dblink.sql6
-rw-r--r--doc/src/sgml/dblink.sgml58
4 files changed, 85 insertions, 17 deletions
diff --git a/contrib/dblink/dblink.c b/contrib/dblink/dblink.c
index a8a6d4a5c4..04354e16b8 100644
--- a/contrib/dblink/dblink.c
+++ b/contrib/dblink/dblink.c
@@ -8,7 +8,7 @@
* Darko Prenosil <[email protected]>
* Shridhar Daithankar <[email protected]>
*
- * $PostgreSQL: pgsql/contrib/dblink/dblink.c,v 1.97 2010/06/15 19:04:15 tgl Exp $
+ * $PostgreSQL: pgsql/contrib/dblink/dblink.c,v 1.98 2010/06/15 20:29:01 tgl Exp $
* Copyright (c) 2001-2010, PostgreSQL Global Development Group
* ALL RIGHTS RESERVED;
*
@@ -2381,11 +2381,13 @@ escape_param_str(const char *str)
* Validate the PK-attnums argument for dblink_build_sql_insert() and related
* functions, and translate to the internal representation.
*
- * The user supplies an int2vector of 1-based physical attnums, plus a count
+ * The user supplies an int2vector of 1-based logical attnums, plus a count
* argument (the need for the separate count argument is historical, but we
* still check it). We check that each attnum corresponds to a valid,
* non-dropped attribute of the rel. We do *not* prevent attnums from being
* listed twice, though the actual use-case for such things is dubious.
+ * Note that before Postgres 9.0, the user's attnums were interpreted as
+ * physical not logical column numbers; this was changed for future-proofing.
*
* The internal representation is a palloc'd int array of 0-based physical
* attnums.
@@ -2416,12 +2418,32 @@ validate_pkattnums(Relation rel,
for (i = 0; i < pknumatts_arg; i++)
{
int pkattnum = pkattnums_arg->values[i];
+ int lnum;
+ int j;
- if (pkattnum <= 0 || pkattnum > natts ||
- tupdesc->attrs[pkattnum - 1]->attisdropped)
+ /* Can throw error immediately if out of range */
+ if (pkattnum <= 0 || pkattnum > natts)
+ ereport(ERROR,
+ (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
+ errmsg("invalid attribute number %d", pkattnum)));
+
+ /* Identify which physical column has this logical number */
+ lnum = 0;
+ for (j = 0; j < natts; j++)
+ {
+ /* dropped columns don't count */
+ if (tupdesc->attrs[j]->attisdropped)
+ continue;
+
+ if (++lnum == pkattnum)
+ break;
+ }
+
+ if (j < natts)
+ (*pkattnums)[i] = j;
+ else
ereport(ERROR,
(errcode(ERRCODE_INVALID_PARAMETER_VALUE),
errmsg("invalid attribute number %d", pkattnum)));
- (*pkattnums)[i] = pkattnum - 1;
}
}
diff --git a/contrib/dblink/expected/dblink.out b/contrib/dblink/expected/dblink.out
index 454588d94c..c59a67c737 100644
--- a/contrib/dblink/expected/dblink.out
+++ b/contrib/dblink/expected/dblink.out
@@ -903,21 +903,21 @@ ALTER TABLE test_dropped
DROP COLUMN col2,
ADD COLUMN col3 VARCHAR(10) NOT NULL DEFAULT 'foo',
ADD COLUMN col4 INT NOT NULL DEFAULT 42;
-SELECT dblink_build_sql_insert('test_dropped', '2', 1,
+SELECT dblink_build_sql_insert('test_dropped', '1', 1,
ARRAY['1'::TEXT], ARRAY['2'::TEXT]);
dblink_build_sql_insert
---------------------------------------------------------------------------
INSERT INTO test_dropped(id,col2b,col3,col4) VALUES('2','113','foo','42')
(1 row)
-SELECT dblink_build_sql_update('test_dropped', '2', 1,
+SELECT dblink_build_sql_update('test_dropped', '1', 1,
ARRAY['1'::TEXT], ARRAY['2'::TEXT]);
dblink_build_sql_update
-------------------------------------------------------------------------------------------
UPDATE test_dropped SET id = '2', col2b = '113', col3 = 'foo', col4 = '42' WHERE id = '2'
(1 row)
-SELECT dblink_build_sql_delete('test_dropped', '2', 1,
+SELECT dblink_build_sql_delete('test_dropped', '1', 1,
ARRAY['2'::TEXT]);
dblink_build_sql_delete
-----------------------------------------
diff --git a/contrib/dblink/sql/dblink.sql b/contrib/dblink/sql/dblink.sql
index b15c4ddaf0..a6d7811bfc 100644
--- a/contrib/dblink/sql/dblink.sql
+++ b/contrib/dblink/sql/dblink.sql
@@ -430,11 +430,11 @@ ALTER TABLE test_dropped
ADD COLUMN col3 VARCHAR(10) NOT NULL DEFAULT 'foo',
ADD COLUMN col4 INT NOT NULL DEFAULT 42;
-SELECT dblink_build_sql_insert('test_dropped', '2', 1,
+SELECT dblink_build_sql_insert('test_dropped', '1', 1,
ARRAY['1'::TEXT], ARRAY['2'::TEXT]);
-SELECT dblink_build_sql_update('test_dropped', '2', 1,
+SELECT dblink_build_sql_update('test_dropped', '1', 1,
ARRAY['1'::TEXT], ARRAY['2'::TEXT]);
-SELECT dblink_build_sql_delete('test_dropped', '2', 1,
+SELECT dblink_build_sql_delete('test_dropped', '1', 1,
ARRAY['2'::TEXT]);
diff --git a/doc/src/sgml/dblink.sgml b/doc/src/sgml/dblink.sgml
index 81f23a28f3..e894a8cfc7 100644
--- a/doc/src/sgml/dblink.sgml
+++ b/doc/src/sgml/dblink.sgml
@@ -1,4 +1,4 @@
-<!-- $PostgreSQL: pgsql/doc/src/sgml/dblink.sgml,v 1.12 2010/06/07 02:01:08 itagaki Exp $ -->
+<!-- $PostgreSQL: pgsql/doc/src/sgml/dblink.sgml,v 1.13 2010/06/15 20:29:01 tgl Exp $ -->
<sect1 id="dblink">
<title>dblink</title>
@@ -1294,9 +1294,9 @@ SELECT *
<title>Description</title>
<para>
- <function>dblink_get_notify</> retrieves notifications on either
+ <function>dblink_get_notify</> retrieves notifications on either
the unnamed connection, or on a named connection if specified.
- To receive notifications via dblink, <function>LISTEN</> must
+ To receive notifications via dblink, <function>LISTEN</> must
first be issued, using <function>dblink_exec</>.
For details see <xref linkend="sql-listen"> and <xref linkend="sql-notify">.
</para>
@@ -1620,6 +1620,10 @@ SELECT * FROM dblink_get_notify();
<programlisting>
CREATE TYPE dblink_pkey_results AS (position int, colname text);
</programlisting>
+
+ The <literal>position</> column simply runs from 1 to <replaceable>N</>;
+ it is the number of the field within the primary key, not the number
+ within the table's columns.
</para>
</refsect1>
@@ -1659,7 +1663,7 @@ test=# select * from dblink_get_pkey('foobar');
<synopsis>
dblink_build_sql_insert(text relname,
int2vector primary_key_attnums,
- int2 num_primary_key_atts,
+ integer num_primary_key_atts,
text[] src_pk_att_vals_array,
text[] tgt_pk_att_vals_array) returns text
</synopsis>
@@ -1746,6 +1750,20 @@ test=# select * from dblink_get_pkey('foobar');
</refsect1>
<refsect1>
+ <title>Notes</title>
+
+ <para>
+ As of <productname>PostgreSQL</> 9.0, the attribute numbers in
+ <parameter>primary_key_attnums</parameter> are interpreted as logical
+ column numbers, corresponding to the column's position in
+ <literal>SELECT * FROM relname</>. Previous versions interpreted the
+ numbers as physical column positions. There is a difference if any
+ column(s) to the left of the indicated column have been dropped during
+ the lifetime of the table.
+ </para>
+ </refsect1>
+
+ <refsect1>
<title>Example</title>
<programlisting>
@@ -1775,7 +1793,7 @@ test=# select * from dblink_get_pkey('foobar');
<synopsis>
dblink_build_sql_delete(text relname,
int2vector primary_key_attnums,
- int2 num_primary_key_atts,
+ integer num_primary_key_atts,
text[] tgt_pk_att_vals_array) returns text
</synopsis>
</refsynopsisdiv>
@@ -1846,6 +1864,20 @@ test=# select * from dblink_get_pkey('foobar');
</refsect1>
<refsect1>
+ <title>Notes</title>
+
+ <para>
+ As of <productname>PostgreSQL</> 9.0, the attribute numbers in
+ <parameter>primary_key_attnums</parameter> are interpreted as logical
+ column numbers, corresponding to the column's position in
+ <literal>SELECT * FROM relname</>. Previous versions interpreted the
+ numbers as physical column positions. There is a difference if any
+ column(s) to the left of the indicated column have been dropped during
+ the lifetime of the table.
+ </para>
+ </refsect1>
+
+ <refsect1>
<title>Example</title>
<programlisting>
@@ -1875,7 +1907,7 @@ test=# select * from dblink_get_pkey('foobar');
<synopsis>
dblink_build_sql_update(text relname,
int2vector primary_key_attnums,
- int2 num_primary_key_atts,
+ integer num_primary_key_atts,
text[] src_pk_att_vals_array,
text[] tgt_pk_att_vals_array) returns text
</synopsis>
@@ -1965,6 +1997,20 @@ test=# select * from dblink_get_pkey('foobar');
</refsect1>
<refsect1>
+ <title>Notes</title>
+
+ <para>
+ As of <productname>PostgreSQL</> 9.0, the attribute numbers in
+ <parameter>primary_key_attnums</parameter> are interpreted as logical
+ column numbers, corresponding to the column's position in
+ <literal>SELECT * FROM relname</>. Previous versions interpreted the
+ numbers as physical column positions. There is a difference if any
+ column(s) to the left of the indicated column have been dropped during
+ the lifetime of the table.
+ </para>
+ </refsect1>
+
+ <refsect1>
<title>Example</title>
<programlisting>