Skip to content

Commit 3f287d0

Browse files
committed
Merge branch 'REL9_5_STABLE' into PGPRO9_5
2 parents 8933d19 + e2c183e commit 3f287d0

File tree

12 files changed

+64
-68
lines changed

12 files changed

+64
-68
lines changed

contrib/test_decoding/expected/ddl.out

Lines changed: 14 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -227,23 +227,28 @@ CREATE TABLE tr_etoomuch (id serial primary key, data int);
227227
INSERT INTO tr_etoomuch(data) SELECT g.i FROM generate_series(1, 10234) g(i);
228228
DELETE FROM tr_etoomuch WHERE id < 5000;
229229
UPDATE tr_etoomuch SET data = - data WHERE id > 5000;
230+
CREATE TABLE tr_oddlength (id text primary key, data text);
231+
INSERT INTO tr_oddlength VALUES('ab', 'foo');
230232
COMMIT;
231233
/* display results, but hide most of the output */
232234
SELECT count(*), min(data), max(data)
233235
FROM pg_logical_slot_get_changes('regression_slot', NULL, NULL, 'include-xids', '0', 'skip-empty-xacts', '1')
234236
GROUP BY substring(data, 1, 24)
235237
ORDER BY 1,2;
236-
count | min | max
237-
-------+-------------------------------------------------+------------------------------------------------------------------------
238-
1 | BEGIN | BEGIN
239-
1 | COMMIT | COMMIT
240-
20467 | table public.tr_etoomuch: DELETE: id[integer]:1 | table public.tr_etoomuch: UPDATE: id[integer]:9999 data[integer]:-9999
241-
(3 rows)
238+
count | min | max
239+
-------+-------------------------------------------------------------------+------------------------------------------------------------------------
240+
1 | BEGIN | BEGIN
241+
1 | COMMIT | COMMIT
242+
1 | table public.tr_oddlength: INSERT: id[text]:'ab' data[text]:'foo' | table public.tr_oddlength: INSERT: id[text]:'ab' data[text]:'foo'
243+
20467 | table public.tr_etoomuch: DELETE: id[integer]:1 | table public.tr_etoomuch: UPDATE: id[integer]:9999 data[integer]:-9999
244+
(4 rows)
242245

243246
-- check updates of primary keys work correctly
244247
BEGIN;
245248
CREATE TABLE spoolme AS SELECT g.i FROM generate_series(1, 5000) g(i);
246249
UPDATE tr_etoomuch SET id = -id WHERE id = 5000;
250+
UPDATE tr_oddlength SET id = 'x', data = 'quux';
251+
UPDATE tr_oddlength SET id = 'yy', data = 'a';
247252
DELETE FROM spoolme;
248253
DROP TABLE spoolme;
249254
COMMIT;
@@ -253,7 +258,9 @@ WHERE data ~ 'UPDATE';
253258
data
254259
-------------------------------------------------------------------------------------------------------------
255260
table public.tr_etoomuch: UPDATE: old-key: id[integer]:5000 new-tuple: id[integer]:-5000 data[integer]:5000
256-
(1 row)
261+
table public.tr_oddlength: UPDATE: old-key: id[text]:'ab' new-tuple: id[text]:'x' data[text]:'quux'
262+
table public.tr_oddlength: UPDATE: old-key: id[text]:'x' new-tuple: id[text]:'yy' data[text]:'a'
263+
(3 rows)
257264

258265
-- check that a large, spooled, upsert works
259266
INSERT INTO tr_etoomuch (id, data)

contrib/test_decoding/sql/ddl.sql

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -115,6 +115,8 @@ CREATE TABLE tr_etoomuch (id serial primary key, data int);
115115
INSERT INTO tr_etoomuch(data) SELECT g.i FROM generate_series(1, 10234) g(i);
116116
DELETE FROM tr_etoomuch WHERE id < 5000;
117117
UPDATE tr_etoomuch SET data = - data WHERE id > 5000;
118+
CREATE TABLE tr_oddlength (id text primary key, data text);
119+
INSERT INTO tr_oddlength VALUES('ab', 'foo');
118120
COMMIT;
119121

