aboutsummaryrefslogtreecommitdiff
path: root/src/backend/replication/logical/worker.c
diff options
context:
space:
mode:
authorAlvaro Herrera <alvherre@alvh.no-ip.org>2018-03-14 21:34:26 -0300
committerAlvaro Herrera <alvherre@alvh.no-ip.org>2018-03-14 21:34:26 -0300
commit24c0a6c649768f428929e76dd7f5012ec9b93ce1 (patch)
treec0b26eba9aaacb6169b3ecada3c19e5229c49d80 /src/backend/replication/logical/worker.c
parent8df5a1c868cc28f89ac6221cff8e2b5c952d0eb6 (diff)
downloadpostgresql-24c0a6c649768f428929e76dd7f5012ec9b93ce1.tar.gz
postgresql-24c0a6c649768f428929e76dd7f5012ec9b93ce1.zip
logical replication: fix OID type mapping mechanism
The logical replication type map seems to have been misused by its only caller -- it would try to use the remote OID as input for local type routines, which unsurprisingly could result in bogus "cache lookup failed for type XYZ" errors, or random other type names being picked up if they happened to use the right OID. Fix that, changing Oid logicalrep_typmap_getid(Oid remoteid) to char *logicalrep_typmap_gettypname(Oid remoteid) which is more useful. If the remote type is not part of the typmap, this simply prints "unrecognized type" instead of choking trying to figure out -- a pointless exercise (because the only input for that comes from replication messages, which are not under the local node's control) and dangerous to boot, when called from within an error context callback. Once that is done, it comes to light that the local OID in the typmap entry was not being used for anything; the type/schema names are what we need, so remove local type OID from that struct. Once you do that, it becomes pointless to attach a callback to regular syscache invalidation. So remove that also. Reported-by: Dang Minh Huong Author: Masahiko Sawada Reviewed-by: Álvaro Herrera, Petr Jelínek, Dang Minh Huong, Atsushi Torikoshi Discussion: https://postgr.es/m/75DB81BEEA95B445AE6D576A0A5C9E936A6BE964@BPXM05GP.gisp.nec.co.jp Discussion: https://postgr.es/m/75DB81BEEA95B445AE6D576A0A5C9E936A6C4B0A@BPXM05GP.gisp.nec.co.jp
Diffstat (limited to 'src/backend/replication/logical/worker.c')
-rw-r--r--src/backend/replication/logical/worker.c63
1 files changed, 41 insertions, 22 deletions
diff --git a/src/backend/replication/logical/worker.c b/src/backend/replication/logical/worker.c
index 04985c9f91d..fdace7eea2b 100644
--- a/src/backend/replication/logical/worker.c
+++ b/src/backend/replication/logical/worker.c
@@ -100,8 +100,9 @@ static dlist_head lsn_mapping = DLIST_STATIC_INIT(lsn_mapping);
typedef struct SlotErrCallbackArg
{
- LogicalRepRelation *rel;
- int attnum;
+ LogicalRepRelMapEntry *rel;
+ int local_attnum;
+ int remote_attnum;
} SlotErrCallbackArg;
static MemoryContext ApplyMessageContext = NULL;
@@ -282,19 +283,29 @@ static void
slot_store_error_callback(void *arg)
{
SlotErrCallbackArg *errarg = (SlotErrCallbackArg *) arg;
+ LogicalRepRelMapEntry *rel;
+ char *remotetypname;
Oid remotetypoid,
localtypoid;
- if (errarg->attnum < 0)
+ /* Nothing to do if remote attribute number is not set */
+ if (errarg->remote_attnum < 0)
return;
- remotetypoid = errarg->rel->atttyps[errarg->attnum];
- localtypoid = logicalrep_typmap_getid(remotetypoid);
+ rel = errarg->rel;
+ remotetypoid = rel->remoterel.atttyps[errarg->remote_attnum];
+
+ /* Fetch remote type name from the LogicalRepTypMap cache */
+ remotetypname = logicalrep_typmap_gettypname(remotetypoid);
+
+ /* Fetch local type OID from the local sys cache */
+ localtypoid = get_atttype(rel->localreloid, errarg->local_attnum + 1);
+
errcontext("processing remote data for replication target relation \"%s.%s\" column \"%s\", "
"remote type %s, local type %s",
- errarg->rel->nspname, errarg->rel->relname,
- errarg->rel->attnames[errarg->attnum],
- format_type_be(remotetypoid),
+ rel->remoterel.nspname, rel->remoterel.relname,
+ rel->remoterel.attnames[errarg->remote_attnum],
+ remotetypname,
format_type_be(localtypoid));
}
@@ -315,8 +326,9 @@ slot_store_cstrings(TupleTableSlot *slot, LogicalRepRelMapEntry *rel,
ExecClearTuple(slot);
/* Push callback + info on the error context stack */
- errarg.rel = &rel->remoterel;
- errarg.attnum = -1;
+ errarg.rel = rel;
+ errarg.local_attnum = -1;
+ errarg.remote_attnum = -1;
errcallback.callback = slot_store_error_callback;
errcallback.arg = (void *) &errarg;
errcallback.previous = error_context_stack;
@@ -334,14 +346,17 @@ slot_store_cstrings(TupleTableSlot *slot, LogicalRepRelMapEntry *rel,
Oid typinput;
Oid typioparam;
- errarg.attnum = remoteattnum;
+ errarg.local_attnum = i;
+ errarg.remote_attnum = remoteattnum;
getTypeInputInfo(att->atttypid, &typinput, &typioparam);
- slot->tts_values[i] = OidInputFunctionCall(typinput,
- values[remoteattnum],
- typioparam,
- att->atttypmod);
+ slot->tts_values[i] =
+ OidInputFunctionCall(typinput, values[remoteattnum],
+ typioparam, att->atttypmod);
slot->tts_isnull[i] = false;
+
+ errarg.local_attnum = -1;
+ errarg.remote_attnum = -1;
}
else
{
@@ -380,8 +395,9 @@ slot_modify_cstrings(TupleTableSlot *slot, LogicalRepRelMapEntry *rel,
ExecClearTuple(slot);
/* Push callback + info on the error context stack */
- errarg.rel = &rel->remoterel;
- errarg.attnum = -1;
+ errarg.rel = rel;
+ errarg.local_attnum = -1;
+ errarg.remote_attnum = -1;
errcallback.callback = slot_store_error_callback;
errcallback.arg = (void *) &errarg;
errcallback.previous = error_context_stack;
@@ -404,14 +420,17 @@ slot_modify_cstrings(TupleTableSlot *slot, LogicalRepRelMapEntry *rel,
Oid typinput;
Oid typioparam;
- errarg.attnum = remoteattnum;
+ errarg.local_attnum = i;
+ errarg.remote_attnum = remoteattnum;
getTypeInputInfo(att->atttypid, &typinput, &typioparam);
- slot->tts_values[i] = OidInputFunctionCall(typinput,
- values[remoteattnum],
- typioparam,
- att->atttypmod);
+ slot->tts_values[i] =
+ OidInputFunctionCall(typinput, values[remoteattnum],
+ typioparam, att->atttypmod);
slot->tts_isnull[i] = false;
+
+ errarg.local_attnum = -1;
+ errarg.remote_attnum = -1;
}
else
{