Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commit24c0a6c

Browse files
committed
logical replication: fix OID type mapping mechanism
The logical replication type map seems to have been misused by its onlycaller -- it would try to use the remote OID as input for local typeroutines, which unsurprisingly could result in bogus "cache lookupfailed for type XYZ" errors, or random other type names being picked upif they happened to use the right OID. Fix that, changingOid logicalrep_typmap_getid(Oid remoteid) tochar *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 tofigure out -- a pointless exercise (because the only input for thatcomes from replication messages, which are not under the local node'scontrol) and dangerous to boot, when called from within an error contextcallback.Once that is done, it comes to light that the local OID in the typmapentry was not being used for anything; the type/schema names are what weneed, so remove local type OID from that struct.Once you do that, it becomes pointless to attach a callback to regularsyscache invalidation. So remove that also.Reported-by: Dang Minh HuongAuthor: Masahiko SawadaReviewed-by: Álvaro Herrera, Petr Jelínek, Dang Minh Huong, Atsushi TorikoshiDiscussion:https://postgr.es/m/75DB81BEEA95B445AE6D576A0A5C9E936A6BE964@BPXM05GP.gisp.nec.co.jpDiscussion:https://postgr.es/m/75DB81BEEA95B445AE6D576A0A5C9E936A6C4B0A@BPXM05GP.gisp.nec.co.jp
1 parent8df5a1c commit24c0a6c

File tree

4 files changed

+74
-88
lines changed

4 files changed

+74
-88
lines changed

‎src/backend/replication/logical/relation.c

Lines changed: 29 additions & 61 deletions
Original file line numberDiff line numberDiff line change
@@ -35,8 +35,6 @@ static MemoryContext LogicalRepRelMapContext = NULL;
3535
staticHTAB*LogicalRepRelMap=NULL;
3636
staticHTAB*LogicalRepTypMap=NULL;
3737

38-
staticvoidlogicalrep_typmap_invalidate_cb(Datumarg,intcacheid,
39-
uint32hashvalue);
4038

4139
/*
4240
* Relcache invalidation callback for our relation map cache.
@@ -115,8 +113,6 @@ logicalrep_relmap_init(void)
115113
/* Watch for invalidation events. */
116114
CacheRegisterRelcacheCallback(logicalrep_relmap_invalidate_cb,
117115
(Datum)0);
118-
CacheRegisterSyscacheCallback(TYPEOID,logicalrep_typmap_invalidate_cb,
119-
(Datum)0);
120116
}
121117

122118
/*
@@ -375,27 +371,6 @@ logicalrep_rel_close(LogicalRepRelMapEntry *rel, LOCKMODE lockmode)
375371
rel->localrel=NULL;
376372
}
377373

378-
379-
/*
380-
* Type cache invalidation callback for our type map cache.
381-
*/
382-
staticvoid
383-
logicalrep_typmap_invalidate_cb(Datumarg,intcacheid,uint32hashvalue)
384-
{
385-
HASH_SEQ_STATUSstatus;
386-
LogicalRepTyp*entry;
387-
388-
/* Just to be sure. */
389-
if (LogicalRepTypMap==NULL)
390-
return;
391-
392-
/* invalidate all cache entries */
393-
hash_seq_init(&status,LogicalRepTypMap);
394-
395-
while ((entry= (LogicalRepTyp*)hash_seq_search(&status))!=NULL)
396-
entry->typoid=InvalidOid;
397-
}
398-
399374
/*
400375
* Free the type map cache entry data.
401376
*/
@@ -404,8 +379,6 @@ logicalrep_typmap_free_entry(LogicalRepTyp *entry)
404379
{
405380
pfree(entry->nspname);
406381
pfree(entry->typname);
407-
408-
entry->typoid=InvalidOid;
409382
}
410383