120122
/* display results, but hide most of the output */
@@ -127,6 +129,8 @@ ORDER BY 1,2;
127129
BEGIN;
128130
CREATE TABLE spoolme AS SELECT g.i FROM generate_series(1, 5000) g(i);
129131
UPDATE tr_etoomuch SET id = -id WHERE id = 5000;
132+
UPDATE tr_oddlength SET id = 'x', data = 'quux';
133+
UPDATE tr_oddlength SET id = 'yy', data = 'a';
130134
DELETE FROM spoolme;
131135
DROP TABLE spoolme;
132136
COMMIT;

doc/src/sgml/ecpg.sgml

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -8559,7 +8559,7 @@ int dectolong(decimal *np, long *lngp);
85598559
int rdatestr(date d, char *str);
85608560
</synopsis>
85618561
The function receives two arguments, the first one is the date to
8562-
convert (<literal>d</> and the second one is a pointer to the target
8562+
convert (<literal>d</>) and the second one is a pointer to the target
85638563
string. The output format is always <literal>yyyy-mm-dd</>, so you need
85648564
to allocate at least 11 bytes (including the zero-byte terminator) for the
85658565
string.
@@ -8912,7 +8912,7 @@ int dttoasc(timestamp *ts, char *output);
89128912
</synopsis>
89138913
The function receives a pointer to the timestamp variable to convert
89148914
(<literal>ts</>) and the string that should hold the result of the
8915-
operation <literal>output</>). It converts <literal>ts</> to its
8915+
operation (<literal>output</>). It converts <literal>ts</> to its
89168916
textual representation according to the SQL standard, which is
89178917
be <literal>YYYY-MM-DD HH:MM:SS</literal>.
89188918
</para>
@@ -8959,7 +8959,7 @@ int intoasc(interval *i, char *str);
89598959
</synopsis>
89608960
The function receives a pointer to the interval variable to convert
89618961
(<literal>i</>) and the string that should hold the result of the
8962-
operation <literal>str</>). It converts <literal>i</> to its
8962+
operation (<literal>str</>). It converts <literal>i</> to its
89638963
textual representation according to the SQL standard, which is
89648964
be <literal>YYYY-MM-DD HH:MM:SS</literal>.
89658965
</para>

src/backend/access/gin/ginget.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -278,6 +278,7 @@ collectMatchBitmap(GinBtreeData *btree, GinBtreeStack *stack,
278278
ipd = ginReadTuple(btree->ginstate, scanEntry->attnum, itup, &nipd);
279279
tbm_add_tuples(scanEntry->matchBitmap, ipd, nipd, false);
280280
scanEntry->predictNumberResult += GinGetNPosting(itup);
281+
pfree(ipd);
281282
}
282283

283284
/*

src/backend/commands/tablecmds.c

Lines changed: 14 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -11019,10 +11019,20 @@ ATExecReplicaIdentity(Relation rel, ReplicaIdentityStmt *stmt, LOCKMODE lockmode
1101911019
int16 attno = indexRel->rd_index->indkey.values[key];
1102011020
Form_pg_attribute attr;
1102111021

11022-
/* Of the system columns, only oid is indexable. */
11023-
if (attno <= 0 && attno != ObjectIdAttributeNumber)
11024-
elog(ERROR, "internal column %u in unique index \"%s\"",
11025-
attno, RelationGetRelationName(indexRel));
11022+
/* Allow OID column to be indexed; it's certainly not nullable */
11023+
if (attno == ObjectIdAttributeNumber)
11024+
continue;
11025+
11026+
/*
11027+
* Reject any other system columns. (Going forward, we'll disallow
11028+
* indexes containing such columns in the first place, but they might
11029+
* exist in older branches.)
11030+
*/
11031+
if (attno <= 0)
11032+
ereport(ERROR,
11033+
(errcode(ERRCODE_INVALID_COLUMN_REFERENCE),
11034+
errmsg("index \"%s\" cannot be used as replica identity because column %d is a system column",
11035+
RelationGetRelationName(indexRel), attno)));
1102611036

1102711037
attr = rel->rd_att->attrs[attno - 1];
1102811038
if (!attr->attnotnull)

src/backend/executor/execIndexing.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -120,7 +120,7 @@ typedef enum
120120
{
121121
CEOUC_WAIT,
122122
CEOUC_NOWAIT,
123-
CEOUC_LIVELOCK_PREVENTING_WAIT,
123+
CEOUC_LIVELOCK_PREVENTING_WAIT
124124
} CEOUC_WAIT_MODE;
125125

