8.2 features?

Started by Andrew Dunstanover 19 years ago124 messages
#1Andrew Dunstan
andrew@dunslane.net

What is the state of the following items that have been previously
discussed?

. MERGE (at least in PK case)
. multiple values clauses for INSERT
. recursive WITH queries

Thanks

andrew

#2Tom Lane
tgl@sss.pgh.pa.us
In reply to: Andrew Dunstan (#1)
Re: 8.2 features?

Andrew Dunstan <andrew@dunslane.net> writes:

What is the state of the following items that have been previously
discussed?

. MERGE (at least in PK case)

No submitted patch; no one working on it AFAIK; doesn't look like
something that could get done in the next three weeks.

. multiple values clauses for INSERT

Also not done, but if we are willing to accept a limited patch
(ie, not necessarily everything that SQL92 says you can do with
VALUES, but at least the INSERT case) I think it could get done.
I might even volunteer to do it ... but won't object if someone
else volunteers to.

. recursive WITH queries

I believe Jonah has given up on fixing the originally-submitted
patch, but he mentioned at the code sprint that non-recursive
WITH is potentially doable in time for 8.2. Not sure if that's
a sufficiently important case to be worth doing.

regards, tom lane

#3Jonah H. Harris
jonah.harris@gmail.com
In reply to: Tom Lane (#2)
Re: 8.2 features?

On 7/13/06, Tom Lane <tgl@sss.pgh.pa.us> wrote:

. recursive WITH queries

I believe Jonah has given up on fixing the originally-submitted
patch, but he mentioned at the code sprint that non-recursive
WITH is potentially doable in time for 8.2. Not sure if that's
a sufficiently important case to be worth doing.

A working WITH clause which will work in most usual use-cases will be submitted.

--
Jonah H. Harris, Software Architect | phone: 732.331.1300
EnterpriseDB Corporation | fax: 732.331.1301
33 Wood Ave S, 2nd Floor | jharris@enterprisedb.com
Iselin, New Jersey 08830 | http://www.enterprisedb.com/

#4Andrew Dunstan
andrew@dunslane.net
In reply to: Tom Lane (#2)
Re: 8.2 features?

Tom Lane wrote:

. multiple values clauses for INSERT

Also not done, but if we are willing to accept a limited patch
(ie, not necessarily everything that SQL92 says you can do with
VALUES, but at least the INSERT case) I think it could get done.
I might even volunteer to do it ... but won't object if someone
else volunteers to.

I would be very happy to see it accepted.

cheers

andrew

#5Jonah H. Harris
jonah.harris@gmail.com
In reply to: Andrew Dunstan (#4)
Re: 8.2 features?

On 7/13/06, Andrew Dunstan <andrew@dunslane.net> wrote:

. multiple values clauses for INSERT

I would be very happy to see it accepted.

Same here.

--
Jonah H. Harris, Software Architect | phone: 732.331.1300
EnterpriseDB Corporation | fax: 732.331.1301
33 Wood Ave S, 2nd Floor | jharris@enterprisedb.com
Iselin, New Jersey 08830 | http://www.enterprisedb.com/

#6David Fetter
david@fetter.org
In reply to: Jonah H. Harris (#5)
Re: 8.2 features?

On Thu, Jul 13, 2006 at 05:09:32PM -0400, Jonah H. Harris wrote:

On 7/13/06, Andrew Dunstan <andrew@dunslane.net> wrote:

. multiple values clauses for INSERT

I would be very happy to see it accepted.

Same here.

<aol>Me, too!</aol>

Cheers,
D
--
David Fetter <david@fetter.org> http://fetter.org/
phone: +1 415 235 3778 AIM: dfetter666
Skype: davidfetter

Remember to vote!

#7Joe Conway
mail@joeconway.com
In reply to: Tom Lane (#2)
Re: 8.2 features?

Tom Lane wrote:

Andrew Dunstan <andrew@dunslane.net> writes:

What is the state of the following items that have been previously
discussed?
. multiple values clauses for INSERT

Also not done, but if we are willing to accept a limited patch
(ie, not necessarily everything that SQL92 says you can do with
VALUES, but at least the INSERT case) I think it could get done.
I might even volunteer to do it ... but won't object if someone
else volunteers to.

I'm looking to contribute something useful for the 8.2 release, and it
seems Bernd is going to finish up updateable views himself, so I'd be
glad to take a look (at the limited case, that is). Any landmines I
should watch out for?

Joe

#8Peter Eisentraut
peter_e@gmx.net
In reply to: Andrew Dunstan (#1)
Re: 8.2 features?

Andrew Dunstan wrote:

. MERGE (at least in PK case)

I think that died after we figured out that it didn't do the sort of
UPDATE-else-INSERT thing that people wanted out of it.

. multiple values clauses for INSERT

Susanne Ebrecht <susanne.ebrecht@credativ.de> was last heard to work on
it. Updates, Susanne?

#9Stephen Frost
sfrost@snowman.net
In reply to: Peter Eisentraut (#8)
Re: 8.2 features?

* Peter Eisentraut (peter_e@gmx.net) wrote:

Andrew Dunstan wrote:

. MERGE (at least in PK case)

I think that died after we figured out that it didn't do the sort of
UPDATE-else-INSERT thing that people wanted out of it.

I agree that it's probably not going to happen for 8.2 but I certainly
have uses for the SQL spec's definition of MERGE (table-level instead of
the individual-tuple case). I'd like to see the individual-tuple
UPSERT/REPLACE issue handled as well but I don't believe MERGE lacking
that necessairly means MERGE should be ignored..

Thanks,

Stephen

#10Jonah H. Harris
jonah.harris@gmail.com
In reply to: Stephen Frost (#9)
Re: 8.2 features?

On 7/13/06, Stephen Frost <sfrost@snowman.net> wrote:

I agree that it's probably not going to happen for 8.2 but I certainly
have uses for the SQL spec's definition of MERGE (table-level instead of
the individual-tuple case). I'd like to see the individual-tuple
UPSERT/REPLACE issue handled as well but I don't believe MERGE lacking
that necessairly means MERGE should be ignored..

Where does Jan stand on it, I know he was doing some thinking about
how to accomplish it.

--
Jonah H. Harris, Software Architect | phone: 732.331.1300
EnterpriseDB Corporation | fax: 732.331.1301
33 Wood Ave S, 2nd Floor | jharris@enterprisedb.com
Iselin, New Jersey 08830 | http://www.enterprisedb.com/

#11Bernd Helmle
mailings@oopsware.de
In reply to: Peter Eisentraut (#8)
Re: 8.2 features?

--On Freitag, Juli 14, 2006 01:23:11 +0200 Peter Eisentraut
<peter_e@gmx.net> wrote:

. multiple values clauses for INSERT

Susanne Ebrecht <susanne.ebrecht@credativ.de> was last heard to work on
it. Updates, Susanne?

I've talked to Susanne today and she's just back from hospital and not
available
online until next week.
She was working on the SET (col1, col2) = (val1, val2) syntax for UPDATE
commands.
Don't know what the status is on this, though.

--
Thanks

Bernd

#12Andrew Dunstan
andrew@dunslane.net
In reply to: Bernd Helmle (#11)
Re: 8.2 features?

Bernd Helmle wrote:

--On Freitag, Juli 14, 2006 01:23:11 +0200 Peter Eisentraut
<peter_e@gmx.net> wrote:

. multiple values clauses for INSERT

Susanne Ebrecht <susanne.ebrecht@credativ.de> was last heard to work on
it. Updates, Susanne?

I've talked to Susanne today and she's just back from hospital and not
available
online until next week.
She was working on the SET (col1, col2) = (val1, val2) syntax for
UPDATE commands.
Don't know what the status is on this, though.

Not the same thing, surely. So maybe we should gratefully accept Joe
Conway's offer to work on it.

cheers

andrew

#13Susanne Ebrecht
miracee@miracee.de
In reply to: Bernd Helmle (#11)
Re: 8.2 features?

Am Freitag, den 14.07.2006, 16:26 +0200 schrieb Bernd Helmle:

--On Freitag, Juli 14, 2006 01:23:11 +0200 Peter Eisentraut
<peter_e@gmx.net> wrote:

. multiple values clauses for INSERT

Susanne Ebrecht <susanne.ebrecht@credativ.de> was last heard to work on
it. Updates, Susanne?

I've talked to Susanne today and she's just back from hospital and not
available
online until next week.
She was working on the SET (col1, col2) = (val1, val2) syntax for UPDATE
commands.
Don't know what the status is on this, though.

Thanks Peter and Bernd for your postings.
I'am working on
update table set (col1, col2, ...) = (val1, val2, ...), (colx,
coly, ...) = (valx, valy, ...), ...
I hope, it will be finished this week. Most of work is done.

Susanne

#14Joe Conway
mail@joeconway.com
In reply to: Andrew Dunstan (#12)
Re: 8.2 features?

Andrew Dunstan wrote:

Bernd Helmle wrote:

--On Freitag, Juli 14, 2006 01:23:11 +0200 Peter Eisentraut
<peter_e@gmx.net> wrote:

. multiple values clauses for INSERT

Susanne Ebrecht <susanne.ebrecht@credativ.de> was last heard to work on
it. Updates, Susanne?

I've talked to Susanne today and she's just back from hospital and not
available online until next week.
She was working on the SET (col1, col2) = (val1, val2) syntax for
UPDATE commands.
Don't know what the status is on this, though.

Not the same thing, surely. So maybe we should gratefully accept Joe
Conway's offer to work on it.

I've played with this a bit now, and the grammar changes seem pretty
straightforward, but the other half is kind of ugly. I can't see a good
way to propagate multiple targetlists that isn't a big hack.

The best way might be to fabricate a selectStmt equiv to
"SELECT <targetlist> UNION ALL SELECT <targetlist>...",
but that still feels like a hack.

Have there been any past discussions on how this might be implemented
(FWIW I couldn't find any in the archives)? Any better ideas for an
approach?

Thanks,

Joe

#15Joe Conway
mail@joeconway.com
In reply to: Joe Conway (#14)
1 attachment(s)
Re: [HACKERS] 8.2 features?

Joe Conway wrote:

. multiple values clauses for INSERT

The best way might be to fabricate a selectStmt equiv to
"SELECT <targetlist> UNION ALL SELECT <targetlist>...",
but that still feels like a hack.

Here is a patch pursuant to my earlier post. It has the advantage of
being fairly simple and noninvasive.

The major downside is that somewhere between 9000 and 10000
VALUES-targetlists produces "ERROR: stack depth limit exceeded".
Perhaps for the typical use-case this is sufficient though.

I'm open to better ideas, comments, objections...

Thanks,

Joe

Attachments:

multi-insert.difftext/x-patch; name=multi-insert.diffDownload
Index: src/backend/parser/gram.y
===================================================================
RCS file: /cvsroot/pgsql/src/backend/parser/gram.y,v
retrieving revision 2.551
diff -c -r2.551 gram.y
*** src/backend/parser/gram.y	3 Jul 2006 22:45:39 -0000	2.551
--- src/backend/parser/gram.y	18 Jul 2006 04:19:45 -0000
***************
*** 238,251 ****
  				qualified_name_list any_name any_name_list
  				any_operator expr_list attrs
  				target_list update_target_list insert_column_list
! 				insert_target_list def_list indirection opt_indirection
! 				group_clause TriggerFuncArgs select_limit
! 				opt_select_limit opclass_item_list
! 				transaction_mode_list_or_empty
  				TableFuncElementList
  				prep_type_clause prep_type_list
  				execute_param_clause using_clause
  
  %type <range>	into_clause OptTempTableName
  
  %type <defelt>	createfunc_opt_item common_func_opt_item
--- 238,253 ----
  				qualified_name_list any_name any_name_list
  				any_operator expr_list attrs
  				target_list update_target_list insert_column_list
! 				insert_target_els
! 				def_list indirection opt_indirection group_clause
! 				TriggerFuncArgs select_limit opt_select_limit
! 				opclass_item_list transaction_mode_list_or_empty
  				TableFuncElementList
  				prep_type_clause prep_type_list
  				execute_param_clause using_clause
  
+ %type <node>	insert_target_list insert_target_lists
+ 
  %type <range>	into_clause OptTempTableName
  
  %type <defelt>	createfunc_opt_item common_func_opt_item
***************
*** 5349,5360 ****
  		;
  
  insert_rest:
! 			VALUES '(' insert_target_list ')'
  				{
  					$$ = makeNode(InsertStmt);
  					$$->cols = NIL;
! 					$$->targetList = $3;
! 					$$->selectStmt = NULL;
  				}
  			| DEFAULT VALUES
  				{
--- 5351,5370 ----
  		;
  
  insert_rest:
! 			VALUES insert_target_lists
  				{
  					$$ = makeNode(InsertStmt);
  					$$->cols = NIL;
! 					if (((SelectStmt *) $2)->op == SETOP_UNION)
! 					{
! 						$$->targetList = NIL;
! 						$$->selectStmt = $2;
! 					}
! 					else
! 					{
! 						$$->targetList = ((SelectStmt *) $2)->targetList;
! 						$$->selectStmt = NULL;
! 					}
  				}
  			| DEFAULT VALUES
  				{
***************
*** 5370,5381 ****
  					$$->targetList = NIL;
  					$$->selectStmt = $1;
  				}
! 			| '(' insert_column_list ')' VALUES '(' insert_target_list ')'
  				{
  					$$ = makeNode(InsertStmt);
  					$$->cols = $2;
! 					$$->targetList = $6;
! 					$$->selectStmt = NULL;
  				}
  			| '(' insert_column_list ')' SelectStmt
  				{
--- 5380,5399 ----
  					$$->targetList = NIL;
  					$$->selectStmt = $1;
  				}
! 			| '(' insert_column_list ')' VALUES insert_target_lists
  				{
  					$$ = makeNode(InsertStmt);
  					$$->cols = $2;
! 					if (((SelectStmt *) $5)->op == SETOP_UNION)
! 					{
! 						$$->targetList = NIL;
! 						$$->selectStmt = $5;
! 					}
! 					else
! 					{
! 						$$->targetList = ((SelectStmt *) $5)->targetList;
! 						$$->selectStmt = NULL;
! 					}
  				}
  			| '(' insert_column_list ')' SelectStmt
  				{
***************
*** 8189,8197 ****
  
  		;
  
  insert_target_list:
! 			insert_target_el						{ $$ = list_make1($1); }
! 			| insert_target_list ',' insert_target_el { $$ = lappend($1, $3); }
  		;
  
  insert_target_el:
--- 8207,8235 ----
  
  		;
  
+ insert_target_lists:
+ 			insert_target_list
+ 				{
+ 					$$ = $1;
+ 				}
+ 			| insert_target_lists ',' insert_target_list
+ 				{
+ 					$$ = makeSetOp(SETOP_UNION, TRUE, $1, $3);
+ 				}
+ 		;
+ 
  insert_target_list:
! 			'(' insert_target_els ')'
! 				{
! 					SelectStmt *n = makeNode(SelectStmt);
! 					n->targetList = $2;
! 					$$ = (Node *) n;
! 				}
! 		;
! 
! insert_target_els:
! 			insert_target_el						 { $$ = list_make1($1); }
! 			| insert_target_els ',' insert_target_el { $$ = lappend($1, $3); }
  		;
  
  insert_target_el:
#16Pavel Stehule
pavel.stehule@hotmail.com
In reply to: Joe Conway (#15)
Re: 8.2 features?

Hello,

I did some work on mutliple value insert. First: SELECT .. UNION ALL SELECT
is wrong idea. VALUES can contain DEFAULT keyword. Second: It's neccessery
general implementation of table values constructor like SQL:2003. Main
problem what I see is biger request on sources if we implement MVI as
classic PostgreSQL stmt.

Regards
Pavel Stehule

_________________________________________________________________
Emotikony a pozadi programu MSN Messenger ozivi vasi konverzaci.
http://messenger.msn.cz/

#17Christopher Kings-Lynne
chris.kings-lynne@calorieking.com
In reply to: Joe Conway (#15)
Re: [HACKERS] 8.2 features?

The major downside is that somewhere between 9000 and 10000
VALUES-targetlists produces "ERROR: stack depth limit exceeded".
Perhaps for the typical use-case this is sufficient though.

I'm open to better ideas, comments, objections...

If the use case is people running MySQL dumps, then there will be
millions of values-targetlists in MySQL dumps.

Chris

#18Andrew Dunstan
andrew@dunslane.net
In reply to: Christopher Kings-Lynne (#17)
Re: [HACKERS] 8.2 features?

Christopher Kings-Lynne wrote:

The major downside is that somewhere between 9000 and 10000
VALUES-targetlists produces "ERROR: stack depth limit exceeded".
Perhaps for the typical use-case this is sufficient though.

I'm open to better ideas, comments, objections...

If the use case is people running MySQL dumps, then there will be
millions of values-targetlists in MySQL dumps.

Yeah. The fabricated select hack does feel wrong to me. Taking a quick
2 minute look at the grammar it looks like a better bet would be to make
InsertStmt.targetList a list of lists of values rather than just a list
of values. Of course, that would make the changes more invasive. Even
with that we'd still be reading the whole thing into memory ... is there
a sane way to cache the inline data before statement execution?

I guess we can just say that for true bulk load our supported mechanism
is still just COPY, but it would be a pity to restrict a feature that is
in the standard that way.

cheers

andrew

#19Joe Conway
mail@joeconway.com
In reply to: Andrew Dunstan (#18)
Re: [HACKERS] 8.2 features?

Andrew Dunstan wrote:

Christopher Kings-Lynne wrote:

The major downside is that somewhere between 9000 and 10000
VALUES-targetlists produces "ERROR: stack depth limit exceeded".
Perhaps for the typical use-case this is sufficient though.

I'm open to better ideas, comments, objections...

If the use case is people running MySQL dumps, then there will be
millions of values-targetlists in MySQL dumps.

Yeah. The fabricated select hack does feel wrong to me. Taking a quick
2 minute look at the grammar it looks like a better bet would be to make
InsertStmt.targetList a list of lists of values rather than just a list
of values. Of course, that would make the changes more invasive. Even
with that we'd still be reading the whole thing into memory ... is there
a sane way to cache the inline data before statement execution?

I started down the path of making InsertStmt.targetList a list of
targetlists. The problem is finding a reasonable way to make that
available to the executor. Back to the drawing board I guess.

I have similar concerns with the millions of values-targetlists comment
that Chris made. But I don't see how we can cache the data easily short
of inventing a List alternative that spills to disk.

I guess we can just say that for true bulk load our supported mechanism
is still just COPY, but it would be a pity to restrict a feature that is
in the standard that way.

True

Joe

#20Tom Lane
tgl@sss.pgh.pa.us
In reply to: Andrew Dunstan (#18)
Re: [HACKERS] 8.2 features?

If the use case is people running MySQL dumps, then there will be
millions of values-targetlists in MySQL dumps.

I did some experimentation just now, and could not get mysql to accept a
command longer than about 1 million bytes. It complains about
Got a packet bigger than 'max_allowed_packet' bytes
which seems a bit odd because max_allowed_packet is allegedly set to
16 million, but anyway I don't think people are going to be loading any
million-row tables using single INSERT commands in mysql either.

regards, tom lane

#21Chris Browne
cbbrowne@acm.org
In reply to: Andrew Dunstan (#1)
Re: [HACKERS] 8.2 features?

chris.kings-lynne@calorieking.com (Christopher Kings-Lynne) writes:

The major downside is that somewhere between 9000 and 10000
VALUES-targetlists produces "ERROR: stack depth limit
exceeded". Perhaps for the typical use-case this is sufficient
though.
I'm open to better ideas, comments, objections...

If the use case is people running MySQL dumps, then there will be
millions of values-targetlists in MySQL dumps.

Curiosity: How do *does* TheirSQL parse that, and not have the One
Gigantic Query blow up their query parser?
--
output = reverse("gro.gultn" "@" "enworbbc")
http://www.ntlug.org/~cbbrowne/unix.html
JOHN CAGE (strapped to table): Do you really expect me to conduct this
antiquated tonal system?
LEONARD BERNSTEIN: No, Mr. Cage, I expect you to die!
[With apologies to music and James Bond fans the world over...]

#22Andrew Dunstan
andrew@dunslane.net
In reply to: Chris Browne (#21)
Re: [HACKERS] 8.2 features?

Chris Browne wrote:

chris.kings-lynne@calorieking.com (Christopher Kings-Lynne) writes:

The major downside is that somewhere between 9000 and 10000
VALUES-targetlists produces "ERROR: stack depth limit
exceeded". Perhaps for the typical use-case this is sufficient
though.
I'm open to better ideas, comments, objections...

If the use case is people running MySQL dumps, then there will be
millions of values-targetlists in MySQL dumps.

Curiosity: How do *does* TheirSQL parse that, and not have the One
Gigantic Query blow up their query parser?

Experimentation shows that mysqldump breaks up the insert into chunks.

Example with 10m rows:

[ad@wired-219 ~]# perl -e 'print "drop table if exists foo; create table
foo (x int);\n"; foreach my $i (0..9_9999) { print "insert into foo
values \n"; foreach my $j (0..99) { print "," if $j; print
"(",100*$i+$j+1,")"; } print ";\n"; } ' > gggggg
[ad@wired-219 ~]# mysql test < gggggg
[ad@wired-219 ~]# mysqldump test foo > aaaaaa
[ad@wired-219 ~]# mysql test < aaaaaa
[ad@wired-219 ~]# grep INSERT aaaaaa | wc -l
104

cheers

andrew

#23Thomas Bley
thbley@gmail.com
In reply to: Tom Lane (#20)
Re: [PATCHES] 8.2 features?

from http://dev.mysql.com/doc/refman/4.1/en/blob.html

You can change the message buffer size by changing the value of the
max_allowed_packet variable, but you must do so for both the server and
your client program. For example, both mysql and mysqldump allow you to
change the client-side max_allowed_packet value.

Tom Lane wrote:

Show quoted text

If the use case is people running MySQL dumps, then there will be
millions of values-targetlists in MySQL dumps.

I did some experimentation just now, and could not get mysql to accept a
command longer than about 1 million bytes. It complains about
Got a packet bigger than 'max_allowed_packet' bytes
which seems a bit odd because max_allowed_packet is allegedly set to
16 million, but anyway I don't think people are going to be loading any
million-row tables using single INSERT commands in mysql either.

regards, tom lane

---------------------------(end of broadcast)---------------------------
TIP 5: don't forget to increase your free space map settings

#24Matthew D. Fuller
fullermd@over-yonder.net
In reply to: Tom Lane (#20)
Re: [PATCHES] 8.2 features?

On Tue, Jul 18, 2006 at 02:19:01PM -0400 I heard the voice of
Tom Lane, and lo! it spake thus:

I did some experimentation just now, and could not get mysql to accept a
command longer than about 1 million bytes. It complains about
Got a packet bigger than 'max_allowed_packet' bytes
which seems a bit odd because max_allowed_packet is allegedly set to
16 million, but anyway I don't think people are going to be loading any
million-row tables using single INSERT commands in mysql either.

On the contrary, I've hit it several times by just trying to import
[into another database] the output of a mysqldump I just did. Great
design, that...

--
Matthew Fuller (MF4839) | fullermd@over-yonder.net
Systems/Network Administrator | http://www.over-yonder.net/~fullermd/
On the Internet, nobody can hear you scream.

#25Christopher Kings-Lynne
chris.kings-lynne@calorieking.com
In reply to: Tom Lane (#20)
Re: [HACKERS] 8.2 features?

I did some experimentation just now, and could not get mysql to accept a
command longer than about 1 million bytes. It complains about
Got a packet bigger than 'max_allowed_packet' bytes
which seems a bit odd because max_allowed_packet is allegedly set to
16 million, but anyway I don't think people are going to be loading any
million-row tables using single INSERT commands in mysql either.

Strange. Last time I checked I thought MySQL dump used 'multivalue
lists in inserts' for dumps, for the same reason that we use COPY

#26Christopher Kings-Lynne
chris.kings-lynne@calorieking.com
In reply to: Tom Lane (#20)
Re: [HACKERS] 8.2 features?

I did some experimentation just now, and could not get mysql to accept a
command longer than about 1 million bytes. It complains about
Got a packet bigger than 'max_allowed_packet' bytes
which seems a bit odd because max_allowed_packet is allegedly set to
16 million, but anyway I don't think people are going to be loading any
million-row tables using single INSERT commands in mysql either.

Ah no, I'm mistaken. It's not by default in mysqldump, but it does seem
"recommended". This is from "man mysqldump":

-e|--extended-insert
Allows utilization of the new, much faster INSERT syntax.

#27Tom Lane
tgl@sss.pgh.pa.us
In reply to: Christopher Kings-Lynne (#25)
Re: [HACKERS] 8.2 features?

Christopher Kings-Lynne <chris.kings-lynne@calorieking.com> writes:

Strange. Last time I checked I thought MySQL dump used 'multivalue
lists in inserts' for dumps, for the same reason that we use COPY

I think Andrew identified the critical point upthread: they don't try
to put an unlimited number of rows into one INSERT, only a megabyte
or so's worth. Typical klugy-but-effective mysql design approach ...

regards, tom lane

#28Joe Conway
mail@joeconway.com
In reply to: Tom Lane (#27)
2 attachment(s)
Re: [HACKERS] 8.2 features?

Tom Lane wrote:

Christopher Kings-Lynne <chris.kings-lynne@calorieking.com> writes:

Strange. Last time I checked I thought MySQL dump used 'multivalue
lists in inserts' for dumps, for the same reason that we use COPY

I think Andrew identified the critical point upthread: they don't try
to put an unlimited number of rows into one INSERT, only a megabyte
or so's worth. Typical klugy-but-effective mysql design approach ...

OK, so given that we don't need to be able to do 1 million
multi-targetlist insert statements, here is rev 2 of the patch.

It is just slightly more invasive, but performs *much* better. In fact,
it can handle as many targetlists as you have memory to deal with. It
also deals with DEFAULT values in the targetlist.

I've attached a php script that I used to do crude testing. Basically I
tested 3 cases in this order:

single-INSERT-multi-statement:
------------------------------
"INSERT INTO foo2a (f1,f2) VALUES (1,2);"
-- repeat statement $loopcount times

single-INSERT-at-once:
----------------------
"INSERT INTO foo2b (f1,f2) VALUES (1,2);INSERT INTO foo2a (f1,f2)
VALUES (1,2);INSERT INTO foo2a (f1,f2) VALUES (1,2)..."
-- build a single SQL string by looping $loopcount times,
-- and execute it all at once

multi-INSERT-at-once:
---------------------
"INSERT INTO foo2c (f1,f2) VALUES (1,2),(1,2),(1,2)..."
-- build a single SQL string by looping $loopcount times,
-- and execute it all at once

Here are the results:
$loopcount = 100000;
single-INSERT-multi-statement Elapsed time is 34 seconds
single-INSERT-at-once Elapsed time is 7 seconds
multi-INSERT-at-once Elapsed time is 4 seconds
about 370MB peak memory usage

$loopcount = 200000;
single-INSERT-multi-statement Elapsed time is 67 seconds
single-INSERT-at-once Elapsed time is 12 seconds
multi-INSERT-at-once Elapsed time is 9 seconds
about 750MB peak memory usage

$loopcount = 300000;
single-INSERT-multi-statement Elapsed time is 101 seconds
single-INSERT-at-once Elapsed time is 18 seconds
multi-INSERT-at-once Elapsed time is 13 seconds
about 1.1GB peak memory usage

Somewhere beyond this, my machine goes into swap hell, and I didn't have
the patience to wait for it to complete :-)

It would be interesting to see a side-by-side comparison with MySQL
since that seems to be our benchmark on this feature. I'll try to do
that tomorrow if no one beats me to it.

There is only one downside to the current approach that I'm aware of.
The command-result tag is only set by the "original" query, meaning that
even if you insert 300,000 rows using this method, the command-result
tag looks like "INSERT 0 1"; e.g.:

regression=# create table foo2(f1 int default 42,f2 int default 6);
CREATE TABLE
regression=# insert into foo2 (f1,f2) values
(default,12),(default,10),(115,21);
INSERT 0 1
regression=# select * from foo2;
f1 | f2
-----+----
42 | 12
42 | 10
115 | 21
(3 rows)

Any thoughts on how to fix that?

Thanks,

Joe

Attachments:

multi-insert-r2.difftext/x-patch; name=multi-insert-r2.diffDownload
Index: src/backend/parser/analyze.c
===================================================================
RCS file: /cvsroot/pgsql/src/backend/parser/analyze.c,v
retrieving revision 1.340
diff -c -r1.340 analyze.c
*** src/backend/parser/analyze.c	14 Jul 2006 14:52:21 -0000	1.340
--- src/backend/parser/analyze.c	19 Jul 2006 03:53:35 -0000
***************
*** 657,667 ****
  	}
  	else
  	{
  		/*
  		 * For INSERT ... VALUES, transform the given list of values to form a
! 		 * targetlist for the INSERT.
  		 */
! 		qry->targetList = transformTargetList(pstate, stmt->targetList);
  	}
  
  	/*
--- 657,699 ----
  	}
  	else
  	{
+ 		ListCell   *tlr;
+ 
  		/*
  		 * For INSERT ... VALUES, transform the given list of values to form a
! 		 * targetlist for the INSERT. In a multi-targetlist INSERT, append all
! 		 * but the first targetlist to extras_after to be processed later by
! 		 * do_parse_analyze
  		 */
! 		qry->targetList = NIL;
! 		foreach(tlr, stmt->targetList)
! 		{
! 			List *tgtlist = (List *) lfirst(tlr);
! 
! 			if (qry->targetList == NIL)
! 			{
! 				/* transform the first targetlist */
! 				qry->targetList = transformTargetList(pstate, tgtlist);
! 			}
! 			else
! 			{
! 				/*
! 				 * Create an InsertStmt node for each additional targetlist
! 				 * and append to extras_after
! 				 */
! 				InsertStmt *insnode = makeNode(InsertStmt);
! 
! 				insnode->cols = NIL;
! 				insnode->targetList = list_make1(tgtlist);
! 				insnode->selectStmt = NULL;
! 				insnode->relation = stmt->relation;
! 
! 				if (*extras_after == NIL)
! 					*extras_after = list_make1(insnode);
! 				else
! 					*extras_after = lappend(*extras_after, insnode);
! 			}
! 		}
  	}
  
  	/*
Index: src/backend/parser/gram.y
===================================================================
RCS file: /cvsroot/pgsql/src/backend/parser/gram.y,v
retrieving revision 2.551
diff -c -r2.551 gram.y
*** src/backend/parser/gram.y	3 Jul 2006 22:45:39 -0000	2.551
--- src/backend/parser/gram.y	19 Jul 2006 03:53:40 -0000
***************
*** 238,247 ****
  				qualified_name_list any_name any_name_list
  				any_operator expr_list attrs
  				target_list update_target_list insert_column_list
! 				insert_target_list def_list indirection opt_indirection
! 				group_clause TriggerFuncArgs select_limit
! 				opt_select_limit opclass_item_list
! 				transaction_mode_list_or_empty
  				TableFuncElementList
  				prep_type_clause prep_type_list
  				execute_param_clause using_clause
--- 238,247 ----
  				qualified_name_list any_name any_name_list
  				any_operator expr_list attrs
  				target_list update_target_list insert_column_list
! 				insert_target_els insert_target_list insert_target_lists
! 				def_list indirection opt_indirection group_clause
! 				TriggerFuncArgs select_limit opt_select_limit
! 				opclass_item_list transaction_mode_list_or_empty
  				TableFuncElementList
  				prep_type_clause prep_type_list
  				execute_param_clause using_clause
***************
*** 5349,5359 ****
  		;
  
  insert_rest:
! 			VALUES '(' insert_target_list ')'
  				{
  					$$ = makeNode(InsertStmt);
  					$$->cols = NIL;
! 					$$->targetList = $3;
  					$$->selectStmt = NULL;
  				}
  			| DEFAULT VALUES
--- 5349,5359 ----
  		;
  
  insert_rest:
! 			VALUES insert_target_lists
  				{
  					$$ = makeNode(InsertStmt);
  					$$->cols = NIL;
! 					$$->targetList = $2;
  					$$->selectStmt = NULL;
  				}
  			| DEFAULT VALUES
***************
*** 5370,5380 ****
  					$$->targetList = NIL;
  					$$->selectStmt = $1;
  				}
! 			| '(' insert_column_list ')' VALUES '(' insert_target_list ')'
  				{
  					$$ = makeNode(InsertStmt);
  					$$->cols = $2;
! 					$$->targetList = $6;
  					$$->selectStmt = NULL;
  				}
  			| '(' insert_column_list ')' SelectStmt
--- 5370,5380 ----
  					$$->targetList = NIL;
  					$$->selectStmt = $1;
  				}
! 			| '(' insert_column_list ')' VALUES insert_target_lists
  				{
  					$$ = makeNode(InsertStmt);
  					$$->cols = $2;
! 					$$->targetList = $5;
  					$$->selectStmt = NULL;
  				}
  			| '(' insert_column_list ')' SelectStmt
***************
*** 8189,8197 ****
  
  		;
  
  insert_target_list:
! 			insert_target_el						{ $$ = list_make1($1); }
! 			| insert_target_list ',' insert_target_el { $$ = lappend($1, $3); }
  		;
  
  insert_target_el:
--- 8189,8215 ----
  
  		;
  
+ insert_target_lists:
+ 			insert_target_list
+ 				{
+ 					$$ = list_make1($1);
+ 				}
+ 			| insert_target_lists ',' insert_target_list
+ 				{
+ 					$$ = lappend($1, $3);
+ 				}
+ 		;
+ 
  insert_target_list:
! 			'(' insert_target_els ')'
! 				{
! 					$$ = $2;
! 				}
! 		;
! 
! insert_target_els:
! 			insert_target_el						 { $$ = list_make1($1); }
! 			| insert_target_els ',' insert_target_el { $$ = lappend($1, $3); }
  		;
  
  insert_target_el:
test-insert.phpapplication/x-php; name=test-insert.phpDownload
#29Joe Conway
mail@joeconway.com
In reply to: Joe Conway (#28)
Re: [PATCHES] 8.2 features?

Joe Conway wrote:

Tom Lane wrote:

Christopher Kings-Lynne <chris.kings-lynne@calorieking.com> writes:

Strange. Last time I checked I thought MySQL dump used 'multivalue
lists in inserts' for dumps, for the same reason that we use COPY

I think Andrew identified the critical point upthread: they don't try
to put an unlimited number of rows into one INSERT, only a megabyte
or so's worth. Typical klugy-but-effective mysql design approach ...

OK, so given that we don't need to be able to do 1 million
multi-targetlist insert statements, here is rev 2 of the patch.

I did some testing today against mysql and found that it will easily
absorb insert statements with 1 million targetlists provided you set
max_allowed_packet high enough for the server. It peaked out at about
600MB, compared to my test similar last night where it was using about
3.8 GB when I killed it.

So the question is, do we care?

If we do, I'll start looking for a new rev 3 strategy (ideas/pointers
etc very welcome). If not, I'll start working on docs and regression test.

Thanks,

Joe

#30Tom Lane
tgl@sss.pgh.pa.us
In reply to: Joe Conway (#29)
Re: [PATCHES] 8.2 features?

Joe Conway <mail@joeconway.com> writes:

I did some testing today against mysql and found that it will easily
absorb insert statements with 1 million targetlists provided you set
max_allowed_packet high enough for the server. It peaked out at about
600MB, compared to my test similar last night where it was using about
3.8 GB when I killed it.

So the question is, do we care?

What's the performance like relative to mysql? It seems hard to believe
that we can afford the overhead of a separate INSERT statement per row
(duplicating all the work of parse analysis, rewrite, planning, executor
start/stop) ... at least not without looking mighty bad.

regards, tom lane

#31Joe Conway
mail@joeconway.com
In reply to: Tom Lane (#30)
Re: [PATCHES] 8.2 features?

Tom Lane wrote:

Joe Conway <mail@joeconway.com> writes:

I did some testing today against mysql and found that it will easily
absorb insert statements with 1 million targetlists provided you set
max_allowed_packet high enough for the server. It peaked out at about
600MB, compared to my test similar last night where it was using about
3.8 GB when I killed it.

So the question is, do we care?

What's the performance like relative to mysql? It seems hard to believe
that we can afford the overhead of a separate INSERT statement per row
(duplicating all the work of parse analysis, rewrite, planning, executor
start/stop) ... at least not without looking mighty bad.

I don't have the exact numbers handy, but not too great.

As I recall, with last night's patch we did 100K inserts in about 4
seconds, and today mysql did 100K in about 1 second. We never finished
the 1 million insert test due to swapping (I killed it after quite a
while), and mysql did 1 million in about 18 seconds (we did 300K in 13
seconds). The hardware was not identical between last night's test and
today's on mysql, but very similar (similar CPUs and memory, although
the machine I did the mysql tests on had scsi drives, while the pg test
was done on sata).

The difficulty is finding a way to avoid all that extra work without a
very ugly special case kludge just for inserts. I've been banging my
head on that on-and-off for a few days now, and every idea looks uglier
than the last. One suggestion I got off list was to figure out a way to
build a tuplestore and use it to feed the executor. That's starting to
sound better and better to me.

Any ideas or guidance would be greatly appreciated.

Joe

#32Tom Lane
tgl@sss.pgh.pa.us
In reply to: Joe Conway (#31)
Re: [PATCHES] 8.2 features?

Joe Conway <mail@joeconway.com> writes:

The difficulty is finding a way to avoid all that extra work without a
very ugly special case kludge just for inserts.

[ thinks a bit ... ]

It seems to me that the reason it's painful is exactly that INSERT
... VALUES is a kluge already. We've special-cased the situation where
the INSERT's <query expression> is a <table value constructor> with
exactly one row --- but actually a <table value constructor> with
multiple rows ought to be allowed anywhere you can currently write
"SELECT ...". So ideally fixing this would include eliminating the
current artificial distinction between two types of INSERT command.

I think the place we'd ultimately like to get to involves changing the
executor's Result node type to have a list of targetlists and sequence
through those lists to produce its results (cf Append --- perhaps while
at it, divorce the "gating node" functionality into a different node
type). That part seems clear, what's a bit less clear is what the
ripple effect on the upstream parser/planner data structures should be.
Should *all* occurrences of Query be changed to have a
list-of-targetlists? Sounds ugly, and I don't understand what it would
mean for any Query other than one representing a VALUES construct.

[ thinks some more ... ]

Maybe the right place to put the list-of-targetlists functionality is
not in Query per se, but in a new type of jointree node. This would
localize the impact as far as changing the datastructures go, but I've
not thought hard enough about what the impact would actually be.

regards, tom lane

#33Joe Conway
mail@joeconway.com
In reply to: Tom Lane (#32)
Re: [PATCHES] 8.2 features?

Tom Lane wrote:

Joe Conway <mail@joeconway.com> writes:

The difficulty is finding a way to avoid all that extra work without a
very ugly special case kludge just for inserts.

[ thinks a bit ... ]

It seems to me that the reason it's painful is exactly that INSERT
... VALUES is a kluge already. We've special-cased the situation where
the INSERT's <query expression> is a <table value constructor> with
exactly one row --- but actually a <table value constructor> with
multiple rows ought to be allowed anywhere you can currently write
"SELECT ...". So ideally fixing this would include eliminating the
current artificial distinction between two types of INSERT command.

I think the place we'd ultimately like to get to involves changing the
executor's Result node type to have a list of targetlists and sequence
through those lists to produce its results

I was actually just looking at that and ended up thinking that it might
be better to deal with it one level down in ExecProject (because it is
already passing targetlists directly to ExecTargetList).

That part seems clear, what's a bit less clear is what the
ripple effect on the upstream parser/planner data structures should be.
Should *all* occurrences of Query be changed to have a
list-of-targetlists? Sounds ugly, and I don't understand what it would
mean for any Query other than one representing a VALUES construct.

There are certainly many places to be looked at if Query.targetList
becomes a list-of-targetlists (about 153 if I grep'd correctly).

[ thinks some more ... ]

Maybe the right place to put the list-of-targetlists functionality is
not in Query per se, but in a new type of jointree node. This would
localize the impact as far as changing the datastructures go, but I've
not thought hard enough about what the impact would actually be.

OK. You've given me a good bit to think about -- thanks!

Joe

#34Tom Lane
tgl@sss.pgh.pa.us
In reply to: Joe Conway (#33)
Re: [PATCHES] 8.2 features?

Joe Conway <mail@joeconway.com> writes:

Tom Lane wrote:

I think the place we'd ultimately like to get to involves changing the
executor's Result node type to have a list of targetlists and sequence
through those lists to produce its results

I was actually just looking at that and ended up thinking that it might
be better to deal with it one level down in ExecProject (because it is
already passing targetlists directly to ExecTargetList).

I'd vote against that, because (a) ExecProject is used by all executor
node types, and we shouldn't add overhead to all of them for the benefit
of one; (b) ExecProject doesn't actually have any internal state at the
moment. To keep track of which targetlist to evaluate next, it would
not only need some internal state, it would have to be told the current
"es_direction". This stuff fits much better at the exec node level ---
again, I'd suggest looking at Append for a comparison.

But really the executor part of this is not the hard part; what we need
to think about first is what's the impact on the Query datastructure
that the parser/rewriter/planner use.

I'm still liking the idea of pushing multi-values into a jointree node
type. Basically this would suggest representing "VALUES ..." as if it
were "SELECT * FROM VALUES ..." (which I believe is actually legal
syntax per spec) --- in the general case you'd need to have a Query node
that has a trivial "col1, col2, col3, ..." targetlist and then the
multiple values lists are in some kind of jointree entry. But possibly
this could be short-circuited somehow, at least for INSERT.

BTW, I noticed an interesting property of historical Postgres behavior:
you can put a table reference into a VALUES targetlist.

regression=# create table foo (like tenk1);
CREATE TABLE
regression=# insert into foo values (tenk1.*);
ERROR: missing FROM-clause entry for table "tenk1"
LINE 1: insert into foo values (tenk1.*);
^
regression=# set add_missing_from to 1;
SET
regression=# insert into foo values (tenk1.*);
NOTICE: adding missing FROM-clause entry for table "tenk1"
LINE 1: insert into foo values (tenk1.*);
^
INSERT 0 10000
regression=#

So that last is really exactly equivalent to

insert into foo select * from tenk1;

I do not feel a need to support this sort of thing when there are
multiple VALUES targetlists, but it'd be nice not to break it for the
single-targetlist case. At least not till we're ready to disable
add_missing_from entirely.

regards, tom lane

#35Joe Conway
mail@joeconway.com
In reply to: Tom Lane (#34)
Re: [PATCHES] 8.2 features?

Tom Lane wrote:

Joe Conway <mail@joeconway.com> writes:

I was actually just looking at that and ended up thinking that it might
be better to deal with it one level down in ExecProject (because it is
already passing targetlists directly to ExecTargetList).

I'd vote against that, because (a) ExecProject is used by all executor
node types, and we shouldn't add overhead to all of them for the benefit
of one; (b) ExecProject doesn't actually have any internal state at the
moment. To keep track of which targetlist to evaluate next, it would
not only need some internal state, it would have to be told the current
"es_direction". This stuff fits much better at the exec node level ---
again, I'd suggest looking at Append for a comparison.

OK.

But really the executor part of this is not the hard part; what we need
to think about first is what's the impact on the Query datastructure
that the parser/rewriter/planner use.

After a quick look, I think changing Query.targetList is too big an
impact, and probably unneeded given your suggestion below.

One of the problems with the current code is that the targetList in the
"VALUES..." case is being used for two purposes -- 1) to define the
column types, and 2) to hold the actual data. By putting the data into a
new node type, I think the targetList reverts to being just a list of
datatypes as it is with INSERT ... SELECT ...

I'm still liking the idea of pushing multi-values into a jointree node
type. Basically this would suggest representing "VALUES ..." as if it
were "SELECT * FROM VALUES ..." (which I believe is actually legal
syntax per spec) --- in the general case you'd need to have a Query node
that has a trivial "col1, col2, col3, ..." targetlist and then the
multiple values lists are in some kind of jointree entry. But possibly
this could be short-circuited somehow, at least for INSERT.

I'm liking this too. But when you say "jointree node", are you saying to
model the new node type after NestLoop/MergeJoin/HashJoin nodes? These
are referred to as "join nodes" in ExecInitNode. Or as you mentioned a
couple of times, should this look more like an Append node?

Thanks,

Joe

#36Tom Lane
tgl@sss.pgh.pa.us
In reply to: Joe Conway (#35)
Re: [PATCHES] 8.2 features?

Joe Conway <mail@joeconway.com> writes:

I'm liking this too. But when you say "jointree node", are you saying to
model the new node type after NestLoop/MergeJoin/HashJoin nodes? These
are referred to as "join nodes" in ExecInitNode. Or as you mentioned a
couple of times, should this look more like an Append node?

No, I guess I confused you by talking about the executor representation
at the same time. This is really unrelated to the executor. The join
tree I'm thinking of here is the data structure that dangles off
Query.jointree --- it's a representation of the query's FROM clause,
and (at present) can contain RangeTblRef, FromExpr, and JoinExpr nodes.
See the last hundred or so lines of primnodes.h for some details.
The jointree is used by the planner to compute the plan node tree that
the executor will run, but it's not the same thing.

There are basically two ways you could go about this:
1. Make a new jointree leaf node type to represent a VALUES construct,
and dangle the list of lists of expressions off that.
2. Make a new RangeTblEntry type to represent a VALUES construct, and
just put a RangeTblRef to it into the jointree. The expressions
dangle off the RangeTblEntry.

Offhand I'm not certain which of these would be cleanest. The second
way has some similarities to the way we handle set operation trees
(UNION et al), so it might be worth looking at that stuff. However,
being a RangeTblEntry has a lot of baggage (eg, various routines expect
to find an RTE alias, column names, column types, etc) and maybe we
don't need all that for VALUES.

One advantage of the first way is that you could use the same node
type for the "raw parser output" delivered by gram.y. This is a bit of
a type cheat, because raw parser output is logically distinct from what
parse analysis produces, but we do it in lots of other places too
(JoinExpr for instance is used that way). You should in any case have a
clear idea of the difference between the raw and analyzed parser
representations --- for instance, the raw form won't contain any
datatype info, whereas the analyzed form must. This might or might not
need to be visible directly in the VALUES node --- it might be that you
can rely on the datatype info embedded in the analyzed expressions.

regards, tom lane

#37Joe Conway
mail@joeconway.com
In reply to: Tom Lane (#36)
Re: [PATCHES] 8.2 features?

Tom Lane wrote:

No, I guess I confused you by talking about the executor representation
at the same time. This is really unrelated to the executor. The join
tree I'm thinking of here is the data structure that dangles off
Query.jointree --- it's a representation of the query's FROM clause,
and (at present) can contain RangeTblRef, FromExpr, and JoinExpr nodes.
See the last hundred or so lines of primnodes.h for some details.
The jointree is used by the planner to compute the plan node tree that
the executor will run, but it's not the same thing.

Ah, that helps. Thanks for the explanation. I'll start digging in again...

Thanks,

Joe

#38Jim C. Nasby
jnasby@pervasive.com
In reply to: Tom Lane (#36)
Re: [PATCHES] 8.2 features?

On Thu, Jul 20, 2006 at 08:46:13PM -0400, Tom Lane wrote:

Joe Conway <mail@joeconway.com> writes:

I'm liking this too. But when you say "jointree node", are you saying to
model the new node type after NestLoop/MergeJoin/HashJoin nodes? These
are referred to as "join nodes" in ExecInitNode. Or as you mentioned a
couple of times, should this look more like an Append node?

No, I guess I confused you by talking about the executor representation
at the same time. This is really unrelated to the executor. The join
tree I'm thinking of here is the data structure that dangles off
Query.jointree --- it's a representation of the query's FROM clause,
and (at present) can contain RangeTblRef, FromExpr, and JoinExpr nodes.
See the last hundred or so lines of primnodes.h for some details.
The jointree is used by the planner to compute the plan node tree that
the executor will run, but it's not the same thing.

There are basically two ways you could go about this:
1. Make a new jointree leaf node type to represent a VALUES construct,
and dangle the list of lists of expressions off that.
2. Make a new RangeTblEntry type to represent a VALUES construct, and
just put a RangeTblRef to it into the jointree. The expressions
dangle off the RangeTblEntry.

Offhand I'm not certain which of these would be cleanest. The second
way has some similarities to the way we handle set operation trees
(UNION et al), so it might be worth looking at that stuff. However,
being a RangeTblEntry has a lot of baggage (eg, various routines expect
to find an RTE alias, column names, column types, etc) and maybe we
don't need all that for VALUES.

I misread that to include SRFs, but it got me thinking... another
possibility would be to changes VALUES() so that it was treated as a
function, and allow it to have an arbitrary number of parameters. That
would automatically allow the case of SELECT * FROM VALUES(...). INSERT
would need to learn how to accept SRFs, but that would have the nice
side-effect of allowing INSERT INTO table set_returning_function();

Of course, adding the ability for functions to have an arbitrary
argument list could well be more complex than any of the options
discussed thusfar... though it would be a very handy feature to have.
--
Jim C. Nasby, Sr. Engineering Consultant jnasby@pervasive.com
Pervasive Software http://pervasive.com work: 512-231-6117
vcard: http://jim.nasby.net/pervasive.vcf cell: 512-569-9461

#39Joe Conway
mail@joeconway.com
In reply to: Tom Lane (#36)
1 attachment(s)
Values list-of-targetlists patch for comments (was Re: [HACKERS] 8.2 features?)

Tom Lane wrote:

Joe Conway <mail@joeconway.com> writes:

I'm liking this too. But when you say "jointree node", are you saying to
model the new node type after NestLoop/MergeJoin/HashJoin nodes? These
are referred to as "join nodes" in ExecInitNode. Or as you mentioned a
couple of times, should this look more like an Append node?

No, I guess I confused you by talking about the executor representation
at the same time. This is really unrelated to the executor. The join
tree I'm thinking of here is the data structure that dangles off
Query.jointree --- it's a representation of the query's FROM clause,
and (at present) can contain RangeTblRef, FromExpr, and JoinExpr nodes.
See the last hundred or so lines of primnodes.h for some details.
The jointree is used by the planner to compute the plan node tree that
the executor will run, but it's not the same thing.

There are basically two ways you could go about this:
1. Make a new jointree leaf node type to represent a VALUES construct,
and dangle the list of lists of expressions off that.
2. Make a new RangeTblEntry type to represent a VALUES construct, and
just put a RangeTblRef to it into the jointree. The expressions
dangle off the RangeTblEntry.

Offhand I'm not certain which of these would be cleanest. The second
way has some similarities to the way we handle set operation trees
(UNION et al), so it might be worth looking at that stuff. However,
being a RangeTblEntry has a lot of baggage (eg, various routines expect
to find an RTE alias, column names, column types, etc) and maybe we
don't need all that for VALUES.

Since the feature freeze is only about a week off, I wanted to post this
patch even though it is not yet ready to be applied.

Executive summary:
==================
1. The patch is now large and invasive based on adding new node
types and associated infrastructure. I modelled the nodes largely
on RangeFunction and FunctionScan.
2. Performance is close enough to mysql to not be a big issue (I think,
more data below) as long as the machine does not get into a memory
swapping regime. Memory usage is now better, but not as good as
mysql.
3. I specifically coded with the intent of preserving current insert
statement behavior and code paths for current functionality. So there
*should* be no performance degradation or subtle semantics changes
for "INSERT DEFAULT VALUES", "INSERT ... VALUES (with one target
list)", "INSERT ... SELECT ...". Even Tom's recently discovered
"insert into foo values (tenk1.*)" still works ;-)

Performance:
============
On my development machine (dual core amd64, 2GB RAM) I get the following
results using the php script posted earlier:

Postgres:
---------
$loopcount = 100000;
multi-INSERT-at-once Elapsed time is 1 second

$loopcount = 300000;
multi-INSERT-at-once Elapsed time is 5 seconds

$loopcount = 500000;
multi-INSERT-at-once Elapsed time is 9 seconds

$loopcount = 800000;
multi-INSERT-at-once Elapsed time is 14 seconds

$loopcount = 900000;
multi-INSERT-at-once Elapsed time is 17 seconds

$loopcount = 1000000;
multi-INSERT-at-once Elapsed time is 42 seconds

$loopcount = 2000000;
killed after 5 minutes due to swapping

MySQL:
------
$loopcount = 100000;
multi-INSERT-at-once Elapsed time is 2 seconds

$loopcount = 300000;
INSERT failed:Got a packet bigger than 'max_allowed_packet' bytes
changed max_allowed_packet=64M
multi-INSERT-at-once Elapsed time is 5 seconds

$loopcount = 500000;
multi-INSERT-at-once Elapsed time is 8 seconds

$loopcount = 800000;
multi-INSERT-at-once Elapsed time is 13 seconds

$loopcount = 900000;
multi-INSERT-at-once Elapsed time is 15 seconds

$loopcount = 1000000;
multi-INSERT-at-once Elapsed time is 17 seconds

$loopcount = 2000000;
multi-INSERT-at-once Elapsed time is 36 seconds

$loopcount = 3000000;
multi-INSERT-at-once Elapsed time is 54 seconds

$loopcount = 4000000;
multi-INSERT-at-once Elapsed time is 134 seconds

<table value constructor>:
==========================
Included in this patch is support for <table value constructor> in the
FROM clause, e.g.:

regression=# select * from {values (1,array[1,2]),(2,array[3,4])};
?column? | array
----------+-------
1 | {1,2}
2 | {3,4}
(2 rows)

The strange syntax is a temporary hack to eliminate shift/reduce
conflicts. I'm not entirely sure we want to try to support this (or
something like it) for 8.2, but much of what is needed is now readily
available. More on known issues next.

Known Issues:
=============

General:
--------
1. Several comments in the patch are marked "FIXME". These are areas
where I was uncertain what was the "right thing to do". Any advice
on these specific spots would be very much appreciated.
2. I broke the rules regression test -- still need to look at what I
did to mess that up. Somewhere in the reconstruction of "VALUES ..."
according to the diff.

VALUES multi-targetlist INSERTS:
--------------------------------
3. Not yet quite sure how to get DEFAULT to work for "INSERT ...
multi-values". As noted above, works fine if there is only
one targetlist.

<table value constructor>:
--------------------------
4. I'm getting shift/reduce conflicts that are not easily eliminated.
Making VALUES fully reserved only made it 1 shift/reduce conflict.
5. Column aliases are still not working correctly. Haven't really looked
closely at this yet.
6. Data types are being deduced currently based on the first row,
and not currently getting checked on subsequent rows. So it is
easy to induce a crash:

regression=# select * from {values (1,array[1,2]),(2,3)};
server closed the connection unexpectedly
This probably means the server terminated abnormally
before or while processing the request.
The connection to the server was lost. Attempting reset: Failed.
!>

7. In general, <table value constructor> in the FROM clause needs
more discussion -- among other things, how should we determine and
enforce column types? I think this could be a very useful feature,
but I'm not comfortable I understand it yet.

=================
As usual, review, advise, comments, flames, etc. requested

Joe

Attachments:

multi-insert-r6a.diff.gzapplication/x-gzip; name=multi-insert-r6a.diff.gzDownload
�=9�Dmulti-insert-r6a.diff�<ks�����_��L[��m��pn�q�������t���"a�
E2$�����~w�"H���4�����c��b�O`�I��{s�K�`�~���H��8	��^��y�{����G6.��h��q�'Gq@?�W��^�E��^@Sx���������rFt����y�$�^z������n�>�h���6�oH��a{�?	��k����I�����{g�a�/��8�����}���Gd�?�����@
H��w�}��� �#�v��e;}��&D!�\O;O�P?����$.��b��Y�}&|��3��}�d�=�^N���t������b_4o�m�WG�y=�'^|W,��EB��,hF$[{r���a��[E�~
{�h��d��� �K#/����4p�J�=�T��IIqCx�M�3V�������H�qAJ\]nx�&5l�/g�V�_�</@��������9��};7�Jj$@pC�lW���6�
�x��W�,��:v��/��6Mx8Z��]Nx8�X�I��&��*)�,�,���f���;/@��Ak�����nW	�Cg^�N��
d�K`����4����� �.����s/����h��2`�Y1����X���'���;/���G��4{�eh�n��M;Dh�A��� a�CN`}=r�W
iP��q����a���5{���J<l
M~j#�
�hZ|s_'���,��t|�o��k.���UE����"����Z�v*j$<B\������j���F19ck���b<r{��6����+UV����V4�ktT��E�}�"y?CI��[yQEo��i)��|F�����uk0�*�x���h����o�n5�N�b���*j�v�t����4C����������>@�[�&����q������Oa���R/e�\�5���Z�����M����rP�%i��#�n�^tB�"J�T��r��:�9h�x!]o�<��\��T�H29�*A��q�e��Y�J������J@B}4j.�@<9�P����f����n���E�������.��Ei�Jg�_�Dm��T|�UZg����e�5��&�V�4�&3�1)�m5Jj��`t��c i��ck�y4|H���H=�f%��,�b�}�\�uc�,����!z������m���``aP�d����jN�T�s�~�����E�a��e�ka6����Z�`���mu"&�#����lWbZ=T@�pvA�P���eo�Sw�LLlt������,g�ka�k/{{��k��Y�S�[���i����&���������3�i�,���TE��/�����V	�S���{V�v5�����3iD��4�e0*�B�Z������bRd+�2wb��m#������J��^5�0Q>������|��4(4jr`���m�t�\t��4�g�E�����O��0�=�:>��4�6�R������Y�P��:����H����C9n}X���&7=��{#�����y$Q[��,�2���b��?f�M P�����H��u�?`uA_��_G�M�@� \C�r��t�"��U?����{5T��L�������lLq�\6��m����m�m��z��f���{�O��4f�<��~
���rZ����mZg���0�H�a����()�v&U�s������gq���4�:;�pb��i|9����������o��8��3��S=s�8D�y���cL~jR�����Jy��� 5�=84c�O^z�j��{z��m��ity����4�(��B�$(n�����C~����O���$"[a~��"����ILa|���7�S��9�����A�$KVE��1�,p�"���@P�F#!�^vC��0/:��l�!��-�������g'�U�#9: ���.�em$�_e����:<��=��emG��G�S��;%�
n_�<��b��^�"�'�n�fI���xdY��D����.WiD�����~�������� A������Y���
DH���n��%�}R�R��>+�c�
�����
f���CE����X�k�L�;��GQI��I�HVQ@�-%���p��h�!�,��x.���X���0.�Lb��q��*����`O��E!�q�*�&�����!�3��>�	�t����=diJ/�18��	��p�e4.*��c�G+��Q�����~�:�?
�H�8���_\&��)�����4��Tb�d�����-����&�g���&-r�E9��>������X�
���b��lV�4)G�J���<��v4��q��.���)1��)����z���i���~��������a �D�!r".����`u$�y�L�y��U;�*��R\�S�� e�$�f��q!].�������R,c��w$�
��Bd%_~��1��@�g��H�f?��p19�k>F��iNH =�v��4�"���[
;��H���r<Tb�g���<p����J�%R�\
�PXT0-`~�5�K�4�xNP�g�&K.Ea
����hu��i-W�tU(������C?]��>�����q������.9���em��Af�UO����I�a\
4���_� �h�M��1��z�Is�ym]hFq|gz~~z���C�����O_Ng���W�������������r��[�7��o:��JW�Z R+��W@s'0a`K
���6�]����W�b��kr7N,0�	_$$����t
rou�)�M���fQ��Qa�
���P|��K^{�H��}w����"���sV(@<6���-�?�T5�}���h�tA$�_{~�&
��������S�����^����H$P�*�H���A�*��F������a1R<�*t>�������j��.����S9�K�X�	�O��%T���.U���7}���1$_��]c{{~���	����5P����Z'�D'��j
��7+|]�� �6Xw*?Y��V!���Zr'2;2CT����Kd�����FW���Q�|I���{��K��N�c����Q�-/n�f~�A�u�(��8�F���XGY��TXD=
�
�����&������.k������L��rm������c�K�Q�YK@�w-f��]juv��{}xz�8u��G���$�O��.]&���gc.���(�:�!T��``/+s��2�_b���s�S��������v��w�3e�s-{�������$�U��Be%�Zc�2�"����j�J��<�8�������pg���,���dK���s!0s���X�kT):�A�`����������3�/'�B�����RW�
f�;L4�$V^�+��~oh��v�������ue�=|����]F�s���[R#I��DM�?�X������pwT=��gR!����!������Q�����N��q�u0�-kr�5��mg��bX[��gU��\�����g,|�Ij5Z%^?�<�N(�2��Ft�Q1"��97M��{qy~t������[���nad�nad����k��1����y�$��|��+����{O���q�}~i�:�3��~�~�u+�O�7X������0P��o�2pzZ
\�*��y+1�1n��q�`�i+�g��y}�#������=�*����M�m����i����C�U�J�����h�>?��q������/+�J�l*S������O�Q\P�_�*��bD��J��jP�����h��	F��^%�����^��aNO�^����R��
��,5�q���?���D��F�J��U�Q?����#x�l�|l�*�d��;g����hh���V�O`�����=Xe�P�Q��&�?�Z��l[��Q�Y
��D�FS7�p�ao�W)c����@�~W�W���#�P����-5(���:�k��3�`V��@�0�������w�����M�;���8H�C�x��]���X���?�{�k��"�8����)O�z�C�e����5={�`R^��#aVD�������sl�.4T�tq3s�� �x���
���������]Y |��OV}�S9� n�JW"O���f$}��[�M��:.��RO; mR~����g%M��)?Nw�v����u	��B������:s���"�y�D�J�8B3TmX-�c�q�l���f�rD�d�
^�	�/�*>}���W��o���M������|�pf�����<lB��?�)����[W6���8�MtQ�\�
��;|�	oi�KA.��|����7�\[��y�[97�����O������B�J��^����������D���jK=0Z�s�����2H^2�pG����&������6�������B�[�#&).�h(�.�#0�N���Pd�df�e�������������
,Q�x����eW���}}�c��T�U:��O�
r���X����������l�8�J�S��m.���(�P���k��6�I6����~/8��������vK��Cxd�1�
����I��_!<��|X��F~v�_���|yV��}V�3���aL�"\�l/����E��W�V�����l�"X�>"����:[������+$�����
�>c�J2��h,������n�@8�2�-�?���iZ�ia��v��G��^�C�DO|f����g�m�x�)G�������A�M�0<��-�YLi@�E�(�DHy�~�e�\}�����)�xo�T�����`��kys
���{��� ,0�w����G~���+������.��L�J�� �.
��N�/��3�*��;Z�����W��DE�QK2d���6~Z�Q���N�Vk����y��3��~@/�OT
�.�$	�����<8��0�"�#���,y��maP,,�X����L�����������i�@h�V�S5�^�9u�>8��
���6�OA�A_����Q{)P��v ;)�;B�����`I)������6�VG�[K+��A�|a���:^�)�nb���*x97���H�����]^}p�������
=fIB��V�i��h���1����yLw`��n�1����5��1G������v�E��&�r#�%�J\���jue�)����$8<��"��@��5��3�48G����s�w�ku\��xBT����	���+[��f?]������kI��9S�(�������y�)V�J#�_)�������3c������W`P�����g9�n�$)Z"�����k�q^�]�e�K�+s�����x��� �E=<���/������DM����6�v�������9~^����SY�rm��V	�i��22�}���?>+GI��a�(Q�+�n�Q�&�!z���H	�X
/jC��������|�����v�����f��?��s�i�,@��=�����@a���\x���p=GU�`�-�u�*/�r}����/|���Z�+��������o��y=:��"d����'S�:5o^��(��6���j�U��Y���O2;z�}����Nm?��P�����Tw~��Ee���8����
*�Z��-a�����H^V�	�-9�@���0���y��0A�7�t���z����e�@p�p�&��h�&��'���i�W�5z��L�K�(�
B:j*���
�r����Se�&���^@`���T�_d���SM���Y
`�@k��3�K�D>+[�p���?�V9����-2o�"���i�xD5�bi����jC��P���0s��������h���Y���l�^A��,�"��#g_)���R~��={���$"XU�ULF��o�J>�V����� N���K�����1�����������
[���*y����9{����y28o�w�U_K��o�����S9c5o>
��s�����h~���A�����lk���.(5�������=D�"'?03��C�r�z
�pd9�W���P���~�GL����k��P�RB�5�%V���0a���<�d�������h@�S�5�&>�m,�V��C��2~U��<�mA���������qf~�B��3�R�(�C:s��#�����b�3y���{�����<�;���-��{~$j#��q������mG~�~E��	Ar$� .)qW�ndJ����	�"b����:���utw�L�����=K�LO��uu�+����C��l1�\�]�;���u�������������ss
T��X�25�����w_��i��iwT���86�7��Ms� �B���$��v'��|l��A�R�zc������ �b�%k�F��Gk�!��}�p�1T�����M�V���,"_�@��V����������!�=
��	��7(4��4�?�4��5Q���s�N����b`���S_����l�����z�g�i�.yk�����T�w�^���8y��x3K�"1Y9��^:�9L����%z���83�w���EM!���f��1�
kpD|����h��%�i?f�]�
��:��> �!>6����m��uB"��e�x
�8���������G"����_��z�,�v��?dLB������RP_0��p4�k+J�&`������L��[�{�u�[#p���,j�C��h����.@�yA/�kX	������:�#������7�Wb�`�5�.�$���Xgw7��n�&�T&"J�5���1�����`�Dm��bgPmziJJ��������bn1��j�����A�����!:��5�Z��4����#�L���&=i��"Gg��?J����������o��_|��r�=�K�E�(�o�����%y���i\s�qgm��>?X��Yxjs���D	!2py@�X�78����C}}9�pG�K�L�nK��-�a��p_�i`X,Y���^[�"�/�`����@�d�Q)��,�V5��b�	I��_�sy���UeMdv�9��+r��:���������������}W�����A�'A��D��Qn�[h�m��������������^�j$����Bu�Sm�l��8�B)cm<5Y�dh���Z$y������dM���R��(��]��e.�e_4���"�U����8��	fUr*�����A�J���S.���k���oq��-��S�6�U���}G^�� �xv�@�"��G��*�{�9�(u�u�[BQ�*m4�����i������	�xgj���P�n�R3�
��vq.�q+E=���I�{
1@��2h�"0?��.�0.Pe���J���T�����S���@��`g_(���5�h������<�@�Q(���#�w"Ya�f�+mn;�8��s���
4��Ls�2�%
������U�Y��A������vt���I���z���'Q�/�T.p|#�L6P��|;���`
i�5��8�B�v�
�vd���t��DRg���.���Y������;�{��z�>����P-����c�[��o��\�-r_��\�W@���\tN��{te�
�z/\E������ P����d��d������������?dXAk����dKI��r������R�S�r+���F��XQq��$h����5l�O<^��%����V*�-�Y��[d�{�#����-$`�����0���~�Mv����������4z
�Q]V�ngu�]Y��y���p;Y�l
{A�I�{hJ[��[����8L�X|�
y��P~>c�1��8�������|�p�����P���<���o���d}�+l�:|��?�xuzu�4�� Y�����Y����)��L#����]��r
��@��m+1�-���M�-	�t�M��������#(�VQ�]���p����:�M�T���d5c�&��iv���W�bM�����q��K���t���p�=���+�E�Q���[y�i8�!�T�/������xQz����=�8�8����d�f	Y�����*�����vc�%p?����i
s(:fN�Ksq;8�-5�R��8����61�X�����u����j����������on3o?���=O~o��z#i�Ix��]�@���Vs�����Ih�����5��S��I�D]��Kih�1�%�
UN�rj�Lf[������i���%/G��X_���t�z
Eo��"�?�B�j������Z����t��4MRk\)xV��6���Vk ���]6�t��o���&
���*�����0)7�-��6�?����
���<�ZNm�:��A�<$]���������������9V���T��@���$M'w�T��9���(�\���>��D�aZ�M4*����;����\�Wc�@������R����&�n��%;�F^��6%�X��^�v��<>�@s��8'o��g���}�h���5Z��
-��[<��n��2�]<����������Q����S��}� ?�9zp�����Q���m�n�ku��?�)|G�������Q���u���q�o��( ��>�B6��/�6d�������r�0�����`��1!�z2
�.~;�X�Y�2�) �*q�I
Z������p�D�z�����>�W$������������5g�[����<��xZP����'��;�������-��e?+6�rG�-mT�i�l��b /�{?�f����.��b��c���~��$tDG$%��I/�����Z�V]���45�3A�A����s�7��&�H�R�<V�T'6 �(p�&n9,�
��i��Y�fZ�`b�����z~�-��nR�����
&���cGG67���8X1�w7rAp��z��6;e��s����Qr�������K��������tu������J+#B�5��{u������xIfl����@����a��|b{�����O�q����&�^�B��G�l���j�������%x�����y���l�����^�B`��*h�6����2%�7I\i�3����Xb�-�e,�K�>"�i��n@��G+������&�,	-��z������ZS�6�5P5��X$�tSh�
x�ft>2����R��d6�=�1��kn2;O6]^���T@�.4��J{S6��7B��M�9��F��#:�G�DxfKMML�K���X�����0�Sl]���9H����R�A�cH���8�������{���i��"U��|�^xL,������D�����
Z=�w)�|��}�w���>�h�Ql��C�)�����.q�#Vp
��I���X%�����U��B<0S��4&��VK�zfb�
a����?�Y��7�d�4�" ���5p�x�g�.��C��w7-Zzxs��&�zFf���y�$��[�Y����B����B��������1�����Ge�3�(�����o�[�&�@�z�<U�=��J�2q�R�HK�����]q���e�>���&c�%�@�t�O����4����&ME-����1�I�	�o��nBo��x�q��x���7�t��(���:[�E�?��aH���KH����'*�������>{y����eq�Y!�����������m'���?�B����/����N*(��$��I$�NwG"POlo5t�s��v:����T����FY(�#y
���y �.�'3��-�F ��R{I���y������G��Ra|�=��>�1t�����<�z ?�D*3�]O�N���H~�3������9������]$������}��iC�d���f����+��T���T?�}uzu���_N/�L=z?��s`1���I��F�WK�����O]M�Vp\X�Y�w�3���_J����$<����>�C:Y>����I4l�MR�i�'}@����V\#�����i����Q�;�:'q�'�����1PV��������<s�i�����\ �&D��9���|D�1���e��f��V����R���D���5���,�*�����~�~���py��Z��h��|������y/���85���K}���8I��r�������A]Q�j_;�A��p�L�=p��h��,MKL��?(�wP����zb�X�U����.?���]v[�}6E�n��>��/�����s��v[��A��������{�5����E:����5l:&h[�v�B�c
#nG��]�n��O�~�#�k��&Fn��[k���wi���P_�?_B�����5����b����^/�I��� �'�!!T<�o!�'�����?�[A���bV��*@�x&�����������@���l^�W��3���>���7���s��w���U��R-��\j�<}���?mq�}������*��yU�����$��{/?������m�~�=�W��w�c�F�K|I0~n����\�C}��#�B�Z�m.=�s�k�����<�_��SXw1�
�>�J����SyV!K
��84��y���.���/>����������2k���~��������Q��`p"��GG���H��\w���Re����M�%��9��	a��zO�5S�-���q~�������u2��lg�s���%5KV9$���t|����r	>�d���^���sf���>��,=vK|�����b������B���n~�>|�,u	���H��b��k�o�����Q��b�;1�R
er�*rw��oktm�e9N�x�bG���_}+@�c�M6�S�Ng������Y�����g
�wM�����/���
88�h�z�L�����B����5�����N���0�
s��jK�P���/�M�~���?�G��6����V���LJu��,H�D���1�����^�B�@��x����%�����a����A�.��<�%B�\+oAW]����q�;��%��O�k������t�
'��Q_���
�����$��,Xfg�&��fjb�x���� 9��BeFJ��,I�J,D-eO��u�Cw0�&k��,����z2��G�������?MD7�xe5���)�Ssp\>9<��+�K���[��-_3e���\��b�zia)D0����9}
 
t�
��O���(wV��g�h�x�����Q��5�h�RI�2���5f�q~�^1*���')&�X��/�����[�p��]	F�L��TU��FS<�p5?.����BLp�'���Q�Mrw��_�������k���|X��[�#Nf���(��������I|�c(����~c+s�n��F\^_�A���_F�H�wh����=m4_&K�����!��M-�Sy�%t�n�O�~�l>���������:��<DCo�'����a������/��S�G��!��?��k@@�p�7)��&��2����V�^�^�]��n��x��4�X��-ha�8f�)d��)�n��-c�H��?L���p�/0K��~�F���|��W&P�d���[&�c��
aJ�,�/hK���Z95~����?\�/��?�<�xy��g����\���i���l4�9��(!��4L���{y[B�W�l�X$�j��C�a�����t,IKC�jsdP�-Q���k�F���EN�Y��!�Kxpj��V�����L2�4��e�%���P����s��|�������
����4������7���p�9�mX��������v�W[z_@sP��J���\��qa_�U!C'�����G�aP-8k�����9��@o��Yy���"�/s��gp�_�JkC�r��|�'kp];g�?�CAQ�lM��g����N�����+��k\��;���������%|�c��`��7������-���6S�T���W��6��s��0�XpI�1���HD��a�'0��2q�6c�%Z?����B�z�b�S��km�&d��8������ih���O��r�G'e�/M�����0o�[���P\��|s����+��s����)�1�'�j�/����X���,!���o8��0��$'���@��W����i��X����Sx��]xP��L@�^�pwo�m}��:n5	|
V��������	���m��u��b���r]4R���y6F'�ht"|!�A���V$���Z���C��,X������u�(@��*F�4x���L�/
�)2������$�h5!��4^�\U�4����|Yk��j�}V�
H���H@�X=fE�OM����t��wT�!�>"aBk�J���_��+_%���l���Vv���
������:L.�Pezg�E]|a�
�o�8�j{��4-X$C�B��?Q�=:�<W��A7�b!�`U��J�Il��kPa�+T�7�lO�q��a}����SZ���P�5�����{��;��l ���������d�4�=>��?��5&��v����N9�z���7��e\� u)���}���fm�	O
��CXc�"��lvM��Imt�(M:�����sp���������|��n���X�8�a��
�|b�3����C��<!Y�CW�KQ���n��G��l�a;Yq�G�{�[%mth�FB�,?�'��4Y�s ��)�B��X ��xVi�r��\����-���upcC7��=����9f��������2���<�goc�����+��i��>G%��i��JA��\����XV�qI�$4�Iu+�,����ZA�G�N�|l�M�S��	�]���(����V�����C���2x�"2.� -T

�`�'

8(�	A����F�����nE�n����q?�x�P�(����-5��5�yz�S�\Z��K�^�����Y�X�'1�F�*��F�c5v`Zr2��.x�����$>��A�W�#v���t=������&�X���7�p���Q��F�#x�5,��(1�m��L]�����Tj2�J�$2��Zi-C�[I�0�33�S6��fV5.)�`9W��+����W���B��5��'����?�����i���^������@��	.�sHU�J���f�/���l�E<~G�k�����D�j$�x�����v/L�P��4�3dx���\3������ �V=��|94p���,������3�0u;��Q���(�����c1�n0�$��*�M��
�=�����L*.���:��@,�5�z5I+gY����N��_�6Ca�������F���o�:����kMP������e���������,(Az����={y~��2�j�f�����d�0�3-���VZ<������B�(�D
��0l�%��������SW� �k5�(�bK��`��t�I����S�{��\����� �#[�S���:��lR����u�5Q�\B]g�w��*���'y�,)�`#���F+�h q�,�I�~2�����|���~����D��9{6�����"�__����n���m:C%�]$C��Cd����C�P�����u�Z��{��~ �����Z/=�C����:� 9�t<��)�:���$�c����k�`�j;7MH]m4ezgS�������=�4�Y����N��5��rP)����f1��R}u��:�W���U����������"��=li�~�������~$�U~�����6i
��Y����(j�6��������=�/�IZ����������������+�I�'��&�cJ3���|'l�~�*��z�uuZ�At��b&l]������y�t��U>i9b$�ec���e�h�=E����@Y����@�k2br�  Dp7"����O�PM��_���,�E��|
Z#r�LOgm{J4���'�'�`j:\s���Z>r �������Uo�(S@�Qf�����N:\Y/�]�g�MBi/��{x�|��u�����"-�	'a#
�VH��V����{?^~�c�%g����4��)��.���%����m���.L(T�����������:�xuvq5~w�*R�'&��b�U��O]]�H������>�v�v��1�������)6�����;�+��s����9���m��r�n���-�������<�!�D�~�u�Wg$��������VA5������,"Vj��?��Bv�i��N�+���F�Q�+�nZ�9�����'J���#�>����3����]��T��q"�t[����(�V8���4���=�3JS���Oo���Z3x������5Pb�FY�����kse]�N���.[���uPT����`���`Ppc���F����0���1X��x�:f��]��:v�?��tE�Z��@�$���^�x!8z�:\����*�z\�I�Y��R��x5�7KC��A��wH"�C���~\�7R[��:l����bA�_%�X2���o91
L�|5���e���PL�x���<?(�"~�����)
�W8��r���zn�E��v����y{�C��b���B�F��������6R��A�J�*�/���7���I=�M\�D[�#��W�H�I���MF�9X����(a���?�
XT����r>���)��@�����'��C���/�����q-�N�����0�����}����Z�5+ZF
��#4`3���5�
���e/��B��|�
7��P\M>0����@��}*�[���������������?T�R��3!��@0���T���M[���p6��z�d�I��������_A��I�z'������}gk�_�g�3�2%�#I��S������y�q�u�����FSz�������~4��'��&X�g(��hfi��5�H�6������ah��V7���2�o/:7L8I����>��Y��{QP�<��{��&K�`@?_���*���x| �cT}����@�I�]]��������&>X�I=������c�#���D��8d�``�}��*����d��&���Y���b�9�n�����ld���!�J��E��=sA��������Q/y�0j�q��.>�	����mZ�@�o�B�?H�J%iM��&�������<���t���M]\z���L�A/����=�zF���OZ"�,���F��q�f��B�;��������\�U��� w�y�����K��V���|���Z�f$���!~����:���b���rS���9��>w�~C	���H 7���3
Z��������x����!������#��#�������������R�Wa��g��W%xt,��x��X�+��G.!K�j�����m:��xeB]���Ww�x��^@����57t%[������+x�k���&F^�=�
����
��W�����3�k�F��!��_�w�7�����\���#�mzl�Ik(K�WS�JZ������O�W��&E\E�	�F�]���|�P����Ve�'�*�>Qr��Zl1���+pTt�'�5J�\�9,N����9��'��tz����8����DF�l��d��7H����
I�XqZ������F#�9Q���o�2-c���7hmr���`BN��w���@���&5w��"jqg�L��?U�t�%�{M�A�!)�0�;�;��=&a$
I�Y@���A]��/g�g�m�>�L��R��P��m�oz}e���4���:{�=��|���������_aO�H�*��V��Y&:=e&ZI��m-K����~��z���=ib�\�Z�@g.������.9#�I��J��eM�*H?w�6_�W9>9~2�g���F�I�Dc)����?�<�Z����i<������	�"zm�b>������Hx@nB��h�B�v9��8}6M������+Q|��T�S-bx��F�#�z��I�y�o�|P���;���h ~B�����	�]�-��F��d�7�]��k����z����=������Q��;'uj���k��b�w��R���2��5�M���H�j��r��������K�1R���7rt��9#:���� 9c)�� ��KQCbp�����������8�4��u�9�2k�a�8�o�s��Og^�u��	����.�e���z*0f�0���^MMZ>5i)1�j��m�*��";������~�$>�=#��TF��F/���Qd��"D�CW���>��~(�u���]!�rop����I�����L�/d�A��)��"�WL��~�R��2�Wq&V\�
zC�p@��g_�E��`:����L�*&.����k���]H1�y4?������t~l\�x`����T��%=V[W���u�'(.V�X�r*���Z�p���an�W�����;����vj��7/l���w����x���%}����7Vqg����`Y=���Y%����3�4/����o��/n����
#40Joe Conway
mail@joeconway.com
In reply to: Joe Conway (#39)
1 attachment(s)
Re: Values list-of-targetlists patch for comments (was Re:

Joe Conway wrote:

Since the feature freeze is only about a week off, I wanted to post this
patch even though it is not yet ready to be applied.

Sorry -- I just realized that two new files for ValuesScan didn't make
it into the patch posted earlier. Here they are now -- please untar in
your postgres sourcetree root in addition to applying the patch.

(I thought "cvs diff -cN" should have included the new files, since I
had earlier done "cvs add" on them, but it didn't work. I could swear
that worked for me in the past...)

Thanks,

Joe

Attachments:

multi-insert-r6a.new.tar.gzapplication/x-gzip; name=multi-insert-r6a.new.tar.gzDownload
#41Tom Lane
tgl@sss.pgh.pa.us
In reply to: Joe Conway (#39)
Re: Values list-of-targetlists patch for comments (was Re: [HACKERS] 8.2 features?)

Joe Conway <mail@joeconway.com> writes:

Tom Lane wrote:

There are basically two ways you could go about this:
1. Make a new jointree leaf node type to represent a VALUES construct,
and dangle the list of lists of expressions off that.
2. Make a new RangeTblEntry type to represent a VALUES construct, and
just put a RangeTblRef to it into the jointree. The expressions
dangle off the RangeTblEntry.

You seem to have done *both*, which is certainly not what I had in mind.
I'd drop the RangeTblEntry changes, I think.

Shoving all the tuples into a tuplestore is not doing anything for you
from a performance point of view. I was thinking more of evaluating the
targetlists on-the-fly. Basically what I foresaw as the executor
mechanism was something like a Result node, except with a list of
targetlists instead of just one, and part of its runtime state would be
an index saying which one to evaluate next. (The update logic for the
index would be just like Append's logic for which subplan to eval next.)

Result as it currently stands is a pretty queer beast because it can
have a child plan or not. I'm tempted to suggest splitting it into
two node types, perhaps call the one with a child "Filter" and reserve
the name "Result" for the one with no child. The reason for doing this
in this context is that we could just make the no-child case be
multi-targetlist-capable (rather than having separate nearly identical
node types with single and multi tlists). AFAICS multi tlists don't
make any sense for the filter-a-child-plan scenario, so that's why I
want to push that case off to a different node type.

regards, tom lane

#42Joe Conway
mail@joeconway.com
In reply to: Tom Lane (#41)
Re: Values list-of-targetlists patch for comments (was Re:

Tom Lane wrote:

There are basically two ways you could go about this:
1. Make a new jointree leaf node type to represent a VALUES construct,
and dangle the list of lists of expressions off that.
2. Make a new RangeTblEntry type to represent a VALUES construct, and
just put a RangeTblRef to it into the jointree. The expressions
dangle off the RangeTblEntry.

You seem to have done *both*, which is certainly not what I had in mind.
I'd drop the RangeTblEntry changes, I think.

Good feedback -- thanks! But without the RTE, how would VALUES in the
FROM clause work? Or should I just drop that part and focus on just the
InsertStmt case?

Joe

#43Tom Lane
tgl@sss.pgh.pa.us
In reply to: Joe Conway (#42)
Re: Values list-of-targetlists patch for comments (was Re: [HACKERS] 8.2 features?)

Joe Conway <mail@joeconway.com> writes:

Good feedback -- thanks! But without the RTE, how would VALUES in the
FROM clause work?

Is it different from INSERT? I'm just imagining a Values node in
the jointree and nothing in the rangetable.

If I'm reading the spec correctly, VALUES is exactly parallel to SELECT
in the grammar, which means that to use it in FROM you would need
parentheses and an alias:

SELECT ... FROM (SELECT ...) AS foo

SELECT ... FROM (VALUES ...) AS foo

ISTM that this should be represented using an RTE_SUBQUERY node in the
outer query; the alias attaches to that node, not to the VALUES itself.
So I don't think you need that alias field in the jointree entry either.

If we stick with the plan of representing VALUES as if it were SELECT *
FROM (valuesnode), then this approach would make the second query above
have a structure like

Query
.rtable -> RTE_SUBQUERY
.subquery -> Query
.jointree -> Values

(leaving out a ton of detail of course, but those are the key nodes).

To get this to reverse-list in the expected form, we'd need a small
kluge in ruleutils.c that short-circuits the display of "SELECT
... FROM" etc when it sees a Values node at the top of the jointree.
This seems like a fairly small price to pay for keeping Query in
approximately its present form, though.

One thought is that we might allow Query.jointree to point to either
a FromExpr or a Values node, and disallow Values from appearing further
down in the jointree (except perhaps after flattening of subqueries
in the planner). The alternative is that there's a FromExpr atop
the Values node in the jointree even in the simple case; which seems
uglier but it might avoid breaking some code that expects the top level
to always be FromExpr.

regards, tom lane

#44Joe Conway
mail@joeconway.com
In reply to: Tom Lane (#43)
Re: Values list-of-targetlists patch for comments (was Re:

Tom Lane wrote:

ISTM that this should be represented using an RTE_SUBQUERY node in the
outer query; the alias attaches to that node, not to the VALUES itself.
So I don't think you need that alias field in the jointree entry either.

If we stick with the plan of representing VALUES as if it were SELECT *
FROM (valuesnode), then this approach would make the second query above
have a structure like

Query
.rtable -> RTE_SUBQUERY
.subquery -> Query
.jointree -> Values

(leaving out a ton of detail of course, but those are the key nodes).

OK, I'll go try to wrap my mind around that this evening and see where
it takes me.

Thanks,

Joe

#45Bruce Momjian
bruce@momjian.us
In reply to: Joe Conway (#28)
Re: [HACKERS] 8.2 features?

Are you going to apply this? Seems it is ready.

---------------------------------------------------------------------------

Joe Conway wrote:

Tom Lane wrote:

Christopher Kings-Lynne <chris.kings-lynne@calorieking.com> writes:

Strange. Last time I checked I thought MySQL dump used 'multivalue
lists in inserts' for dumps, for the same reason that we use COPY

I think Andrew identified the critical point upthread: they don't try
to put an unlimited number of rows into one INSERT, only a megabyte
or so's worth. Typical klugy-but-effective mysql design approach ...

OK, so given that we don't need to be able to do 1 million
multi-targetlist insert statements, here is rev 2 of the patch.

It is just slightly more invasive, but performs *much* better. In fact,
it can handle as many targetlists as you have memory to deal with. It
also deals with DEFAULT values in the targetlist.

I've attached a php script that I used to do crude testing. Basically I
tested 3 cases in this order:

single-INSERT-multi-statement:
------------------------------
"INSERT INTO foo2a (f1,f2) VALUES (1,2);"
-- repeat statement $loopcount times

single-INSERT-at-once:
----------------------
"INSERT INTO foo2b (f1,f2) VALUES (1,2);INSERT INTO foo2a (f1,f2)
VALUES (1,2);INSERT INTO foo2a (f1,f2) VALUES (1,2)..."
-- build a single SQL string by looping $loopcount times,
-- and execute it all at once

multi-INSERT-at-once:
---------------------
"INSERT INTO foo2c (f1,f2) VALUES (1,2),(1,2),(1,2)..."
-- build a single SQL string by looping $loopcount times,
-- and execute it all at once

Here are the results:
$loopcount = 100000;
single-INSERT-multi-statement Elapsed time is 34 seconds
single-INSERT-at-once Elapsed time is 7 seconds
multi-INSERT-at-once Elapsed time is 4 seconds
about 370MB peak memory usage

$loopcount = 200000;
single-INSERT-multi-statement Elapsed time is 67 seconds
single-INSERT-at-once Elapsed time is 12 seconds
multi-INSERT-at-once Elapsed time is 9 seconds
about 750MB peak memory usage

$loopcount = 300000;
single-INSERT-multi-statement Elapsed time is 101 seconds
single-INSERT-at-once Elapsed time is 18 seconds
multi-INSERT-at-once Elapsed time is 13 seconds
about 1.1GB peak memory usage

Somewhere beyond this, my machine goes into swap hell, and I didn't have
the patience to wait for it to complete :-)

It would be interesting to see a side-by-side comparison with MySQL
since that seems to be our benchmark on this feature. I'll try to do
that tomorrow if no one beats me to it.

There is only one downside to the current approach that I'm aware of.
The command-result tag is only set by the "original" query, meaning that
even if you insert 300,000 rows using this method, the command-result
tag looks like "INSERT 0 1"; e.g.:

regression=# create table foo2(f1 int default 42,f2 int default 6);
CREATE TABLE
regression=# insert into foo2 (f1,f2) values
(default,12),(default,10),(115,21);
INSERT 0 1
regression=# select * from foo2;
f1 | f2
-----+----
42 | 12
42 | 10
115 | 21
(3 rows)

Any thoughts on how to fix that?

Thanks,

Joe

[ application/x-php is not supported, skipping... ]

---------------------------(end of broadcast)---------------------------
TIP 5: don't forget to increase your free space map settings

--
Bruce Momjian bruce@momjian.us
EnterpriseDB http://www.enterprisedb.com

+ If your life is a hard drive, Christ can be your backup. +

#46Tom Lane
tgl@sss.pgh.pa.us
In reply to: Bruce Momjian (#45)
Re: [HACKERS] 8.2 features?

Bruce Momjian <bruce@momjian.us> writes:

Are you going to apply this? Seems it is ready.

I thought Joe was off in a corner doing a whole new version.
(I'm willing to help if he needs help...)

regards, tom lane

#47Bruce Momjian
bruce@momjian.us
In reply to: Tom Lane (#46)
Re: [HACKERS] 8.2 features?

Tom Lane wrote:

Bruce Momjian <bruce@momjian.us> writes:

Are you going to apply this? Seems it is ready.

I thought Joe was off in a corner doing a whole new version.
(I'm willing to help if he needs help...)

OK, just checking.

--
Bruce Momjian bruce@momjian.us
EnterpriseDB http://www.enterprisedb.com

+ If your life is a hard drive, Christ can be your backup. +

#48Joe Conway
mail@joeconway.com
In reply to: Tom Lane (#46)
Re: [HACKERS] 8.2 features?

Tom Lane wrote:

Bruce Momjian <bruce@momjian.us> writes:

Are you going to apply this? Seems it is ready.

I thought Joe was off in a corner doing a whole new version.
(I'm willing to help if he needs help...)

Yeah, I was going to post the latest tonight.

I'm afraid though that after 2 or so days heading down the last path you
suggested (namely making a new jointree leaf node) I was having trouble,
and at the same time came to the conclusion that adding a new RTE was
alot cleaner and made more sense to me. So I'm hoping you won't want to
send me back to the drawing board again. I believe I have cleaned up the
things you objected to:

1. Now I'm not doing both alternative -- the targetlists are only
attached to the RTE from the point of parse analysis onward.
2. I've eliminated the tuplestore in favor of runtime evaluation
of the targetlists which are in an array (allowing forward or
backward scanning -- although I haven't tested the latter yet).

I've also solved the INSERT related issues that I had earlier:

1. Fixed the rules regression test -- now all regression tests pass
2. Fixed evaluation of DEFAULT values
3. Improved memory consumption and speed some more -- basically
we are approximately equal to mysql as long as we don't swap,
and we consume about twice the RAM as mysql instead of several
times as much. I have more analysis of memory use I'd also like
to share later.
4. I think the INSERT part of this is ready to go basically, but
I need a bit more time to test corner cases.

I've made some progress on "SELECT ... FROM (VALUES ...) AS ..."

1. No more shift/reduce issues
2. The ValuesScan work and memory improvements mentioned above
applies here too.
3. This part still needs the most work though.

I'll post a patch in a few hours -- there is some debug code in there
currently that I should clean up before I send it to the list.

BTW, I'm reserving Saturday, Sunday, and Monday (taking Monday off from
my day job) to work on outstanding issues. I can continue to work
through the end of next Friday, 4 August. After that I'm heading to
Germany on a business trip and my "spare" time will evaporate for a few
weeks.

Joe

#49Joe Conway
mail@joeconway.com
In reply to: Joe Conway (#48)
1 attachment(s)
Re: [HACKERS] 8.2 features?

Joe Conway wrote:

Tom Lane wrote:

I thought Joe was off in a corner doing a whole new version.
(I'm willing to help if he needs help...)

Yeah, I was going to post the latest tonight.

Sorry for the delay. Ever see the movie "The Money Pit"? This afternoon
I started to think I lived in that house :-(

Anyway, as mentioned below, I think the attached works well for the
"INSERT ... VALUES (...), (...), ..." and related cases. There are still
things wrong that I have not even tried to fix with respect to FROM
clause VALUES lists. Namely column aliases have no effect, and neither
does "ORDER BY" clause (I'm pretty sure addRangeTableEntryForValues
needs work among other places).

From a memory usage standpoint, I got the following using 1,000,000
values targetlists:

sql length = 6000032

NOTICE: enter transformInsertStmt
MessageContext: 478142520 total in 66 blocks; 5750400 free (3 chunks);
472392120 used

NOTICE: enter transformRangeValues
MessageContext: 478142520 total in 66 blocks; 5749480 free (6 chunks);
472393040 used

NOTICE: enter updateTargetListEntry
MessageContext: 629137464 total in 84 blocks; 44742464 free (999991
chunks); 584395000 used

NOTICE: exit transformInsertStmt
MessageContext: 629137464 total in 84 blocks; 44742408 free (999991
chunks); 584395056 used

NOTICE: start ExecInitValuesScan
MessageContext: 1015013432 total in 130 blocks; 6614008 free (8 chunks);
1008399424 used

NOTICE: end ExecInitValuesScan
MessageContext: 1015013432 total in 130 blocks; 6614008 free (8 chunks);
1008399424 used
ExecutorState: 8024632 total in 3 blocks; 21256 free (8 chunks); 8003376
used

This shows original SQL statement is about 6MB, by the time we get to
parse analysis we're at almost 500 MB, and that memory is never
recovered. Transforming from ResTarget to TargetEntry chews up about
100MB. Then between exiting transformInsertStmt and entering
ExecInitValuesScan we double in memory usage to about 1 GB. It isn't
shown here, but we add another 200 MB or so during tuple projection. So
we top out at about 1.2 GB. Note that mysql tops out at about 600 MB for
this same SQL.

I'm not sure what if anything can be done to improve the above -- I'm
open to suggestions.

Please note that this patch requires an initdb, although I have not yet
bothered to bump CATVERSION.

Thanks for help, comments, suggestions, etc...

Joe

Show quoted text

I'm afraid though that after 2 or so days heading down the last path you
suggested (namely making a new jointree leaf node) I was having trouble,
and at the same time came to the conclusion that adding a new RTE was
alot cleaner and made more sense to me. So I'm hoping you won't want to
send me back to the drawing board again. I believe I have cleaned up the
things you objected to:

1. Now I'm not doing both alternative -- the targetlists are only
attached to the RTE from the point of parse analysis onward.
2. I've eliminated the tuplestore in favor of runtime evaluation
of the targetlists which are in an array (allowing forward or
backward scanning -- although I haven't tested the latter yet).

I've also solved the INSERT related issues that I had earlier:

1. Fixed the rules regression test -- now all regression tests pass
2. Fixed evaluation of DEFAULT values
3. Improved memory consumption and speed some more -- basically
we are approximately equal to mysql as long as we don't swap,
and we consume about twice the RAM as mysql instead of several
times as much. I have more analysis of memory use I'd also like
to share later.
4. I think the INSERT part of this is ready to go basically, but
I need a bit more time to test corner cases.

I've made some progress on "SELECT ... FROM (VALUES ...) AS ..."

1. No more shift/reduce issues
2. The ValuesScan work and memory improvements mentioned above
applies here too.
3. This part still needs the most work though.

I'll post a patch in a few hours -- there is some debug code in there
currently that I should clean up before I send it to the list.

BTW, I'm reserving Saturday, Sunday, and Monday (taking Monday off from
my day job) to work on outstanding issues. I can continue to work
through the end of next Friday, 4 August. After that I'm heading to
Germany on a business trip and my "spare" time will evaporate for a few
weeks.

Attachments:

multi-insert-r17.diff.gzapplication/x-gzip; name=multi-insert-r17.diff.gzDownload
#50Joe Conway
mail@joeconway.com
In reply to: Tom Lane (#43)
Re: Values list-of-targetlists patch for comments (was Re: [PATCHES]

Tom Lane wrote:

If I'm reading the spec correctly, VALUES is exactly parallel to SELECT
in the grammar, which means that to use it in FROM you would need
parentheses and an alias:

SELECT ... FROM (SELECT ...) AS foo

SELECT ... FROM (VALUES ...) AS foo

One of the things I'm struggling with is lack of column aliases. Would
it be reasonable to require something like this?

SELECT ... FROM (VALUES ...) AS foo(col1, col2, ...)

The other issue is how to determine column type. Even better would be to
require (similar to SRF returning record):

SELECT ... FROM (VALUES ...) AS foo(col1 type1, col2 type2, ...)

This would unambiguously identify the column aliases and types. Assuming
we stick with the spec:
SELECT ... FROM (VALUES ...) AS foo

1. How should we assign column names?
values1, values2, ...?
or
col1, col2, ...?
or
???

2. How should we assign datatypes? Use the first "row" and try to coerce
the rest to that type?

Joe

#51Tom Lane
tgl@sss.pgh.pa.us
In reply to: Joe Conway (#49)
Re: [HACKERS] 8.2 features?

Joe Conway <mail@joeconway.com> writes:

I'm afraid though that after 2 or so days heading down the last path you
suggested (namely making a new jointree leaf node) I was having trouble,
and at the same time came to the conclusion that adding a new RTE was
alot cleaner and made more sense to me. So I'm hoping you won't want to
send me back to the drawing board again. I believe I have cleaned up the
things you objected to:

I was just objecting to having both a new RTE type and a new jointree
node type --- you only need one or the other. Opting for the new RTE
type is fine with me, and it probably is a bit cleaner at the end of
the day.

I still dislike the way you're doing things in the executor though.
I don't see the point of using the execScan.c machinery; most of the
time that'll be useless overhead. As I said before, I think the right
direction here is to split Result into two single-purpose node types
and make the non-filter version capable of taking a list of targetlists.

As far as reducing memory use goes, it seems to me that there's no need
for the individual "targetlists" to have ResTarget/TargetEntry
decoration. For the simple case where the expressions are just Const
nodes, this could save something like a third of the space (there's also
a List node per item, which we can't do much about). I think we'd have
to gin up a fake targetlist to attach to the Plan node, but there'd be
only one.

Since the result-node split is my hot button, I'm willing to volunteer
to make it happen. Do you want to concentrate on the remaining
parser-area issues and leave the executor part to me?

regards, tom lane

#52Tom Lane
tgl@sss.pgh.pa.us
In reply to: Joe Conway (#50)
Re: Values list-of-targetlists patch for comments (was Re: [PATCHES] 8.2 features?)

Joe Conway <mail@joeconway.com> writes:

One of the things I'm struggling with is lack of column aliases. Would
it be reasonable to require something like this?

SELECT ... FROM (VALUES ...) AS foo(col1, col2, ...)

Requiring column aliases is counter to spec ...

The other issue is how to determine column type. Even better would be to
require (similar to SRF returning record):

SELECT ... FROM (VALUES ...) AS foo(col1 type1, col2 type2, ...)

... and this is even further away from it.

As for the names, just use "?column?", same as we do now in INSERT
... VALUES. Anyone who wants to refer to those columns explicitly will
need to assign aliases, but if they don't assign aliases, we don't have
to do anything very intelligent.

As for the types, I believe that the spec pretty much dictates that we
apply the same type resolution algorithm as for a UNION. This is fairly
expensive and we should avoid it in the case of INSERT ... VALUES, but
for VALUES appearing anywhere else I think we have little choice.

regards, tom lane

#53Joe Conway
mail@joeconway.com
In reply to: Tom Lane (#51)
Re: [HACKERS] 8.2 features?

Tom Lane wrote:

Joe Conway <mail@joeconway.com> writes:

I'm afraid though that after 2 or so days heading down the last path you
suggested (namely making a new jointree leaf node) I was having trouble,
and at the same time came to the conclusion that adding a new RTE was
alot cleaner and made more sense to me. So I'm hoping you won't want to
send me back to the drawing board again. I believe I have cleaned up the
things you objected to:

I was just objecting to having both a new RTE type and a new jointree
node type --- you only need one or the other. Opting for the new RTE
type is fine with me, and it probably is a bit cleaner at the end of
the day.

Great!

I still dislike the way you're doing things in the executor though.
I don't see the point of using the execScan.c machinery; most of the
time that'll be useless overhead. As I said before, I think the right
direction here is to split Result into two single-purpose node types
and make the non-filter version capable of taking a list of targetlists.

OK.

As far as reducing memory use goes, it seems to me that there's no need
for the individual "targetlists" to have ResTarget/TargetEntry
decoration. For the simple case where the expressions are just Const
nodes, this could save something like a third of the space (there's also
a List node per item, which we can't do much about). I think we'd have
to gin up a fake targetlist to attach to the Plan node, but there'd be
only one.

OK, I'll take a look at that (actually I was just in that general
vicinity anyway).

Since the result-node split is my hot button, I'm willing to volunteer
to make it happen. Do you want to concentrate on the remaining
parser-area issues and leave the executor part to me?

Sure, sounds good to me.

Joe

#54Joe Conway
mail@joeconway.com
In reply to: Tom Lane (#52)
Re: Values list-of-targetlists patch for comments (was Re: [PATCHES]

Tom Lane wrote:

Joe Conway <mail@joeconway.com> writes:

One of the things I'm struggling with is lack of column aliases. Would
it be reasonable to require something like this?

Requiring column aliases is counter to spec ...

SELECT ... FROM (VALUES ...) AS foo(col1 type1, col2 type2, ...)

... and this is even further away from it.

I figured as much, but thought I'd ask anyway :-). I did find something
in the appendix to the spec after sending this:

Annex C
(informative)
Implementation-dependent elements

18) Subclause 7.3, �<table value constructor>�:
a) The column names of a <table value constructor> or a <contextually
typed table value constructor>
are implementation-dependent.

As for the names, just use "?column?", same as we do now in INSERT
... VALUES. Anyone who wants to refer to those columns explicitly will
need to assign aliases, but if they don't assign aliases, we don't have
to do anything very intelligent.

OK, I just thought "?column?" was ugly and useless.

As for the types, I believe that the spec pretty much dictates that we
apply the same type resolution algorithm as for a UNION. This is fairly
expensive and we should avoid it in the case of INSERT ... VALUES, but
for VALUES appearing anywhere else I think we have little choice.

Where do I find that algorithm -- somewhere in nodeAppend.c?

Thanks,

Joe

#55Tom Lane
tgl@sss.pgh.pa.us
In reply to: Joe Conway (#54)
Re: Values list-of-targetlists patch for comments (was Re: [PATCHES] 8.2 features?)

Joe Conway <mail@joeconway.com> writes:

Tom Lane wrote:

As for the types, I believe that the spec pretty much dictates that we
apply the same type resolution algorithm as for a UNION.

Where do I find that algorithm -- somewhere in nodeAppend.c?

select_common_type(), in the parser.

regards, tom lane

#56Tom Lane
tgl@sss.pgh.pa.us
In reply to: Tom Lane (#51)
Re: [PATCHES] 8.2 features?

I wrote:

I still dislike the way you're doing things in the executor though.
I don't see the point of using the execScan.c machinery; most of the
time that'll be useless overhead. As I said before, I think the right
direction here is to split Result into two single-purpose node types
and make the non-filter version capable of taking a list of targetlists.

After more thought I've reconsidered this. The "ValuesScan" node is
still redundant with Result's non-filter case, but we should probably
get rid of the latter not the former. The reason is that in the general
case of VALUES-in-FROM, we do need all the generality of execScan.
Consider

SELECT x,y,x+y
FROM (VALUES (1,2),(3,4),...) AS foo(x,y)
WHERE x < y;

which AFAICS is perfectly legal SQL. We need a qual condition for the
WHERE and a projection step to form the x+y result. We could make a
non-filtering Result clause do all that but it'd really be reinventing
the execScan wheel.

So what I'm currently thinking is

1. Implement ValuesScan.
2. Convert all existing uses of Result without a child node into
ValuesScan.
3. Rename Result to Filter and rip out whatever code is only used for
the no-child-node case.

Steps 2 and 3 are just in the nature of housekeeping and can wait till
after the VALUES feature is in.

As far as avoiding overhead goes, here's what I'm thinking:

* The Values RTE node should contain a list of lists of bare
expressions, without TargetEntry decoration (you probably do not
need ResTarget in the raw parse tree for VALUES, either).

* The ValuesScan plan node will just reference this list-of-lists
(avoiding making a copy). It will need to contain a targetlist
because all plan nodes do, but the base version of that will just
be a trivial "Var 1", "Var 2", etc. (The planner might replace that
with a nontrivial targetlist in cases such as the example above.)

* At runtime, ValuesScan evaluates each sublist of expressions and
stores the results into a virtual tuple slot which is returned as
the "scan tuple" to execScan. If the targetlist is nontrivial then
it is evaluated with this tuple as input. If the targetlist is
a trivial Var list then the existing "physical tuple" optimization
kicks in and execScan will just return the scan tuple unmodified.
So for INSERT ... VALUES, the execScan layer will cost us nothing
in memory space and not much in execution time.

There are still some things I don't like about the way you did
ValuesScan but I'll work on improving that.

regards, tom lane

#57Joe Conway
mail@joeconway.com
In reply to: Tom Lane (#56)
Re: [PATCHES] 8.2 features?

Tom Lane wrote:

So what I'm currently thinking is

1. Implement ValuesScan.
2. Convert all existing uses of Result without a child node into
ValuesScan.
3. Rename Result to Filter and rip out whatever code is only used for
the no-child-node case.

Steps 2 and 3 are just in the nature of housekeeping and can wait till
after the VALUES feature is in.

Sounds good to me.

As far as avoiding overhead goes, here's what I'm thinking:

* The Values RTE node should contain a list of lists of bare
expressions, without TargetEntry decoration (you probably do not
need ResTarget in the raw parse tree for VALUES, either).

* The ValuesScan plan node will just reference this list-of-lists
(avoiding making a copy). It will need to contain a targetlist
because all plan nodes do, but the base version of that will just
be a trivial "Var 1", "Var 2", etc. (The planner might replace that
with a nontrivial targetlist in cases such as the example above.)

I'll work on that today.

* At runtime, ValuesScan evaluates each sublist of expressions and
stores the results into a virtual tuple slot which is returned as
the "scan tuple" to execScan. If the targetlist is nontrivial then
it is evaluated with this tuple as input. If the targetlist is
a trivial Var list then the existing "physical tuple" optimization
kicks in and execScan will just return the scan tuple unmodified.
So for INSERT ... VALUES, the execScan layer will cost us nothing
in memory space and not much in execution time.

There are still some things I don't like about the way you did
ValuesScan but I'll work on improving that.

OK.

Thanks,

Joe

#58Joe Conway
mail@joeconway.com
In reply to: Tom Lane (#56)
1 attachment(s)
Re: [HACKERS] 8.2 features?

Tom Lane wrote:

As far as avoiding overhead goes, here's what I'm thinking:

* The Values RTE node should contain a list of lists of bare
expressions, without TargetEntry decoration (you probably do not
need ResTarget in the raw parse tree for VALUES, either).

* The ValuesScan plan node will just reference this list-of-lists
(avoiding making a copy). It will need to contain a targetlist
because all plan nodes do, but the base version of that will just
be a trivial "Var 1", "Var 2", etc. (The planner might replace that
with a nontrivial targetlist in cases such as the example above.)

I wanted to post an updated patch even though there are still things not
working again after conversion to bare expressions. Note that I hacked
enough of the executor stuff so I could test my changes on the parser
area. The basic "INSERT ... VALUES (...), (...), ..." does work, but
without DEFAULT again :-(.

The good news is that from a memory and perfomance standpoint, my simple
test now shows us outperforming mysql:

$loopcount = 1000000;
Postgres:
multi-INSERT-at-once Elapsed time is 12 seconds
~420MB
MySQL:
multi-INSERT-at-once Elapsed time is 17 seconds
~600MB

$loopcount = 2000000;
Postgres:
multi-INSERT-at-once Elapsed time is 29 seconds
~730MB
MySQL:
multi-INSERT-at-once Elapsed time is 37 seconds
~1.2GB (this one is from memory -- I didn't write it in my notes)

Joe

Attachments:

multi-insert-r18.diff.gzapplication/x-gzip; name=multi-insert-r18.diff.gzDownload
�iN�Dmulti-insert-r18.diff�]{s����[���i+���~9'>�:J�;��ZJ�t���� �	E*$�����~w�$(��������.���o�oG�F�������q#��7� �Q�����I������;��Ec�Vn�����w�`�����yr~<aK���1���0L�K�h{�����'������E�'�����[�����\����#��R�wwwoT��e�l|�n6���=��ZCVo�OEP������������54���8��N��fT��EA�����*��s6�����9���UT������Qu+w��������>�KI���{�F=�g<np��Mx��~�wU������
���;�A+p�?r��N:`��>l����o���%�~�#��Bon��j���w��d�j�n�����a_#�{v��5��/��r��|z���$�a��;JfK�����r��j@����(q/|^�R����j�������B�5v�Q�k�y��1��u���)�a�!��FB<���,��g�|:��vt�f<�DU?4��<���z
:>��\���'��v����sp��R���@Q�@`�Z[��a���3=�\�X����	u�k��/���d�>����=t�N���^����u;��%��66<�)Tdy��U�q��6��q�*�^�?:z
�V���|X�;��m
k1���o�0j�t�s4�_���.5��N���;Ls��������#4�=�ntz��6�@9o���i�[#�����O.�O^�r�����d?4
ib�����||�%���BO5�?�,����K.���H��p-[*�4h��V��J.��>���3��+EdF����� ��z+OU���u�X0����\>7So!�%1�p7��5�� ^{�!��������&�O��gB����3�k.������m	?���	G�}����0c��C��[j�t��`h�Z���=�Rg�t
��_�jm����f�����0�W;�
��ok#u���51��(��]���v���Z����u
�9�jI�s������'��H�F��`4'����J��jzZ�N�I��~r����e0�	�.��]�}�����Z���u$61��}��1;|q��f�_����a�E�Kz�|���
M����T�&�iX��UV���6
Y
�N;�dU��#
+���J���:���i����8�������2�/����Vtp�r�`�7Q��h�K��9�~���0�*c�r�2��
2l�w[�NEs�m��8�<z`��X[�������a"*O�p�^G�;��0�={szZ�aLn�������3��2P
z�l�
X����!m�@@/[�A���M������R���8�H��<(]��b4v������l@ed���f������^��/}�2����!�X�=c����
���^��7=�F
�|���3�4v�_��0�!R�*j�mj�&�i������C������/���n����C��:}��5`W���u�d���D���M�L�0������-�c!�]kjK
���?l;�Q+�����t@v�h����u����c����\F��|g�[}�hSi�2B?��O������"�uR�����#c6��(�)a�|.>���E�l���6��0l�<8�_`)~���@S+�R��];dQ�I��T����!3X��v[�.��V�@y-�}}mMq�ra���q��6�����`�SG`��~1dr�KA�Q�^�8LvY�Y�\�
/��y�O_p�lSYm��z
��n�F�<!����9��D�9���9,�9�*���K�
��$.����a�AQ���p�/��{�����
.0E�Rnb�F�%W�������2���3^���n���Pf�E5� ��s7����BH�z�O�C�#:�~�
S>'|uB�h�A�s�����?jr�6�XS�������|���KBB��}�/���aD2B���_�]H(���+��/i�L���yT'E`+�M��9���!Q.�h�I53_�zf:������~�����=��g�o!t��P#���4C����?w�I�
*�C�OK7 �+������	PHw����)�Z�U��2;\,������R��P	�Bz)�mo���_�K2#o=���`��@H+!��\k�Ct�G�Q7��;t������K�]'�������x��m*=���������� �]����$q__7t�C���v�a��Q�X�%���@)�/��
Xe�A�&��Z��9SZF��*����3.Y��H�/|	)��(�q��i���n�#��9��A�vW�1��H�+���������c`������7K�x��4�)��"��T�f-352C��DM�����(���O5��V��M����@@"&9����p�~����GU����ZM<����]~��3E��`^L���G^2�������(�������	(&Z�k���h��dq���F\lY?o/p��O��gi�1`���O���G%�j��f�z�������}�����\�����������q�5���^��T�54Y�y@���.��y����F��t�m�����%
V�8�0~��l�k��:����M����!C,��A�q|�U���k���wP{"<�%NS���^p��������U�5��_G�9������S��^�>{����W<Hmn�F��������o�����K�a���M94O����'/N���'���t���t�� ��t�k��I�A��b�>`��.����?�|7�����M��/����������xbD�����|�� q��������`����� ���)/��0Z��|>�����{���<��S��S�� �I� >wc"rC�����s �(r/�`���`Q=��j���^�X1���f3�����/�TTcA4��Z�Q���I"^H�Ls��|X����D<40�x��Mq����M���ZK��{�X��?����I��.��b4M��+����c���<P#��xP%�5���J���(��Zd(D�K��R/J���]<678��s/���P��N��*2*:I"�O��BF���`���YF�J�)D��f�L
}52:1 67�x��C��A��~Q@�m��B���D]i!����#%#D�����,��g�ej����V�mY��A�V��66s5�����8�����'r�)�23i'1���n��j1���K�S<�D��[|b����$�<D����C������#G���'�g{-��NNu�D�)e�0=��e���wgG����J�������\9f�D��nR��r\XZL����6��E"��3{�7�@6�eO�	i��/��,�s����T�T��"�'z����T��%�����d��:<�U����ZS���C{��n�2���Ll�%6��C�N�����{��������������Xf��5��#��������U��T>^y�+��a,mN�9# h�Y�VN��6�����cn\�QY>c��:������(<�g_&��A��hs���
�2��,0��E�e���;�au�@�?G���k�B3�t�>�5:5V!uD���"���u����NM���F,r)���~S�/�%�����y
@]i�	�����/"��
��`
�y�Y�zj�����M�
7�����	E�����}�����3���$��n���O�DQ���Ru����/�x��<��i�GM4����,#���<Kr����]��#�����}��?|��Pd?&�Gg���������Cn�� ��7���w��KsZ]���X��<TT�4�:kH=����k+�����=�M���.X`C�����D/��}Y����]z����5�Khg��uht����-3t�����lx�[����1Oo���88b�GU#A_N� X�5c�t���O$7�U���1��<�+�/�8Wk�]5]n�RN����$���YUuX����W�8���k>�������v�]��{� x�\�Q����N(�e�4$�"I�����n��p���k�(���^�>[�t
3�En0^d.])x���bU�HwY� \*����*e���9@Phv/�� ����=�r����������Ah?r���Q:�x��Kf*m���_P���<fv@`uH����m0�}�����E:=�n1���x�I���K�BdIL
Z&���`�ig==H�!�]jl/
��-sF�,��G�����3a�Y�#���������������=��=��0�+(���3����Alb"3�dA��-����!��+����/�j��������>+�|��4�SbCDRmqUD
�+�����=O&rI����YXc�r.D��j3���Xk"s5�\�"��]����������u{���St�rA[���J�����!������9I�nZ�&���N�w�����$��]��Z�]dj����]�y~n���v�������;���l*��\Z�������x����y(��u���n7{&��e&��Sy��O�#�z�lF���L�p�U�������P�P�X��/6���a��06�L����<�V��������q,���aD
s�61L*����s���H_<�\8L�}���,��:�G�1~�`G���Y�/�O"�Z��Nk���a�3v��F�&CyqSrZ�7tZ��q9��t����t������W���'���Udb�"�����
����s�
�� �7�
XK���v#���M���B�����9e�y�U�~����Pz#S(�f�i������LJ���KI[y�G��QX�4�(o����F�V�;	��N	o�z������E����jZ%��`,6���������M(��x���X�}�ju|�w�e)VE���\��tp�Yy�
V+���;����N��t:��58�o5Rk������� L�.	��3w��,�J7���c��9d����1
����;�0mw�f��>;����{:�V�3������z��c6n���^K���d����a��^�>:��$�Z����=��(���b�}���O����B�&��;�����,{�W����A���e��AkE���+���K��6�Y�du�w���`�ujM�ia���������0��#(�4[��n��i��y�e������}�����O��7�72oi�[��(g�F�`�n�����KF�i���^��\u������u��>}�"��/��x���d*�����cu��;�T!q|6}�c
�8 k��+F\���Cx^r"
W��_^�V��!rm63`�E-����9>{�2g�Sm�*f�v�d]��n�\�2�	��wYr?�����_�;lgD|^�!���n��;00��)����Z�A�i
���
�X���|�E9X%}�`T��������S)R��t� �g1�1`jE+WY���J����Jv[��f�tM��)YkyqL���y�xS%��=�X<�jHF�S��eu�������m���?���B��9����+Pa�{16��L_6���E��&���'G�ec�g��������w�}cv�M�;��W�U"f�?��"�=R����9���<��7�\i�3�O�M/���_�_zx��{����>��O]�7��jd�J��,:��+���V}���{q�7�������m����;����!_�����j���.��)��O����gK�0�����L�}�qJ���2|����_��������8�*[�a�\��%����ZN�oj�n�'
gW�c8��������t��+t��a���Rk=d5A��y���\JO�@����
��^rE_/�k�u������k�^�|�:�u����f?�L��������Y2H��E;;/���}.��-	z�F[2'���K��z����n�A���Y�~s��i��i��������"}�x�90vv����OI�"&�-���??����j���{,�V��p�&�4��_���Xa0���u({_>Rr&�v�H��4���o�?��q����De�\�q[|�h��z��������j-n{�O�o�$��9F��3j~R�/�==�������<"�W����*�,��-��o��F`r�p}�~U�,e�^�%��y^9K;���m�5H9)��������-�[��F�D?�����)	���(g|V+����W�d����C���I0hE����z���� %�mMv�$2�hT������w�2
����
�S�ht�$�����q�o���)D/2V~�D�m��p��.U��_le���B�{����
3�^���!*�����Zc>S�X/]0��[����!2C��|�H�I2S�M)#Y��W+L�f�+��-��[v�w�#G��o���r��<���E=�"MyR�������y��bxWe&l���m���n��n��Q����C��{��cL4�(�V���`�z�
i(8S�2��Wh��|g=
��v���l�ko�a��z%}����G�/	
�����1p��9��\a���<�w��:��C����/h�;���v!������.�Y
�9���:M&4�:u�=-���^�3�%��d���6Z&h��P� ��m���[6����BAU�����0q�2/�XK4�3d=�u��e���t�vU����'�l|���6���Nqx|��v������4���o81m�Z�'��&���HW���S�������/�,�k6*6>6$0UkB^'E��)T����_�%�	_b�Y��/�=<����ip�q�a�_�#^���}w��d ����_e�E�x�\��wr���Y���F���gS�VN#l�PX���(��������(�t����k�SY�cr���
1�)�>���K�Deo�����$�$`��X�r�0/��!�\��8�L�����1_S9�;?DfP�#��4.��U�e��n��2�5p�%�k��X����e �.�����V����@u��J��*%MR��o0�m�a�Ka��Vp�(��0��j�Q1z���F�g�e�F�2��w�OBu������`d�N}g��>���p[l[�,�:V�'^xr���*W���'5�MWd�1��j4�i�����	��"UFo������d�^U3�Y�:+���,��x�;�'Du<����G���H���~��D�P�#M���%P!DT���`��"OfW�~�fj/����X��c����j�����7"{�I�&���]�N����u�[t��0�x|�28��
?#�S�g��T�R����Rwb�/w��$?��a��NT[4��A�9�_�d��8lV�����wl�li
�UVf���#,a
b��{�j��yH�F�<������a�
�!��+@�����"1#�O�A#���r��w>c�Z�o^��o���U�����\�@�J�u�Jd��{��'T�s����y���~E��BZU��,�z��4Z�$�ItPW�[:s������ucF�_��]0�ka�T�6}�\��@_��Nz�(@�����,��e�����\���O�^��J��n
�iLCi��@SB!��i�f�<5�h
�,��Y����VOQ��qK�f�E��Y�kZ?�E��Q
��
�*S��Qy-�RN��f����^#t5`:�Sq��.C��n��v�����S�����2���m�2��4t{f�gr���\a�~FYo}�]����:`�\����3�E�U:��:�1�ugGo)g���|'��/�����:��wKA�;[��m�O���~�n[�����!�;�>���l]�n^3�A\,����{�Y��I�\�1����^�!���B�}3;8H���Vd�-�����}o��7F��SJv�$w'T���#����8!'���!�0RM]��|E�$1{F�*�������a��o��=
8����7�pP�!K�?�4�ZI�B�:������������+���l��6������8�����I��������h�����$%��hadb�0Z�9��!���%~Q��b���e��@�B�4�G���"X�-�+J�nZ�U/��cur���B��v�
���ju5��20��\^�`���r$�����=���hI�;�����y�����v�SB�����A��/���m����a���`����U��f�����zi�����E8aW1ES��lh0������U)�(�%WZ����"���B��PA��N��G��r��?i!F���H��9�4g�F'�[�oV�,��>�����Z���T/�nd���^�b*�w[��vs�k�A��
J��������5[&�,����%���KMVz�r�F�������O���p|�zx������SbH�3�K�Y�Fh��G�mO����\��&w�2�3:W{�_��$���J�3"J4"�����V�t��_oJ6�N2w�z(s-��w�-�����l�7�NS1d���7���Aa%���C�qO�hln?�@��,"?<bkCTzc�B�����$�������g�gN�f]M���we%,nM����t�e��h�$;�U�m4��
Y"��a����UY�^]�������oy�s����R5�@Z8.K}(p��8S�q���78�������g@]T
�P*���j�;�\G�����>#���W@��N��	���GZ�r��^���|f�����Mui�k��Q�����:qB
��F���e�C)z�@������E�ui����W�j������O��t��"2
�Y�������GB�;���VWyx�?.�����f�"g������$�Yh�(��pJ'&��V�m���f=��}����]�Q#�A<Io0b7_�#�0{���jK��l��������������$������������	�Y��a}�:��
Z]�dn�����C5+�t�7�9�}������f��s
�{2D�V'��Db{*h�,~:y���w�"������e�k���r�L_��j�<����eU/�977��H������IU���p[�h�:���NM!�"n�0��tl��5�3��7�zw�O���
q(.eA+�]�y�?1����.��Y1�a+�R��{���"�:K�$k3�]��g�l	�\T�J��0����LDL��7�~C����!���o��o���]WWF�SE��^4��f�$c��=���[[FFw������o&���-����:�)��[_fib�7���p�&�9hvb�#h(<�AQ���ErS�@�ZO����o=0��=������OGu�^h&+_(F�^���g'�{T�fs��Q'O���.T������=�@l�Z�%6rw����
oKheI��I��l�Q*�qQ�Q��4��K��Pgwd��q����Ll,����I��d`���oCmal�hn��0|��~-�0�EP|�Z�w�����`�/��d'^��(��xkXzU\����*O��W��~���y�t{�Lt<z�8���/h�lL�:
)z�����}���
���&'���S���L�4�.nR
���������Hp{�F/�m~�g�������I/�y�H�����n�H��jJ;wb�K'���b�x��:�yC�%c��I�������|L	r�w#�_�7l�~�l������7.�E�p��(�T��s�j���l+q�vADl>��{A���(L��
�+��07]����7�I����uxc9�H���w�OWY�,�o�)���P��w�v�G��5=��v^��� �����L���.���=���gm�^��5�Tk�-�,�c�$Z���-�zRD�e��qBn���l,VsFN�NeF�"xbrxSR���:�%���&��(��>l>]�!rn������+����a;ruyHs#��g�M�B�f��b�;���>�o|;\���xq�m�\�����ox�������}���2��7s	�=7q�w��	������g�e��Bf�.�����_W���	���o��.x�7q�����l�1|�1����_�(�k�2����v�=�J7E�e��2�3[���ttU$[�������u�
h�`����S����l,qG�f'_]Y�(Ox�`���[�U�o���V�E���v\��P���v��x�r1�b��,7�|������w���'�GgD
�:/�p���	���z��f�����-���r�bV�������Z������*������f�t�_b�������V�dd�y�����8EK�tH�J�K�
�y����c	s�\ai��M���tI�B}�u�qO{�D��"��c����Dhv�gzl�\D��<��:�Ta�A	�@m-��_���/-�}�R�i�����6��#���-��A����6DP`�"�3'��h��t���Rc�o.���.d�v�B)���;|�����\�bv`�Q�ba|=�g�2G���$n!#����s�s��o��"�l  ��
��\t���KE&�<Y/te^5+%�c��c8&�]�v*�{{���zv���-m^�b�L.�=E�"�S� �M3�I���~�����X�_�5(���)ZtV�������'�������KM&���	����~[��,�#��
x��bt5���������^(��m3��\L��������������� �O1�7��j>O��KC�#A U�����n��xMV��mD��\0���x�����_�N�����d�;��$��o�������� ]e��]d�(���w���E:�c�d���r��nu����|mj0B���(d�����2��\�0�J?���8w("2�6Mfx�:%[uWv�'����O�],^��@R�>�_�z�,�����w����7��Ru�M��N���3&&��Re	��Js���z�ec�`(>���>�8���jm����j��?Q�SHa���5Z1�P����-�@e�x�J#P�Cj�1�(����P��c6����/���rsl�
�����1E�U��`u�43d���� ��[Mwm��D�&����k�^�V�c���q�+,.��j��\���������1��Z��>�+{8�������O���bx�����gG��b�����Go�/�7�g�O�_\���xpv�F~�cwc���5��
��\�U�/�o�3F��kG����x#�#ru����1XK���=v��v9k�k�����7W�q�����nW���s�zZ�V���LTj�NM}P������zq�-������|G����c�U�D�$c} �2'�[u|���j����$;]$G |��j K���0Cd(���*7g�'�K(�]=���3�*�.f�f$�{Z*���$�
p��ta��N���N����&ml�������u{/nu��
����+�aC���)&��'�CO0~�e6�Z��7E�������i��P��7���A3�V/d]����L8�Y}M��kh�V�prX���S�B���rf� a�n�:b�����a�
����Uc�������W��4D����b^����1���I�/�o�8�q����
��D���RU����\S������55K��l�[Y��.m7:1�ST�TQ��^����y���.o����|
s1U#�e��aBHbZ��o��(����
���7/I&|U3�����C\��m���U��I�n}(p���P8�+���y�<UC�*a��t��(��!z��'�<*��bO@����AW�tT�a��l����+/E���^��_���������8�3����-����=�?�g���g��������B���;?}J������bG���|����]�^�1������z��������@�z��}z�}K*N#\���.����5��sf���M��������[u���6q�	F�r�X��������&�-����������v�u�����i.��������@����6��n�i��`��`���\�����/O���p�]�OQ>������&i�����Nn�e�Q�w8�?jN������b���a�*�it�@�gE�L���E���#t<�X��,�D�~�^Q�e�<]�N:�ZL����NW��pJ���F�
U�g�U6OW4��^aKY�D����t<E-��p�.W�Q,^���xS��,)���Ik4w?�K�H�m�J�BZ�P��C����M�1�b�����o�0���
��4��N��;A��~��F��$�Gh����]&E�1�Q�$�]��s�'�Y�bV������qZ����"zsv�N����������O�� ;������E�)�rp�_0��GwH�����F����u���is����y��;b�C������C���3����(��*���Ao�E�#�?�����\z���1)��f�d����HD�h��1��F4��<�mMf�@#-���h���G��MWj?OR�X��|���d�( �s�x��A�&{��v��j�8�XA���(��?"Z'��d7���/#s�8��g8Ad�p����f���[2S=iI������
s�������	�>*�6�������U���u�6r��k����x�����I�\�
�A-r!3J��c����D��n}�]!9����!pe*�o��/Bf��j9�5��0A.��4W���C��O�?�2�<�����u�:�p��i\���<�JC��]1,�d��Q��<%u��&�;D���9��s�H�X2�4�����}�;Q��d�D<�R����z:�j���?���>�=~�<\���%&����||�{�x|���}����1�7�^��YsV�[m�"<@���>��Hn����������������>��K^����gv���Q��V=����|��_����������[+�P��u���`�y���z�1"�O�px�;��r��
�2_�(�G@?�u4�t���^��������@��!ZmR��2���%p��	ebX �*���L^���n�IT��F�S!���B�)X
����Z�Z<����9��,�vN��X��"4��3��(N��������������������]'�	�2i�c�2��vR�s�5uuthe��2������3����$h�r�p���"�	2�;P�z��������sYK����������c\����(1j�n�y�����NX@���veP6�~��t��lG�e�c0����D��Hk+�w��n�����K9Ih�n�w1L��@�=n���Y#��V��Q)�iD�'���]�z�5z(�M���&\����
im��U�����]�
�R������Q�F��~����(���&Z��,I��$Y��O���P�i8_Y��u��wN�k�	
3k�����3�,���}[�������t��C��d������"�G�8 �]Ai{�~�o5-��YS�_������R�������t��-7g����\�.����X���$K��]�.�>+��M�/�������-��r����s�n�H��C�%N�T��K�9Wh3y�k�
i�z���.4.�9Ur���73T��Zc��5��S�9;�9Jb��s�DHf���kp5��M8��8�`16�X��$
n�Z�xr�@���k��r�nYc�A�P@F{]P�.�=���VT�i�l��H�W�*c�j�!po�4�H)�����������"��J��&i>����(��`�{c�S%�^��X�]���xk:9(����5z��_^���W��{MT���`�Eg�L����i��5�s�^��vT��Z���j�Ft��A��~{ ������t?oa�{a���r����<���m]�[/*�S�y��p�H�W�%M������0��0�I�"��v�H:�9u����N�^J����'�Q6��nNH7�/�@��b�+J�V}��q�,T����~^�C�,�����%���Q��������
���V�~�Xs�a�G�[��w�sWZx�r����G�5�+��:T��"*�,S��)�U����VDS����*����������)�b�w&3��������7+TSO���q�`�����<�v�/X
�b�\�����6Z-�
�l��9�d�CK�Z�S���]�g�uo�zV��neg��zM��";FGvD<1�O�L?�������������1��y�����-H����w�>E��d~|Bz�������������)��[`���'������M���>��3"Tx?.^�5~b���\J����1XQ�D�	������OI�of���zx���(���J��}�4��$�Va�(���qE>"�L��d��%R�`z$��e�.�)�D�)oE4�������M��D��
^\8�o�I�5s6]\G:�43��lg)�~�$>�?%���j�%��	������zz���p�@9
<��'���0��:�����*:s$�"H�X�Z�dX��H��O�+�R=��H�
y��PA}�4����($l����B�h@��_y���j����F��
7�v;�?2bj�1��m�)����}�	x�G�x��J��D�du���d4�
V��N�Z�G,$5��B��q5*R��8��"���"�C���K�M��3"]hZ 5�c���&�y��-��X��Y�5��QNp?��lu�=1�[NQOR:�����l6Y-������-";�M�O�e5"���TY�O�7'��gU��Ej�~)�2"M
�c�aW�������`�L�
�-g���>�c��g���9����W�d\��������fo�7�N"�/��:�!��L11��q�V���LO��/�$#�ig��o�b�E����]D7��
1���	 ^pw���N�rU��%V�C��ynK
�w�51f�P`�p&����M4�I��Lq��P��������B�����3���& c��6"~�`(L�\ 3�������+����x������������5��	��������x}�G�y}�QlR�)�C)�t����N�U�uz�����3]k�jZY�:3`������ttr���;���Q���r
,�t���q��w�VF�B��
9��s�UJzm� )�4��[m$�j
�V�#C�Q��p�����VF�
!J����u����x�{���g%������-����
;��p�����W���u0(b�������x���������u������
"���Eo���:KW��\���������V��o���(�9=�&$D�H?�Sb3��sJ*�W�����q��.�f>
M�gM[�|f�ML���Gh|�msW�����:.�u�R�}2Z��J
M���R��v����;"/>:Bh�9�h��N["g'��p>7��/�$�2���0���JC�%���Bg��{`7����W�w������&n�N9�S��!��_���Bf���[�����Pg)����5�����SM� ��i�9��������'���������9��
�7����8���hh<*�*��AEk�-^JvqZ3��d�[�z��WM��EKL[�Qi)���H��4j�h���P���8"t�{�*�K9�kTG��X���?��^(���%em���L]R��g����4���V�_�b��c�+KQ��WJ7 �/KZ��=�D����E�xNq���S�H���s�L��14�N
�0IF��o�r����v�>fSO���T�2�N��0�x��������.8�����?��G��%`�����TD���k�`�O
�x?�:0��C��W�J����87�4���'��d�����`]�fK7*��HH�#�^F��>bv~��-���_�K���^L����2c~�*� *�������<�r�K6
���������
Pg�%�U�|�+�L	�h>4]�������n��"R��S����O!Ye���3������5�|j����`������"��"={�0nH��yM���k�7����Q�~-nRb=s�
�i#���;�/>�������������F+�o�z�Q2)�*{l��YJ��<��#k���.P�kX�]�9���.&[�B66&Y�qq99���X��*�VN������)I�H�3�k�5/#���XQ�gQ���,��m�5f�����zT��[�41o��*��K�|��E(��/o?���d6����!X�����I:GsLbn�����8M@������;���
,�M��n�������������o��/���^����������5�,h�_	���(��f�CWvh����5��/���#_@���{����������Bq]�R���\��W\�~7n���NV4���:9�\2!���:����/no�w@Z1I���(o4�d��k�~N��zyr����i\�j���|����5�a�I�A�`) �p�9���V��M@�!����T��0�]%F'���k�l5S�/�W�1uzh)#u��L�����5{:�{T�XN�u�������-�e��/�:?������QD�	��ohY���+B��LDGBvS��\E;����^�s�bb�SH������.�������+�"M���H�����'�e�Y��w|�?����_.Q���Xh�M\�A���uG5��=��Z1vvK�������@��s��T����]��J�W��7('��=�c������t��2�H�\��wF�?\_-�^c��3�W����R����X�3k}C�e���$�-7"<G����2=��gs����`������v���4��y�N�E�A��#s��~yr"��k�����F���ru�SVq
^c�ttp�����u��Ur]���st +s��Q�)L�U�&��)���r��4����G��l[5U��^28�`K*�}[�Pr6�����y���"���TWF���tw�a,�#���Ee��}���VM�%'��`���N�dR�%*�kk��L�m�u��'����G��US�B@3uOW[p�-����{����L��O�q���G�Y�L�J�X��������P��=����:�V^�4m�	�����]�X�V�?}�����O�������� 3&�)����.���Q��8�.a�Y> ����^]�"(]>'�,R��*{0��������"�ZN��f��z����D�3�U�.S�������zfeg#��iB��I�\�"�w�p�A��j�q��4�0]����_����<�to�1��7Rd)W����Ub�,����"��R]��B�ZPe��RR��t���yt��H�:�����cn��$����?8��J^�
O���ZU%,��g]��{��Z�vP�o���
��*D�� /������>���Da<�!�GJ(�O�}����������Iq]��,������x�����uZ�L�k;x�T6m�h�ju�pc��4�G�V�P�W��* �1.�������X�-���Cr{�f��9��GO]����?;��������������8*���s�9�l��|Fw8#/�h������[�2�����f���x9��)����9eR@����,=������[�)Y
<W�_2&PJ6���'�1[���,P�;n��UtH+��� �7x���=��F���[�^��7S��r����AS��qv��^���g3�Z��2�0��j�b����
�q������IL$f�b�/��J�����nP��?����/	��9�3���l�:���[�81�����9CjW�X�������xq����k_������G��Z��t���FQ�i�����u@���:m+�6��MX`���I�@�f�9�%���ky�n��"�N/���K$�����m��>K�^�H�34��+�R�^?�Nh1���9�&�T�LFK!�w����|FJ�R��jj�\b����U���u�t� ����EJY����H�U����#��CiT�p��t��#���d�=�cmD��I�q�Fj�j 6�F�h����Ub����*��4��2�GU��/��#�4|�JTz�f����������xfe�{��~
�Y�y/~?K/G��520��l�~���6���M������'�O�)Y��Xr����l1��=�
�Gk��?��#�3Z��F�����i�w{�_S�l���m��N<�V�gz��*:9}}��������G|E)-���G2�
�.i���c�X��JS"g���R���M[�?9��$9�����P��b��qt�*'*f6�\����u�2VA��FW���b�Y�qM�����w@u���>��g��
������Rix}���q5��0������<Zv��&J�Cw��`��j��$�f��-����&/o���]���l�e��O�Zi/��t6'�K����b��@?�U�v�H�������#�����(��K��xb����&���r�F�8F
�����'3�5i����N?�P8�RzSx	�5�����F�	�p��k��wz$9$���W���Z}]i
jy�R�S�� �t6���J�0���!���n�����t�wY��~��$-���d�@�o\��!��� <R���c�yQh���J%�z ���`�y��{�h=�2T������j�WA�>�Hu1)���������b:A���I��E�J��p1���� b��'�w���R=���un�����r��98\����DLK}���G�Y�Z�����P���v�n��7�<l�1�����
��^���n���j.�^���z<$}���J=���l�q�N�K��N���=�n�9{
�#����%��O�
�w���[�������dT�7����/9��H����G2�X�)&`=~{p4��U]���Q��:�3�����9/ �>Y��Q���T�0d�TG�#�d��k������oI��f�N,
L�G��t�G�,�]�s��p|%�n��Q.zh�1��`.7��B]*wa������u���XM��
��Au�
���(��}��
�+��C��
�[?9����������������PE���b��0�?�*���V\f����������q����Wx{�=�M��',�-�Z��'p����5����F}������b�DhR��dv}��O�>���E�t�n�N��n�X��w!"�c�
 ������������]C�j ����9�a���T���
U����^�$4�^p�c�h1.�SLF�\�0bh=�/��s�o�@��w{��62AE:����eI�<]&�����dK6c�9�����K�V���y����$TSf��ln\�5�kq.$?E6!�����41={���(���(�\��X�3TLX��f���B��b�l�����c��W�O��z�i�S�<	���Z�p�"">�"�D)y�(�Ne�9"�t4���(��M���PZb�?W] 5�ZN-������n�v�`��3	�4�k4��
Am��bs���5���r���|�*=����u��%
/�1uu�?P��d�k����WON/��u`��A��\h/�oQs��<#��������`�F��ws�������kr����%�C�.��J����*�V�$���6���F��(:��i��I30����M�Z� f+`.�������%F���`�����0�N���)��H�I�]P�h�<�2���]U���������5eP����������`M���E� ���vQs)_�u�����Z7z7����~wo�k�]k
����I�����������#�.���%����=�L��7�Qq�Kr���?���b�M8r���N����$_�Y��|�u�z�F�0K��,�~L��gx���R�/c��7���/VQ�8"r�0U)��'��8��)~�-W�x�����"�U�}�.���ow��]cy���+(#z������/�!DG�C��@���~�io)j���`S�����f	�1��!��0�_cHT|����d�zg-���1��E�v>L)��C�G��_��=���N��p�s812��,.�����W��A"���H~hJ��4���|�������d�E���kq���P{�����9q&8�n�5M�`��Y����&�c�m����9��BBIl�����R�F$�\MQl�Z�%�Bw��t�J�h+��������F����4PlE��`]�Cu���{�{����>�~(�����a4�ls .�`���*x���pq#��p<��"y��J,��V�����>����I[��NW^*w�w�@����$Z�Ms����J�����xq}JBu�^�/���7��I�>bt�$Wo5��8�y��5�1�U[�KM�2s9i��3z�q�`�k����h$�1P9d�j\�@�U-��T���M;���{�=a;P�+�n.�n)��}a�ab#@����Q����[C���90��
����W�8>�W�Fg���`E����N`�����{�7�c��3I[���fn��+��Q�dy�H�A��_)	P�I��_��@��;��,�K��0�]wN�OD�G�)�n�K�vy����U����(�������b�TZ�K�����u�����U��\
#59Tom Lane
tgl@sss.pgh.pa.us
In reply to: Joe Conway (#58)
Re: [HACKERS] 8.2 features?

Joe Conway <mail@joeconway.com> writes:

The good news is that from a memory and perfomance standpoint, my simple
test now shows us outperforming mysql:

Sweet ;-)

I'm up to my *ss in fixing relation locking, but will get back to your
thing as soon as that's done. I think you're close enough to qualify
as having made the feature freeze deadline, in any case.

regards, tom lane

#60Alvaro Herrera
alvherre@commandprompt.com
In reply to: Tom Lane (#59)
Re: [HACKERS] 8.2 features?

Tom Lane wrote:

Joe Conway <mail@joeconway.com> writes:

The good news is that from a memory and perfomance standpoint, my simple
test now shows us outperforming mysql:

Sweet ;-)

I love this team. Kudos!

--
Alvaro Herrera http://www.CommandPrompt.com/
PostgreSQL Replication, Consulting, Custom Development, 24x7 support

#61Michael Fuhr
mike@fuhr.org
In reply to: Alvaro Herrera (#60)
Re: [HACKERS] 8.2 features?

On Mon, Jul 31, 2006 at 04:19:43PM -0400, Alvaro Herrera wrote:

Tom Lane wrote:

Joe Conway <mail@joeconway.com> writes:

The good news is that from a memory and perfomance standpoint, my simple
test now shows us outperforming mysql:

Sweet ;-)

I love this team. Kudos!

So now it's MySQL users' turn to say, "Sure, but speed isn't
everything...." :-)

--
Michael Fuhr

#62Joshua D. Drake
jd@commandprompt.com
In reply to: Michael Fuhr (#61)
Re: [HACKERS] 8.2 features?

Michael Fuhr wrote:

On Mon, Jul 31, 2006 at 04:19:43PM -0400, Alvaro Herrera wrote:

Tom Lane wrote:

Joe Conway <mail@joeconway.com> writes:

The good news is that from a memory and perfomance standpoint, my simple
test now shows us outperforming mysql:

Sweet ;-)

I love this team. Kudos!

So now it's MySQL users' turn to say, "Sure, but speed isn't
everything...." :-)

"Sure, but speed isn't everything... We can accept 02/31/2006 as a valid
date. Let's see PostgreSQL do that!"

Joshua D. Drake

--

=== The PostgreSQL Company: Command Prompt, Inc. ===
Sales/Support: +1.503.667.4564 || 24x7/Emergency: +1.800.492.2240
Providing the most comprehensive PostgreSQL solutions since 1997
http://www.commandprompt.com/

#63Tom Lane
tgl@sss.pgh.pa.us
In reply to: Joe Conway (#58)
Re: [HACKERS] 8.2 features?

Joe Conway <mail@joeconway.com> writes:

I wanted to post an updated patch even though there are still things not
working again after conversion to bare expressions.

I've been through the planner part of this and it looks OK (one or two
small errors). I'm currently messing with a revised version of the
grammar that supports putting VALUES everyplace that the spec allows,
and is a bit simpler than the old one to boot: it folds VALUES and
SELECT together, so we need fewer cases in the INSERT production.
Of course this breaks most of what you did in the parser :-( ...
I'm working on fixing that.

I'm about to go out to dinner but thought I'd post the gram.y and
parsenodes.h files so you could see where I'm headed. These are
diffs from CVS tip, not from your patch.

regards, tom lane

#64Joe Conway
mail@joeconway.com
In reply to: Tom Lane (#63)
1 attachment(s)
Re: [HACKERS] 8.2 features?

Tom Lane wrote:

Joe Conway <mail@joeconway.com> writes:

I wanted to post an updated patch even though there are still things not
working again after conversion to bare expressions.

I've been through the planner part of this and it looks OK (one or two
small errors). I'm currently messing with a revised version of the
grammar that supports putting VALUES everyplace that the spec allows,
and is a bit simpler than the old one to boot: it folds VALUES and
SELECT together, so we need fewer cases in the INSERT production.
Of course this breaks most of what you did in the parser :-( ...
I'm working on fixing that.

I'm about to go out to dinner but thought I'd post the gram.y and
parsenodes.h files so you could see where I'm headed. These are
diffs from CVS tip, not from your patch.

Yup, I can see where you're headed. Looks nice!

In case you can make use of it, here's my latest. I found that I was
being too aggressive at freeing the input nodes to transformExpr() in
transformRangeValues() after using them. In many cases the returned node
is a new palloc'd node, but in some cases it is not.

The other issue I found was that I had neglected to fixup/coerce the raw
expressions ala updateTargetListEntry(). I ended up creating a somewhat
simpler updateValuesExprListEntry() to use on values expression lists.

I have yet to get to the similar/more general issue of coercing values
expression lists to common datatypes (i.e. using select_common_type()).

FWIW, here's a list of non-working cases at the moment:

8<-------------------------------------
create table inserttest (col1 int4, col2 int4 NOT NULL, col3 text
default 'testing');

--doesn't work
---------------
--wrong result
insert into inserttest (col2, col3) values (23, DEFAULT), (24, DEFAULT),
(25, 'hello'), (26, DEFAULT);
select * from (values (3,4),(2,3)) as t1(f1,f2) join (values
(3,8),(2,6)) as t2(f1,f2) using (f1);
select * from (values (3,4),(2,3)) as t1(f1,f2) join (values
(3,8),(2,6)) as t2(f1,f2) using (f1) where t2.f2 = 8;
select * from (values (3,4),(2,3)) as t1(f1,f2) join (values
(3,8),(2,6)) as t2(f1,f2) on t1.f1 = t2.f2 where t1.f1 = 3;

--corrupt result but no crash
select f1,f2 from (values (11,2),(26,'a'),(6,4)) as t(f1,f2) order by 1
desc;

--crash
select f1 from (values (1,2),(2,3)) as t(f1,f2) order by 1 desc;
select f1,f2 from (values (11,'a'),(26,13),(6,'c')) as t(f1,f2) order by
1 desc;
8<-------------------------------------

Joe

Attachments:

multi-insert-r19.diff.gzapplication/x-gzip; name=multi-insert-r19.diff.gzDownload
#65Harald Armin Massa
haraldarminmassa@gmail.com
In reply to: Joshua D. Drake (#62)
Re: [HACKERS] 8.2 features?

Joshua,

So now it's MySQL users' turn to say, "Sure, but speed isn't

everything...." :-)

"Sure, but speed isn't everything... We can accept 02/31/2006 as a valid
date. Let's see PostgreSQL do that!"

I got the joke :)

But: it is still a problem when converting. As accepting 2006-02-31 as a
valid date would require brainwashing at least the entire core team, we
should find a "recommended path of date migration from different universes".

My idea would be to:

a) declare date fields as text
b) load the dump of the other db
c) add another column for the date fields, type timestampe (w/wo tz)
d) try to update the column of c) with the converted field from a)
e) replace the failing ones manually

is this really best practice? especially finding the invalid ones would be
challenging :(
idea: sort after the textual date fields; look at hot spots (0000-00-00,
xxxx-02-31)

Are there better ideas? shall we document the best practice somewhere?

Harald
--
GHUM Harald Massa
persuadere et programmare
Harald Armin Massa
Reinsburgstraße 202b
70197 Stuttgart
0173/9409607
-
Let's set so double the killer delete select all.

#66Michael Glaesemann
grzm@seespotcode.net
In reply to: Harald Armin Massa (#65)
Re: [PATCHES] 8.2 features?

On Aug 1, 2006, at 16:15 , Harald Armin Massa wrote:

As accepting 2006-02-31 as a valid date would require brainwashing
at least the entire core team, we should find a "recommended path
of date migration from different universes".

Have you checked out the mysql2pgsql[1](http://gborg.postgresql.org/project/mysql2psql/projdisplay.php) or my2postgres projects?
Perhaps they've included this as part of the conversion process.

Michael Glaesemann
grzm seespotcode net

[1]: (http://gborg.postgresql.org/project/mysql2psql/projdisplay.php)
[2]: (http://pgfoundry.org/projects/my2postgres/)

#67Tom Lane
tgl@sss.pgh.pa.us
In reply to: Joe Conway (#64)
Re: [HACKERS] 8.2 features?

Joe Conway <mail@joeconway.com> writes:

In case you can make use of it, here's my latest. I found that I was
being too aggressive at freeing the input nodes to transformExpr() in
transformRangeValues() after using them. In many cases the returned node
is a new palloc'd node, but in some cases it is not.

Great, I'll incorporate these updates and keep plugging --- should be
done today barring problems. If you have some spare cycles today,
want to work on regression tests and docs?

regards, tom lane

#68Tom Lane
tgl@sss.pgh.pa.us
In reply to: Joe Conway (#50)
Re: Values list-of-targetlists patch for comments (was Re: [PATCHES] 8.2 features?)

I've found a problem with the VALUES-as-RTE approach:

regression=# create table src(f1 int, f2 int);
CREATE TABLE
regression=# create table log(f1 int, f2 int, tag text);
CREATE TABLE
regression=# insert into src values(1,2);
INSERT 0 1
regression=# create rule r2 as on update to src do
regression-# insert into log values(old.*, 'old'), (new.*, 'new');
CREATE RULE
regression=# update src set f2 = f2 + 1;
server closed the connection unexpectedly

The problem with this is that the rewriter is substituting Vars
referencing "src" into the values lists of the VALUES RTE, within
a query that looks like a Cartesian product of src and *VALUES*:

regression=# explain update src set f2 = f2 + 1;
QUERY PLAN
--------------------------------------------------------------------
Nested Loop (cost=0.00..97.62 rows=3880 width=40)
-> Values Scan on "*VALUES*" (cost=0.00..0.02 rows=2 width=40)
-> Seq Scan on src (cost=0.00..29.40 rows=1940 width=0)

Seq Scan on src (cost=0.00..34.25 rows=1940 width=14)
(5 rows)

The ValuesScan node doesn't have access to the values of the current
row of src ... indeed, the planner doesn't know that it shouldn't
put the VALUES on the outside of the join, as it's done here, so
there *isn't* a current row of src.

AFAICT, the only way to make this work would be to implement SQL99's
LATERAL construct (or something pretty close to it --- I'm not entirely
sure I understand what LATERAL is supposed to do) so that the rewritten
query could be expressed like

insert into log select ... from src, LATERAL VALUES(src.f1, ...)

That's obviously not something we can get done for 8.2.

We could maybe kluge something to work for 8.2 if we were willing to
abandon the VALUES-as-RTE approach and go back to the notion of some
kind of multiple targetlist in a Query. I'm disinclined to do that
though, because as I've been working with your patch I've come to agree
that the RTE solution is a pretty clean one.

What I'm inclined to do for 8.2 is to disallow OLD/NEW references in
multi-element VALUES clauses; the feature is still tremendously useful
without that.

regards, tom lane

#69Alvaro Herrera
alvherre@commandprompt.com
In reply to: Tom Lane (#68)
Re: Values list-of-targetlists patch for comments (was Re: [PATCHES] 8.2 features?)

Tom Lane wrote:

I've found a problem with the VALUES-as-RTE approach:

regression=# create table src(f1 int, f2 int);
CREATE TABLE
regression=# create table log(f1 int, f2 int, tag text);
CREATE TABLE
regression=# insert into src values(1,2);
INSERT 0 1
regression=# create rule r2 as on update to src do
regression-# insert into log values(old.*, 'old'), (new.*, 'new');
CREATE RULE
regression=# update src set f2 = f2 + 1;
server closed the connection unexpectedly

Does it work if you do

regression=# create rule r2 as on update to src do
regression-# insert into log values(old.f1, old.f2, 'old'), (new.f1, new.f2, 'new');
?

--
Alvaro Herrera http://www.CommandPrompt.com/
PostgreSQL Replication, Consulting, Custom Development, 24x7 support

#70Joe Conway
mail@joeconway.com
In reply to: Tom Lane (#68)
Re: Values list-of-targetlists patch for comments (was Re: [PATCHES]

Tom Lane wrote:

What I'm inclined to do for 8.2 is to disallow OLD/NEW references in
multi-element VALUES clauses; the feature is still tremendously useful
without that.

Given the timing, this sounds like a reasonable approach. I agree that
the feature has lots of interesting uses -- I'd hate to see us lose
that. Disallowing OLD/NEW references doesn't contradict the spec in any
way AFAIK either.

Joe

#71Tom Lane
tgl@sss.pgh.pa.us
In reply to: Alvaro Herrera (#69)
Re: Values list-of-targetlists patch for comments (was Re: [PATCHES] 8.2 features?)

Alvaro Herrera <alvherre@commandprompt.com> writes:

Does it work if you do

regression=# create rule r2 as on update to src do
regression-# insert into log values(old.f1, old.f2, 'old'), (new.f1, new.f2, 'new');

No, that's not the problem. "*" expansion works just fine here, it's
the executor that can't deal with the resulting Vars.

regards, tom lane

#72Tom Lane
tgl@sss.pgh.pa.us
In reply to: Joe Conway (#70)
Re: Values list-of-targetlists patch for comments (was Re: [HACKERS] 8.2 features?)

Here's what I've got so far. I think there's probably more gold to be
mined in terms of reducing runtime memory consumption (I don't like the
list_free_deep bit, we should use a context), but functionally it seems
complete. I'm off to dinner again, it's in your court to look over some
more if you want.

(PS: if you want to apply, go ahead, don't forget catversion bump.)

regards, tom lane

#73Gavin Sherry
swm@linuxworld.com.au
In reply to: Tom Lane (#72)
Re: Values list-of-targetlists patch for comments (was Re:

Tom,

Is this intentional:

template1=# values(1), (2);
column1
---------
1
2
(2 rows)

This is legal because of:

simple_select:
/* ... */
| values_clause { $$ = $2; }

Also, I am working out some docs and regression tests.

Gavin

#74Joe Conway
mail@joeconway.com
In reply to: Tom Lane (#72)
Re: Values list-of-targetlists patch for comments (was Re:

Tom Lane wrote:

Here's what I've got so far. I think there's probably more gold to be
mined in terms of reducing runtime memory consumption (I don't like the
list_free_deep bit, we should use a context), but functionally it seems
complete. I'm off to dinner again, it's in your court to look over some
more if you want.

OK, I'll continue to look at it this week.

(PS: if you want to apply, go ahead, don't forget catversion bump.)

Sure, I'll commit shortly.

Thanks,

Joe

#75Joe Conway
mail@joeconway.com
In reply to: Gavin Sherry (#73)
Re: Values list-of-targetlists patch for comments (was Re:

Gavin Sherry wrote:

Is this intentional:

template1=# values(1), (2);
column1
---------
1
2
(2 rows)

This is legal because of:

simple_select:
/* ... */
| values_clause { $$ = $2; }

hmm, not sure about that...

Also, I am working out some docs and regression tests.

Oh, cool. I was going to start working on that myself tonight, but if
you're already working on it, don't let me stand in the way ;-)

Actually, if you want me to finish up whatever you have started, I'm
happy to do that too.

Joe

#76Gavin Sherry
swm@linuxworld.com.au
In reply to: Joe Conway (#75)
Re: Values list-of-targetlists patch for comments (was Re:

On Tue, 1 Aug 2006, Joe Conway wrote:

Gavin Sherry wrote:

Is this intentional:

template1=# values(1), (2);
column1
---------
1
2
(2 rows)

This is legal because of:

simple_select:
/* ... */
| values_clause { $$ = $2; }

hmm, not sure about that...

Also, I am working out some docs and regression tests.

Oh, cool. I was going to start working on that myself tonight, but if
you're already working on it, don't let me stand in the way ;-)

Actually, if you want me to finish up whatever you have started, I'm
happy to do that too.

I've got to go out but I'll send a complete patch when I get back.

Gavin

#77Joe Conway
mail@joeconway.com
In reply to: Tom Lane (#72)
Re: Values list-of-targetlists patch for comments (was Re:

Tom Lane wrote:

Here's what I've got so far. I think there's probably more gold to be
mined in terms of reducing runtime memory consumption (I don't like the
list_free_deep bit, we should use a context), but functionally it seems
complete. I'm off to dinner again, it's in your court to look over some
more if you want.

(PS: if you want to apply, go ahead, don't forget catversion bump.)

Committed, with catversion bump.

Joe

#78Tom Lane
tgl@sss.pgh.pa.us
In reply to: Gavin Sherry (#73)
Re: Values list-of-targetlists patch for comments (was Re: [HACKERS] 8.2 features?)

Gavin Sherry <swm@linuxworld.com.au> writes:

Is this intentional:

template1=# values(1), (2);
column1
---------
1
2
(2 rows)

You bet. VALUES is parallel to SELECT in the SQL grammar, so AFAICS
it should be legal anywhere you can write SELECT.

The basic productions in the spec's grammar are respectively

<query specification> ::=
SELECT [ <set quantifier> ] <select list>
<table expression>

and

<table value constructor> ::=
VALUES <row value expression list>

and both of them link into the rest of the grammar here:

<simple table> ::=
<query specification>
| <table value constructor>
| <explicit table>

There is no construct I can find in the spec grammar that allows
<query specification> but not <table value constructor>. QED.

Try some stuff like
DECLARE c CURSOR FOR VALUES ...
WHERE foo IN (VALUES ...

regards, tom lane

#79Tom Lane
tgl@sss.pgh.pa.us
In reply to: Joe Conway (#70)
Re: Values list-of-targetlists patch for comments (was Re: [PATCHES] 8.2 features?)

Joe Conway <mail@joeconway.com> writes:

Tom Lane wrote:

What I'm inclined to do for 8.2 is to disallow OLD/NEW references in
multi-element VALUES clauses; the feature is still tremendously useful
without that.

Given the timing, this sounds like a reasonable approach. I agree that
the feature has lots of interesting uses -- I'd hate to see us lose
that. Disallowing OLD/NEW references doesn't contradict the spec in any
way AFAIK either.

I don't think rules are in the spec at all ;-) ... so no, that's not
a problem. My example demonstrated a pretty likely use:

create rule r2 as on update to src do
insert into log values(old.*, 'old'), (new.*, 'new');

but for the moment we can tell people to work around it the way
they always have:

create rule r2 as on update to src do
insert into log select old.*, 'old' union all new.*, 'new';

or just use two separate INSERT commands in the rule.

We oughta fix it later, but I don't feel ashamed to have a restriction
like this in the first cut.

regards, tom lane

#80Bruce Momjian
bruce@momjian.us
In reply to: Tom Lane (#79)
Re: Values list-of-targetlists patch for comments (was Re: [PATCHES]

Should we wait for someone to actually ask for this before adding it to
the TODO list? Does it cause a crash now?

---------------------------------------------------------------------------

Tom Lane wrote:

Joe Conway <mail@joeconway.com> writes:

Tom Lane wrote:

What I'm inclined to do for 8.2 is to disallow OLD/NEW references in
multi-element VALUES clauses; the feature is still tremendously useful
without that.

Given the timing, this sounds like a reasonable approach. I agree that
the feature has lots of interesting uses -- I'd hate to see us lose
that. Disallowing OLD/NEW references doesn't contradict the spec in any
way AFAIK either.

I don't think rules are in the spec at all ;-) ... so no, that's not
a problem. My example demonstrated a pretty likely use:

create rule r2 as on update to src do
insert into log values(old.*, 'old'), (new.*, 'new');

but for the moment we can tell people to work around it the way
they always have:

create rule r2 as on update to src do
insert into log select old.*, 'old' union all new.*, 'new';

or just use two separate INSERT commands in the rule.

We oughta fix it later, but I don't feel ashamed to have a restriction
like this in the first cut.

regards, tom lane

---------------------------(end of broadcast)---------------------------
TIP 4: Have you searched our list archives?

http://archives.postgresql.org

--
Bruce Momjian bruce@momjian.us
EnterpriseDB http://www.enterprisedb.com

+ If your life is a hard drive, Christ can be your backup. +

#81Joe Conway
mail@joeconway.com
In reply to: Bruce Momjian (#80)
Re: Values list-of-targetlists patch for comments (was Re: [PATCHES]

Bruce Momjian wrote:

Should we wait for someone to actually ask for this before adding it
to the TODO list?

Probably worth adding it to the TODO list so it doen't get lost.

Does it cause a crash now?

Nope:

regression=# create table log(f1 int, f2 int, tag text);
CREATE TABLE
regression=# insert into src values(1,2);
INSERT 0 1
regression=# create rule r2 as on update to src do insert into log
values(old.*, 'old'), (new.*, 'new');
ERROR: VALUES must not contain OLD or NEW references

Joe

#82Joe Conway
mail@joeconway.com
In reply to: Tom Lane (#72)
1 attachment(s)
Re: Values list-of-targetlists patch for comments (was Re:

Tom Lane wrote:

Here's what I've got so far. I think there's probably more gold to be
mined in terms of reducing runtime memory consumption (I don't like the
list_free_deep bit, we should use a context), but functionally it seems
complete.

I checked out memory usage, and it had regressed to about 1.4 GB (from
730 MB as reported yesterday) for 2 million inserts of 2 integers (i.e.
with the php script I've been using).

I know you're not too happy with the attached approach to solving this,
but I'm not sure how creating a memory context is going to help. Part of
the problem is that the various transformXXX functions sometimes return
freshly palloc'd memory, and sometimes return the pointer they are given.

Anyway, with the attached diff, the 2 million inserts case is back to
about 730 MB memory use, and speed is pretty much the same as reported
yesterday (i.e both memory use and performance better than mysql with
innodb tables).

Thoughts?

Thanks,

Joe

Attachments:

multi-insert-memleak.r00.difftext/x-patch; name=multi-insert-memleak.r00.diffDownload
Index: src/backend/parser/analyze.c
===================================================================
RCS file: /cvsroot/pgsql/src/backend/parser/analyze.c,v
retrieving revision 1.341
diff -c -r1.341 analyze.c
*** src/backend/parser/analyze.c	2 Aug 2006 01:59:46 -0000	1.341
--- src/backend/parser/analyze.c	2 Aug 2006 05:13:20 -0000
***************
*** 872,877 ****
--- 872,878 ----
  	foreach(lc, exprlist)
  	{
  		Expr *expr = (Expr *) lfirst(lc);
+ 		Expr *p = expr;
  		ResTarget  *col;
  
  		col = (ResTarget *) lfirst(icols);
***************
*** 885,893 ****
--- 886,898 ----
  
  		result = lappend(result, expr);
  
+ 		if (expr != p)
+ 			pfree(p);
+ 
  		icols = lnext(icols);
  		attnos = lnext(attnos);
  	}
+ 	list_free(exprlist);
  
  	return result;
  }
***************
*** 2191,2196 ****
--- 2196,2202 ----
  	for (i = 0; i < sublist_length; i++)
  	{
  		coltypes[i] = select_common_type(coltype_lists[i], "VALUES");
+ 		list_free(coltype_lists[i]);
  	}
  
  	newExprsLists = NIL;
***************
*** 2203,2216 ****
  		foreach(lc2, sublist)
  		{
  			Node  *col = (Node *) lfirst(lc2);
  
- 			col = coerce_to_common_type(pstate, col, coltypes[i], "VALUES");
- 			newsublist = lappend(newsublist, col);
  			i++;
  		}
  
  		newExprsLists = lappend(newExprsLists, newsublist);
  	}
  
  	/*
  	 * Generate the VALUES RTE
--- 2209,2228 ----
  		foreach(lc2, sublist)
  		{
  			Node  *col = (Node *) lfirst(lc2);
+ 			Node  *new_col;
+ 
+ 			new_col = coerce_to_common_type(pstate, col, coltypes[i], "VALUES");
+ 			newsublist = lappend(newsublist, new_col);
+ 			if (new_col != col)
+ 				pfree(col);
  
  			i++;
  		}
  
  		newExprsLists = lappend(newExprsLists, newsublist);
+ 		list_free(sublist);
  	}
+ 	list_free(exprsLists);
  
  	/*
  	 * Generate the VALUES RTE
Index: src/backend/parser/parse_target.c
===================================================================
RCS file: /cvsroot/pgsql/src/backend/parser/parse_target.c,v
retrieving revision 1.147
diff -c -r1.147 parse_target.c
*** src/backend/parser/parse_target.c	2 Aug 2006 01:59:47 -0000	1.147
--- src/backend/parser/parse_target.c	2 Aug 2006 05:13:21 -0000
***************
*** 172,177 ****
--- 172,178 ----
  	foreach(lc, exprlist)
  	{
  		Node	   *e = (Node *) lfirst(lc);
+ 		Node	   *p = e;
  
  		/*
  		 * Check for "something.*".  Depending on the complexity of the
***************
*** 188,193 ****
--- 189,195 ----
  				result = list_concat(result,
  									 ExpandColumnRefStar(pstate, cref,
  														 false));
+ 				pfree(e);
  				continue;
  			}
  		}
***************
*** 203,208 ****
--- 205,211 ----
  				result = list_concat(result,
  									 ExpandIndirectionStar(pstate, ind,
  														   false));
+ 				pfree(e);
  				continue;
  			}
  		}
***************
*** 210,218 ****
  		/*
  		 * Not "something.*", so transform as a single expression
  		 */
! 		result = lappend(result,
! 						 transformExpr(pstate, e));
  	}
  
  	return result;
  }
--- 213,224 ----
  		/*
  		 * Not "something.*", so transform as a single expression
  		 */
! 		p = transformExpr(pstate, e);
! 		result = lappend(result, p);
! 		if (e != p)
! 			pfree(e);
  	}
+ 	list_free(exprlist);
  
  	return result;
  }
#83Joshua D. Drake
jd@commandprompt.com
In reply to: Joe Conway (#82)
Re: Values list-of-targetlists patch for comments (was Re:

Anyway, with the attached diff, the 2 million inserts case is back to
about 730 MB memory use, and speed is pretty much the same as reported
yesterday (i.e both memory use and performance better than mysql with
innodb tables).

That's all that matters ;)

Joshua D. Drake

--

=== The PostgreSQL Company: Command Prompt, Inc. ===
Sales/Support: +1.503.667.4564 || 24x7/Emergency: +1.800.492.2240
Providing the most comprehensive PostgreSQL solutions since 1997
http://www.commandprompt.com/

#84Joe Conway
mail@joeconway.com
In reply to: Joe Conway (#82)
1 attachment(s)
Re: Values list-of-targetlists patch for comments (was Re:

Joe Conway wrote:

Tom Lane wrote:

Here's what I've got so far. I think there's probably more gold to be
mined in terms of reducing runtime memory consumption (I don't like the
list_free_deep bit, we should use a context), but functionally it seems
complete.

I checked out memory usage, and it had regressed to about 1.4 GB (from
730 MB as reported yesterday) for 2 million inserts of 2 integers (i.e.
with the php script I've been using).

I know you're not too happy with the attached approach to solving this,
but I'm not sure how creating a memory context is going to help. Part of
the problem is that the various transformXXX functions sometimes return
freshly palloc'd memory, and sometimes return the pointer they are given.

Anyway, with the attached diff, the 2 million inserts case is back to
about 730 MB memory use, and speed is pretty much the same as reported
yesterday (i.e both memory use and performance better than mysql with
innodb tables).

Of course it also breaks a bunch of regression tests -- I guess that
just points to the fragility of this approach.

This patch retains the memory consumption savings but doesn't break any
regression tests...

Joe

Attachments:

multi-insert-memleak.r01.difftext/x-patch; name=multi-insert-memleak.r01.diffDownload
? src/test/regress/sql/insert.sql.new
Index: src/backend/parser/analyze.c
===================================================================
RCS file: /cvsroot/pgsql/src/backend/parser/analyze.c,v
retrieving revision 1.341
diff -c -r1.341 analyze.c
*** src/backend/parser/analyze.c	2 Aug 2006 01:59:46 -0000	1.341
--- src/backend/parser/analyze.c	2 Aug 2006 05:48:18 -0000
***************
*** 888,893 ****
--- 888,894 ----
  		icols = lnext(icols);
  		attnos = lnext(attnos);
  	}
+ 	list_free(exprlist);
  
  	return result;
  }
***************
*** 2191,2196 ****
--- 2192,2198 ----
  	for (i = 0; i < sublist_length; i++)
  	{
  		coltypes[i] = select_common_type(coltype_lists[i], "VALUES");
+ 		list_free(coltype_lists[i]);
  	}
  
  	newExprsLists = NIL;
***************
*** 2203,2216 ****
  		foreach(lc2, sublist)
  		{
  			Node  *col = (Node *) lfirst(lc2);
  
- 			col = coerce_to_common_type(pstate, col, coltypes[i], "VALUES");
- 			newsublist = lappend(newsublist, col);
  			i++;
  		}
  
  		newExprsLists = lappend(newExprsLists, newsublist);
  	}
  
  	/*
  	 * Generate the VALUES RTE
--- 2205,2224 ----
  		foreach(lc2, sublist)
  		{
  			Node  *col = (Node *) lfirst(lc2);
+ 			Node  *new_col;
+ 
+ 			new_col = coerce_to_common_type(pstate, col, coltypes[i], "VALUES");
+ 			newsublist = lappend(newsublist, new_col);
+ 			if (new_col != col)
+ 				pfree(col);
  
  			i++;
  		}
  
  		newExprsLists = lappend(newExprsLists, newsublist);
+ 		list_free(sublist);
  	}
+ 	list_free(exprsLists);
  
  	/*
  	 * Generate the VALUES RTE
Index: src/backend/parser/parse_target.c
===================================================================
RCS file: /cvsroot/pgsql/src/backend/parser/parse_target.c,v
retrieving revision 1.147
diff -c -r1.147 parse_target.c
*** src/backend/parser/parse_target.c	2 Aug 2006 01:59:47 -0000	1.147
--- src/backend/parser/parse_target.c	2 Aug 2006 05:48:18 -0000
***************
*** 172,177 ****
--- 172,178 ----
  	foreach(lc, exprlist)
  	{
  		Node	   *e = (Node *) lfirst(lc);
+ 		Node	   *p = e;
  
  		/*
  		 * Check for "something.*".  Depending on the complexity of the
***************
*** 188,193 ****
--- 189,195 ----
  				result = list_concat(result,
  									 ExpandColumnRefStar(pstate, cref,
  														 false));
+ 				pfree(e);
  				continue;
  			}
  		}
***************
*** 203,208 ****
--- 205,211 ----
  				result = list_concat(result,
  									 ExpandIndirectionStar(pstate, ind,
  														   false));
+ 				pfree(e);
  				continue;
  			}
  		}
***************
*** 210,218 ****
  		/*
  		 * Not "something.*", so transform as a single expression
  		 */
! 		result = lappend(result,
! 						 transformExpr(pstate, e));
  	}
  
  	return result;
  }
--- 213,224 ----
  		/*
  		 * Not "something.*", so transform as a single expression
  		 */
! 		p = transformExpr(pstate, e);
! 		result = lappend(result, p);
! 		if (e != p)
! 			pfree(e);
  	}
+ 	list_free(exprlist);
  
  	return result;
  }
#85Michael Glaesemann
grzm@seespotcode.net
In reply to: Joe Conway (#81)
Re: Values list-of-targetlists patch for comments (was Re: [PATCHES]

On Aug 2, 2006, at 12:47 , Joe Conway wrote:

regression=# create rule r2 as on update to src do insert into log
values(old.*, 'old'), (new.*, 'new');
ERROR: VALUES must not contain OLD or NEW references

Would it make sense to add a HINT as well, recommending the UNION
construct Tom mentioned earlier?

On Aug 2, 2006, at 11:52 , Tom Lane wrote:

create rule r2 as on update to src do
insert into log select old.*, 'old' union all new.*, 'new';

or just use two separate INSERT commands in the rule.

Or is the general case too, uh, general for a HINT?

Michael Glaesemann
grzm seespotcode net

#86Bruce Momjian
bruce@momjian.us
In reply to: Joe Conway (#81)
Re: Values list-of-targetlists patch for comments (was Re:

Joe Conway wrote:

Bruce Momjian wrote:

Should we wait for someone to actually ask for this before adding it
to the TODO list?

Probably worth adding it to the TODO list so it doen't get lost.

Added:

o In rules, allow VALUES() to contain a mixture of 'old' and 'new'
references

--
Bruce Momjian bruce@momjian.us
EnterpriseDB http://www.enterprisedb.com

+ If your life is a hard drive, Christ can be your backup. +

#87Bruce Momjian
bruce@momjian.us
In reply to: Michael Glaesemann (#85)
Re: Values list-of-targetlists patch for comments (was Re:

Michael Glaesemann wrote:

On Aug 2, 2006, at 12:47 , Joe Conway wrote:

regression=# create rule r2 as on update to src do insert into log
values(old.*, 'old'), (new.*, 'new');
ERROR: VALUES must not contain OLD or NEW references

Would it make sense to add a HINT as well, recommending the UNION
construct Tom mentioned earlier?

Agreed.

--
Bruce Momjian bruce@momjian.us
EnterpriseDB http://www.enterprisedb.com

+ If your life is a hard drive, Christ can be your backup. +

#88Tom Lane
tgl@sss.pgh.pa.us
In reply to: Joe Conway (#84)
Re: Values list-of-targetlists patch for comments (was Re:

Joe Conway <mail@joeconway.com> writes:

This patch retains the memory consumption savings but doesn't break any
regression tests...

I'm unconvinced that retail pfree's are the way to go. I just did some
profiling of this test case:

insert into foo values
(0,0,0),
(1,1,1),
(2,2,2),
(3,3,3),
... one million rows ...
(999997,999997,999997),
(999998,999998,999998),
(999999,999999,999999);

using CVS tip, and got these oprofile results:

samples % symbol name
39742 10.1656 base_yyparse
38338 9.8065 XLogInsert
28247 7.2253 AllocSetAlloc
20490 5.2411 expression_tree_walker
16822 4.3029 ExecInitExpr
16469 4.2126 base_yylex
14789 3.7829 PageAddItem
11174 2.8582 LWLockAcquire
11167 2.8564 LWLockRelease
9195 2.3520 RewriteQuery
9120 2.3328 AllocSetFree
7788 1.9921 ExecInitValuesScan
7596 1.9430 ExecEvalConst
7586 1.9404 lappend
6860 1.7547 ValuesNext
6261 1.6015 heap_fill_tuple
6141 1.5708 MemoryContextAllocZeroAligned
5619 1.4373 fix_expr_references_walker
5613 1.4357 transformExpressionList
5269 1.3478 heap_insert
5177 1.3242 contain_vars_of_level_walker
4601 1.1769 heap_form_tuple
4345 1.1114 ExecutorRun
4299 1.0996 hash_any
4201 1.0746 MemoryContextAlloc
4061 1.0388 check_stack_depth

It's slightly depressing that there's not more time being spent in
places we can easily tweak, but anyway the salient point to me is
that AllocSetFree is already chewing a nontrivial part of the runtime.

regards, tom lane

#89Joe Conway
mail@joeconway.com
In reply to: Tom Lane (#88)
Re: Values list-of-targetlists patch for comments (was Re:

Tom Lane wrote:

Joe Conway <mail@joeconway.com> writes:

This patch retains the memory consumption savings but doesn't break any
regression tests...

I'm unconvinced that retail pfree's are the way to go. I just did some
profiling of this test case:

<snip>

It's slightly depressing that there's not more time being spent in
places we can easily tweak, but anyway the salient point to me is
that AllocSetFree is already chewing a nontrivial part of the runtime.

That's undoubtedly true, and important for the case that isn't memory
constrained (but where I'm already seeing us perform relatively well).
But once we start the machine swapping, runtime goes in the toilet. And
without addressing the memory leak somehow, we will start a machine
swapping significantly earlier than mysql.

Joe

#90Tom Lane
tgl@sss.pgh.pa.us
In reply to: Bruce Momjian (#87)
Re: Values list-of-targetlists patch for comments (was Re:

Bruce Momjian <bruce@momjian.us> writes:

Michael Glaesemann wrote:

Would it make sense to add a HINT as well, recommending the UNION
construct Tom mentioned earlier?

Agreed.

Done.

regards, tom lane

#91Tom Lane
tgl@sss.pgh.pa.us
In reply to: Joe Conway (#89)
Re: Values list-of-targetlists patch for comments (was Re:

Joe Conway <mail@joeconway.com> writes:

That's undoubtedly true, and important for the case that isn't memory
constrained (but where I'm already seeing us perform relatively well).
But once we start the machine swapping, runtime goes in the toilet. And
without addressing the memory leak somehow, we will start a machine
swapping significantly earlier than mysql.

I'm not arguing that we don't need to work on the memory usage ... just
that I'm not very happy with that particular approach.

I wonder whether there is any reasonable way to determine which data
structures are responsible for how much space ... in my test I'm seeing

MessageContext: 822075440 total in 104 blocks; 4510280 free (1 chunks); 817565160 used
ExecutorState: 8024624 total in 3 blocks; 20592 free (12 chunks); 8004032 used

so it seems mostly not the executor's fault, but that's not much to go
on.

regards, tom lane

#92Joe Conway
mail@joeconway.com
In reply to: Tom Lane (#91)
Re: Values list-of-targetlists patch for comments (was Re:

Tom Lane wrote:

I wonder whether there is any reasonable way to determine which data
structures are responsible for how much space ... in my test I'm seeing

MessageContext: 822075440 total in 104 blocks; 4510280 free (1 chunks); 817565160 used
ExecutorState: 8024624 total in 3 blocks; 20592 free (12 chunks); 8004032 used

so it seems mostly not the executor's fault, but that's not much to go
on.

I was doing it by sprinkling MemoryContextStats() in various places.
I'll spend some time again later today and see if I can narrow it down
to specific data structures using that. It shouldn't be too hard -- the
patch I sent last night only pfrees a few structures, and they represent
the bulk of what we need to clean up.

Joe

#93Tom Lane
tgl@sss.pgh.pa.us
In reply to: Joe Conway (#92)
Re: Values list-of-targetlists patch for comments (was Re:

Joe Conway <mail@joeconway.com> writes:

Tom Lane wrote:

I wonder whether there is any reasonable way to determine which data
structures are responsible for how much space ... in my test I'm seeing

I was doing it by sprinkling MemoryContextStats() in various places.

Yeah, I've just been doing that and some hand analysis too. What I get
(on a 64-bit machine) is that essentially all the space goes into

lists of A_Const lists: 320000000
lists of Const lists: 320000000
transformInsertRow extra lists: 144000000

I think we could safely list_free the input list in transformInsertRow
as your patch suggests, which would buy back the 144M part. But I don't
believe it's safe at all to free the raw_parser output --- the grammar
sometimes makes multiple links to the same subtree, eg in BETWEEN.
In any case the patch as proposed wouldn't catch all the detritus for
any case more complicated than a simple integer constant.

The way that the list memory usage works (again, 64-bit machine) is

sizeof(List) = 24
sizeof(ListCell) = 16
sizeof(A_Const) = 32

Each of these nodes will have 16 bytes palloc overhead, and the List
header will be rounded up to 32 bytes as well, so we have total space
for a 3-element integer list of
32+16 + (16+16 + 32+16) * 3
Add in 16+16 for the associated ListCell of the top list-of-lists,
and you come to 320 bytes per sublist. Const happens to also be
32 bytes so the transformed lists are the same size.

It's interesting to reflect on the fact that this comes to 184 bytes
of useful data and 136 bytes of palloc overhead per row ... not sure
if we can do much about the overhead though.

regards, tom lane

#94Joe Conway
mail@joeconway.com
In reply to: Tom Lane (#93)
Re: Values list-of-targetlists patch for comments (was Re:

Tom Lane wrote:

Yeah, I've just been doing that and some hand analysis too. What I get
(on a 64-bit machine) is that essentially all the space goes into

lists of A_Const lists: 320000000
lists of Const lists: 320000000
transformInsertRow extra lists: 144000000

I think we could safely list_free the input list in transformInsertRow
as your patch suggests, which would buy back the 144M part. But I don't
believe it's safe at all to free the raw_parser output --- the grammar
sometimes makes multiple links to the same subtree, eg in BETWEEN.
In any case the patch as proposed wouldn't catch all the detritus for
any case more complicated than a simple integer constant.

:-(

The way that the list memory usage works (again, 64-bit machine) is

sizeof(List) = 24
sizeof(ListCell) = 16
sizeof(A_Const) = 32

Each of these nodes will have 16 bytes palloc overhead, and the List
header will be rounded up to 32 bytes as well, so we have total space
for a 3-element integer list of
32+16 + (16+16 + 32+16) * 3
Add in 16+16 for the associated ListCell of the top list-of-lists,
and you come to 320 bytes per sublist. Const happens to also be
32 bytes so the transformed lists are the same size.

What if we built an array of A_Const nodes instead of a List? Maybe we
could use something akin to appendStringInfo()/enlargeStringInfo() to
build the array of nodes and enlarge it in chunks.

Joe

#95Alvaro Herrera
alvherre@commandprompt.com
In reply to: Joe Conway (#94)
Re: Values list-of-targetlists patch for comments (was Re:

Joe Conway wrote:

What if we built an array of A_Const nodes instead of a List? Maybe we
could use something akin to appendStringInfo()/enlargeStringInfo() to
build the array of nodes and enlarge it in chunks.

In inval.c you find this:

/*
* To minimize palloc traffic, we keep pending requests in successively-
* larger chunks (a slightly more sophisticated version of an expansible
* array). All request types can be stored as SharedInvalidationMessage
* records. The ordering of requests within a list is never significant.
*/
typedef struct InvalidationChunk
{
struct InvalidationChunk *next; /* list link */
int nitems; /* # items currently stored in chunk */
int maxitems; /* size of allocated array in this chunk */
SharedInvalidationMessage msgs[1]; /* VARIABLE LENGTH ARRAY */
} InvalidationChunk; /* VARIABLE LENGTH STRUCTURE */

Which might give you an idea ...

--
Alvaro Herrera http://www.CommandPrompt.com/
The PostgreSQL Company - Command Prompt, Inc.

#96Tom Lane
tgl@sss.pgh.pa.us
In reply to: Joe Conway (#94)
Re: Values list-of-targetlists patch for comments (was Re:

Joe Conway <mail@joeconway.com> writes:

What if we built an array of A_Const nodes instead of a List? Maybe we
could use something akin to appendStringInfo()/enlargeStringInfo() to
build the array of nodes and enlarge it in chunks.

For lists this short I'm not sure how much of a win it'd be. It's
interesting though to think about doing something like that within the
List abstraction itself. We did a "fastlist" hack once before and it
was a crock ... don't want to do that again. But now that we've got a
distinction between List and ListCell you could imagine that a List
header has a small private array of ListCells ... tuning the size might
be tricky though.

Another thing we could consider is flattening the double-level list into
a single list ... probably be a pain notationally, but it'd save one
List header and one ListCell per VALUES sublist. And it would offer
more traction for an array-inside-Lists optimization.

regards, tom lane

#97Joe Conway
mail@joeconway.com
In reply to: Tom Lane (#93)
VALUES clause memory optimization (was: Values list-of-targetlists patch...)

Tom Lane wrote:

I think we could safely list_free the input list in transformInsertRow
as your patch suggests, which would buy back the 144M part. But I don't
believe it's safe at all to free the raw_parser output --- the grammar
sometimes makes multiple links to the same subtree, eg in BETWEEN.

In transformExpr the comment implies that it should be safe to reapply
to an already transformed expression. What if we free the raw_parser
expression list/cells/nodes and replace it with the as-transformed one?

Joe

#98Gavin Sherry
swm@linuxworld.com.au
In reply to: Joe Conway (#75)
1 attachment(s)
Re: Values list-of-targetlists patch for comments (was Re:

Docs and regression tests attached.

One slightly annoying thing is this:

---
regression=# declare foo cursor with hold for VALUES(1,2), (3, 4);
DECLARE CURSOR
regression=# declare foo2 cursor with hold for (VALUES(1,2), (3, 4)) as
foo(i, j);
ERROR: syntax error at or near "as"
LINE 1: ...e foo2 cursor with hold for (VALUES(1,2), (3, 4)) as foo(i, ...
---

Now, we can just rewrite the second query as:

---
declare foo2 cursor with hold for select * from (VALUES(1,2), (3, 4)) as
foo(i, j);
---

but it's not immediately obvious. Not worth busting up the grammar for it,
though. And, it's not spec.

Gavin

Attachments:

values_doc_test.difftext/plain; CHARSET=US-ASCII; NAME=values_doc_test.diffDownload
Index: doc/src/sgml/ref/declare.sgml
===================================================================
RCS file: /usr/local/cvsroot/pgsql/doc/src/sgml/ref/declare.sgml,v
retrieving revision 1.37
diff -c -p -r1.37 declare.sgml
*** doc/src/sgml/ref/declare.sgml	26 Feb 2006 03:20:46 -0000	1.37
--- doc/src/sgml/ref/declare.sgml	3 Aug 2006 04:18:28 -0000
*************** DECLARE liahona CURSOR FOR SELECT * FROM
*** 275,280 ****
--- 275,288 ----
     See <xref linkend="sql-fetch" endterm="sql-fetch-title"> for more
     examples of cursor usage.
    </para>
+ 
+   <para>
+    The cursor <replaceable class="parameter">query</> clause can also
+    be a <literal>VALUES</> list:
+ <programlisting>
+ DECLARE cols CURSOR FOR VALUES(1,2), (3,4);
+ </programlisting>
+   </para>
   </refsect1>
  
   <refsect1>
Index: doc/src/sgml/ref/delete.sgml
===================================================================
RCS file: /usr/local/cvsroot/pgsql/doc/src/sgml/ref/delete.sgml,v
retrieving revision 1.26
diff -c -p -r1.26 delete.sgml
*** doc/src/sgml/ref/delete.sgml	22 Jan 2006 05:20:33 -0000	1.26
--- doc/src/sgml/ref/delete.sgml	3 Aug 2006 03:26:58 -0000
*************** DELETE FROM [ ONLY ] <replaceable class=
*** 117,122 ****
--- 117,128 ----
        in the <replaceable class="PARAMETER">usinglist</replaceable>,
        unless you wish to set up a self-join.
       </para>
+ 
+      <para>
+       The <replaceable class="PARAMETER">usinglist</> may also contain a
+       <literal>VALUES</> list, evaluating to one or more rows. These
+       rows may also be referenced in the <literal>WHERE</> clause.
+ 	 </para>
      </listitem>
     </varlistentry>
  
*************** DELETE FROM films WHERE kind &lt;&gt; 'M
*** 191,196 ****
--- 197,213 ----
  DELETE FROM films;
  </programlisting>      
    </para>
+ 
+   <para>
+    Delete films made after 1990 which are 'Horror' and films made
+    after 2000 which are 'Crime'. To do this, we use a <literal>VALUES</>
+    list in the <literal>USING</> clause.
+ <programlisting>
+ DELETE FROM films USING (VALUES('1990-01-01, 'Horror'), ('2000-01-01', 'Crime))
+     AS det (year, kind) WHERE films.date_prod >= det.year AND
+     films.kind = det.kind;
+ </programlisting>
+   </para>
   </refsect1>
  
   <refsect1>
Index: doc/src/sgml/ref/insert.sgml
===================================================================
RCS file: /usr/local/cvsroot/pgsql/doc/src/sgml/ref/insert.sgml,v
retrieving revision 1.30
diff -c -p -r1.30 insert.sgml
*** doc/src/sgml/ref/insert.sgml	17 Nov 2005 22:14:51 -0000	1.30
--- doc/src/sgml/ref/insert.sgml	2 Aug 2006 22:40:14 -0000
*************** PostgreSQL documentation
*** 21,27 ****
   <refsynopsisdiv>
  <synopsis>
  INSERT INTO <replaceable class="PARAMETER">table</replaceable> [ ( <replaceable class="PARAMETER">column</replaceable> [, ...] ) ]
!     { DEFAULT VALUES | VALUES ( { <replaceable class="PARAMETER">expression</replaceable> | DEFAULT } [, ...] ) | <replaceable class="PARAMETER">query</replaceable> }
  </synopsis>
   </refsynopsisdiv>
  
--- 21,27 ----
   <refsynopsisdiv>
  <synopsis>
  INSERT INTO <replaceable class="PARAMETER">table</replaceable> [ ( <replaceable class="PARAMETER">column</replaceable> [, ...] ) ]
!     { DEFAULT VALUES | VALUES ( { <replaceable class="PARAMETER">expression</replaceable> | DEFAULT } [, ...] ) [, ( ... ) ] | <replaceable class="PARAMETER">query</replaceable> }
  </synopsis>
   </refsynopsisdiv>
  
*************** INSERT INTO <replaceable class="PARAMETE
*** 30,37 ****
  
    <para>
     <command>INSERT</command> inserts new rows into a table.
!    One can insert a single row specified by value expressions,
!    or several rows as a result of a query.
    </para>
  
    <para>
--- 30,37 ----
  
    <para>
     <command>INSERT</command> inserts new rows into a table.
!    One can insert one or more rows specified by value expressions,
!    or zero or more rows resulting from a query.
    </para>
  
    <para>
*************** INSERT INTO films VALUES
*** 162,167 ****
--- 162,177 ----
    </para>
  
    <para>
+    Insert multiple rows into a table <literal>films</>:
+ 
+ <programlisting>
+ INSERT INTO films VALUES
+ 	('B6717', 'Tampopo', 110, '1985-02-10', 'Comedy'),
+ 	('HG120', 'The Dinner Game', 140, '1998-10-12', 'Comedy');
+ </programlisting>
+   </para>
+ 
+   <para>
     In this example, the <literal>len</literal> column is
     omitted and therefore it will have the default value:
  
Index: doc/src/sgml/ref/select.sgml
===================================================================
RCS file: /usr/local/cvsroot/pgsql/doc/src/sgml/ref/select.sgml,v
retrieving revision 1.91
diff -c -p -r1.91 select.sgml
*** doc/src/sgml/ref/select.sgml	30 Apr 2006 18:30:38 -0000	1.91
--- doc/src/sgml/ref/select.sgml	2 Aug 2006 22:40:12 -0000
*************** SELECT [ ALL | DISTINCT [ ON ( <replacea
*** 35,40 ****
--- 35,41 ----
  where <replaceable class="parameter">from_item</replaceable> can be one of:
  
      [ ONLY ] <replaceable class="parameter">table_name</replaceable> [ * ] [ [ AS ] <replaceable class="parameter">alias</replaceable> [ ( <replaceable class="parameter">column_alias</replaceable> [, ...] ) ] ]
+     ( VALUES ( <replaceable class="parameter">expression</replaceable> [, ... ] ) [, ( ... ) ] [ AS ] <replaceable class="parameter">alias</replaceable> [ ( <replaceable class="parameter">column_alias</replaceable> [, ...] ) ]
      ( <replaceable class="parameter">select</replaceable> ) [ AS ] <replaceable class="parameter">alias</replaceable> [ ( <replaceable class="parameter">column_alias</replaceable> [, ...] ) ]
      <replaceable class="parameter">function_name</replaceable> ( [ <replaceable class="parameter">argument</replaceable> [, ...] ] ) [ AS ] <replaceable class="parameter">alias</replaceable> [ ( <replaceable class="parameter">column_alias</replaceable> [, ...] | <replaceable class="parameter">column_definition</replaceable> [, ...] ) ]
      <replaceable class="parameter">function_name</replaceable> ( [ <replaceable class="parameter">argument</replaceable> [, ...] ] ) AS ( <replaceable class="parameter">column_definition</replaceable> [, ...] )
*************** where <replaceable class="parameter">fro
*** 197,202 ****
--- 198,214 ----
         </para>
        </listitem>
       </varlistentry>
+ 
+      <varlistentry>
+       <term><literal>VALUES(<replaceable class="parameter">expression</replaceable> [, ...]) [, ...]</literal></term>
+       <listitem>
+        <para>
+         One or more rows may be constructed in the from clause. Each
+         <replaceable class="parameter">expression</> will be evaluated and
+         assigned to the corresponding column.
+        </para>
+       </listitem>
+      </varlistentry>
       
       <varlistentry>
        <term><replaceable class="parameter">alias</replaceable></term>
*************** SELECT f.title, f.did, d.name, f.date_pr
*** 916,921 ****
--- 928,947 ----
    </para>
  
    <para>
+    To join the table <literal>films</> with a <literal>VALUES</> list:
+ <programlisting>
+ SELECT f.title, f.did, f.date_prod, f.kind
+     FROM films f, (VALUES('Horror'), ('Sci-Fi')) as k (kind)
+     WHERE f.kind = k.kind;
+             title             | did | date_prod  |  kind
+ ------------------------------+-----+------------+--------
+  The Texas Chain Saw Massacre | 190 | 1974-06-11 | Horror
+  2001: A Space Odyssey        | 210 | 1968-08-24 | Sci-Fi
+  ...
+ </programlisting>
+   </para>
+ 
+   <para>
     To sum the column <literal>len</literal> of all films and group
     the results by <literal>kind</literal>:
  
Index: doc/src/sgml/ref/update.sgml
===================================================================
RCS file: /usr/local/cvsroot/pgsql/doc/src/sgml/ref/update.sgml,v
retrieving revision 1.37
diff -c -p -r1.37 update.sgml
*** doc/src/sgml/ref/update.sgml	8 Mar 2006 22:59:09 -0000	1.37
--- doc/src/sgml/ref/update.sgml	3 Aug 2006 03:27:07 -0000
*************** UPDATE [ ONLY ] <replaceable class="PARA
*** 134,139 ****
--- 134,145 ----
        <replaceable>fromlist</>, unless you intend a self-join (in which
        case it must appear with an alias in the <replaceable>fromlist</>).
       </para>
+ 
+ 	 <para>
+ 	  The <replaceable class="PARAMETER">from_list</> may also contain a
+ 	  <literal>VALUES</> list, evaluating to one or more rows. These
+ 	  rows may also be referenced in the <literal>WHERE</> clause.
+      </para>
      </listitem>
     </varlistentry>
  
*************** UPDATE employees SET sales_count = sales
*** 233,238 ****
--- 239,255 ----
    </para>
  
    <para>
+    Perform an update on <literal>employees</> with a join against a 
+    <literal>VALUES</> list:
+ <programlisting>
+ UPDATE employees SET salary = salary * increase
+    FROM (VALUES(1, 200000, 1.2), (2, 400000, 1.4)) 
+    as prof (depno, target, increase)
+    WHERE employees.sales &gt;= prof.target and employees.depno = prof.depno;
+ </programlisting>
+   </para>
+ 
+   <para>
     Attempt to insert a new stock item along with the quantity of stock. If
     the item already exists, instead update the stock count of the existing
     item. To do this without failing the entire transaction, use savepoints.
Index: src/test/regress/sql/insert.sql
===================================================================
RCS file: /usr/local/cvsroot/pgsql/src/test/regress/sql/insert.sql,v
retrieving revision 1.2
diff -c -p -r1.2 insert.sql
*** src/test/regress/sql/insert.sql	24 Apr 2002 02:22:54 -0000	1.2
--- src/test/regress/sql/insert.sql	3 Aug 2006 05:13:57 -0000
*************** insert into inserttest (col1, col2, col3
*** 18,22 ****
--- 18,29 ----
  insert into inserttest (col1) values (1, 2);
  insert into inserttest (col1) values (DEFAULT, DEFAULT);
  
+ --
+ -- VALUES test
+ --
+ 
+ insert into inserttest values(10, 20, '40'), (-1, 2, DEFAULT),
+ 	((select 2), (select i from (values(3)) as foo (i)), 'values are fun!');
+ 
  select * from inserttest;
  drop table inserttest;
Index: src/test/regress/sql/select.sql
===================================================================
RCS file: /usr/local/cvsroot/pgsql/src/test/regress/sql/select.sql,v
retrieving revision 1.10
diff -c -p -r1.10 select.sql
*** src/test/regress/sql/select.sql	14 Dec 2005 16:28:32 -0000	1.10
--- src/test/regress/sql/select.sql	3 Aug 2006 05:04:15 -0000
*************** SELECT p.name, p.age FROM person* p ORDE
*** 110,112 ****
--- 110,125 ----
  select foo from (select 1) as foo;
  select foo from (select null) as foo;
  select foo from (select 'xyzzy',1,null) as foo;
+ 
+ --
+ -- Test VALUES lists
+ --
+ select * from onek, (values(147, 'RFAAAA'), (931, 'VJAAAA')) as v (i, j) WHERE
+ 	onek.unique1 = v.i and onek.stringu1 = v.j;
+ 
+ -- a more complex case
+ -- looks like we're coding lisp :-)
+ select * from onek, (values((select i from 
+ 	(values(10000), (2), (389), (1000), (2000), ((select 10029))) as foo(i)
+ 	order by i asc limit 1))) bar (i)
+ 	where onek.unique1 = bar.i;
Index: src/test/regress/sql/update.sql
===================================================================
RCS file: /usr/local/cvsroot/pgsql/src/test/regress/sql/update.sql,v
retrieving revision 1.3
diff -c -p -r1.3 update.sql
*** src/test/regress/sql/update.sql	22 Jan 2006 05:20:35 -0000	1.3
--- src/test/regress/sql/update.sql	3 Aug 2006 04:32:03 -0000
*************** SELECT * FROM update_test;
*** 23,28 ****
--- 23,35 ----
  
  UPDATE update_test t SET b = t.b + 10 WHERE t.a = 10;
  
+ --
+ -- Test VALUES in FROM
+ --
+ 
+ UPDATE update_test SET a=v.i FROM (VALUES(100, 20)) AS v(i, j)
+ 	WHERE update_test.b = v.j;
+ 
  SELECT * FROM update_test;
  
  -- if an alias for the target table is specified, don't allow references
*************** SET LOCAL add_missing_from = false;
*** 32,35 ****
--- 39,43 ----
  UPDATE update_test AS t SET b = update_test.b + 10 WHERE t.a = 10;
  ROLLBACK;
  
+ 
  DROP TABLE update_test;
Index: src/test/regress/expected/insert.out
===================================================================
RCS file: /usr/local/cvsroot/pgsql/src/test/regress/expected/insert.out,v
retrieving revision 1.7
diff -c -p -r1.7 insert.out
*** src/test/regress/expected/insert.out	25 Sep 2003 06:58:06 -0000	1.7
--- src/test/regress/expected/insert.out	3 Aug 2006 05:19:01 -0000
*************** insert into inserttest (col1) values (1,
*** 28,40 ****
  ERROR:  INSERT has more expressions than target columns
  insert into inserttest (col1) values (DEFAULT, DEFAULT);
  ERROR:  INSERT has more expressions than target columns
  select * from inserttest;
   col1 | col2 |  col3   
! ------+------+---------
        |    3 | testing
        |    5 | testing
        |    5 | test
        |    7 | testing
! (4 rows)
  
  drop table inserttest;
--- 28,48 ----
  ERROR:  INSERT has more expressions than target columns
  insert into inserttest (col1) values (DEFAULT, DEFAULT);
  ERROR:  INSERT has more expressions than target columns
+ --
+ -- VALUES test
+ --
+ insert into inserttest values(10, 20, '40'), (-1, 2, DEFAULT),
+ 	((select 2), (select i from (values(3)) as foo (i)), 'values are fun!');
  select * from inserttest;
   col1 | col2 |  col3   
! ------+------+-----------------
        |    3 | testing
        |    5 | testing
        |    5 | test
        |    7 | testing
!    10 |   20 | 40
!    -1 |    2 | testing
!     2 |    3 | values are fun!
! (7 rows)
  
  drop table inserttest;
Index: src/test/regress/expected/select.out
===================================================================
RCS file: /usr/local/cvsroot/pgsql/src/test/regress/expected/select.out,v
retrieving revision 1.14
diff -c -p -r1.14 select.out
*** src/test/regress/expected/select.out	14 Dec 2005 16:28:32 -0000	1.14
--- src/test/regress/expected/select.out	3 Aug 2006 04:50:36 -0000
*************** select foo from (select 'xyzzy',1,null) 
*** 452,454 ****
--- 452,476 ----
   (xyzzy,1,)
  (1 row)
  
+ --
+ -- Test VALUES lists
+ --
+ select * from onek, (values(147, 'RFAAAA'), (931, 'VJAAAA')) as v (i, j) WHERE
+ 	onek.unique1 = v.i and onek.stringu1 = v.j;
+  unique1 | unique2 | two | four | ten | twenty | hundred | thousand | twothousand | fivethous | tenthous | odd | even | stringu1 | stringu2 | string4 |  i  |   j    
+ ---------+---------+-----+------+-----+--------+---------+----------+-------------+-----------+----------+-----+------+----------+----------+---------+-----+--------
+      147 |       0 |   1 |    3 |   7 |      7 |       7 |       47 |         147 |       147 |      147 |  14 |   15 | RFAAAA   | AAAAAA   | AAAAxx  | 147 | RFAAAA
+      931 |       1 |   1 |    3 |   1 |     11 |       1 |       31 |         131 |       431 |      931 |   2 |    3 | VJAAAA   | BAAAAA   | HHHHxx  | 931 | VJAAAA
+ (2 rows)
+ 
+ -- a more complex case
+ -- looks like we're coding lisp :-)
+ select * from onek, (values((select i from 
+ 	(values(10000), (2), (389), (1000), (2000), ((select 10029))) as foo(i)
+ 	order by i asc limit 1))) bar (i)
+ 	where onek.unique1 = bar.i;
+  unique1 | unique2 | two | four | ten | twenty | hundred | thousand | twothousand | fivethous | tenthous | odd | even | stringu1 | stringu2 | string4 | i 
+ ---------+---------+-----+------+-----+--------+---------+----------+-------------+-----------+----------+-----+------+----------+----------+---------+---
+        2 |     326 |   0 |    2 |   2 |      2 |       2 |        2 |           2 |         2 |        2 |   4 |    5 | CAAAAA   | OMAAAA   | OOOOxx  | 2
+ (1 row)
+ 
Index: src/test/regress/expected/update.out
===================================================================
RCS file: /usr/local/cvsroot/pgsql/src/test/regress/expected/update.out,v
retrieving revision 1.3
diff -c -p -r1.3 update.out
*** src/test/regress/expected/update.out	14 Mar 2006 22:48:25 -0000	1.3
--- src/test/regress/expected/update.out	3 Aug 2006 04:50:48 -0000
*************** SELECT * FROM update_test;
*** 32,42 ****
  (2 rows)
  
  UPDATE update_test t SET b = t.b + 10 WHERE t.a = 10;
  SELECT * FROM update_test;
   a  | b  
! ----+----
!  10 | 20
!  10 | 20
  (2 rows)
  
  -- if an alias for the target table is specified, don't allow references
--- 32,47 ----
  (2 rows)
  
  UPDATE update_test t SET b = t.b + 10 WHERE t.a = 10;
+ --
+ -- Test VALUES in FROM
+ --
+ UPDATE update_test SET a=v.i FROM (VALUES(100, 20)) AS v(i, j)
+ 	WHERE update_test.b = v.j;
  SELECT * FROM update_test;
   a  | b  
! -----+----
!  100 | 20
!  100 | 20
  (2 rows)
  
  -- if an alias for the target table is specified, don't allow references
#99Tom Lane
tgl@sss.pgh.pa.us
In reply to: Joe Conway (#97)
Re: VALUES clause memory optimization (was: Values list-of-targetlists patch...)

Joe Conway <mail@joeconway.com> writes:

In transformExpr the comment implies that it should be safe to reapply
to an already transformed expression. What if we free the raw_parser
expression list/cells/nodes and replace it with the as-transformed one?

How are you going to do the "replace" bit? The entire problem is that
you don't know where are all the down-links leading to the subexpression
you are currently working on.

The reason we could safely list_free inside transformInsertRow is that
we know all its callers have just built the passed-in list and so there
are no other pointers to it. That doesn't apply in the general case of
grammar output.

I think in the long run we probably ought to fix things so that the
grammar never outputs any multiply-linked trees; that little shortcut
has been a continuing source of grief for many reasons. I can't see
doing that for 8.2 though. My advice is to get that low-hanging fruit
in transformInsertRow and leave the other ideas for 8.3.

regards, tom lane

#100Tom Lane
tgl@sss.pgh.pa.us
In reply to: Gavin Sherry (#98)
Re: Values list-of-targetlists patch for comments (was Re: [PATCHES]

Gavin Sherry <swm@linuxworld.com.au> writes:

Docs and regression tests attached.

I've applied the regression tests (with a few additions), but I'm
feeling dissatisfied with this approach to documenting VALUES.
It seems to be mostly missing the point about VALUES being usable
whereever SELECT is. I'm not at all sure what I'd do instead though.
Should we give VALUES its own reference page? That doesn't quite
seem helpful either. cc'ing to pgsql-docs for ideas.

regards, tom lane

#101Michael Glaesemann
grzm@seespotcode.net
In reply to: Tom Lane (#100)
Re: Values list-of-targetlists patch for comments (was Re: [PATCHES]

On Aug 3, 2006, at 23:58 , Tom Lane wrote:

Should we give VALUES its own reference page? That doesn't quite
seem helpful either.

I think we should go for a separate reference page, as VALUES appears
to be expanding quite a bit. Up till now I've thought of VALUES only
in conjunction with UPDATE, so perhaps a useful alternative would be
to keep all of the information regarding VALUES and its syntax would
be as a large part of the UPDATE reference page, though that would
imply by placement (even if explained otherwise) that VALUES is only
a part of the UPDATE syntax, which it no longer (?) is. That brings
me back to the idea of VALUES deserving its own reference page.

I wonder how soon pretty much the entire SQL spec will be duplicated
in the PostgreSQL documentation. :)

Michael Glaesemann
grzm seespotcode net

#102Peter Eisentraut
peter_e@gmx.net
In reply to: Tom Lane (#100)
Re: Values list-of-targetlists patch for comments (was Re: [PATCHES]

Tom Lane wrote:

Should we give VALUES its own reference page? That doesn't quite
seem helpful either. cc'ing to pgsql-docs for ideas.

This is probably the sort of thing that should be explained part II "The
SQL Language". In particular, section 7.2 is about table expressions,
which this is either a case of or related to.

A few examples on the command references pages to show how it can be
useful are probably OK, but the big picture shoulbd be developed in
chapter 7 or so.

--
Peter Eisentraut
http://developer.postgresql.org/~petere/

#103Joe Conway
mail@joeconway.com
In reply to: Peter Eisentraut (#102)
Re: Values list-of-targetlists patch for comments (was Re:

Peter Eisentraut wrote:

Tom Lane wrote:

Should we give VALUES its own reference page? That doesn't quite
seem helpful either. cc'ing to pgsql-docs for ideas.

This is probably the sort of thing that should be explained part II "The
SQL Language". In particular, section 7.2 is about table expressions,
which this is either a case of or related to.

A few examples on the command references pages to show how it can be
useful are probably OK, but the big picture shoulbd be developed in
chapter 7 or so.

I'll need some time (perhaps a few weeks because I'm just starting to do
business travel again), but I'll take responsibility to write something
up if you'd like.

Joe

#104Gavin Sherry
swm@linuxworld.com.au
In reply to: Joe Conway (#103)
Re: Values list-of-targetlists patch for comments (was Re:

On Thu, 3 Aug 2006, Joe Conway wrote:

Peter Eisentraut wrote:

Tom Lane wrote:

Should we give VALUES its own reference page? That doesn't quite
seem helpful either. cc'ing to pgsql-docs for ideas.

This is probably the sort of thing that should be explained part II "The
SQL Language". In particular, section 7.2 is about table expressions,
which this is either a case of or related to.

A few examples on the command references pages to show how it can be
useful are probably OK, but the big picture shoulbd be developed in
chapter 7 or so.

I'll need some time (perhaps a few weeks because I'm just starting to do
business travel again), but I'll take responsibility to write something
up if you'd like.

I'm happy to finish what I started.

Gavin

#105Gavin Sherry
swm@linuxworld.com.au
In reply to: Tom Lane (#100)
Re: Values list-of-targetlists patch for comments (was Re: [PATCHES]

On Thu, 3 Aug 2006, Tom Lane wrote:

Gavin Sherry <swm@linuxworld.com.au> writes:

Docs and regression tests attached.

I've applied the regression tests (with a few additions), but I'm
feeling dissatisfied with this approach to documenting VALUES.
It seems to be mostly missing the point about VALUES being usable
whereever SELECT is. I'm not at all sure what I'd do instead though.
Should we give VALUES its own reference page? That doesn't quite
seem helpful either. cc'ing to pgsql-docs for ideas.

Good point. One question: are we happy calling this a 'VALUES list'? It's
better than a 'table value constructor'. I took the lead from a comment in the
source.

Thanks,

gavin

#106Gavin Sherry
swm@linuxworld.com.au
In reply to: Michael Glaesemann (#101)
Re: Values list-of-targetlists patch for comments (was Re:

On Fri, 4 Aug 2006, Michael Glaesemann wrote:

On Aug 3, 2006, at 23:58 , Tom Lane wrote:

Should we give VALUES its own reference page? That doesn't quite
seem helpful either.

I think we should go for a separate reference page, as VALUES appears
to be expanding quite a bit. Up till now I've thought of VALUES only
in conjunction with UPDATE, so perhaps a useful alternative would be
to keep all of the information regarding VALUES and its syntax would
be as a large part of the UPDATE reference page, though that would
imply by placement (even if explained otherwise) that VALUES is only
a part of the UPDATE syntax, which it no longer (?) is. That brings
me back to the idea of VALUES deserving its own reference page.

... with update? I associate it very closely with INSERT. After all,
INSERT is the only statement where we've had VALUES as part of the
grammar.

Thanks,

Gavin

#107Gavin Sherry
swm@linuxworld.com.au
In reply to: Peter Eisentraut (#102)
Re: Values list-of-targetlists patch for comments (was Re:

On Thu, 3 Aug 2006, Peter Eisentraut wrote:

Tom Lane wrote:

Should we give VALUES its own reference page? That doesn't quite
seem helpful either. cc'ing to pgsql-docs for ideas.

This is probably the sort of thing that should be explained part II "The
SQL Language". In particular, section 7.2 is about table expressions,
which this is either a case of or related to.

Yes, good idea.

A few examples on the command references pages to show how it can be
useful are probably OK, but the big picture shoulbd be developed in
chapter 7 or so.

What do we want to do about documenting:

regression=# values(1);
column1
---------
1
(1 row)

It seems to me that if this isn't in the command reference we'll see an
email every few months say 'is this an undocumented feature?'. We can
cover it easily in Part II, 7.2 but people wont look there. Then again, it
just doesn't seem right to put it in the command reference as a 'top
level' command.

Gavin

#108Michael Glaesemann
grzm@seespotcode.net
In reply to: Gavin Sherry (#106)
Re: Values list-of-targetlists patch for comments (was Re: [PATCHES]

On Aug 4, 2006, at 9:42 , Gavin Sherry wrote:

... with update? I associate it very closely with INSERT. After all,
INSERT is the only statement where we've had VALUES as part of the
grammar.

Of course! Thanks for catching the glitch. I must have a bad RAM chip.

Michael Glaesemann
grzm seespotcode net

#109Peter Eisentraut
peter_e@gmx.net
In reply to: Gavin Sherry (#107)
Re: Values list-of-targetlists patch for comments (was Re: [PATCHES]

Gavin Sherry wrote:

What do we want to do about documenting:

regression=# values(1);

Out of curiosity, according to what theory should that be allowed?

--
Peter Eisentraut
http://developer.postgresql.org/~petere/

#110Gavin Sherry
swm@linuxworld.com.au
In reply to: Peter Eisentraut (#109)
Re: Values list-of-targetlists patch for comments (was Re:

On Fri, 4 Aug 2006, Peter Eisentraut wrote:

Gavin Sherry wrote:

What do we want to do about documenting:

regression=# values(1);

Out of curiosity, according to what theory should that be allowed?

I asked this too. Tom pointed this out (I'd give the URL if I could find
it on archives):

--
You bet. VALUES is parallel to SELECT in the SQL grammar, so AFAICS
it should be legal anywhere you can write SELECT.

The basic productions in the spec's grammar are respectively

<query specification> ::=
SELECT [ <set quantifier> ] <select list>
<table expression>

and

<table value constructor> ::=
VALUES <row value expression list>
--

which seems to be the case from my reading of the spec.

Gavin

#111Tom Lane
tgl@sss.pgh.pa.us
In reply to: Peter Eisentraut (#109)
Re: Values list-of-targetlists patch for comments (was Re: [PATCHES]

Peter Eisentraut <peter_e@gmx.net> writes:

Gavin Sherry wrote:

What do we want to do about documenting:
regression=# values(1);

Out of curiosity, according to what theory should that be allowed?

Wrong question. SELECT (for the general case of multi-row results)
and VALUES are exactly parallel in the SQL grammar; the right question
is "according to what theory are you allowed to issue a general SELECT?"

AFAICT the SQL spec only envisions "SELECT ... INTO some-variables",
restricted to a single-row result (cf <select statement: single row>
production) as being something a client can issue directly. Every more-
complex case is apparently supposed to be handled by one-row-at-a-time
fetches from a cursor.

If you can persuade the community that they don't want SELECT in its
current form, you might be able to persuade me that VALUES shouldn't
be allowed either.

regards, tom lane

#112Tom Lane
tgl@sss.pgh.pa.us
In reply to: Gavin Sherry (#106)
Re: [PATCHES] Values list-of-targetlists patch for comments (was Re:

Gavin Sherry <swm@linuxworld.com.au> writes:

On Fri, 4 Aug 2006, Michael Glaesemann wrote:

On Aug 3, 2006, at 23:58 , Tom Lane wrote:

Should we give VALUES its own reference page? That doesn't quite
seem helpful either.

I think we should go for a separate reference page, as VALUES appears
to be expanding quite a bit.

... with update? I associate it very closely with INSERT. After all,
INSERT is the only statement where we've had VALUES as part of the
grammar.

True, but I think that's just a historical artifact. If you look at the
SQL spec, INSERT ... VALUES and INSERT ... SELECT are not distinct
constructs: they fall out of the fact that VALUES and SELECT are allowed
interchangeably.

<insert statement> ::=
INSERT INTO <table name>
<insert columns and source>

<insert columns and source> ::=
[ <left paren> <insert column list> <right paren> ]
<query expression>
| DEFAULT VALUES

<insert column list> ::= <column name list>

and when you trace down <query expression> you find the SELECT
and VALUES options entering at exactly the same place ...

I'd like to see us refactor the docs as necessary to reflect that idea.
Peter is right that this needs some discussion in syntax.sgml as well as
in the reference pages --- but I'm still not very clear on how the
presentation should go.

regards, tom lane

#113Joe Conway
mail@joeconway.com
In reply to: Tom Lane (#99)
Re: VALUES clause memory optimization

Tom Lane wrote:

The reason we could safely list_free inside transformInsertRow is that
we know all its callers have just built the passed-in list and so there
are no other pointers to it. That doesn't apply in the general case of
grammar output.

What about for the specific case of an InsertStmt? It seems that we
could at least get away with freeing the raw-expression list in that case.

In terms of freeing an entire arbitrary node, could we create a
backend/nodes/freefuncs.c file that does a recursive freeObject()
similar to the way copyObject() does in backend/nodes/copyfuncs.c?

My advice is to get that low-hanging fruit
in transformInsertRow and leave the other ideas for 8.3.

OK. This should be safe also, correct?

Thanks,

Joe

8<----------------------------------------
diff -c -r1.341 analyze.c
*** src/backend/parser/analyze.c	2 Aug 2006 01:59:46 -0000	1.341
--- src/backend/parser/analyze.c	2 Aug 2006 05:13:20 -0000
***************
*** 2191,2196 ****
--- 2196,2202 ----
   	for (i = 0; i < sublist_length; i++)
   	{
   		coltypes[i] = select_common_type(coltype_lists[i], "VALUES");
+ 		list_free(coltype_lists[i]);
   	}

newExprsLists = NIL;

#114Pavel Stehule
pavel.stehule@hotmail.com
In reply to: Gavin Sherry (#105)
Re: Values list-of-targetlists patch for comments (was Re: [PATCHES]

Good point. One question: are we happy calling this a 'VALUES list'? It's
better than a 'table value constructor'. I took the lead from a comment in
the
source.

table value constructor is name from ANSI. All people wiil find t.v.c., not
values list. I vote table value constructor.

Regards
Pavel Stehule

_________________________________________________________________
Emotikony a pozadi programu MSN Messenger ozivi vasi konverzaci.
http://messenger.msn.cz/

#115Tom Lane
tgl@sss.pgh.pa.us
In reply to: Joe Conway (#113)
Re: VALUES clause memory optimization

Joe Conway <mail@joeconway.com> writes:

What about for the specific case of an InsertStmt? It seems that we
could at least get away with freeing the raw-expression list in that case.

Not sure ... what about rules, BETWEEN, yadda yadda?

In terms of freeing an entire arbitrary node, could we create a
backend/nodes/freefuncs.c file that does a recursive freeObject()
similar to the way copyObject() does in backend/nodes/copyfuncs.c?

We got rid of freefuncs.c years ago, for good and sufficient reasons
that have not gone away. The problem is exactly that you don't know
whether any shortcuts were taken in constructing the node tree:
multiple links, pointers to constants, pointers to stuff that wasn't
supposed to be freed are all severe hazards.

My advice is to get that low-hanging fruit
in transformInsertRow and leave the other ideas for 8.3.

OK. This should be safe also, correct?

Yes, but what's your point? The case that seems worth trying to
optimize is "INSERT INTO foo VALUES ... real long list ...". Certainly
the MySQL crowd is not going to be stressing transformValuesClause,
because they don't know it exists.

$ mysql test
Reading table information for completion of table and column names
You can turn off this feature to get a quicker startup with -A

Welcome to the MySQL monitor. Commands end with ; or \g.
Your MySQL connection id is 12 to server version: 5.0.22

Type 'help;' or '\h' for help. Type '\c' to clear the buffer.

mysql> values (1),(2);
ERROR 1064 (42000): You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'values (1),(2)' at line 1
mysql> select * from (values (1),(2)) as x(y);
ERROR 1064 (42000): You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'values (1),(2)) as x(y)' at line 1
mysql> select * from foo where x in (values (1),(2));
ERROR 1064 (42000): You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near '1),(2))' at line 1
mysql>

mysql shortcomings aside, I don't really see the use-case for enormously
long VALUES lists anywhere except the bulk-data-load scenario, ie,
exactly INSERT ... VALUES. So I don't feel a need to be real tense
in transformValuesClause.

regards, tom lane

#116Peter Eisentraut
peter_e@gmx.net
In reply to: Tom Lane (#111)
Re: Values list-of-targetlists patch for comments (was Re: [PATCHES]

Tom Lane wrote:

Wrong question. SELECT (for the general case of multi-row results)
and VALUES are exactly parallel in the SQL grammar; the right
question is "according to what theory are you allowed to issue a
general SELECT?"

The "top-level" SELECT for interactive use is

<direct SQL statement> ::= <directly executable statement> <semicolon>

<directly executable statement> ::= <direct SQL data statement> | ...

<direct SQL data statement> ::= <direct select statement: multiple rows> | ...

But this actually does resolve as just VALUES (something), so nevermind.

--
Peter Eisentraut
http://developer.postgresql.org/~petere/

#117Simon Riggs
simon@2ndquadrant.com
In reply to: Tom Lane (#100)
Re: Values list-of-targetlists patch for comments (was Re:

On Thu, 2006-08-03 at 10:58 -0400, Tom Lane wrote:

Gavin Sherry <swm@linuxworld.com.au> writes:

Docs and regression tests attached.

I've applied the regression tests (with a few additions), but I'm
feeling dissatisfied with this approach to documenting VALUES.
It seems to be mostly missing the point about VALUES being usable
whereever SELECT is. I'm not at all sure what I'd do instead though.
Should we give VALUES its own reference page? That doesn't quite
seem helpful either. cc'ing to pgsql-docs for ideas.

The DB2 manual does exactly that and is not any clearer as a result,
even if it is fully normalised.

If we did that we'd need to emphasise that VALUES is more of a clause
than a new command.

--
Simon Riggs
EnterpriseDB http://www.enterprisedb.com

#118Peter Eisentraut
peter_e@gmx.net
In reply to: Tom Lane (#112)
Re: [HACKERS] [PATCHES] Values list-of-targetlists patch for comments (was Re:

Am Freitag, 4. August 2006 04:50 schrieb Tom Lane:

I'd like to see us refactor the docs as necessary to reflect that idea.
Peter is right that this needs some discussion in syntax.sgml as well as
in the reference pages --- but I'm still not very clear on how the
presentation should go.

I'm beginning to think that VALUES might be a separate command after all.

--
Peter Eisentraut
http://developer.postgresql.org/~petere/

#119David Fetter
david@fetter.org
In reply to: Peter Eisentraut (#118)
Re: [HACKERS] [PATCHES] Values list-of-targetlists patch for comments (was Re:

On Wed, Aug 09, 2006 at 03:05:02PM +0200, Peter Eisentraut wrote:

Am Freitag, 4. August 2006 04:50 schrieb Tom Lane:

I'd like to see us refactor the docs as necessary to reflect that
idea. Peter is right that this needs some discussion in
syntax.sgml as well as in the reference pages --- but I'm still
not very clear on how the presentation should go.

I'm beginning to think that VALUES might be a separate command after
all.

What's below definitely bolsters that idea :)

postgres=# VALUES(1);
column1
---------
1
(1 row)

However, there are some oddities:

postgres=# SELECT * FROM (VALUES (1,2)) AS foo(bar,baz);
bar | baz
-----+-----
1 | 2
(1 row)

postgres=# (VALUES (1,2)) AS foo(bar,baz);
ERROR: syntax error at or near "AS"
LINE 1: (VALUES (1,2)) AS foo(bar,baz);

Does the SQL standard have anything to say about assigning identifiers
both to the entire VALUES() statement and to its columns when the
VALUES() statement is by itself?

Cheers,
D
--
David Fetter <david@fetter.org> http://fetter.org/
phone: +1 415 235 3778 AIM: dfetter666
Skype: davidfetter

Remember to vote!

#120Tom Lane
tgl@sss.pgh.pa.us
In reply to: David Fetter (#119)
Re: [HACKERS] [PATCHES] Values list-of-targetlists patch for comments (was Re:

David Fetter <david@fetter.org> writes:

However, there are some oddities:
postgres=# SELECT * FROM (VALUES (1,2)) AS foo(bar,baz);
[ works ]
postgres=# (VALUES (1,2)) AS foo(bar,baz);
ERROR: syntax error at or near "AS"

This is per spec. Effectively, AS is part of the FROM-clause syntax
not part of a standalone command. You can't write this either:

regression=# (select 1,2) as foo(bar,baz);
ERROR: syntax error at or near "as"
LINE 1: (select 1,2) as foo(bar,baz);
^

regards, tom lane

#121Bruce Momjian
bruce@momjian.us
In reply to: Gavin Sherry (#107)
Re: Values list-of-targetlists patch for comments (was Re:

Gavin Sherry wrote:

A few examples on the command references pages to show how it can be
useful are probably OK, but the big picture shoulbd be developed in
chapter 7 or so.

What do we want to do about documenting:

regression=# values(1);
column1
---------
1
(1 row)

It seems to me that if this isn't in the command reference we'll see an
email every few months say 'is this an undocumented feature?'. We can
cover it easily in Part II, 7.2 but people wont look there. Then again, it
just doesn't seem right to put it in the command reference as a 'top
level' command.

How many people are going to think of doing a VALUES(1)? Isn't it just
like SELECT 1? We can try making VALUES a non-toplevel command, and if
people get confused, we can promote in the documenation. I think
starting it at top-level is perhaps confusing.

--
Bruce Momjian bruce@momjian.us
EnterpriseDB http://www.enterprisedb.com

+ If your life is a hard drive, Christ can be your backup. +

#122Michael Glaesemann
grzm@seespotcode.net
In reply to: Bruce Momjian (#121)
Re: Values list-of-targetlists patch for comments (was Re:

On Aug 11, 2006, at 12:07 , Bruce Momjian wrote:

Gavin Sherry wrote:

A few examples on the command references pages to show how it can be
useful are probably OK, but the big picture shoulbd be developed in
chapter 7 or so.

What do we want to do about documenting:

regression=# values(1);
column1
---------
1
(1 row)

It seems to me that if this isn't in the command reference we'll
see an
email every few months say 'is this an undocumented feature?'. We can
cover it easily in Part II, 7.2 but people wont look there. Then
again, it
just doesn't seem right to put it in the command reference as a 'top
level' command.

How many people are going to think of doing a VALUES(1)? Isn't it
just
like SELECT 1? We can try making VALUES a non-toplevel command,
and if
people get confused, we can promote in the documenation. I think
starting it at top-level is perhaps confusing.

Perhaps it may be confusing, but at the same time, it's educational
to put VALUES at the top level. Having not read the SQL spec in
detail, I do rely on the Postgres documentation as a quick reference.
Thanks to the high-level of SQL-spec compliance, the Postgres
documentation is pretty helpful in that way. And I'm always
pleasantly surprised when I learn something new just from looking
indices such as this.

Michael Glaesemann
grzm seespotcode net

#123Bruce Momjian
bruce@momjian.us
In reply to: Joe Conway (#113)
Re: VALUES clause memory optimization

Has this been addressed?

---------------------------------------------------------------------------

Joe Conway wrote:

Tom Lane wrote:

The reason we could safely list_free inside transformInsertRow is that
we know all its callers have just built the passed-in list and so there
are no other pointers to it. That doesn't apply in the general case of
grammar output.

What about for the specific case of an InsertStmt? It seems that we
could at least get away with freeing the raw-expression list in that case.

In terms of freeing an entire arbitrary node, could we create a
backend/nodes/freefuncs.c file that does a recursive freeObject()
similar to the way copyObject() does in backend/nodes/copyfuncs.c?

My advice is to get that low-hanging fruit
in transformInsertRow and leave the other ideas for 8.3.

OK. This should be safe also, correct?

Thanks,

Joe

8<----------------------------------------
diff -c -r1.341 analyze.c
*** src/backend/parser/analyze.c	2 Aug 2006 01:59:46 -0000	1.341
--- src/backend/parser/analyze.c	2 Aug 2006 05:13:20 -0000
***************
*** 2191,2196 ****
--- 2196,2202 ----
for (i = 0; i < sublist_length; i++)
{
coltypes[i] = select_common_type(coltype_lists[i], "VALUES");
+ 		list_free(coltype_lists[i]);
}

newExprsLists = NIL;

---------------------------(end of broadcast)---------------------------
TIP 3: Have you checked our extensive FAQ?

http://www.postgresql.org/docs/faq

--
Bruce Momjian bruce@momjian.us
EnterpriseDB http://www.enterprisedb.com

+ If your life is a hard drive, Christ can be your backup. +

#124Joe Conway
mail@joeconway.com
In reply to: Bruce Momjian (#123)
Re: VALUES clause memory optimization

Bruce Momjian wrote:

Has this been addressed?

Tom Lane wrote:

The reason we could safely list_free inside transformInsertRow is that
we know all its callers have just built the passed-in list and so there
are no other pointers to it. That doesn't apply in the general case of
grammar output.

After another look, even in this case there could be other pointers.
Starting around line 667 of analyze.c:

8<------------------
foreach(lc, selectQuery->targetList)
{
TargetEntry *tle = (TargetEntry *) lfirst(lc);
Expr *expr;

if (tle->resjunk)
continue;
if (tle->expr &&
(IsA(tle->expr, Const) ||IsA(tle->expr, Param)) &&
exprType((Node *) tle->expr) == UNKNOWNOID)
expr = tle->expr;
else
expr = (Expr *) makeVar(rtr->rtindex,
tle->resno,
exprType((Node *) tle->expr),
exprTypmod((Node *) tle->expr),
0);
exprList = lappend(exprList, expr);
}

/* Prepare row for assignment to target table */
exprList = transformInsertRow(pstate, exprList,
stmt->cols,
icolumns, attrnos);

8<------------------

So in the UNKNOWNOID case, it wouldn't be safe to free the node after
transformation because it originates in the grammar output. The *only*
safe thing to free up would be a the input exprList itself. Not much to
be saved there.

My advice is to get that low-hanging fruit
in transformInsertRow and leave the other ideas for 8.3.

This one case doesn't provide that much memory savings by itself anyway.
I guess we'll just live with it until we can come up with a safe way to
free grammar output.

Joe