patch: plpgsql - access records with rec.(expr) - Mailing list pgsql-hackers

From Matt
Subject patch: plpgsql - access records with rec.(expr)
Date
Msg-id 1100783879.4229.96.camel@matt.kynx.org
Whole thread Raw
Responses Re: patch: plpgsql - access records with rec.(expr)  (Matt <matt@kynx.org>)
Re: patch: plpgsql - access records with rec.(expr)  (Matt <matt@kynx.org>)
Re: patch: plpgsql - access records with rec.(expr)  (Neil Conway <neilc@samurai.com>)
List pgsql-hackers
Hi,

I got extremely frustrated with having to create a temp table every time
I wanted to access an arbitrary column from a record plpgsql. After
seeing a note on the developers TODO about accessing plpgsql records
with a 'dot bracket' notation I started digging into the plpgsql source.

My diff (against 8beta4) is attached.

Warning: I Am Not a C Programmer! I haven't even written a hello world
in C before, and I knew nothing about Flex before yesterday. It was fun
figuring stuff out, I'm amazed it mostly works, but I'm really hoping
someone can point out my mistakes.

Goal:

Enable users to access fields in record variables using the following
syntax like the following:
  rec.(1)
  rec.('foo')
  rec.(myvar::int)
  rec.(myvar || '_id')

Files changed:

plpgsql.h
- added 'expr' member to PLpgSQL_recfield type for holding the
PLpgSQL_expr structure.

scan.l
- added match for {identifier}{space}*\.  AFAIK this should only match
if a longer expression doesn't?

pl_comp.c
- added plpgsql_parse_wordexpr() function called by above match. Ripped
off code from plpgsql_parse_word that deals with arg_v[expr] to find our
expression. Prob a dumb name for the function!

pl_exec.c
- hacked exec_assign_value() and exec_eval_datum() to use the expression
to get the field name/number.

Stuff I need help with:

1. It should recognise OLD.(1) as a field number, not a column name. I
think I've got to check the returned type from exec_eval_expr() then
exec_simple_cast_value() on it, but that seems beyond me.

2. Freeing stuff. As I explained, this is all pretty new to me, and the
comments about it around exec_eval_expr() et al just confused me :(
Please give some hints about what needs freeing!

3. Would probably be good to add check in pl_comp.c to see if the
expression actually needs to be evaluated at runtime (ie isn't just a
field name/number). How?

4. Make this also work for row.(expr), label.record.(expr) and
label.row.(expr) - but want to get the basics working first!

5. Because of the way the expression is parsed (looking for closing
parenth), this will choke if you try and put a function in there. Would
it be better to use curly braces '{expr}' or another character to mark
the expression?

I hope at this eventually leads to some really useful extra
functionality, particularly for writing generic triggers. And it's a
tribute to the existing code that a complete newbie can cut-and-paste
their way to a halfarsed solution in a (rather long) night!

Regards,

Matt

Attachment

pgsql-hackers by date:

Previous
From: "Zeugswetter Andreas DAZ SD"
Date:
Subject: Re: pg_resetxlog options
Next
From: James Robinson
Date:
Subject: plpgsql on 8.0b4 bug?