1
0
mirror of https://github.com/postgres/postgres.git synced 2025-05-17 06:41:24 +03:00

Back-patch 8.0 version of plperl_hash_from_tuple() into prior releases

to fix failure to cope with quote marks in field values; not to mention
that it is shorter and faster.  Per report from Charles Haron.
This commit is contained in:
Tom Lane 2005-01-26 17:09:21 +00:00
parent db78e53fac
commit 03a7dd013e

View File

@ -33,7 +33,7 @@
* ENHANCEMENTS, OR MODIFICATIONS. * ENHANCEMENTS, OR MODIFICATIONS.
* *
* IDENTIFICATION * IDENTIFICATION
* $Header: /cvsroot/pgsql/src/pl/plperl/plperl.c,v 1.40 2003/09/04 15:16:39 tgl Exp $ * $Header: /cvsroot/pgsql/src/pl/plperl/plperl.c,v 1.40.2.1 2005/01/26 17:09:21 tgl Exp $
* *
**********************************************************************/ **********************************************************************/
@ -737,76 +737,53 @@ compile_plperl_function(Oid fn_oid, bool is_trigger)
/********************************************************************** /**********************************************************************
* plperl_build_tuple_argument() - Build a string for a ref to a hash * plperl_build_tuple_argument() - Build a ref to a hash
* from all attributes of a given tuple * from all attributes of a given tuple
**********************************************************************/ **********************************************************************/
static SV * static SV *
plperl_build_tuple_argument(HeapTuple tuple, TupleDesc tupdesc) plperl_build_tuple_argument(HeapTuple tuple, TupleDesc tupdesc)
{ {
HV *hv;
int i; int i;
SV *output;
Datum attr;
bool isnull;
char *attname;
char *outputstr;
HeapTuple typeTup;
Oid typoutput;
Oid typelem;
output = sv_2mortal(newSVpv("{", 0)); hv = newHV();
for (i = 0; i < tupdesc->natts; i++) for (i = 0; i < tupdesc->natts; i++)
{ {
/* ignore dropped attributes */ Datum attr;
bool isnull;
char *attname;
char *outputstr;
Oid typoutput;
Oid typioparam;
bool typisvarlena;
int namelen;
if (tupdesc->attrs[i]->attisdropped) if (tupdesc->attrs[i]->attisdropped)
continue; continue;
/************************************************************ attname = NameStr(tupdesc->attrs[i]->attname);
* Get the attribute name namelen = strlen(attname);
************************************************************/
attname = tupdesc->attrs[i]->attname.data;
/************************************************************
* Get the attributes value
************************************************************/
attr = heap_getattr(tuple, i + 1, tupdesc, &isnull); attr = heap_getattr(tuple, i + 1, tupdesc, &isnull);
/************************************************************ if (isnull) {
* If it is null it will be set to undef in the hash. /* Store (attname => undef) and move on. */
************************************************************/ hv_store(hv, attname, namelen, newSV(0), 0);
if (isnull)
{
sv_catpvf(output, "'%s' => undef,", attname);
continue; continue;
} }
/************************************************************ /* XXX should have a way to cache these lookups */
* Lookup the attribute type in the syscache
* for the output function
************************************************************/
typeTup = SearchSysCache(TYPEOID,
ObjectIdGetDatum(tupdesc->attrs[i]->atttypid),
0, 0, 0);
if (!HeapTupleIsValid(typeTup))
elog(ERROR, "cache lookup failed for type %u",
tupdesc->attrs[i]->atttypid);
typoutput = ((Form_pg_type) GETSTRUCT(typeTup))->typoutput; getTypeOutputInfo(tupdesc->attrs[i]->atttypid,
typelem = ((Form_pg_type) GETSTRUCT(typeTup))->typelem; &typoutput, &typioparam, &typisvarlena);
ReleaseSysCache(typeTup);
/************************************************************
* Append the attribute name and the value to the list.
************************************************************/
outputstr = DatumGetCString(OidFunctionCall3(typoutput, outputstr = DatumGetCString(OidFunctionCall3(typoutput,
attr, attr,
ObjectIdGetDatum(typelem), ObjectIdGetDatum(typioparam),
Int32GetDatum(tupdesc->attrs[i]->atttypmod))); Int32GetDatum(tupdesc->attrs[i]->atttypmod)));
sv_catpvf(output, "'%s' => '%s',", attname, outputstr);
pfree(outputstr); hv_store(hv, attname, namelen, newSVpv(outputstr, 0), 0);
} }
sv_catpv(output, "}"); return newRV_noinc((SV *) hv);
output = perl_eval_pv(SvPV(output, PL_na), TRUE);
return output;
} }