Re: writable FDWs / update targets confusion - Mailing list pgsql-hackers

From Albe Laurenz
Subject Re: writable FDWs / update targets confusion
Date
Msg-id A737B7A37273E048B164557ADEF4A58B17C5A4F2@ntex2010i.host.magwien.gv.at
Whole thread Raw
In response to writable FDWs / update targets confusion  ("Tomas Vondra" <tv@fuzzy.cz>)
Responses Re: writable FDWs / update targets confusion  (Tom Lane <tgl@sss.pgh.pa.us>)
List pgsql-hackers
Tomas Vondra wrote:
> I'm working on adding write support to one of my FDWs. Adding INSERT went
> pretty fine, but when adding DELETE/UPDATE I got really confused about how
> the update targets are supposed to work.
> 
> My understanding of how it's supposed to work is this:
> 
>  (1) AddForeignUpdateTargets adds columns that serve as ID of the record
>      (e.g. postgres_fdw adds 'ctid')
> 
>  (2) planning the inner foreign scan handles the new column appropriately
>      (e.g. scans system columns, as in case of 'ctid' etc.)
> 
>  (3) IterateForeignScan will see the column in the tuple descriptor, will
>      set it just like any other column, etc.
> 
>  (4) ExecForeignDelete will fetch the new column and do something with it
> 
> However no matter what I do, I can't get the steps (3) and (4) working this
> way.

I have no idea either.

> And looking at postgres_fdw it seems to me it does not really set the ctid
> into the tuple as a column, but just does this:
> 
>     if (ctid)
>         tuple->t_self = *ctid;
> 
> which I can't really do because I need to use INT8 and not TID. But even
> if I do this,

What exactly did you do?
Did you try  tuple->t_self = myInt8;

That would write 8 bytes into a 6-byte variable, thus scribbling
past the end, right?

> Interestingly, if I do this in ExecForeignDelete
> 
>     static TupleTableSlot *
>     myExecForeignDelete(EState *estate,
>                               ResultRelInfo *resultRelInfo,
>                               TupleTableSlot *slot,
>                               TupleTableSlot *planSlot)
>     {
> 
>         bool isNull;
>         MyModifyState state = (MyModifyState)resultRelInfo->ri_FdwState;
>         int64 ctid;
> 
>         Datum datum = ExecGetJunkAttribute(planSlot,
>                                            state->ctidAttno, &isNull);
> 
>         ctid = DatumGetInt64(datum);
> 
>         elog(WARNING, "ID = %ld", ctid);
> 
>         if (isNull)
>             elog(ERROR, "ctid is NULL");
> 
>         /* FIXME not yet implemented */
>         return NULL;
>     }
> 
> I do get (isNull=FALSE) but the ctid evaluates to some random number, e.g.
> 
>     WARNING:  ID = 44384788 (44384788)
>     WARNING:  ID = 44392980 (44392980)
> 
> and so on.

Maybe that's the effect of writing past the end of the variable.

> So what did I get wrong? Is it possible to use arbitrary hidden column as
> "junk" columns (documentation seems to suggest that)? What is the right
> way to do that / whad did I get wrong?

I would like to know an answer to this as well.

I don't think that assigning to tuple->t_self will work, and I
know too little about the executor to know if there's any way
to fit a ctid that is *not* an ItemPointerData into a TupleTableSlot
so that it will show up as resjunk TargerEntry in ExecForeignUpdate.

Tom, could you show us a rope if there is one?

Yours,
Laurenz Albe

pgsql-hackers by date:

Previous
From: "Erik Rijkers"
Date:
Subject: Re: Minmax indexes (timings)
Next
From: Andres Freund
Date:
Subject: Re: Minmax indexes (timings)