Re: proposal: auxiliary functions for record type - Mailing list pgsql-hackers
From | Pavel Stehule |
---|---|
Subject | Re: proposal: auxiliary functions for record type |
Date | |
Msg-id | AANLkTikBU81hE54gavuTjR20TSnvL0pYk69k8WcPDs-N@mail.gmail.com Whole thread Raw |
In response to | Re: proposal: auxiliary functions for record type (Florian Pflug <fgp@phlo.org>) |
Responses |
Re: proposal: auxiliary functions for record type
|
List | pgsql-hackers |
2010/12/11 Florian Pflug <fgp@phlo.org>: > On Dec11, 2010, at 16:03 , Pavel Stehule wrote: >> 2010/12/11 Florian Pflug <fgp@phlo.org>: >>> On Dec11, 2010, at 06:20 , Pavel Stehule wrote: >>>> I wrote a few functions for record type - record_expand, >>>> record_get_fields, record_get_field, record_set_fields. >>> >>> Just FYI, I've created something similar a while ago. The code can be found at >>> https://github.com/fgp/pg_record_inspect >>> >>> The main difference seems to be that my code allows you to retrieve fields from a record without casting it to text.As a consequence, however, it lacks the set-returning functions that your's provides. It also doesn't provide a wayto modify fields. >> >> Casting to text is necessary for PL/pgSQL. I am not happy from this, >> but there are not other way than using a common type - text - because >> you don't know a target type. > > > I use the anyarray/anyelement machinery to cheat there, at least a bit. My function fieldvalue() returns anyelement andtakes a parameter <defval> of type anyelement, which serves two purposes. > > First, by virtue of the anyelement machinery, the return type of fieldvalue() is that of <defval>. If the actual type ofthe requested field matches that type, the value is returned. If they don't match, the parameter <coerce> decided whetherfieldvalue() tries to cast the value to the requested type, or simply raises an error. It same trick, that I use in record_set_fields. But I don't want to use it for reading of value. I don't like it. You don't need to know a value, you have to know a type - NULL::type. it is just not nice :). I though about it too, and maybe is a time for new polymorphic type "anytype" - and then you don't need to write a litte bit strange NULL::type it can be "fieldvalue(myrec, type1, false)" Regards Pavel Stehule > > Second, to also give the *value*, not only the *type* of <defval> a meaning, it serves as the default return value. Ifrequested field contains NULL, <defvalue> is returned instead. You are, of course, free to pass NULL for <defvalue> itselfto turn that mapping into a NOP. > > Note that the returned value's type is always the same as <defval>'s type, so the whole thing is perfectly type-safe fromthe point of view of the rest of the system. > > As long as you know all possible types than can appear in your record's fields, you can do in Pl/PgSQL something alongthe line of > declare > v_value_type1 type1; > v_value_type2 type2; > ... > v_value_typeN typeN; > begin > for v_field in select * from fieldinfos(myrec) loop > case > when v_field.fieldtype = 'type1'::regtype then > v_value_type1 := fieldvalue(myrec, NULL::type1, false); > <Do something with v_value_type1> > ... > when v_field.fieldtype = 'typeN'::regtype then > v_value_typeN := fieldvalue(myrec, NULL::typeN, false); > <Do something with v_value_typeN> > else raise exception 'Unexpected type % in record %', v_field.fieldtype, myrec; > end case; > end loop; > end; > > It works pretty well for me... > > best regards, > Florian Pflug > >
pgsql-hackers by date: