Re: sorting table columns

From: Alvaro Herrera <alvherre(at)commandprompt(dot)com>
To: Tom Lane <tgl(at)sss(dot)pgh(dot)pa(dot)us>
Cc: Pg Hackers <pgsql-hackers(at)postgresql(dot)org>
Subject: Re: sorting table columns
Date: 2011-12-27 20:04:32
Message-ID: 1325014534-sup-2086@alvh.no-ip.org
Views: Raw Message | Whole Thread | Download mbox | Resend email
Thread:
Lists: pgsql-hackers


Excerpts from Tom Lane's message of mar dic 20 22:23:36 -0300 2011:
>
> Alvaro Herrera <alvherre(at)commandprompt(dot)com> writes:
> > Excerpts from Tom Lane's message of mar dic 20 18:24:29 -0300 2011:
> >> You do *not* want to store either of the latter two numbers in
> >> parse-time Var nodes, because then you can't rearrange columns without
> >> having to update stored rules. But it might be useful to decree that
> >> one thing setrefs.c does is renumber Vars in scan nodes to use the
> >> physical column numbers instead of the permanent IDs.
>
> > Hmm, having the numbers in Var nodes seems a fundamental part of the way
> > I'm attacking the problem. Hopefully after I give setrefs.c a read I
> > will have a clearer picture of the way to do it without that.
>
> To clarify a bit: one thing that setrefs.c already does is to renumber
> Var nodes above the scan level, so that their attnums refer not to
> original table column attnums but to column numbers in the output of the
> next plan level down. Vars in scan nodes currently don't need any
> renumbering, but it'd be easy enough to extend the logic to do something
> to them as well. I'm visualizing the run-time transformation from
> physical to logical column ordering as a sort of projection, much like
> the mapping that happens in a join node.

After more playing with this, it turned out that those logical numbers
stored in Var and TargetEntry are actually completely useless; after
they served their purpose in helping me track down that I actually
needed to sort columns at the RangeTblEntry level, I was able to revert
all those bits and things work fine (actually they work better). So
far, I have had no need to touch setrefs.c that I see. The reason is
that * expansion happens much earlier than setrefs.c is involved, at the
parse analysis level; the target lists generated at that point must
already follow the logical column order. So that part of the patch
becomes this:

diff --git a/src/include/nodes/parsenodes.h b/src/include/nodes/parsenodes.h
index 9e277c5..f640bd8 100644
--- a/src/include/nodes/parsenodes.h
+++ b/src/include/nodes/parsenodes.h
@@ -701,6 +701,7 @@ typedef struct RangeTblEntry
*/
Oid relid; /* OID of the relation */
char relkind; /* relation kind (see pg_class.relkind) */
+ List *lognums; /* int list of logical column numbers */

/*
* Fields valid for a subquery RTE (else NULL):

Note that the the eref->colnames list is built in logical column order
(which is what it should be, because it then matches the alias->colnames
list). With all that, it's easy to map the attnums to the logical
numbers when the target list is being constructed. And things work fine
from that point onwards, because we still keep track of the original
attnum to reference the TupleDesc.

A RTE in a stored rule looks like this:

{RTE :alias <> :eref {ALIAS :aliasname bar :colnames ("z" "y" "x")} :rtekind 0
:relid 16404 :relkind r :lognums (i 3 2 1) :inh true :inFromCl true
:requiredPerms 2 :checkAsUser 0 :selectedCols (b 9 10 11) :modifiedCols (b)}

The original table was created with columns "x, y, z", and then I
reversed the order. So if I change the column order in the original
table, the rule does not need any change and it continues to return the
logical order that the table had when the view was originally defined.

(I wonder what the other two RTEs, those named "new" and "old", are
for.)

One thing I'm finding necessary (for COPY support as well as things that
travel through different DestReceivers, such as SQL functions) is that
TupleTableSlots need to keep track of logical vs. physical order, and
form/deform tuples using the correct ordering. So the values/isnull
arrays may be in either order depending on what the caller is doing. At
some point a MinimalTuple might be constructed in logical order, for
example, and the caller must be aware of this so that it can be
deconstructed correctly later on. I mention this so that there's time
for bells to ring ...

--
Álvaro Herrera <alvherre(at)commandprompt(dot)com>
The PostgreSQL Company - Command Prompt, Inc.
PostgreSQL Replication, Consulting, Custom Development, 24x7 support

In response to

Browse pgsql-hackers by date

  From Date Subject
Next Message Heikki Linnakangas 2011-12-27 20:05:11 Re: 16-bit page checksums for 9.2
Previous Message Peter Eisentraut 2011-12-27 20:01:42 improve line-breaking and indentation of foreign options dump