Skip site navigation (1) Skip section navigation (2)

Peripheral Links

Header And Logo

PostgreSQL
| The world's most advanced open source database.

Site Navigation

Search for
  Advanced Search

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);
}





Home | Main Index | Thread Index

Privacy Policy | PostgreSQL Archives hosted by Command Prompt, Inc. | Designed by tinysofa
Copyright © 1996 – 2008 PostgreSQL Global Development Group