Re: writable FDWs / update targets confusion

From: Albe Laurenz <laurenz(dot)albe(at)wien(dot)gv(dot)at>
To: Tomas Vondra *EXTERN* <tv(at)fuzzy(dot)cz>, PostgreSQL-development <pgsql-hackers(at)postgresql(dot)org>
Subject: Re: writable FDWs / update targets confusion
Date: 2013-11-15 16:15:38
Message-ID: A737B7A37273E048B164557ADEF4A58B17C5A4F2@ntex2010i.host.magwien.gv.at
Views: Raw Message | Whole Thread | Download mbox | Resend email
Thread:
Lists: 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

In response to

Responses

Browse pgsql-hackers by date

  From Date Subject
Next Message Andres Freund 2013-11-15 16:28:57 Re: Minmax indexes (timings)
Previous Message Erik Rijkers 2013-11-15 16:11:46 Re: Minmax indexes (timings)