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

Commit 3b3706d

Browse files
committed
Fix dblink_build_sql_insert() and related functions to handle dropped
columns correctly. In passing, get rid of some dead logic in the underlying get_sql_insert() etc functions --- there is no caller that will pass null value-arrays to them. Per bug report from Robert Voinea.
1 parent 4a96908 commit 3b3706d

File tree

3 files changed

+101
-32
lines changed

3 files changed

+101
-32
lines changed

contrib/dblink/dblink.c

+38-32
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
* Darko Prenosil <Darko.Prenosil@finteh.hr>
99
* Shridhar Daithankar <shridhar_daithankar@persistent.co.in>
1010
*
11-
* $PostgreSQL: pgsql/contrib/dblink/dblink.c,v 1.96 2010/06/15 16:22:19 tgl Exp $
11+
* $PostgreSQL: pgsql/contrib/dblink/dblink.c,v 1.97 2010/06/15 19:04:15 tgl Exp $
1212
* Copyright (c) 2001-2010, PostgreSQL Global Development Group
1313
* ALL RIGHTS RESERVED;
1414
*
@@ -1741,7 +1741,7 @@ get_sql_insert(Relation rel, int *pkattnums, int pknumatts, char **src_pkattvals
17411741
appendStringInfo(&buf, ") VALUES(");
17421742

17431743
/*
1744-
* remember attvals are 1 based
1744+
* Note: i is physical column number (counting from 0).
17451745
*/
17461746
needComma = false;
17471747
for (i = 0; i < natts; i++)
@@ -1752,12 +1752,9 @@ get_sql_insert(Relation rel, int *pkattnums, int pknumatts, char **src_pkattvals
17521752
if (needComma)
17531753
appendStringInfo(&buf, ",");
17541754

1755-
if (tgt_pkattvals != NULL)
1756-
key = get_attnum_pk_pos(pkattnums, pknumatts, i);
1757-
else
1758-
key = -1;
1755+
key = get_attnum_pk_pos(pkattnums, pknumatts, i);
17591756

1760-
if (key > -1)
1757+
if (key >= 0)
17611758
val = tgt_pkattvals[key] ? pstrdup(tgt_pkattvals[key]) : NULL;
17621759
else
17631760
val = SPI_getvalue(tuple, tupdesc, i + 1);
@@ -1802,10 +1799,6 @@ get_sql_delete(Relation rel, int *pkattnums, int pknumatts, char **tgt_pkattvals
18021799
appendStringInfoString(&buf,
18031800
quote_ident_cstr(NameStr(tupdesc->attrs[pkattnum]->attname)));
18041801

1805-
if (tgt_pkattvals == NULL)
1806-
/* internal error */
1807-
elog(ERROR, "target key array must not be NULL");
1808-
18091802
if (tgt_pkattvals[i] != NULL)
18101803
appendStringInfo(&buf, " = %s",
18111804
quote_literal_cstr(tgt_pkattvals[i]));
@@ -1845,6 +1838,9 @@ get_sql_update(Relation rel, int *pkattnums, int pknumatts, char **src_pkattvals
18451838

18461839
appendStringInfo(&buf, "UPDATE %s SET ", relname);
18471840

1841+
/*
1842+
* Note: i is physical column number (counting from 0).
1843+
*/
18481844
needComma = false;
18491845
for (i = 0; i < natts; i++)
18501846
{
@@ -1857,12 +1853,9 @@ get_sql_update(Relation rel, int *pkattnums, int pknumatts, char **src_pkattvals
18571853
appendStringInfo(&buf, "%s = ",
18581854
quote_ident_cstr(NameStr(tupdesc->attrs[i]->attname)));
18591855

1860-
if (tgt_pkattvals != NULL)
1861-
key = get_attnum_pk_pos(pkattnums, pknumatts, i);
1862-
else
1863-
key = -1;
1856+
key = get_attnum_pk_pos(pkattnums, pknumatts, i);
18641857

1865-
if (key > -1)
1858+
if (key >= 0)
18661859
val = tgt_pkattvals[key] ? pstrdup(tgt_pkattvals[key]) : NULL;
18671860
else
18681861
val = SPI_getvalue(tuple, tupdesc, i + 1);
@@ -1889,16 +1882,10 @@ get_sql_update(Relation rel, int *pkattnums, int pknumatts, char **src_pkattvals
18891882
appendStringInfo(&buf, "%s",
18901883
quote_ident_cstr(NameStr(tupdesc->attrs[pkattnum]->attname)));
18911884

1892-
if (tgt_pkattvals != NULL)
1893-
val = tgt_pkattvals[i] ? pstrdup(tgt_pkattvals[i]) : NULL;
1894-
else
1895-
val = SPI_getvalue(tuple, tupdesc, pkattnum + 1);
1885+
val = tgt_pkattvals[i];
18961886

18971887
if (val != NULL)
1898-
{
18991888
appendStringInfo(&buf, " = %s", quote_literal_cstr(val));
1900-
pfree(val);
1901-
}
19021889
else
19031890
appendStringInfo(&buf, " IS NULL");
19041891
}
@@ -1964,30 +1951,49 @@ get_tuple_of_interest(Relation rel, int *pkattnums, int pknumatts, char **src_pk
19641951
{
19651952
char *relname;
19661953
TupleDesc tupdesc;
1954+
int natts;
19671955
StringInfoData buf;
19681956
int ret;
19691957
HeapTuple tuple;
19701958
int i;
19711959

1960+
/*
1961+
* Connect to SPI manager
1962+
*/
1963+
if ((ret = SPI_connect()) < 0)
1964+
/* internal error */
1965+
elog(ERROR, "SPI connect failure - returned %d", ret);
1966+
19721967
initStringInfo(&buf);
19731968

19741969
/* get relation name including any needed schema prefix and quoting */
19751970
relname = generate_relation_name(rel);
19761971

19771972
tupdesc = rel->rd_att;
1973+
natts = tupdesc->natts;
19781974

19791975
/*
1980-
* Connect to SPI manager
1976+
* Build sql statement to look up tuple of interest, ie, the one matching
1977+
* src_pkattvals. We used to use "SELECT *" here, but it's simpler to
1978+
* generate a result tuple that matches the table's physical structure,
1979+
* with NULLs for any dropped columns. Otherwise we have to deal with
1980+
* two different tupdescs and everything's very confusing.
19811981
*/
1982-
if ((ret = SPI_connect()) < 0)
1983-
/* internal error */
1984-
elog(ERROR, "SPI connect failure - returned %d", ret);
1982+
appendStringInfoString(&buf, "SELECT ");
19851983

1986-
/*
1987-
* Build sql statement to look up tuple of interest Use src_pkattvals as
1988-
* the criteria.
1989-
*/
1990-
appendStringInfo(&buf, "SELECT * FROM %s WHERE ", relname);
1984+
for (i = 0; i < natts; i++)
1985+
{
1986+
if (i > 0)
1987+
appendStringInfoString(&buf, ", ");
1988+
1989+
if (tupdesc->attrs[i]->attisdropped)
1990+
appendStringInfoString(&buf, "NULL");
1991+
else
1992+
appendStringInfoString(&buf,
1993+
quote_ident_cstr(NameStr(tupdesc->attrs[i]->attname)));
1994+
}
1995+
1996+
appendStringInfo(&buf, " FROM %s WHERE ", relname);
19911997

19921998
for (i = 0; i < pknumatts; i++)
19931999
{

contrib/dblink/expected/dblink.out

+37
Original file line numberDiff line numberDiff line change
@@ -887,3 +887,40 @@ SELECT dblink_disconnect();
887887
OK
888888
(1 row)
889889

890+
-- test dropped columns in dblink_build_sql_insert, dblink_build_sql_update
891+
CREATE TEMP TABLE test_dropped
892+
(
893+
col1 INT NOT NULL DEFAULT 111,
894+
id SERIAL PRIMARY KEY,
895+
col2 INT NOT NULL DEFAULT 112,
896+
col2b INT NOT NULL DEFAULT 113
897+
);
898+
NOTICE: CREATE TABLE will create implicit sequence "test_dropped_id_seq" for serial column "test_dropped.id"
899+
NOTICE: CREATE TABLE / PRIMARY KEY will create implicit index "test_dropped_pkey" for table "test_dropped"
900+
INSERT INTO test_dropped VALUES(default);
901+
ALTER TABLE test_dropped
902+
DROP COLUMN col1,
903+
DROP COLUMN col2,
904+
ADD COLUMN col3 VARCHAR(10) NOT NULL DEFAULT 'foo',
905+
ADD COLUMN col4 INT NOT NULL DEFAULT 42;
906+
SELECT dblink_build_sql_insert('test_dropped', '2', 1,
907+
ARRAY['1'::TEXT], ARRAY['2'::TEXT]);
908+
dblink_build_sql_insert
909+
---------------------------------------------------------------------------
910+
INSERT INTO test_dropped(id,col2b,col3,col4) VALUES('2','113','foo','42')
911+
(1 row)
912+
913+
SELECT dblink_build_sql_update('test_dropped', '2', 1,
914+
ARRAY['1'::TEXT], ARRAY['2'::TEXT]);
915+
dblink_build_sql_update
916+
-------------------------------------------------------------------------------------------
917+
UPDATE test_dropped SET id = '2', col2b = '113', col3 = 'foo', col4 = '42' WHERE id = '2'
918+
(1 row)
919+
920+
SELECT dblink_build_sql_delete('test_dropped', '2', 1,
921+
ARRAY['2'::TEXT]);
922+
dblink_build_sql_delete
923+
-----------------------------------------
924+
DELETE FROM test_dropped WHERE id = '2'
925+
(1 row)
926+

contrib/dblink/sql/dblink.sql

+26
Original file line numberDiff line numberDiff line change
@@ -412,3 +412,29 @@ SELECT notify_name, be_pid = (select t.be_pid from dblink('select pg_backend_pid
412412
SELECT * from dblink_get_notify();
413413

414414
SELECT dblink_disconnect();
415+
416+
-- test dropped columns in dblink_build_sql_insert, dblink_build_sql_update
417+
CREATE TEMP TABLE test_dropped
418+
(
419+
col1 INT NOT NULL DEFAULT 111,
420+
id SERIAL PRIMARY KEY,
421+
col2 INT NOT NULL DEFAULT 112,
422+
col2b INT NOT NULL DEFAULT 113
423+
);
424+
425+
INSERT INTO test_dropped VALUES(default);
426+
427+
ALTER TABLE test_dropped
428+
DROP COLUMN col1,
429+
DROP COLUMN col2,
430+
ADD COLUMN col3 VARCHAR(10) NOT NULL DEFAULT 'foo',
431+
ADD COLUMN col4 INT NOT NULL DEFAULT 42;
432+
433+
SELECT dblink_build_sql_insert('test_dropped', '2', 1,
434+
ARRAY['1'::TEXT], ARRAY['2'::TEXT]);
435+
436+
SELECT dblink_build_sql_update('test_dropped', '2', 1,
437+
ARRAY['1'::TEXT], ARRAY['2'::TEXT]);
438+
439+
SELECT dblink_build_sql_delete('test_dropped', '2', 1,
440+
ARRAY['2'::TEXT]);

0 commit comments

Comments
 (0)