logo       
Google Custom Search
    AddThis Social Bookmark Button
-->

PQoidValue - get last ID of primary key after INSERT - small fix: msg#00014

Subject: PQoidValue - get last ID of primary key after INSERT - small fix
Hi,

In psycopg2 the value of ID after INSERT statement is derived by 'cursor.lastrowid' attribute which in turn calls PQoidValue().

The easiest way to fix the problem were to fix heap_insert() to get the right value in case there is no OID column declared in the table.

In case there is an OID, the function works the 'old' manner.
If there is no OID, we serach for PKEY column which is declared 'SERIAL' (at the moment I check the type to be 'int4').

I think the best way is to develop brand new functions PQid4Value and PQid8Value similar to PQoidValue (or something else) to solve the whole problem with SERIAL and BIGSERIAL.

Bellow is the piece of the code I have noticed. I can propose it as a diff patch or else as needed. If there are some better ideas of fixing the problem I will be very glad to discuss them :)


/backend/access/heap/heapam.c:1097
Oid
heap_insert(Relation relation, HeapTuple tup, CommandId cid,
                        bool use_wal, bool use_fsm)
{
...
        if (!OidIsValid(HeapTupleGetOid(tup)))
        {
                TupleDesc       tupdesc = RelationGetDescr(relation);
                int                     natts = tupdesc->natts;
                int                     varattno;
                Form_pg_attribute att;

                List       *indexoidlist;
                ListCell   *indexoidscan;

                indexoidlist = RelationGetIndexList(relation);
        
                foreach(indexoidscan, indexoidlist)
                {
                        Oid                     indexoid = 
lfirst_oid(indexoidscan);
                        HeapTuple       indexTuple;
                        Form_pg_index indexStruct;
                        int                     i;                      
        
                        indexTuple = SearchSysCache(INDEXRELID,
                                                                                
ObjectIdGetDatum(indexoid),
                                                                                
0, 0, 0);
                        if (!HeapTupleIsValid(indexTuple))
                                elog(ERROR, "cache lookup failed for index %u", 
indexoid);
                        indexStruct = (Form_pg_index) GETSTRUCT(indexTuple);
        
                        if (indexStruct->indisprimary && indexStruct->indnatts 
== 1)
                        {
                                for (varattno = 0; varattno < natts; varattno++)
                                {
                                        att = tupdesc->attrs[varattno];
                                        if (indexStruct->indkey.values[0] == 
att->attnum)
                                        {
                                                Oid                     typoid;
                                                HeapTuple       typeTuple;
                                                char       *atttype;
                                                                        
                                                typoid = 
tupdesc->attrs[varattno]->atttypid;                              
                                                typeTuple = 
SearchSysCache(TYPEOID,
                                                                                
                ObjectIdGetDatum(typoid),
                                                                                
                0, 0, 0);                       
                                                if 
(!HeapTupleIsValid(typeTuple))
                                                        return NULL;            
        
atttype = pstrdup(NameStr(((Form_pg_type) GETSTRUCT(typeTuple))->typname));
                                                ReleaseSysCache(typeTuple);
                        
                                                if (strcmp(atttype, "int4")==0)
                                                {
                                                        Datum           origval;
                                                        bool            isnull;
                
                                                        origval = heap_getattr(tup, 
varattno+1, tupdesc, &isnull);

                                                        
ReleaseSysCache(indexTuple);
                                                        list_free(indexoidlist);
                                                        return 
DatumGetInt32(origval);
                                                }
                                        }
                                }                                       
                        }
                        ReleaseSysCache(indexTuple);
                }       
                list_free(indexoidlist);
        }
        return HeapTupleGetOid(tup);
}



---------------------------(end of broadcast)---------------------------
TIP 6: explain analyze is your friend



<Prev in Thread] Current Thread [Next in Thread>