126126
static bool check_exclusion_or_unique_constraint(Relation heap, Relation index,

src/backend/replication/logical/origin.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -120,9 +120,9 @@ typedef struct ReplicationState
120120
XLogRecPtr local_lsn;
121121

122122
/*
123-
* Slot is setup in backend?
123+
* PID of backend that's acquired slot, or 0 if none.
124124
*/
125-
pid_t acquired_by;
125+
int acquired_by;
126126

127127
/*
128128
* Lock protecting remote_lsn and local_lsn.

src/backend/replication/logical/reorderbuffer.c

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2347,6 +2347,10 @@ ReorderBufferRestoreChanges(ReorderBuffer *rb, ReorderBufferTXN *txn,
23472347
/*
23482348
* Convert change from its on-disk format to in-memory format and queue it onto
23492349
* the TXN's ->changes list.
2350+
*
2351+
* Note: although "data" is declared char*, at entry it points to a
2352+
* maxalign'd buffer, making it safe in most of this function to assume
2353+
* that the pointed-to data is suitably aligned for direct access.
23502354
*/
23512355
static void
23522356
ReorderBufferRestoreChange(ReorderBuffer *rb, ReorderBufferTXN *txn,
@@ -2374,7 +2378,7 @@ ReorderBufferRestoreChange(ReorderBuffer *rb, ReorderBufferTXN *txn,
23742378
case REORDER_BUFFER_CHANGE_INTERNAL_SPEC_INSERT:
23752379
if (change->data.tp.oldtuple)
23762380
{
2377-
Size tuplelen = ((HeapTuple) data)->t_len;
2381+
uint32 tuplelen = ((HeapTuple) data)->t_len;
23782382

23792383
change->data.tp.oldtuple =
23802384
ReorderBufferGetTupleBuf(rb, tuplelen - SizeofHeapTupleHeader);
@@ -2395,7 +2399,11 @@ ReorderBufferRestoreChange(ReorderBuffer *rb, ReorderBufferTXN *txn,
23952399

23962400
if (change->data.tp.newtuple)
23972401
{
2398-
Size tuplelen = ((HeapTuple) data)->t_len;
2402+
/* here, data might not be suitably aligned! */
2403+
uint32 tuplelen;
2404+
2405+
memcpy(&tuplelen, data + offsetof(HeapTupleData, t_len),
2406+
sizeof(uint32));
23992407

24002408
change->data.tp.newtuple =
24012409
ReorderBufferGetTupleBuf(rb, tuplelen - SizeofHeapTupleHeader);

src/bin/pg_dump/pg_dump.c

Lines changed: 1 addition & 46 deletions
Original file line numberDiff line numberDiff line change
@@ -11522,9 +11522,7 @@ dumpOpclass(Archive *fout, OpclassInfo *opcinfo)
1152211522
appendPQExpBuffer(q, "FOR TYPE %s USING %s",
1152311523
opcintype,
1152411524
fmtId(amname));
11525-
if (strlen(opcfamilyname) > 0 &&
11526-
(strcmp(opcfamilyname, opcinfo->dobj.name) != 0 ||
11527-
strcmp(opcfamilynsp, opcinfo->dobj.namespace->dobj.name) != 0))
11525+
if (strlen(opcfamilyname) > 0)
1152811526
{
1152911527
appendPQExpBufferStr(q, " FAMILY ");
1153011528
if (strcmp(opcfamilynsp, opcinfo->dobj.namespace->dobj.name) != 0)
@@ -11808,15 +11806,6 @@ dumpOpfamily(Archive *fout, OpfamilyInfo *opfinfo)
1180811806
if (!opfinfo->dobj.dump || dopt->dataOnly)
1180911807
return;
1181011808

11811-
/*
11812-
* We want to dump the opfamily only if (1) it contains "loose" operators
11813-
* or functions, or (2) it contains an opclass with a different name or
11814-
* owner. Otherwise it's sufficient to let it be created during creation
11815-
* of the contained opclass, and not dumping it improves portability of
11816-
* the dump. Since we have to fetch the loose operators/funcs anyway, do
11817-
* that first.
11818-
*/
11819-
1182011809
query = createPQExpBuffer();
1182111810
q = createPQExpBuffer();
1182211811
delq = createPQExpBuffer();
@@ -11899,40 +11888,6 @@ dumpOpfamily(Archive *fout, OpfamilyInfo *opfinfo)
1189911888

1190011889
res_procs = ExecuteSqlQuery(fout, query->data, PGRES_TUPLES_OK);
1190111890

11902-
if (PQntuples(res_ops) == 0 && PQntuples(res_procs) == 0)
11903-
{
11904-
/* No loose members, so check contained opclasses */
11905-
resetPQExpBuffer(query);
11906-
11907-
appendPQExpBuffer(query, "SELECT 1 "
11908-
"FROM pg_catalog.pg_opclass c, pg_catalog.pg_opfamily f, pg_catalog.pg_depend "
11909-
"WHERE f.oid = '%u'::pg_catalog.oid "
11910-
"AND refclassid = 'pg_catalog.pg_opfamily'::pg_catalog.regclass "
11911-
"AND refobjid = f.oid "
11912-
"AND classid = 'pg_catalog.pg_opclass'::pg_catalog.regclass "
11913-
"AND objid = c.oid "
11914-
"AND (opcname != opfname OR opcnamespace != opfnamespace OR opcowner != opfowner) "
11915-
"LIMIT 1",
11916-
opfinfo->dobj.catId.oid);
11917-
11918-
res = ExecuteSqlQuery(fout, query->data, PGRES_TUPLES_OK);
11919-
11920-
if (PQntuples(res) == 0)
11921-
{
11922-
/* no need to dump it, so bail out */
11923-
PQclear(res);
11924-
PQclear(res_ops);
11925-
PQclear(res_procs);
11926-
destroyPQExpBuffer(query);
11927-
destroyPQExpBuffer(q);
11928-
destroyPQExpBuffer(delq);
11929-
destroyPQExpBuffer(labelq);
11930-
return;
11931-
}
11932-
11933-
PQclear(res);
11934-
}
11935-
1193611891
/* Get additional fields from the pg_opfamily row */
1193711892
resetPQExpBuffer(query);
1193811893

src/include/access/xlog_internal.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -252,7 +252,7 @@ typedef enum
252252
{
253253
RECOVERY_TARGET_ACTION_PAUSE,
254254
RECOVERY_TARGET_ACTION_PROMOTE,
255-
RECOVERY_TARGET_ACTION_SHUTDOWN,
255+
RECOVERY_TARGET_ACTION_SHUTDOWN
256256
} RecoveryTargetAction;
257257

258258
/*

src/test/regress/expected/replica_identity.out

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,10 +5,11 @@ CREATE TABLE test_replica_identity (
55
nonkey text,
66
CONSTRAINT test_replica_identity_unique_defer UNIQUE (keya, keyb) DEFERRABLE,
77
CONSTRAINT test_replica_identity_unique_nondefer UNIQUE (keya, keyb)
8-
);
8+
) WITH OIDS;
99
CREATE TABLE test_replica_identity_othertable (id serial primary key);
1010
CREATE INDEX test_replica_identity_keyab ON test_replica_identity (keya, keyb);
1111
CREATE UNIQUE INDEX test_replica_identity_keyab_key ON test_replica_identity (keya, keyb);
12+
CREATE UNIQUE INDEX test_replica_identity_oid_idx ON test_replica_identity (oid);
1213
CREATE UNIQUE INDEX test_replica_identity_nonkey ON test_replica_identity (keya, nonkey);
1314
CREATE INDEX test_replica_identity_hash ON test_replica_identity USING hash (nonkey);
1415
WARNING: hash indexes are not WAL-logged and their use is discouraged
@@ -88,12 +89,15 @@ Indexes:
8889
"test_replica_identity_expr" UNIQUE, btree (keya, keyb, (3))
8990
"test_replica_identity_keyab_key" UNIQUE, btree (keya, keyb)
9091
"test_replica_identity_nonkey" UNIQUE, btree (keya, nonkey)
92+
"test_replica_identity_oid_idx" UNIQUE, btree (oid)
9193
"test_replica_identity_partial" UNIQUE, btree (keya, keyb) WHERE keyb <> '3'::text
9294
"test_replica_identity_unique_defer" UNIQUE CONSTRAINT, btree (keya, keyb) DEFERRABLE
9395
"test_replica_identity_unique_nondefer" UNIQUE CONSTRAINT, btree (keya, keyb)
9496
"test_replica_identity_hash" hash (nonkey)
9597
"test_replica_identity_keyab" btree (keya, keyb)
9698

99+
-- succeed, oid unique index
100+
ALTER TABLE test_replica_identity REPLICA IDENTITY USING INDEX test_replica_identity_oid_idx;
97101
-- succeed, nondeferrable unique constraint over nonullable cols
98102
ALTER TABLE test_replica_identity REPLICA IDENTITY USING INDEX test_replica_identity_unique_nondefer;
99103
-- succeed unique index over nonnullable cols
@@ -118,6 +122,7 @@ Indexes:
118122
"test_replica_identity_expr" UNIQUE, btree (keya, keyb, (3))
119123
"test_replica_identity_keyab_key" UNIQUE, btree (keya, keyb) REPLICA IDENTITY
120124
"test_replica_identity_nonkey" UNIQUE, btree (keya, nonkey)
125+
"test_replica_identity_oid_idx" UNIQUE, btree (oid)
121126
"test_replica_identity_partial" UNIQUE, btree (keya, keyb) WHERE keyb <> '3'::text
122127
"test_replica_identity_unique_defer" UNIQUE CONSTRAINT, btree (keya, keyb) DEFERRABLE
123128
"test_replica_identity_unique_nondefer" UNIQUE CONSTRAINT, btree (keya, keyb)
@@ -166,12 +171,14 @@ Indexes:
166171
"test_replica_identity_expr" UNIQUE, btree (keya, keyb, (3))
167172
"test_replica_identity_keyab_key" UNIQUE, btree (keya, keyb)
168173
"test_replica_identity_nonkey" UNIQUE, btree (keya, nonkey)
174+
"test_replica_identity_oid_idx" UNIQUE, btree (oid)
169175
"test_replica_identity_partial" UNIQUE, btree (keya, keyb) WHERE keyb <> '3'::text
170176
"test_replica_identity_unique_defer" UNIQUE CONSTRAINT, btree (keya, keyb) DEFERRABLE
171177
"test_replica_identity_unique_nondefer" UNIQUE CONSTRAINT, btree (keya, keyb)
172178
"test_replica_identity_hash" hash (nonkey)
173179
"test_replica_identity_keyab" btree (keya, keyb)
174180
Replica Identity: FULL
181+
Has OIDs: yes
175182

176183
ALTER TABLE test_replica_identity REPLICA IDENTITY NOTHING;
177184
SELECT relreplident FROM pg_class WHERE oid = 'test_replica_identity'::regclass;

src/test/regress/sql/replica_identity.sql

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,12 +5,13 @@ CREATE TABLE test_replica_identity (
55
nonkey text,
66
CONSTRAINT test_replica_identity_unique_defer UNIQUE (keya, keyb) DEFERRABLE,
77
CONSTRAINT test_replica_identity_unique_nondefer UNIQUE (keya, keyb)
8-
);
8+
) WITH OIDS;
99

1010
CREATE TABLE test_replica_identity_othertable (id serial primary key);
1111

1212
CREATE INDEX test_replica_identity_keyab ON test_replica_identity (keya, keyb);
1313
CREATE UNIQUE INDEX test_replica_identity_keyab_key ON test_replica_identity (keya, keyb);
14+
CREATE UNIQUE INDEX test_replica_identity_oid_idx ON test_replica_identity (oid);
1415
CREATE UNIQUE INDEX test_replica_identity_nonkey ON test_replica_identity (keya, nonkey);
1516
CREATE INDEX test_replica_identity_hash ON test_replica_identity USING hash (nonkey);
1617
CREATE UNIQUE INDEX test_replica_identity_expr ON test_replica_identity (keya, keyb, (3));
@@ -52,6 +53,9 @@ ALTER TABLE test_replica_identity REPLICA IDENTITY USING INDEX test_replica_iden
5253
SELECT relreplident FROM pg_class WHERE oid = 'test_replica_identity'::regclass;
5354
\d test_replica_identity
5455

56+
-- succeed, oid unique index
57+
ALTER TABLE test_replica_identity REPLICA IDENTITY USING INDEX test_replica_identity_oid_idx;
58+
5559
-- succeed, nondeferrable unique constraint over nonullable cols
5660
ALTER TABLE test_replica_identity REPLICA IDENTITY USING INDEX test_replica_identity_unique_nondefer;
5761

0 commit comments

Comments
 (0)