patch: plpgsql - access records with rec.(expr)

From: Matt <matt(at)kynx(dot)org>
To: pgsql-hackers(at)postgresql(dot)org
Subject: patch: plpgsql - access records with rec.(expr)
Date: 2004-11-18 13:18:00
Message-ID: 1100783879.4229.96.camel@matt.kynx.org
Views: Raw Message | Whole Thread | Download mbox | Resend email
Thread:
Lists: 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 Content-Type Size
record_dot_parenth.diff text/x-patch 9.4 KB

Responses

Browse pgsql-hackers by date

  From Date Subject
Next Message James Robinson 2004-11-18 14:36:01 plpgsql on 8.0b4 bug?
Previous Message Zeugswetter Andreas DAZ SD 2004-11-18 13:06:30 Re: pg_resetxlog options