setLastTid() and currtid()

From: Andres Freund <andres(at)anarazel(dot)de>
To: pgsql-hackers(at)postgresql(dot)org
Cc: Heikki Linnakangas <hlinnaka(at)iki(dot)fi>, Michael Paquier <michael(dot)paquier(at)gmail(dot)com>, Hiroshi Inoue <inoue(at)tpf(dot)co(dot)jp>, pgsql-odbc(at)postgresql(dot)org
Subject: setLastTid() and currtid()
Date: 2019-03-26 00:44:42
Message-ID: 20190326004442.l2jq43inhakuruzn@alap3.anarazel.de
Views: Raw Message | Whole Thread | Download mbox | Resend email
Thread:
Lists: pgsql-hackers pgsql-odbc

Hi,

For the tableam work I'd like to remove heapam.h from
nodeModifyTable.c. The only remaining impediment to that is a call to
setLastTid(), which is defined in tid.c but declared in heapam.h.

That doesn't seem like a particularly accurate location, it doesn't
really have that much to do with heap. It seems more like a general
executor facility or something. Does anybody have a good idea where to
put the declaration?

Looking at how this function is used, lead to some confusion on my part.

We currently call setLastTid in ExecInsert():

if (canSetTag)
{
(estate->es_processed)++;
setLastTid(&slot->tts_tid);
}

And Current_last_tid, the variable setLastTid sets, is only used in
currtid_byreloid():

Datum
currtid_byreloid(PG_FUNCTION_ARGS)
{
Oid reloid = PG_GETARG_OID(0);
ItemPointer tid = PG_GETARG_ITEMPOINTER(1);
ItemPointer result;
Relation rel;
AclResult aclresult;
Snapshot snapshot;

result = (ItemPointer) palloc(sizeof(ItemPointerData));
if (!reloid)
{
*result = Current_last_tid;
PG_RETURN_ITEMPOINTER(result);
}

I've got to say I'm a bit baffled by this interface. If somebody passes
in a 0 reloid, we just ignore the passed in tid, and return the last tid
inserted into any table?

I then was even more baffled to find that there's no documentation of
this function, nor this special case behaviour, to be found
anywhere. Not in the docs (which don't mention the function, nor it's
special case behaviour for relation 0), nor in the code.

It's unfortunately used in psqlobdc:

else if ((flag & USE_INSERTED_TID) != 0)
printfPQExpBuffer(&selstr, "%s where ctid = (select currtid(0, '(0,0)'))", load_stmt);

I gotta say, all that currtid code looks to me like it just should be
ripped out. It really doesn't make a ton of sense to just walk the tid
chain for a random tid - without an open snapshot, there's absolutely no
guarantee that you get back anything meaningful. Nor am I convinced
it's perfectly alright to just return the latest inserted tid for a
relation the user might not have any permission for.

OTOH, we probably can't just break psqlodbc, so we probably have to hold
our noses a bit longer and just move the prototype elsewhere? But I'm
inclined to just say that this functionality is going to get ripped out
soon, unless somebody from the odbc community works on making it make a
bit more sense (tests, docs at the very very least).

Greetings,

Andres Freund

Responses

Browse pgsql-hackers by date

  From Date Subject
Next Message Kuroda, Hayato 2019-03-26 00:54:48 RE: Re: Log a sample of transactions
Previous Message Amit Langote 2019-03-26 00:36:39 Re: selecting from partitions and constraint exclusion

Browse pgsql-odbc by date

  From Date Subject
Next Message Inoue, Hiroshi 2019-03-27 01:01:08 Re: setLastTid() and currtid()
Previous Message Tom Lane 2019-03-24 05:15:57 Re: Building libpq independently of server