Received: from localhost (unknown [200.46.204.183]) by mail.postgresql.org (Postfix) with ESMTP id E5351633AE6 for ; Thu, 23 Apr 2009 07:34:34 -0300 (ADT) Received: from mail.postgresql.org ([200.46.204.86]) by localhost (mx1.hub.org [200.46.204.183]) (amavisd-maia, port 10024) with ESMTP id 52025-02 for ; Thu, 23 Apr 2009 07:34:28 -0300 (ADT) X-Greylist: from auto-whitelisted by SQLgrey-1.7.6 Received: from mx45.mail.ru (mx45.mail.ru [94.100.176.59]) by mail.postgresql.org (Postfix) with ESMTP id 4D30A6332A1 for ; Thu, 23 Apr 2009 07:34:27 -0300 (ADT) Received: from f183.mail.ru (f183.mail.ru [194.67.57.216]) by mx45.mail.ru (mPOP.Fallback_MX) with ESMTP id 37BD4E00A490 for ; Thu, 23 Apr 2009 12:35:01 +0400 (MSD) Received: from mail by f183.mail.ru with local id 1LwuOP-0000KO-00 for pgsql-sql@postgresql.org; Thu, 23 Apr 2009 12:34:49 +0400 Received: from [193.227.120.34] by win.mail.ru with HTTP; Thu, 23 Apr 2009 11:34:49 +0300 From: ShuA To: pgsql-sql@postgresql.org Subject: =?koi8-r?Q?Re[3]=3A__Need_a_script_that_bakes_INSERT_script_from_SELECT_results?= Mime-Version: 1.0 X-Mailer: mPOP Web-Mail 2.19 X-Originating-IP: 10.105.30.72 via proxy [193.227.120.34] Date: Thu, 23 Apr 2009 11:34:49 +0300 References: X-Mru-Data: 2988:0:1:0:196:0 In-Reply-To: Reply-To: ShuA Content-Type: text/plain; charset=koi8-r Content-Transfer-Encoding: 8bit Message-Id: X-Spam: Not detected X-Mras: Ok X-Virus-Scanned: Maia Mailguard 1.0.1 X-Spam-Status: No, hits=1 tagged_above=0 required=5 tests=SUBJ_RE_NUM=1 X-Spam-Level: * X-Archive-Number: 200904/109 X-Sequence-Number: 32455 -----Original Message----- From: ShuA To: John DeSoi Date: Thu, 16 Apr 2009 16:24:05 +0300 Subject: Re[2]: [SQL] Need a script that bakes INSERT script from SELECT results > > -----Original Message----- > From: John DeSoi > To: ShuA > Date: Thu, 16 Apr 2009 08:25:15 -0400 > Subject: Re: [SQL] Need a script that bakes INSERT script from SELECT results > > > On Apr 16, 2009, at 7:29 AM, ShuA wrote: > > > > > Could someone post an example how to LOOP through row fields to wrap > > > them into 'VALUES(...,,)' list? > > > > > > If you declare record or table row types, you can insert the values > > using (rec.*), something like this: > > > > > > create or replace function test () > > returns void as $$ > > declare > > rec record; > > begin > > for rec in select * from whatever loop > > insert into some_table values (rec.*); > > end loop; > > end; > > $$ language plpgsql; > > > > John DeSoi, Ph.D. > > The functionality I need is about to replicate table data into remote DB. > > > for rec in select * from whatever loop > > insert into some_table values (rec.*); > > end loop; > > ^^^ that is not my case, unfortunately. > > The next, what is supposed to do with baked INSERT statements, is push them thru dblink_exec(), as text param, to make insert works on remote DB. > > Olksy Finally, I get down to PL/Perl scripting, and created the next pieces of code that work as I stated above. Code piece #1 ------------- CREATE OR REPLACE FUNCTION build_insert(relation text, where_filter text) RETURNS text AS $$ # converts value to sql literal my $to_literal = sub { my $value = shift; return 'NULL' if !defined $value; $value =~ s/'/''/g; # escape quotes, return "'$value'"; # return quoted literal }; my ($relation, $where_filter) = @_; $rv = spi_exec_query("SELECT * FROM $relation WHERE $where_filter"); return '' if !$rv->{processed}; # columns comma separated list my $columns; # values lists formatted for INSERT my @values; my $nrows = $rv->{processed}; foreach my $rn (0 .. $nrows - 1) { my $rowref = $rv->{rows}[$rn]; # doesnt support column names like "ja hitrovijebaniy column". # assume columns order is the same for all rows. $columns = join ', ' => keys %$rowref; my $tuple_values = join ', ' => map($to_literal->($_), values %$rowref); push @values, "($tuple_values)"; } return sprintf 'INSERT INTO %s (%s) VALUES %s' ,$relation ,$columns ,join ', ' => @values ; $$ LANGUAGE plperl; Code piece #2 ------------- CREATE OR REPLACE FUNCTION dblink_replica(conn text, relation text, where_filter text) RETURNS text AS $$ DECLARE insert_sql text; BEGIN SELECT build_insert(relation, where_filter) INTO insert_sql; IF '' = insert_sql THEN RETURN ''; ELSE -- dblink_exec() will raise error if fail RETURN (SELECT dblink_exec(conn, insert_sql)); END IF; END; $$ LANGUAGE plpgsql; Code piece #3 (use case) ------------------------ SELECT tru_dblink_replica( 'conname1', 'units' 'unit_id = $unit_id' )