411384
/*
@@ -436,58 +409,53 @@ logicalrep_typmap_update(LogicalRepTyp *remotetyp)
436409
entry->nspname=pstrdup(remotetyp->nspname);
437410
entry->typname=pstrdup(remotetyp->typname);
438411
MemoryContextSwitchTo(oldctx);
439-
entry->typoid=InvalidOid;
440412
}
441413

442414
/*
443-
* Fetch type info from the cache.
415+
* Fetch type name from the cache by remote type OID.
416+
*
417+
* Return a substitute value if we cannot find the data type; no message is
418+
* sent to the log in that case, because this is used by error callback
419+
* already.
444420
*/
445-
Oid
446-
logicalrep_typmap_getid(Oidremoteid)
421+
char*
422+
logicalrep_typmap_gettypname(Oidremoteid)
447423
{
448424
LogicalRepTyp*entry;
449425
boolfound;
450-
Oidnspoid;
451426

452427
/* Internal types are mapped directly. */
453428
if (remoteid<FirstNormalObjectId)
454429
{
455430
if (!get_typisdefined(remoteid))
456-
ereport(ERROR,
457-
(errmsg("built-in type %u not found",remoteid),
458-
errhint("This can be caused by having a publisher with a higher PostgreSQL major version than the subscriber.")));
459-
returnremoteid;
431+
{
432+
/*
433+
* This can be caused by having a publisher with a higher
434+
* PostgreSQL major version than the subscriber.
435+
*/
436+
returnpsprintf("unrecognized %u",remoteid);
437+
}
438+
439+
returnformat_type_be(remoteid);
460440
}
461441

462442
if (LogicalRepTypMap==NULL)
463-
logicalrep_relmap_init();
443+
{
444+
/*
445+
* If the typemap is not initialized yet, we cannot possibly attempt
446+
* to search the hash table; but there's no way we know the type
447+
* locally yet, since we haven't received a message about this type,
448+
* so this is the best we can do.
449+
*/
450+
returnpsprintf("unrecognized %u",remoteid);
451+
}
464452

465-
/*Try findingthe mapping. */
453+
/*searchthe mapping */
466454
entry=hash_search(LogicalRepTypMap, (void*)&remoteid,
467455
HASH_FIND,&found);
468-
469456
if (!found)
470-
elog(ERROR,"no type map entry for remote type %u",
471-
remoteid);
472-
473-
/* Found and mapped, return the oid. */
474-
if (OidIsValid(entry->typoid))
475-
returnentry->typoid;
476-
477-
/* Otherwise, try to map to local type. */
478-
nspoid=LookupExplicitNamespace(entry->nspname, true);
479-
if (OidIsValid(nspoid))
480-
entry->typoid=GetSysCacheOid2(TYPENAMENSP,
481-
PointerGetDatum(entry->typname),
482-
ObjectIdGetDatum(nspoid));
483-
else
484-
entry->typoid=InvalidOid;
485-
486-
if (!OidIsValid(entry->typoid))
487-
ereport(ERROR,
488-
(errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),
489-
errmsg("data type \"%s.%s\" required for logical replication does not exist",
490-
entry->nspname,entry->typname)));
457+
returnpsprintf("unrecognized %u",remoteid);
491458

492-
returnentry->typoid;
459+
Assert(OidIsValid(entry->remoteid));
460+
returnpsprintf("%s.%s",entry->nspname,entry->typname);
493461
}

‎src/backend/replication/logical/worker.c

Lines changed: 41 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -100,8 +100,9 @@ static dlist_head lsn_mapping = DLIST_STATIC_INIT(lsn_mapping);
100100

101101
typedefstructSlotErrCallbackArg
102102
{
103-
LogicalRepRelation*rel;
104-
intattnum;
103+
LogicalRepRelMapEntry*rel;
104+
intlocal_attnum;
105+
intremote_attnum;
105106
}SlotErrCallbackArg;
106107

107108
staticMemoryContextApplyMessageContext=NULL;
@@ -282,19 +283,29 @@ static void
282283
slot_store_error_callback(void*arg)
283284
{
284285
SlotErrCallbackArg*errarg= (SlotErrCallbackArg*)arg;
286+
LogicalRepRelMapEntry*rel;
287+
char*remotetypname;
285288
Oidremotetypoid,
286289
localtypoid;
287290

288-
if (errarg->attnum<0)
291+
/* Nothing to do if remote attribute number is not set */
292+
if (errarg->remote_attnum<0)
289293
return;
290294

291-
remotetypoid=errarg->rel->atttyps[errarg->attnum];
292-
localtypoid=logicalrep_typmap_getid(remotetypoid);
295+
rel=errarg->rel;
296+
remotetypoid=rel->remoterel.atttyps[errarg->remote_attnum];
297+
298+
/* Fetch remote type name from the LogicalRepTypMap cache */
299+
remotetypname=logicalrep_typmap_gettypname(remotetypoid);
300+
301+
/* Fetch local type OID from the local sys cache */
302+
localtypoid=get_atttype(rel->localreloid,errarg->local_attnum+1);
303+
293304
errcontext("processing remote data for replication target relation \"%s.%s\" column \"%s\", "
294305
"remote type %s, local type %s",
295-
errarg->rel->nspname,errarg->rel->relname,
296-
errarg->rel->attnames[errarg->attnum],
297-
format_type_be(remotetypoid),
306+
rel->remoterel.nspname,rel->remoterel.relname,
307+
rel->remoterel.attnames[errarg->remote_attnum],
308+
remotetypname,
298309
format_type_be(localtypoid));
299310
}
300311

