Hi,
(Tomas, CCing you because you IIRC mentioned encountered an issue like
this)
I just spent quite a while debugging an issue where running logical
decoding yielded a:
ERROR: could not map filenode "base/$X/$Y" to relation OID
error.
After discarding like 30 different theories, I have found the cause:
During rewrites (i.e. VACUUM FULL / CLUSTER) of a mapped relation with a
toast table with actual live toasted tuples (pg_proc in my case and
henceforth) heap inserts with the toast data happen into the new toast
relation, triggered by:
static void
raw_heap_insert(RewriteState state, HeapTuple tup)
...
/*
* If the new tuple is too big for storage or contains already toasted
* out-of-line attributes from some other relation, invoke the toaster.
*
* Note: below this point, heaptup is the data we actually intend to
store
* into the relation; tup is the caller's original untoasted data.
*/
if (state->rs_new_rel->rd_rel->relkind == RELKIND_TOASTVALUE)
{
/* toast table entries should never be recursively toasted */
Assert(!HeapTupleHasExternal(tup));
heaptup = tup;
}
else if (HeapTupleHasExternal(tup) || tup->t_len >
TOAST_TUPLE_THRESHOLD)
heaptup = toast_insert_or_update(state->rs_new_rel, tup, NULL,
HEAP_INSERT_SKIP_FSM |
(state->rs_use_wal ?
0 : HEAP_INSERT_SKIP_WAL));
else
heaptup = tup;
At that point the new toast relation does *NOT* appear to be a system
catalog, it's just appears as an "independent" table. Therefore we do
not trigger, in heap_insert():
/*
* RelationIsLogicallyLogged
* True if we need to log enough information to extract the data
from the
* WAL stream.
*
* We don't log information for unlogged tables (since they don't WAL log
* anyway) and for system tables (their content is hard to make sense of, and
* it would complicate decoding slightly for little gain). Note that we *do*
* log information for user defined catalog tables since they presumably are
* interesting to the user...
*/
#define RelationIsLogicallyLogged(relation) \
(XLogLogicalInfoActive() && \
RelationNeedsWAL(relation) && \
!IsCatalogRelation(relation))
/*
* For logical decoding, we need the tuple even if we're doing
a full
* page write, so make sure it's included even if we take a
full-page
* image. (XXX We could alternatively store a pointer into the
FPW).
*/
if (RelationIsLogicallyLogged(relation))
{
xlrec.flags |= XLH_INSERT_CONTAINS_NEW_TUPLE;
bufflags |= REGBUF_KEEP_DATA;
}
i.e. the inserted toast tuple will be marked as
XLH_INSERT_CONTAINS_NEW_TUPLE - which it shouldn't, because it's a
system table. Which we currently do not allow do be logically decoded.
That normally ends up being harmless, because ReorderBufferCommit() has the
following check:
if
(!RelationIsLogicallyLogged(relation))
goto change_done;
but to reach that check, we first have to map the relfilenode from the
WAL to the corresponding OID:
reloid =
RelidByRelfilenode(change->data.tp.relnode.spcNode,
change->data.tp.relnode.relNode);
That works correctly if there's only one rewrite - the relmapper
contains the data for the new toast table. But if there's been *two*
consecutive rewrites, the relmapper *does not* contain the intermediary
relfilenode of pg_proc. There's no such problem for non-mapped tables,
because historic snapshots allow us to access the relevant data, but the
relmapper isn't mvcc.
Therefore the catalog-rewrite escape hatch of:
/*
* Catalog tuple without data, emitted
while catalog was
* in the process of being rewritten.
*/
if (reloid == InvalidOid &&
change->data.tp.newtuple ==
NULL &&
change->data.tp.oldtuple ==
NULL)
goto change_done;
does not trigger and we run into:
else if (reloid == InvalidOid)
elog(ERROR, "could not map
filenode \"%s\" to relation OID",
relpathperm(change->data.tp.relnode,
MAIN_FORKNUM));
commenting out this error / converting it into a warning makes this case
harmless, but could obviously be problematic in other scenarios.
I suspect the proper fix would be to have a new HEAP_INSERT_NO_LOGICAL
option, and specify that in raw_heap_insert() iff
RelationIsLogicallyLogged(state->rs_old_rel) or something like that.
Attached is a *prototype* patch of that approach. Without the code
level changes the addition to test_decoding's rewrite.sql trigger the
bug, after it they're fixed.
The only reason the scenario I was debugging hit this was that there was
a cluster wide VACUUM FULL a couple times a day, and replication was
several hours behind due to slow network / receiving side.
Now I'm having a beer outside.
Greetings,
Andres Freund
diff --git a/contrib/test_decoding/expected/rewrite.out b/contrib/test_decoding/expected/rewrite.out
index 4dcd4895438..12eaab99b83 100644
--- a/contrib/test_decoding/expected/rewrite.out
+++ b/contrib/test_decoding/expected/rewrite.out
@@ -34,6 +34,407 @@ VACUUM FULL pg_opclass;
VACUUM FULL pg_type;
VACUUM FULL pg_index;
VACUUM FULL pg_database;
+-- ensure there's a catalog table that is toasted.
+CREATE FUNCTION speaketh() RETURNS TEXT IMMUTABLE LANGUAGE SQL AS $f$
+SELECT text $t$
+ACT I
+SCENE I. Elsinore. A platform before the castle.
+
+ FRANCISCO at his post. Enter to him BERNARDO
+
+BERNARDO
+
+ Who's there?
+
+FRANCISCO
+
+ Nay, answer me: stand, and unfold yourself.
+
+BERNARDO
+
+ Long live the king!
+
+FRANCISCO
+
+ Bernardo?
+
+BERNARDO
+
+ He.
+
+FRANCISCO
+
+ You come most carefully upon your hour.
+
+BERNARDO
+
+ 'Tis now struck twelve; get thee to bed, Francisco.
+
+FRANCISCO
+
+ For this relief much thanks: 'tis bitter cold,
+ And I am sick at heart.
+
+BERNARDO
+
+ Have you had quiet guard?
+
+FRANCISCO
+
+ Not a mouse stirring.
+
+BERNARDO
+
+ Well, good night.
+ If you do meet Horatio and Marcellus,
+ The rivals of my watch, bid them make haste.
+
+FRANCISCO
+
+ I think I hear them. Stand, ho! Who's there?
+
+ Enter HORATIO and MARCELLUS
+
+HORATIO
+
+ Friends to this ground.
+
+MARCELLUS
+
+ And liegemen to the Dane.
+
+FRANCISCO
+
+ Give you good night.
+
+MARCELLUS
+
+ O, farewell, honest soldier:
+ Who hath relieved you?
+
+FRANCISCO
+
+ Bernardo has my place.
+ Give you good night.
+
+ Exit
+
+MARCELLUS
+
+ Holla! Bernardo!
+
+BERNARDO
+
+ Say,
+ What, is Horatio there?
+
+HORATIO
+
+ A piece of him.
+
+BERNARDO
+
+ Welcome, Horatio: welcome, good Marcellus.
+
+MARCELLUS
+
+ What, has this thing appear'd again to-night?
+
+BERNARDO
+
+ I have seen nothing.
+
+MARCELLUS
+
+ Horatio says 'tis but our fantasy,
+ And will not let belief take hold of him
+ Touching this dreaded sight, twice seen of us:
+ Therefore I have entreated him along
+ With us to watch the minutes of this night;
+ That if again this apparition come,
+ He may approve our eyes and speak to it.
+
+HORATIO
+
+ Tush, tush, 'twill not appear.
+
+BERNARDO
+
+ Sit down awhile;
+ And let us once again assail your ears,
+ That are so fortified against our story
+ What we have two nights seen.
+
+HORATIO
+
+ Well, sit we down,
+ And let us hear Bernardo speak of this.
+
+BERNARDO
+
+ Last night of all,
+ When yond same star that's westward from the pole
+ Had made his course to illume that part of heaven
+ Where now it burns, Marcellus and myself,
+ The bell then beating one,--
+
+ Enter Ghost
+
+MARCELLUS
+
+ Peace, break thee off; look, where it comes again!
+
+BERNARDO
+
+ In the same figure, like the king that's dead.
+
+MARCELLUS
+
+ Thou art a scholar; speak to it, Horatio.
+
+BERNARDO
+
+ Looks it not like the king? mark it, Horatio.
+
+HORATIO
+
+ Most like: it harrows me with fear and wonder.
+
+BERNARDO
+
+ It would be spoke to.
+
+MARCELLUS
+
+ Question it, Horatio.
+
+HORATIO
+
+ What art thou that usurp'st this time of night,
+ Together with that fair and warlike form
+ In which the majesty of buried Denmark
+ Did sometimes march? by heaven I charge thee, speak!
+
+MARCELLUS
+
+ It is offended.
+
+BERNARDO
+
+ See, it stalks away!
+
+HORATIO
+
+ Stay! speak, speak! I charge thee, speak!
+
+ Exit Ghost
+
+MARCELLUS
+
+ 'Tis gone, and will not answer.
+
+BERNARDO
+
+ How now, Horatio! you tremble and look pale:
+ Is not this something more than fantasy?
+ What think you on't?
+
+HORATIO
+
+ Before my God, I might not this believe
+ Without the sensible and true avouch
+ Of mine own eyes.
+
+MARCELLUS
+
+ Is it not like the king?
+
+HORATIO
+
+ As thou art to thyself:
+ Such was the very armour he had on
+ When he the ambitious Norway combated;
+ So frown'd he once, when, in an angry parle,
+ He smote the sledded Polacks on the ice.
+ 'Tis strange.
+
+MARCELLUS
+
+ Thus twice before, and jump at this dead hour,
+ With martial stalk hath he gone by our watch.
+
+HORATIO
+
+ In what particular thought to work I know not;
+ But in the gross and scope of my opinion,
+ This bodes some strange eruption to our state.
+
+MARCELLUS
+
+ Good now, sit down, and tell me, he that knows,
+ Why this same strict and most observant watch
+ So nightly toils the subject of the land,
+ And why such daily cast of brazen cannon,
+ And foreign mart for implements of war;
+ Why such impress of shipwrights, whose sore task
+ Does not divide the Sunday from the week;
+ What might be toward, that this sweaty haste
+ Doth make the night joint-labourer with the day:
+ Who is't that can inform me?
+
+HORATIO
+
+ That can I;
+ At least, the whisper goes so. Our last king,
+ Whose image even but now appear'd to us,
+ Was, as you know, by Fortinbras of Norway,
+ Thereto prick'd on by a most emulate pride,
+ Dared to the combat; in which our valiant Hamlet--
+ For so this side of our known world esteem'd him--
+ Did slay this Fortinbras; who by a seal'd compact,
+ Well ratified by law and heraldry,
+ Did forfeit, with his life, all those his lands
+ Which he stood seized of, to the conqueror:
+ Against the which, a moiety competent
+ Was gaged by our king; which had return'd
+ To the inheritance of Fortinbras,
+ Had he been vanquisher; as, by the same covenant,
+ And carriage of the article design'd,
+ His fell to Hamlet. Now, sir, young Fortinbras,
+ Of unimproved mettle hot and full,
+ Hath in the skirts of Norway here and there
+ Shark'd up a list of lawless resolutes,
+ For food and diet, to some enterprise
+ That hath a stomach in't; which is no other--
+ As it doth well appear unto our state--
+ But to recover of us, by strong hand
+ And terms compulsatory, those foresaid lands
+ So by his father lost: and this, I take it,
+ Is the main motive of our preparations,
+ The source of this our watch and the chief head
+ Of this post-haste and romage in the land.
+
+BERNARDO
+
+ I think it be no other but e'en so:
+ Well may it sort that this portentous figure
+ Comes armed through our watch; so like the king
+ That was and is the question of these wars.
+
+HORATIO
+
+ A mote it is to trouble the mind's eye.
+ In the most high and palmy state of Rome,
+ A little ere the mightiest Julius fell,
+ The graves stood tenantless and the sheeted dead
+ Did squeak and gibber in the Roman streets:
+ As stars with trains of fire and dews of blood,
+ Disasters in the sun; and the moist star
+ Upon whose influence Neptune's empire stands
+ Was sick almost to doomsday with eclipse:
+ And even the like precurse of fierce events,
+ As harbingers preceding still the fates
+ And prologue to the omen coming on,
+ Have heaven and earth together demonstrated
+ Unto our climatures and countrymen.--
+ But soft, behold! lo, where it comes again!
+
+ Re-enter Ghost
+ I'll cross it, though it blast me. Stay, illusion!
+ If thou hast any sound, or use of voice,
+ Speak to me:
+ If there be any good thing to be done,
+ That may to thee do ease and grace to me,
+ Speak to me:
+
+ Cock crows
+ If thou art privy to thy country's fate,
+ Which, happily, foreknowing may avoid, O, speak!
+ Or if thou hast uphoarded in thy life
+ Extorted treasure in the womb of earth,
+ For which, they say, you spirits oft walk in death,
+ Speak of it: stay, and speak! Stop it, Marcellus.
+
+MARCELLUS
+
+ Shall I strike at it with my partisan?
+
+HORATIO
+
+ Do, if it will not stand.
+
+BERNARDO
+
+ 'Tis here!
+
+HORATIO
+
+ 'Tis here!
+
+MARCELLUS
+
+ 'Tis gone!
+
+ Exit Ghost
+ We do it wrong, being so majestical,
+ To offer it the show of violence;
+ For it is, as the air, invulnerable,
+ And our vain blows malicious mockery.
+
+BERNARDO
+
+ It was about to speak, when the cock crew.
+
+HORATIO
+
+ And then it started like a guilty thing
+ Upon a fearful summons. I have heard,
+ The cock, that is the trumpet to the morn,
+ Doth with his lofty and shrill-sounding throat
+ Awake the god of day; and, at his warning,
+ Whether in sea or fire, in earth or air,
+ The extravagant and erring spirit hies
+ To his confine: and of the truth herein
+ This present object made probation.
+
+MARCELLUS
+
+ It faded on the crowing of the cock.
+ Some say that ever 'gainst that season comes
+ Wherein our Saviour's birth is celebrated,
+ The bird of dawning singeth all night long:
+ And then, they say, no spirit dares stir abroad;
+ The nights are wholesome; then no planets strike,
+ No fairy takes, nor witch hath power to charm,
+ So hallow'd and so gracious is the time.
+
+HORATIO
+
+ So have I heard and do in part believe it.
+ But, look, the morn, in russet mantle clad,
+ Walks o'er the dew of yon high eastward hill:
+ Break we our watch up; and by my advice,
+ Let us impart what we have seen to-night
+ Unto young Hamlet; for, upon my life,
+ This spirit, dumb to us, will speak to him.
+ Do you consent we shall acquaint him with it,
+ As needful in our loves, fitting our duty?
+
+MARCELLUS
+
+ Let's do't, I pray; and I this morning know
+ Where we shall find him most conveniently.
+
+ Exeunt
+$t$
+$f$;
+SELECT pg_relation_size((SELECT reltoastrelid FROM pg_class WHERE oid = 'pg_proc'::regclass)) > 0;
+ ?column?
+----------
+ t
+(1 row)
+
+VACUUM FULL pg_proc;
-- repeated rewrites that fail
BEGIN;
CLUSTER pg_class USING pg_class_oid_index;
@@ -76,6 +477,13 @@ SELECT data FROM pg_logical_slot_get_changes('regression_slot', NULL, NULL, 'inc
COMMIT
(15 rows)
+VACUUM FULL pg_proc;
+VACUUM FULL pg_proc;
+SELECT data FROM pg_logical_slot_get_changes('regression_slot', NULL, NULL, 'include-xids', '0', 'skip-empty-xacts', '1');
+ data
+------
+(0 rows)
+
SELECT pg_drop_replication_slot('regression_slot');
pg_drop_replication_slot
--------------------------
@@ -83,3 +491,4 @@ SELECT pg_drop_replication_slot('regression_slot');
(1 row)
DROP TABLE IF EXISTS replication_example;
+DROP FUNCTION speaketh();
diff --git a/contrib/test_decoding/sql/rewrite.sql b/contrib/test_decoding/sql/rewrite.sql
index 8a7329423de..b3ea848cad0 100644
--- a/contrib/test_decoding/sql/rewrite.sql
+++ b/contrib/test_decoding/sql/rewrite.sql
@@ -28,6 +28,404 @@ VACUUM FULL pg_type;
VACUUM FULL pg_index;
VACUUM FULL pg_database;
+-- ensure there's a catalog table that is toasted.
+CREATE FUNCTION speaketh() RETURNS TEXT IMMUTABLE LANGUAGE SQL AS $f$
+SELECT text $t$
+ACT I
+SCENE I. Elsinore. A platform before the castle.
+
+ FRANCISCO at his post. Enter to him BERNARDO
+
+BERNARDO
+
+ Who's there?
+
+FRANCISCO
+
+ Nay, answer me: stand, and unfold yourself.
+
+BERNARDO
+
+ Long live the king!
+
+FRANCISCO
+
+ Bernardo?
+
+BERNARDO
+
+ He.
+
+FRANCISCO
+
+ You come most carefully upon your hour.
+
+BERNARDO
+
+ 'Tis now struck twelve; get thee to bed, Francisco.
+
+FRANCISCO
+
+ For this relief much thanks: 'tis bitter cold,
+ And I am sick at heart.
+
+BERNARDO
+
+ Have you had quiet guard?
+
+FRANCISCO
+
+ Not a mouse stirring.
+
+BERNARDO
+
+ Well, good night.
+ If you do meet Horatio and Marcellus,
+ The rivals of my watch, bid them make haste.
+
+FRANCISCO
+
+ I think I hear them. Stand, ho! Who's there?
+
+ Enter HORATIO and MARCELLUS
+
+HORATIO
+
+ Friends to this ground.
+
+MARCELLUS
+
+ And liegemen to the Dane.
+
+FRANCISCO
+
+ Give you good night.
+
+MARCELLUS
+
+ O, farewell, honest soldier:
+ Who hath relieved you?
+
+FRANCISCO
+
+ Bernardo has my place.
+ Give you good night.
+
+ Exit
+
+MARCELLUS
+
+ Holla! Bernardo!
+
+BERNARDO
+
+ Say,
+ What, is Horatio there?
+
+HORATIO
+
+ A piece of him.
+
+BERNARDO
+
+ Welcome, Horatio: welcome, good Marcellus.
+
+MARCELLUS
+
+ What, has this thing appear'd again to-night?
+
+BERNARDO
+
+ I have seen nothing.
+
+MARCELLUS
+
+ Horatio says 'tis but our fantasy,
+ And will not let belief take hold of him
+ Touching this dreaded sight, twice seen of us:
+ Therefore I have entreated him along
+ With us to watch the minutes of this night;
+ That if again this apparition come,
+ He may approve our eyes and speak to it.
+
+HORATIO
+
+ Tush, tush, 'twill not appear.
+
+BERNARDO
+
+ Sit down awhile;
+ And let us once again assail your ears,
+ That are so fortified against our story
+ What we have two nights seen.
+
+HORATIO
+
+ Well, sit we down,
+ And let us hear Bernardo speak of this.
+
+BERNARDO
+
+ Last night of all,
+ When yond same star that's westward from the pole
+ Had made his course to illume that part of heaven
+ Where now it burns, Marcellus and myself,
+ The bell then beating one,--
+
+ Enter Ghost
+
+MARCELLUS
+
+ Peace, break thee off; look, where it comes again!
+
+BERNARDO
+
+ In the same figure, like the king that's dead.
+
+MARCELLUS
+
+ Thou art a scholar; speak to it, Horatio.
+
+BERNARDO
+
+ Looks it not like the king? mark it, Horatio.
+
+HORATIO
+
+ Most like: it harrows me with fear and wonder.
+
+BERNARDO
+
+ It would be spoke to.
+
+MARCELLUS
+
+ Question it, Horatio.
+
+HORATIO
+
+ What art thou that usurp'st this time of night,
+ Together with that fair and warlike form
+ In which the majesty of buried Denmark
+ Did sometimes march? by heaven I charge thee, speak!
+
+MARCELLUS
+
+ It is offended.
+
+BERNARDO
+
+ See, it stalks away!
+
+HORATIO
+
+ Stay! speak, speak! I charge thee, speak!
+
+ Exit Ghost
+
+MARCELLUS
+
+ 'Tis gone, and will not answer.
+
+BERNARDO
+
+ How now, Horatio! you tremble and look pale:
+ Is not this something more than fantasy?
+ What think you on't?
+
+HORATIO
+
+ Before my God, I might not this believe
+ Without the sensible and true avouch
+ Of mine own eyes.
+
+MARCELLUS
+
+ Is it not like the king?
+
+HORATIO
+
+ As thou art to thyself:
+ Such was the very armour he had on
+ When he the ambitious Norway combated;
+ So frown'd he once, when, in an angry parle,
+ He smote the sledded Polacks on the ice.
+ 'Tis strange.
+
+MARCELLUS
+
+ Thus twice before, and jump at this dead hour,
+ With martial stalk hath he gone by our watch.
+
+HORATIO
+
+ In what particular thought to work I know not;
+ But in the gross and scope of my opinion,
+ This bodes some strange eruption to our state.
+
+MARCELLUS
+
+ Good now, sit down, and tell me, he that knows,
+ Why this same strict and most observant watch
+ So nightly toils the subject of the land,
+ And why such daily cast of brazen cannon,
+ And foreign mart for implements of war;
+ Why such impress of shipwrights, whose sore task
+ Does not divide the Sunday from the week;
+ What might be toward, that this sweaty haste
+ Doth make the night joint-labourer with the day:
+ Who is't that can inform me?
+
+HORATIO
+
+ That can I;
+ At least, the whisper goes so. Our last king,
+ Whose image even but now appear'd to us,
+ Was, as you know, by Fortinbras of Norway,
+ Thereto prick'd on by a most emulate pride,
+ Dared to the combat; in which our valiant Hamlet--
+ For so this side of our known world esteem'd him--
+ Did slay this Fortinbras; who by a seal'd compact,
+ Well ratified by law and heraldry,
+ Did forfeit, with his life, all those his lands
+ Which he stood seized of, to the conqueror:
+ Against the which, a moiety competent
+ Was gaged by our king; which had return'd
+ To the inheritance of Fortinbras,
+ Had he been vanquisher; as, by the same covenant,
+ And carriage of the article design'd,
+ His fell to Hamlet. Now, sir, young Fortinbras,
+ Of unimproved mettle hot and full,
+ Hath in the skirts of Norway here and there
+ Shark'd up a list of lawless resolutes,
+ For food and diet, to some enterprise
+ That hath a stomach in't; which is no other--
+ As it doth well appear unto our state--
+ But to recover of us, by strong hand
+ And terms compulsatory, those foresaid lands
+ So by his father lost: and this, I take it,
+ Is the main motive of our preparations,
+ The source of this our watch and the chief head
+ Of this post-haste and romage in the land.
+
+BERNARDO
+
+ I think it be no other but e'en so:
+ Well may it sort that this portentous figure
+ Comes armed through our watch; so like the king
+ That was and is the question of these wars.
+
+HORATIO
+
+ A mote it is to trouble the mind's eye.
+ In the most high and palmy state of Rome,
+ A little ere the mightiest Julius fell,
+ The graves stood tenantless and the sheeted dead
+ Did squeak and gibber in the Roman streets:
+ As stars with trains of fire and dews of blood,
+ Disasters in the sun; and the moist star
+ Upon whose influence Neptune's empire stands
+ Was sick almost to doomsday with eclipse:
+ And even the like precurse of fierce events,
+ As harbingers preceding still the fates
+ And prologue to the omen coming on,
+ Have heaven and earth together demonstrated
+ Unto our climatures and countrymen.--
+ But soft, behold! lo, where it comes again!
+
+ Re-enter Ghost
+ I'll cross it, though it blast me. Stay, illusion!
+ If thou hast any sound, or use of voice,
+ Speak to me:
+ If there be any good thing to be done,
+ That may to thee do ease and grace to me,
+ Speak to me:
+
+ Cock crows
+ If thou art privy to thy country's fate,
+ Which, happily, foreknowing may avoid, O, speak!
+ Or if thou hast uphoarded in thy life
+ Extorted treasure in the womb of earth,
+ For which, they say, you spirits oft walk in death,
+ Speak of it: stay, and speak! Stop it, Marcellus.
+
+MARCELLUS
+
+ Shall I strike at it with my partisan?
+
+HORATIO
+
+ Do, if it will not stand.
+
+BERNARDO
+
+ 'Tis here!
+
+HORATIO
+
+ 'Tis here!
+
+MARCELLUS
+
+ 'Tis gone!
+
+ Exit Ghost
+ We do it wrong, being so majestical,
+ To offer it the show of violence;
+ For it is, as the air, invulnerable,
+ And our vain blows malicious mockery.
+
+BERNARDO
+
+ It was about to speak, when the cock crew.
+
+HORATIO
+
+ And then it started like a guilty thing
+ Upon a fearful summons. I have heard,
+ The cock, that is the trumpet to the morn,
+ Doth with his lofty and shrill-sounding throat
+ Awake the god of day; and, at his warning,
+ Whether in sea or fire, in earth or air,
+ The extravagant and erring spirit hies
+ To his confine: and of the truth herein
+ This present object made probation.
+
+MARCELLUS
+
+ It faded on the crowing of the cock.
+ Some say that ever 'gainst that season comes
+ Wherein our Saviour's birth is celebrated,
+ The bird of dawning singeth all night long:
+ And then, they say, no spirit dares stir abroad;
+ The nights are wholesome; then no planets strike,
+ No fairy takes, nor witch hath power to charm,
+ So hallow'd and so gracious is the time.
+
+HORATIO
+
+ So have I heard and do in part believe it.
+ But, look, the morn, in russet mantle clad,
+ Walks o'er the dew of yon high eastward hill:
+ Break we our watch up; and by my advice,
+ Let us impart what we have seen to-night
+ Unto young Hamlet; for, upon my life,
+ This spirit, dumb to us, will speak to him.
+ Do you consent we shall acquaint him with it,
+ As needful in our loves, fitting our duty?
+
+MARCELLUS
+
+ Let's do't, I pray; and I this morning know
+ Where we shall find him most conveniently.
+
+ Exeunt
+$t$
+$f$;
+SELECT pg_relation_size((SELECT reltoastrelid FROM pg_class WHERE oid = 'pg_proc'::regclass)) > 0;
+
+VACUUM FULL pg_proc;
+
-- repeated rewrites that fail
BEGIN;
CLUSTER pg_class USING pg_class_oid_index;
@@ -57,6 +455,11 @@ COMMIT;
CHECKPOINT;
SELECT data FROM pg_logical_slot_get_changes('regression_slot', NULL, NULL, 'include-xids', '0', 'skip-empty-xacts', '1');
-SELECT pg_drop_replication_slot('regression_slot');
+VACUUM FULL pg_proc;
+VACUUM FULL pg_proc;
+SELECT data FROM pg_logical_slot_get_changes('regression_slot', NULL, NULL, 'include-xids', '0', 'skip-empty-xacts', '1');
+
+SELECT pg_drop_replication_slot('regression_slot');
DROP TABLE IF EXISTS replication_example;
+DROP FUNCTION speaketh();
diff --git a/src/backend/access/heap/heapam.c b/src/backend/access/heap/heapam.c
index 56f1d82f962..f971705507e 100644
--- a/src/backend/access/heap/heapam.c
+++ b/src/backend/access/heap/heapam.c
@@ -2551,7 +2551,7 @@ heap_insert(Relation relation, HeapTuple tup, CommandId cid,
* page write, so make sure it's included even if we take a full-page
* image. (XXX We could alternatively store a pointer into the FPW).
*/
- if (RelationIsLogicallyLogged(relation))
+ if (RelationIsLogicallyLogged(relation) && !(options & HEAP_INSERT_NO_LOGICAL))
{
xlrec.flags |= XLH_INSERT_CONTAINS_NEW_TUPLE;
bufflags |= REGBUF_KEEP_DATA;
diff --git a/src/backend/access/heap/rewriteheap.c b/src/backend/access/heap/rewriteheap.c
index 85f92973c95..6bae129f6a6 100644
--- a/src/backend/access/heap/rewriteheap.c
+++ b/src/backend/access/heap/rewriteheap.c
@@ -652,10 +652,18 @@ raw_heap_insert(RewriteState state, HeapTuple tup)
heaptup = tup;
}
else if (HeapTupleHasExternal(tup) || tup->t_len > TOAST_TUPLE_THRESHOLD)
+ {
+ int options = HEAP_INSERT_SKIP_FSM;
+
+ if (!state->rs_use_wal)
+ options |= HEAP_INSERT_SKIP_WAL;
+
+ if (!RelationIsLogicallyLogged(state->rs_old_rel))
+ options |= HEAP_INSERT_NO_LOGICAL;
+
heaptup = toast_insert_or_update(state->rs_new_rel, tup, NULL,
- HEAP_INSERT_SKIP_FSM |
- (state->rs_use_wal ?
- 0 : HEAP_INSERT_SKIP_WAL));
+ options);
+ }
else
heaptup = tup;
diff --git a/src/include/access/heapam.h b/src/include/access/heapam.h
index ca5cad7497f..40e153f71ad 100644
--- a/src/include/access/heapam.h
+++ b/src/include/access/heapam.h
@@ -29,6 +29,7 @@
#define HEAP_INSERT_SKIP_FSM 0x0002
#define HEAP_INSERT_FROZEN 0x0004
#define HEAP_INSERT_SPECULATIVE 0x0008
+#define HEAP_INSERT_NO_LOGICAL 0x0010
typedef struct BulkInsertStateData *BulkInsertState;