Hi Sawada-san,

Sorry for my late response.

On 2017/12/05 0:11, Masahiko Sawada wrote:
There is one more case that user-defined data type is not supported in Logical 
Replication.
That is when remote data type's name does not exist in SUBSCRIBE.

In relation.c:logicalrep_typmap_gettypname
We search OID in syscache by remote's data type name and mapping it, if it does 
not exist in syscache
We will be faced with the bellow error.

         if (!OidIsValid(entry->typoid))
                 ereport(ERROR,
                                 
(errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),
                                  errmsg("data type \"%s.%s\" required for logical 
replication does not exist",
                                                 entry->nspname, 
entry->typname)));

I think, it is not necessary to check typoid here in order to avoid above case, 
is that right?
I think it's not right. We should end up with an error in the case where the same type name doesn't exist on subscriber. With your proposed patch, logicalrep_typmap_gettypname() can return an invalid string (entry->typname) in that case, which can be a cause of SEGV.
Thanks, I think you are right.
# I thought that entry->typname was received from walsender, and it is already be qualified in logicalrep_write_typ. # But we also need check it in subscriber, because it could be lost info in transmission. Also we do not need to fix for the case above too, because user can change type name by ALTER TYPE statement. I attached the patch, which based on your patch with a bit of modified messages.

---
Thanks and best regards,
Dang Minh Huong


diff --git a/src/backend/replication/logical/relation.c 
b/src/backend/replication/logical/relation.c
index 46e515e4b6..0ae676a8d6 100644
--- a/src/backend/replication/logical/relation.c
+++ b/src/backend/replication/logical/relation.c
@@ -441,8 +441,8 @@ logicalrep_typmap_update(LogicalRepTyp *remotetyp)
 /*
  * Fetch type info from the cache.
  */
-Oid
-logicalrep_typmap_getid(Oid remoteid)
+char *
+logicalrep_typmap_gettypname(Oid remoteid)
 {
        LogicalRepTyp *entry;
        bool            found;
@@ -453,9 +453,9 @@ logicalrep_typmap_getid(Oid remoteid)
        {
                if (!get_typisdefined(remoteid))
                        ereport(ERROR,
-                                       (errmsg("built-in type %u not found", 
remoteid),
+                                       (errmsg("built-in type oid %u not 
found", remoteid),
                                         errhint("This can be caused by having 
a publisher with a higher PostgreSQL major version than the subscriber.")));
-               return remoteid;
+               return format_type_be(remoteid);
        }
 
        if (LogicalRepTypMap == NULL)
@@ -466,12 +466,12 @@ logicalrep_typmap_getid(Oid remoteid)
                                                HASH_FIND, &found);
 
        if (!found)
-               elog(ERROR, "no type map entry for remote type %u",
+               elog(ERROR, "no type map entry for remote type oid %u",
                         remoteid);
 
-       /* Found and mapped, return the oid. */
+       /* Found and mapped, return the type name. */
        if (OidIsValid(entry->typoid))
-               return entry->typoid;
+               return entry->typname;
 
        /* Otherwise, try to map to local type. */
        nspoid = LookupExplicitNamespace(entry->nspname, true);
@@ -488,5 +488,6 @@ logicalrep_typmap_getid(Oid remoteid)
                                 errmsg("data type \"%s.%s\" required for 
logical replication does not exist",
                                                entry->nspname, 
entry->typname)));
 
-       return entry->typoid;
+       /* Return type name */
+       return entry->typname;
 }
diff --git a/src/backend/replication/logical/worker.c 
b/src/backend/replication/logical/worker.c
index eedc3a8816..6cf037684b 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                     remote_attnum;
+       int                     local_attnum;
 } SlotErrCallbackArg;
 
 static MemoryContext ApplyMessageContext = NULL;
@@ -282,17 +283,20 @@ slot_store_error_callback(void *arg)
        SlotErrCallbackArg *errarg = (SlotErrCallbackArg *) arg;
        Oid                     remotetypoid,
                                localtypoid;
+       char            *remotetypname;
 
-       if (errarg->attnum < 0)
+       if (errarg->remote_attnum < 0)
                return;
 
-       remotetypoid = errarg->rel->atttyps[errarg->attnum];
-       localtypoid = logicalrep_typmap_getid(remotetypoid);
+       remotetypoid = errarg->rel->remoterel.atttyps[errarg->remote_attnum];
+       remotetypname = logicalrep_typmap_gettypname(remotetypoid);
+       localtypoid = get_atttype(errarg->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),
+                          "remote type \"%s\", local type \"%s\"",
+                          errarg->rel->remoterel.nspname, 
errarg->rel->remoterel.relname,
+                          
errarg->rel->remoterel.attnames[errarg->remote_attnum],
+                          remotetypname,
                           format_type_be(localtypoid));
 }
 
@@ -313,8 +317,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;
@@ -332,7 +337,8 @@ 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,
@@ -378,8 +384,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;
@@ -402,7 +409,8 @@ 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,
diff --git a/src/include/replication/logicalrelation.h 
b/src/include/replication/logicalrelation.h
index 8352705650..563bb4f37d 100644
--- a/src/include/replication/logicalrelation.h
+++ b/src/include/replication/logicalrelation.h
@@ -37,6 +37,6 @@ extern void logicalrep_rel_close(LogicalRepRelMapEntry *rel,
                                         LOCKMODE lockmode);
 
 extern void logicalrep_typmap_update(LogicalRepTyp *remotetyp);
-extern Oid     logicalrep_typmap_getid(Oid remoteid);
+extern char    *logicalrep_typmap_gettypname(Oid remoteid);
 
 #endif                                                 /* LOGICALRELATION_H */

Reply via email to