@@ -315,8 +326,9 @@ slot_store_cstrings(TupleTableSlot *slot, LogicalRepRelMapEntry *rel,
315326
ExecClearTuple(slot);
316327

317328
/* Push callback + info on the error context stack */
318-
errarg.rel=&rel->remoterel;
319-
errarg.attnum=-1;
329+
errarg.rel=rel;
330+
errarg.local_attnum=-1;
331+
errarg.remote_attnum=-1;
320332
errcallback.callback=slot_store_error_callback;
321333
errcallback.arg= (void*)&errarg;
322334
errcallback.previous=error_context_stack;
@@ -334,14 +346,17 @@ slot_store_cstrings(TupleTableSlot *slot, LogicalRepRelMapEntry *rel,
334346
Oidtypinput;
335347
Oidtypioparam;
336348

337-
errarg.attnum=remoteattnum;
349+
errarg.local_attnum=i;
350+
errarg.remote_attnum=remoteattnum;
338351

339352
getTypeInputInfo(att->atttypid,&typinput,&typioparam);
340-
slot->tts_values[i]=OidInputFunctionCall(typinput,
341-
values[remoteattnum],
342-
typioparam,
343-
att->atttypmod);
353+
slot->tts_values[i]=
354+
OidInputFunctionCall(typinput,values[remoteattnum],
355+
typioparam,att->atttypmod);
344356
slot->tts_isnull[i]= false;
357+
358+
errarg.local_attnum=-1;
359+
errarg.remote_attnum=-1;
345360
}
346361
else
347362
{
@@ -380,8 +395,9 @@ slot_modify_cstrings(TupleTableSlot *slot, LogicalRepRelMapEntry *rel,
380395
ExecClearTuple(slot);
381396

382397
/* Push callback + info on the error context stack */
383-
errarg.rel=&rel->remoterel;
384-
errarg.attnum=-1;
398+
errarg.rel=rel;
399+
errarg.local_attnum=-1;
400+
errarg.remote_attnum=-1;
385401
errcallback.callback=slot_store_error_callback;
386402
errcallback.arg= (void*)&errarg;
387403
errcallback.previous=error_context_stack;
@@ -404,14 +420,17 @@ slot_modify_cstrings(TupleTableSlot *slot, LogicalRepRelMapEntry *rel,
404420
Oidtypinput;
405421
Oidtypioparam;
406422

407-
errarg.attnum=remoteattnum;
423+
errarg.local_attnum=i;
424+
errarg.remote_attnum=remoteattnum;
408425

409426
getTypeInputInfo(att->atttypid,&typinput,&typioparam);
410-
slot->tts_values[i]=OidInputFunctionCall(typinput,
411-
values[remoteattnum],
412-
typioparam,
413-
att->atttypmod);
427+
slot->tts_values[i]=
428+
OidInputFunctionCall(typinput,values[remoteattnum],
429+
typioparam,att->atttypmod);
414430
slot->tts_isnull[i]= false;
431+
432+
errarg.local_attnum=-1;
433+
errarg.remote_attnum=-1;
415434
}
416435
else
417436
{

‎src/include/replication/logicalproto.h

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -55,10 +55,9 @@ typedef struct LogicalRepRelation
5555
/* Type mapping info */
5656
typedefstructLogicalRepTyp
5757
{
58-
Oidremoteid;/* unique id of the type */
59-
char*nspname;/* schema name */
60-
char*typname;/* name of the type */
61-
Oidtypoid;/* local type Oid */
58+
Oidremoteid;/* unique id of the remote type */
59+
char*nspname;/* schema name of remote type */
60+
char*typname;/* name of the remote type */
6261
}LogicalRepTyp;
6362

6463
/* Transaction info */

‎src/include/replication/logicalrelation.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,6 @@ extern void logicalrep_rel_close(LogicalRepRelMapEntry *rel,
3737
LOCKMODElockmode);
3838

3939
externvoidlogicalrep_typmap_update(LogicalRepTyp*remotetyp);
40-
externOidlogicalrep_typmap_getid(Oidremoteid);
40+
externchar*logicalrep_typmap_gettypname(Oidremoteid);
4141

4242
#endif/* LOGICALRELATION_H */

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp