[PATCHES] Feature: give pg_dump a WHERE clause expression

2008-06-01 Thread Davy Durham
Greetings, 
  I have developed a fairly simple patch to the pg_dump utility.  It is
against version 8.3.1 source code.

  I have added a new parameter, -w/--where=EXPR 

  This lets you specify an expression that will be used in a WHERE
clause when the data is dumped.

  I have implemented and tested that it works when generating either
COPY statements (the default), or INSERT statements (-d and -D).  These
two modes of operation have two different sections of code that select
the data to be dumped.

  Though this change could arguably be removed, when a -w/--where
expression is specified, it is also indicated in the comments of the
dump output so one viewing the dump can see that it was not necessarily
all of the data.  

  When -w/--where is not specified, the dump output is just as if this
patch had not been applied.

  I've also updated the pg_dump.sgml file to add a description of this
new flag.

  The code changes should also conform to the existing code style within
pg_dump.  

  The patch should be applied from the root of the source tree with a
-p1 option to the patch command.


Please give any feedback if the patch needs improvement

Thanks for a great DB!

  
diff -cr postgresql-8.3.1.orig/doc/src/sgml/ref/pg_dump.sgml postgresql-8.3.1/doc/src/sgml/ref/pg_dump.sgml
*** postgresql-8.3.1.orig/doc/src/sgml/ref/pg_dump.sgml	2008-05-31 17:48:38.0 -0500
--- postgresql-8.3.1/doc/src/sgml/ref/pg_dump.sgml	2008-06-01 00:23:32.0 -0500
***
*** 535,540 
--- 535,562 
   /varlistentry
  
   varlistentry
+   termoption-w replaceable class=parameterexpression/replaceable/option/term
+   termoption--where=replaceable class=parameterexpression/replaceable/option/term
+   listitem
+para
+ Dump only table data for which the given commandWHERE/command
+ clause expression is true.  The given expression is used for all
+ tables that will be dumped.  Therefore, an error will occur if the
+ expression refers to columns that do not exist in the table being
+ dumped.
+/para
+ 
+note
+ para
+  When giving the expression at the shell prompt, it must be correctly
+  quoted and escaped since otherwise it may be received as multiple
+  arguments to applicationpg_dump/application.
+ /para
+/note
+   /listitem
+  /varlistentry
+ 
+  varlistentry
termoption-x//term
termoption--no-privileges//term
termoption--no-acl//term
diff -cr postgresql-8.3.1.orig/src/bin/pg_dump/pg_dump.c postgresql-8.3.1/src/bin/pg_dump/pg_dump.c
*** postgresql-8.3.1.orig/src/bin/pg_dump/pg_dump.c	2008-05-31 17:48:25.0 -0500
--- postgresql-8.3.1/src/bin/pg_dump/pg_dump.c	2008-06-01 00:33:30.0 -0500
***
*** 76,81 
--- 76,82 
  bool		attrNames;			/* put attr names into insert strings */
  bool		schemaOnly;
  bool		dataOnly;
+ char		*whereClauseExpr;
  bool		aclsSkip;
  
  /* subquery used to convert user ID (eg, datdba) to user name */
***
*** 191,197 
  static void dumpEncoding(Archive *AH);
  static void dumpStdStrings(Archive *AH);
  static const char *getAttrName(int attrnum, TableInfo *tblInfo);
! static const char *fmtCopyColumnList(const TableInfo *ti);
  static void do_sql_command(PGconn *conn, const char *query);
  static void check_sql_result(PGresult *res, PGconn *conn, const char *query,
   ExecStatusType expected);
--- 192,198 
  static void dumpEncoding(Archive *AH);
  static void dumpStdStrings(Archive *AH);
  static const char *getAttrName(int attrnum, TableInfo *tblInfo);
! static const char *fmtCopyColumnList(const TableInfo *ti, bool addParens);
  static void do_sql_command(PGconn *conn, const char *query);
  static void check_sql_result(PGresult *res, PGconn *conn, const char *query,
   ExecStatusType expected);
***
*** 231,236 
--- 232,238 
  
  	static struct option long_options[] = {
  		{data-only, no_argument, NULL, 'a'},
+ 		{where, no_argument, NULL, 'w'},
  		{blobs, no_argument, NULL, 'b'},
  		{clean, no_argument, NULL, 'c'},
  		{create, no_argument, NULL, 'C'},
***
*** 281,286 
--- 283,289 
  	strcpy(g_opaque_type, opaque);
  
  	dataOnly = schemaOnly = dumpInserts = attrNames = false;
+ 	whereClauseExpr = NULL;
  
  	progname = get_progname(argv[0]);
  
***
*** 302,308 
  		}
  	}
  
! 	while ((c = getopt_long(argc, argv, abcCdDE:f:F:h:in:N:oOp:RsS:t:T:U:vWxX:Z:,
  			long_options, optindex)) != -1)
  	{
  		switch (c)
--- 305,311 
  		}
  	}
  
! 	while ((c = getopt_long(argc, argv, abcCdDE:f:F:h:in:N:oOp:RsS:t:T:U:vw:WxX:Z:,
  			long_options, optindex)) != -1)
  	{
  		switch (c)
***
*** 403,408 
--- 406,415 
  g_verbose = true;
  break;
  
+ 			case 'w':			/* where clause expression */
+ whereClauseExpr = strdup(optarg);
+ break;
+ 
  			case 'W':
  

Re: [PATCHES] Feature: give pg_dump a WHERE clause expression

2008-06-01 Thread Tom Lane
Davy Durham [EMAIL PROTECTED] writes:
   I have added a new parameter, -w/--where=EXPR 
   This lets you specify an expression that will be used in a WHERE
 clause when the data is dumped.

This seems pretty poorly thought out.  It can hardly work in a dump
of more than one table, which means that there's not any real reason
to use pg_dump at all.  Just do a COPY (SELECT ...) TO somefile.

regards, tom lane

-- 
Sent via pgsql-patches mailing list (pgsql-patches@postgresql.org)
To make changes to your subscription:
http://www.postgresql.org/mailpref/pgsql-patches


Re: [PATCHES] partial header cleanup

2008-06-01 Thread Alvaro Herrera
Zdenek Kotala wrote:
 This replace xlog.h with xlogdefs.h in bufpage.h. All other changes are  
 forgotten include somewhere. It reduce e.g. bloat to half in itup.h. But, 
 There are still unresolved problems. htup should include bufpage.h, 
 because it needs PageHeader size, but there is still unnecessary bufmgr.h 
 include in bufpage which generates bloat.

I agree with this patch -- in fact I had done the same before PGCon and
then neglected it for some reason.  (I think I was distracted trying to
get the struct RelationData definition out of rel.h, but that did not
turn out too well).

I was thinking maybe we need a third buffer manager header file.  One
would have the current bufmgr.h, another would have the page stuff that
does not know about bufmgr.h (so most of current bufpage.h), and the
third one would be both plus the #define that needs both (which is
currently in bufpage.h).  I am not sure what kind of fallout that
causes.  Maybe that would help you too.  We need to come up with a good
name for that file however ... bufmgrpage.h seems ugly.

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

-- 
Sent via pgsql-patches mailing list (pgsql-patches@postgresql.org)
To make changes to your subscription:
http://www.postgresql.org/mailpref/pgsql-patches


Re: [PATCHES] partial header cleanup

2008-06-01 Thread Zdenek Kotala

Alvaro Herrera napsal(a):

Zdenek Kotala wrote:
This replace xlog.h with xlogdefs.h in bufpage.h. All other changes are  
forgotten include somewhere. It reduce e.g. bloat to half in itup.h. But, 
There are still unresolved problems. htup should include bufpage.h, 
because it needs PageHeader size, but there is still unnecessary bufmgr.h 
include in bufpage which generates bloat.


I agree with this patch -- in fact I had done the same before PGCon and
then neglected it for some reason.  (I think I was distracted trying to
get the struct RelationData definition out of rel.h, but that did not
turn out too well).


I think rel.h is atomic. There is no space to split it.


I was thinking maybe we need a third buffer manager header file.  One
would have the current bufmgr.h, another would have the page stuff that
does not know about bufmgr.h (so most of current bufpage.h), and the
third one would be both plus the #define that needs both (which is
currently in bufpage.h).  I am not sure what kind of fallout that
causes.  Maybe that would help you too.  We need to come up with a good
name for that file however ... bufmgrpage.h seems ugly.


I don't think that we need third header file. It seems to me, that only macros 
BufferGetPage requires both headers (Page and Buffer datatype). Other content 
seems to me independent.


I'm thinking about renaming bufpage.h to page.h, but it is cosmetic change and 
IIRC CVS does not like file renaming.


Zdenek




--
Sent via pgsql-patches mailing list (pgsql-patches@postgresql.org)
To make changes to your subscription:
http://www.postgresql.org/mailpref/pgsql-patches


Re: [PATCHES] Feature: give pg_dump a WHERE clause expression

2008-06-01 Thread Davy Durham
On Sun, 2008-06-01 at 10:43 -0400, Tom Lane wrote:
 Davy Durham [EMAIL PROTECTED] writes:
I have added a new parameter, -w/--where=EXPR 
This lets you specify an expression that will be used in a WHERE
  clause when the data is dumped.
 
 This seems pretty poorly thought out.  It can hardly work in a dump
 of more than one table, which means that there's not any real reason
 to use pg_dump at all.  Just do a COPY (SELECT ...) TO somefile.
 
   regards, tom lane
 

Well, my primary reason for writing the patch was to have a standard SQL
file using INSERT statements in order to load the some of a table's data
into a database other than postgresql which does not support the COPY
statement.  

I'll admit that the single where clause would often not be applicable
across all tables in a database, but when pg_dump is told specific
tables to dump (a nice existing feature of pg_dump for doing something
specialized other than a simple entire database backup), then it can be
useful.

My particular case is that I have several tables that are simple event
logs.  Each table has a timestamp column.  I'm periodically bringing
these tables into sync on another database and I only want to pull rows
newer than since the last sync..  So, a where-clause of..
'ts  $last_sync' 
..works for me.  However, I'm sure there are other uses too..


== Thinking Further ==

Beyond serving my own needs, I'm trying to generically extend the
general idea that pg_dump already supports:
1) pg_dump can be made to dump an entire database
2) pg_dump can be made to dump only requested tables
3) [my addition] pg_dump can be made to dump only requested rows
from requested tables

However, it's no SO generic in that the where clause applies to all
tables.

So, if this patch is not acceptable as-is, what would you feel about
this: 
I could enhance the -t/--table=NAME option to accept more than a
simple NAME.  Rather it could accept something in the form:

--table=table_name:where-clause expression

For example, pg_dump --table='foo:col1  10 AND f2  14'

Currently, the user can specify -t/--table multiple times to
have more than one table dumped.  Or the user can use a pattern
to a single -t option to request multiple tabes.

This way, a user could specify a WHERE clause per table he has
requested to dump.  Granted, the WHERE clause may then apply to
multiple tables if a pattern was used, but that may very well be
desirable to the user.

Unless you disagree, this is a more generic solution (than what my patch
contains) to allowing the user of pg_dump to further refine what they
wish to dump.


Thoughts?

Thanks for the feedback


-- 
Sent via pgsql-patches mailing list (pgsql-patches@postgresql.org)
To make changes to your subscription:
http://www.postgresql.org/mailpref/pgsql-patches


Re: [PATCHES] [BUGS] BUG #4203: perform dblink() in begin/exception returns wrong SQLSTATE code

2008-06-01 Thread Tom Lane
Joe Conway [EMAIL PROTECTED] writes:
 Here is my proposed patch -- as suggested for cvs tip only.

A few comments:

Don't use errstart/errfinish directly.  A reasonable way to deal with
the type of situation you have here is

ereport(ERROR,
(errcode(...),
 errmsg(...),
 det_msg ? errdetail(%s, det_msg) : 0,
 hint_msg ? errhint(%s, hint_msg) : 0,
 ...));

You can't expect the result of PQresultErrorField to still be valid
after you've PQclear'd the PGresult.  I think you'll need to pstrdup
the non-null results first.  Or maybe use a PG_TRY block to free the
PGresult on the way out after the error escape ... but pstrdup is
probably cleaner.

This code doesn't cope with the possibility that no SQLSTATE
is available (a distinct possibility for libpq-detected errors).
You'll need to use some generic error code in that case.  I'm tempted
to suggest ERRCODE_CONNECTION_FAILURE, on the assumption that if it's
libpq-detected then it's a connection problem.

It would probably be useful to show the name of the dblink connection
in the context.

I'm thinking that you are getting well past what is reasonable to
put in a macro.  Time to use an out-of-line function.

Don't use unable to... --- this is against the message style guide.
could not is approved style.  Also note the expectation that context
entries be complete sentences.

 I haven't been around enough lately to be sure I understand the process 
 these days. Should I be posting this to the wiki and waiting for the 
 next commit fest, or just apply myself in a day or two assuming no 
 objections?

No, you can apply it yourself when you feel it's ready.  The wiki queue
is just to keep track of stuff that is submitted by non-committers or
that a committer wants extra review of.

regards, tom lane

-- 
Sent via pgsql-patches mailing list (pgsql-patches@postgresql.org)
To make changes to your subscription:
http://www.postgresql.org/mailpref/pgsql-patches


Re: [PATCHES] Feature: give pg_dump a WHERE clause expression

2008-06-01 Thread Tom Lane
Davy Durham [EMAIL PROTECTED] writes:
 So, if this patch is not acceptable as-is, what would you feel about
 this: 
 I could enhance the -t/--table=NAME option to accept more than a
 simple NAME.  Rather it could accept something in the form:

 --table=table_name:where-clause expression

Well, that would at least address the complaint that it doesn't scale
to multiple tables, but the whole thing still seems like a frammish
that will never see enough use to justify maintaining it.

(BTW, what will you do with a table whose name contains a colon?)

regards, tom lane

-- 
Sent via pgsql-patches mailing list (pgsql-patches@postgresql.org)
To make changes to your subscription:
http://www.postgresql.org/mailpref/pgsql-patches


Re: [PATCHES] Feature: give pg_dump a WHERE clause expression

2008-06-01 Thread Andrew Dunstan



Tom Lane wrote:

Davy Durham [EMAIL PROTECTED] writes:
  

So, if this patch is not acceptable as-is, what would you feel about
this: 
I could enhance the -t/--table=NAME option to accept more than a

simple NAME.  Rather it could accept something in the form:


  

--table=table_name:where-clause expression



Well, that would at least address the complaint that it doesn't scale
to multiple tables, but the whole thing still seems like a frammish
that will never see enough use to justify maintaining it.

(BTW, what will you do with a table whose name contains a colon?)


  


ISTM this would be better off waiting until we turn large parts of 
pg_dump into a library, as has been often discussed, at which point it 
should be relatively simple to write a custom client to do what the OP 
wants. I agree that it does not at all belong in pg_dump.


cheers

andrew

--
Sent via pgsql-patches mailing list (pgsql-patches@postgresql.org)
To make changes to your subscription:
http://www.postgresql.org/mailpref/pgsql-patches


Re: [PATCHES] Feature: give pg_dump a WHERE clause expression

2008-06-01 Thread daveg

On Sun, Jun 01, 2008 at 04:13:34PM -0400, Andrew Dunstan wrote:
 
 
 Tom Lane wrote:
 Davy Durham [EMAIL PROTECTED] writes:
   
 So, if this patch is not acceptable as-is, what would you feel about
 this: 
 I could enhance the -t/--table=NAME option to accept more than a
 simple NAME.  Rather it could accept something in the form:
 
 
   
 --table=table_name:where-clause expression
 
 
 Well, that would at least address the complaint that it doesn't scale
 to multiple tables, but the whole thing still seems like a frammish
 that will never see enough use to justify maintaining it.
 
 (BTW, what will you do with a table whose name contains a colon?)
 
  
   
 
 ISTM this would be better off waiting until we turn large parts of 
 pg_dump into a library, as has been often discussed, at which point it 
 should be relatively simple to write a custom client to do what the OP 
 wants. I agree that it does not at all belong in pg_dump.

I can't imagine many of my clients ever writing another C program or even
being willing to pay me to do so. While modularizing pg_dump is a fine idea,
I don't think it addresses the same set of use cases and users as this
proposal.

-dg

-- 
David Gould   [EMAIL PROTECTED]  510 536 1443510 282 0869
If simplicity worked, the world would be overrun with insects.

-- 
Sent via pgsql-patches mailing list (pgsql-patches@postgresql.org)
To make changes to your subscription:
http://www.postgresql.org/mailpref/pgsql-patches


Re: [PATCHES] Feature: give pg_dump a WHERE clause expression

2008-06-01 Thread Davy Durham
On Sun, 2008-06-01 at 15:47 -0400, Tom Lane wrote:
 Davy Durham [EMAIL PROTECTED] writes:
  So, if this patch is not acceptable as-is, what would you feel about
  this: 
  I could enhance the -t/--table=NAME option to accept more than a
  simple NAME.  Rather it could accept something in the form:
 
  --table=table_name:where-clause expression
 
 Well, that would at least address the complaint that it doesn't scale
 to multiple tables, but the whole thing still seems like a frammish
 that will never see enough use to justify maintaining it.
 

The code is not all that much to maintain as it is, and making it an
addition to an existing parameter instead of a new one may not increase
the code size by much more at all.

BTW- I looked it up, and mysqldump supports such an option as mine, but
it too is global for all tables and cannot be specified per table
AFAICT.

 (BTW, what will you do with a table whose name contains a colon?)
 

I thought about that, but didn't know if tables could contain a colon or
not, but I see that this is possible by enclosing the table name in
double-quotes.  I suppose they could escape the colon as I believe they
may have to do if a table contains  '*', or '?'  ??  Is there another
character that is more appropriate?


Another option I just thought about was to leave the -w/--where flag in
place, but it applies to all subsequent -t/--table flags.. 

So you could do something like:
pg_dump -w 'expr1' -t tab1 -t tab2 -w 'expr2' -t tab3

So that the expr1 filters tab1 and tab2, and expr2 filters tab3.. 

This should be a simple modification to the existing patch to make the
where clause tracked per table rather than merely a global variable. 

However there the becomes an importance on the order that args are given
to pg_dump which you may object to.   But then again, if order of the
tables in the dump file matters, then the -t/--tables flags already
indicate what order the tables will be dumped.  (By pointing this out, I
mean there may already be an importance of argument order in some
circumstances)

This also solves the ':' syntax problem you mentioned above.


   regards, tom lane
 


-- 
Sent via pgsql-patches mailing list (pgsql-patches@postgresql.org)
To make changes to your subscription:
http://www.postgresql.org/mailpref/pgsql-patches


Re: [PATCHES] Feature: give pg_dump a WHERE clause expression

2008-06-01 Thread Andrew Dunstan



daveg wrote:



ISTM this would be better off waiting until we turn large parts of 
pg_dump into a library, as has been often discussed, at which point it 
should be relatively simple to write a custom client to do what the OP 
wants. I agree that it does not at all belong in pg_dump.



I can't imagine many of my clients ever writing another C program or even
being willing to pay me to do so. While modularizing pg_dump is a fine idea,
I don't think it addresses the same set of use cases and users as this
proposal.


  


It's not clear to me that your use case is very compelling. Does your 
foreign database not support import via CSV or XML? Postgres can now 
produce both of these for any arbitrary query.


cheers

andrew

--
Sent via pgsql-patches mailing list (pgsql-patches@postgresql.org)
To make changes to your subscription:
http://www.postgresql.org/mailpref/pgsql-patches


Re: [PATCHES] Feature: give pg_dump a WHERE clause expression

2008-06-01 Thread daveg

On Sun, Jun 01, 2008 at 04:40:15PM -0400, Andrew Dunstan wrote:
 daveg wrote:
 
 I can't imagine many of my clients ever writing another C program or even
 being willing to pay me to do so. While modularizing pg_dump is a fine 
 idea,
 I don't think it addresses the same set of use cases and users as this
 proposal.
 
 It's not clear to me that your use case is very compelling. Does your 
 foreign database not support import via CSV or XML? Postgres can now 
 produce both of these for any arbitrary query.

The foreign database in question is postgresql.

The feature that the proposed patch enables is to create pg_dump custom
format archives for multiple tables with a predicate. No amount of csv or
xml will do that. Contrived example:

 pg_dump -Fc --table=*._stats:where ts = now()::date -f todays_stats.pgd

If I have not been successful in explaining this clearly, please reply
privately to avoid cluttering the list. If you simply disagree about the
usefulness of the feature, I'm fine with that.

-dg


-- 
David Gould   [EMAIL PROTECTED]  510 536 1443510 282 0869
If simplicity worked, the world would be overrun with insects.

-- 
Sent via pgsql-patches mailing list (pgsql-patches@postgresql.org)
To make changes to your subscription:
http://www.postgresql.org/mailpref/pgsql-patches


[PATCHES] Re: [BUGS] BUG #4203: perform dblink() in begin/exception returns wrong SQLSTATE code

2008-06-01 Thread Joe Conway

Tom Lane wrote:

Joe Conway [EMAIL PROTECTED] writes:

Here is my proposed patch -- as suggested for cvs tip only.


A few comments:


[...great comments as usual...]

Thanks for the excellent feedback! I think the attached addresses it all.

I haven't been around enough lately to be sure I understand the process 
these days. Should I be posting this to the wiki and waiting for the 
next commit fest, or just apply myself in a day or two assuming no 
objections?


No, you can apply it yourself when you feel it's ready.  The wiki queue
is just to keep track of stuff that is submitted by non-committers or
that a committer wants extra review of.


Great. Assuming no other objections I'll commit in a day or three.

Joe

Index: dblink.c
===
RCS file: /opt/src/cvs/pgsql/contrib/dblink/dblink.c,v
retrieving revision 1.73
diff -c -r1.73 dblink.c
*** dblink.c	4 Apr 2008 17:02:56 -	1.73
--- dblink.c	1 Jun 2008 21:58:46 -
***
*** 94,99 
--- 94,100 
  static Oid	get_relid_from_relname(text *relname_text);
  static char *generate_relation_name(Oid relid);
  static void dblink_security_check(PGconn *conn, remoteConn *rconn);
+ static void dblink_res_error(const char *conname, PGresult *res, const char *dblink_context_msg, bool fail);
  
  /* Global */
  static remoteConn *pconn = NULL;
***
*** 125,158 
  		} \
  	} while (0)
  
! #define DBLINK_RES_INTERNALERROR(p2) \
! 	do { \
! 			msg = pstrdup(PQerrorMessage(conn)); \
! 			if (res) \
! PQclear(res); \
! 			elog(ERROR, %s: %s, p2, msg); \
! 	} while (0)
! 
! #define DBLINK_RES_ERROR(p2) \
  	do { \
! 			msg = pstrdup(PQerrorMessage(conn)); \
! 			if (res) \
! PQclear(res); \
! 			ereport(ERROR, \
! 	(errcode(ERRCODE_SYNTAX_ERROR), \
! 	 errmsg(%s, p2), \
! 	 errdetail(%s, msg))); \
  	} while (0)
  
! #define DBLINK_RES_ERROR_AS_NOTICE(p2) \
  	do { \
  			msg = pstrdup(PQerrorMessage(conn)); \
  			if (res) \
  PQclear(res); \
! 			ereport(NOTICE, \
! 	(errcode(ERRCODE_SYNTAX_ERROR), \
! 	 errmsg(%s, p2), \
! 	 errdetail(%s, msg))); \
  	} while (0)
  
  #define DBLINK_CONN_NOT_AVAIL \
--- 126,145 
  		} \
  	} while (0)
  
! #define xpstrdup(var_c, var_) \
  	do { \
! 		if (var_ != NULL) \
! 			var_c = pstrdup(var_); \
! 		else \
! 			var_c = NULL; \
  	} while (0)
  
! #define DBLINK_RES_INTERNALERROR(p2) \
  	do { \
  			msg = pstrdup(PQerrorMessage(conn)); \
  			if (res) \
  PQclear(res); \
! 			elog(ERROR, %s: %s, p2, msg); \
  	} while (0)
  
  #define DBLINK_CONN_NOT_AVAIL \
***
*** 396,408 
  	res = PQexec(conn, buf.data);
  	if (!res || PQresultStatus(res) != PGRES_COMMAND_OK)
  	{
! 		if (fail)
! 			DBLINK_RES_ERROR(sql error);
! 		else
! 		{
! 			DBLINK_RES_ERROR_AS_NOTICE(sql error);
  			PG_RETURN_TEXT_P(cstring_to_text(ERROR));
- 		}
  	}
  
  	PQclear(res);
--- 383,391 
  	res = PQexec(conn, buf.data);
  	if (!res || PQresultStatus(res) != PGRES_COMMAND_OK)
  	{
! 		dblink_res_error(conname, res, could not open cursor, fail);
! 		if (!fail)
  			PG_RETURN_TEXT_P(cstring_to_text(ERROR));
  	}
  
  	PQclear(res);
***
*** 470,482 
  	res = PQexec(conn, buf.data);
  	if (!res || PQresultStatus(res) != PGRES_COMMAND_OK)
  	{
! 		if (fail)
! 			DBLINK_RES_ERROR(sql error);
! 		else
! 		{
! 			DBLINK_RES_ERROR_AS_NOTICE(sql error);
  			PG_RETURN_TEXT_P(cstring_to_text(ERROR));
- 		}
  	}
  
  	PQclear(res);
--- 453,461 
  	res = PQexec(conn, buf.data);
  	if (!res || PQresultStatus(res) != PGRES_COMMAND_OK)
  	{
! 		dblink_res_error(conname, res, could not close cursor, fail);
! 		if (!fail)
  			PG_RETURN_TEXT_P(cstring_to_text(ERROR));
  	}
  
  	PQclear(res);
***
*** 513,519 
  	int			call_cntr;
  	int			max_calls;
  	AttInMetadata *attinmeta;
- 	char	   *msg;
  	PGresult   *res = NULL;
  	MemoryContext oldcontext;
  	char	   *conname = NULL;
--- 492,497 
***
*** 590,602 
  			(PQresultStatus(res) != PGRES_COMMAND_OK 
  			 PQresultStatus(res) != PGRES_TUPLES_OK))
  		{
! 			if (fail)
! DBLINK_RES_ERROR(sql error);
! 			else
! 			{
! DBLINK_RES_ERROR_AS_NOTICE(sql error);
  SRF_RETURN_DONE(funcctx);
- 			}
  		}
  		else if (PQresultStatus(res) == PGRES_COMMAND_OK)
  		{
--- 568,576 
  			(PQresultStatus(res) != PGRES_COMMAND_OK 
  			 PQresultStatus(res) != PGRES_TUPLES_OK))
  		{
! 			dblink_res_error(conname, res, could not fetch from cursor, fail);
! 			if (!fail)
  SRF_RETURN_DONE(funcctx);
  		}
  		else if (PQresultStatus(res) == PGRES_COMMAND_OK)
  		{
***
*** 846,856 
  (PQresultStatus(res) != PGRES_COMMAND_OK 
   PQresultStatus(res) != PGRES_TUPLES_OK))
  			{
! if (fail)
! 	DBLINK_RES_ERROR(sql error);
! else
  {
- 	DBLINK_RES_ERROR_AS_NOTICE(sql error);
  	if (freeconn)
  		PQfinish(conn);
  	SRF_RETURN_DONE(funcctx);
--- 820,828 
  

Re: [PATCHES] [BUGS] BUG #4203: perform dblink() in begin/exception returns wrong SQLSTATE code

2008-06-01 Thread Tom Lane
Joe Conway [EMAIL PROTECTED] writes:
 [ improved patch ]

Still a couple quibbles:

 + ereport(level,
 + (errcode(sqlstate),
 +  errmsg(message_primary),

This *must* be errmsg(%s, message_primary), else you have big problems
with % in the text.  Also, I think it's at least theoretically possible
for message_primary to be null, in which case you'd better substitute
unknown error or some such.

You could avoid the ugly cast-away-const by making
dblink_context_conname be const char *, no?

Since dblink_res_error isn't going to return if fail = true, seems
like you could skip the if (!fail) tests occurring after calls to it.

regards, tom lane

-- 
Sent via pgsql-patches mailing list (pgsql-patches@postgresql.org)
To make changes to your subscription:
http://www.postgresql.org/mailpref/pgsql-patches


[PATCHES] Re: [BUGS] BUG #4203: perform dblink() in begin/exception returns wrong SQLSTATE code

2008-06-01 Thread Joe Conway

Tom Lane wrote:

Joe Conway [EMAIL PROTECTED] writes:

[ improved patch ]


Still a couple quibbles:


[ more good feedback ]

All valid complaints, and noticeably improved/simplified code as a 
result. Third patch attached.


Joe
Index: dblink.c
===
RCS file: /opt/src/cvs/pgsql/contrib/dblink/dblink.c,v
retrieving revision 1.73
diff -c -r1.73 dblink.c
*** dblink.c	4 Apr 2008 17:02:56 -	1.73
--- dblink.c	1 Jun 2008 23:52:39 -
***
*** 94,99 
--- 94,100 
  static Oid	get_relid_from_relname(text *relname_text);
  static char *generate_relation_name(Oid relid);
  static void dblink_security_check(PGconn *conn, remoteConn *rconn);
+ static void dblink_res_error(const char *conname, PGresult *res, const char *dblink_context_msg, bool fail);
  
  /* Global */
  static remoteConn *pconn = NULL;
***
*** 125,158 
  		} \
  	} while (0)
  
! #define DBLINK_RES_INTERNALERROR(p2) \
! 	do { \
! 			msg = pstrdup(PQerrorMessage(conn)); \
! 			if (res) \
! PQclear(res); \
! 			elog(ERROR, %s: %s, p2, msg); \
! 	} while (0)
! 
! #define DBLINK_RES_ERROR(p2) \
  	do { \
! 			msg = pstrdup(PQerrorMessage(conn)); \
! 			if (res) \
! PQclear(res); \
! 			ereport(ERROR, \
! 	(errcode(ERRCODE_SYNTAX_ERROR), \
! 	 errmsg(%s, p2), \
! 	 errdetail(%s, msg))); \
  	} while (0)
  
! #define DBLINK_RES_ERROR_AS_NOTICE(p2) \
  	do { \
  			msg = pstrdup(PQerrorMessage(conn)); \
  			if (res) \
  PQclear(res); \
! 			ereport(NOTICE, \
! 	(errcode(ERRCODE_SYNTAX_ERROR), \
! 	 errmsg(%s, p2), \
! 	 errdetail(%s, msg))); \
  	} while (0)
  
  #define DBLINK_CONN_NOT_AVAIL \
--- 126,145 
  		} \
  	} while (0)
  
! #define xpstrdup(var_c, var_) \
  	do { \
! 		if (var_ != NULL) \
! 			var_c = pstrdup(var_); \
! 		else \
! 			var_c = NULL; \
  	} while (0)
  
! #define DBLINK_RES_INTERNALERROR(p2) \
  	do { \
  			msg = pstrdup(PQerrorMessage(conn)); \
  			if (res) \
  PQclear(res); \
! 			elog(ERROR, %s: %s, p2, msg); \
  	} while (0)
  
  #define DBLINK_CONN_NOT_AVAIL \
***
*** 396,408 
  	res = PQexec(conn, buf.data);
  	if (!res || PQresultStatus(res) != PGRES_COMMAND_OK)
  	{
! 		if (fail)
! 			DBLINK_RES_ERROR(sql error);
! 		else
! 		{
! 			DBLINK_RES_ERROR_AS_NOTICE(sql error);
! 			PG_RETURN_TEXT_P(cstring_to_text(ERROR));
! 		}
  	}
  
  	PQclear(res);
--- 383,390 
  	res = PQexec(conn, buf.data);
  	if (!res || PQresultStatus(res) != PGRES_COMMAND_OK)
  	{
! 		dblink_res_error(conname, res, could not open cursor, fail);
! 		PG_RETURN_TEXT_P(cstring_to_text(ERROR));
  	}
  
  	PQclear(res);
***
*** 470,482 
  	res = PQexec(conn, buf.data);
  	if (!res || PQresultStatus(res) != PGRES_COMMAND_OK)
  	{
! 		if (fail)
! 			DBLINK_RES_ERROR(sql error);
! 		else
! 		{
! 			DBLINK_RES_ERROR_AS_NOTICE(sql error);
! 			PG_RETURN_TEXT_P(cstring_to_text(ERROR));
! 		}
  	}
  
  	PQclear(res);
--- 452,459 
  	res = PQexec(conn, buf.data);
  	if (!res || PQresultStatus(res) != PGRES_COMMAND_OK)
  	{
! 		dblink_res_error(conname, res, could not close cursor, fail);
! 		PG_RETURN_TEXT_P(cstring_to_text(ERROR));
  	}
  
  	PQclear(res);
***
*** 513,519 
  	int			call_cntr;
  	int			max_calls;
  	AttInMetadata *attinmeta;
- 	char	   *msg;
  	PGresult   *res = NULL;
  	MemoryContext oldcontext;
  	char	   *conname = NULL;
--- 490,495 
***
*** 590,602 
  			(PQresultStatus(res) != PGRES_COMMAND_OK 
  			 PQresultStatus(res) != PGRES_TUPLES_OK))
  		{
! 			if (fail)
! DBLINK_RES_ERROR(sql error);
! 			else
! 			{
! DBLINK_RES_ERROR_AS_NOTICE(sql error);
! SRF_RETURN_DONE(funcctx);
! 			}
  		}
  		else if (PQresultStatus(res) == PGRES_COMMAND_OK)
  		{
--- 566,573 
  			(PQresultStatus(res) != PGRES_COMMAND_OK 
  			 PQresultStatus(res) != PGRES_TUPLES_OK))
  		{
! 			dblink_res_error(conname, res, could not fetch from cursor, fail);
! 			SRF_RETURN_DONE(funcctx);
  		}
  		else if (PQresultStatus(res) == PGRES_COMMAND_OK)
  		{
***
*** 846,860 
  (PQresultStatus(res) != PGRES_COMMAND_OK 
   PQresultStatus(res) != PGRES_TUPLES_OK))
  			{
! if (fail)
! 	DBLINK_RES_ERROR(sql error);
! else
! {
! 	DBLINK_RES_ERROR_AS_NOTICE(sql error);
! 	if (freeconn)
! 		PQfinish(conn);
! 	SRF_RETURN_DONE(funcctx);
! }
  			}
  
  			if (PQresultStatus(res) == PGRES_COMMAND_OK)
--- 817,826 
  (PQresultStatus(res) != PGRES_COMMAND_OK 
   PQresultStatus(res) != PGRES_TUPLES_OK))
  			{
! dblink_res_error(conname, res, could not execute query, fail);
! if (freeconn)
! 	PQfinish(conn);
! SRF_RETURN_DONE(funcctx);
  			}
  
  			if (PQresultStatus(res) == PGRES_COMMAND_OK)
***
*** 1180,1189 
  		(PQresultStatus(res) != PGRES_COMMAND_OK 
  		 PQresultStatus(res) != PGRES_TUPLES_OK))
  	{
! 		if (fail)
! 			DBLINK_RES_ERROR(sql 

Re: [PATCHES] Feature: give pg_dump a WHERE clause expression

2008-06-01 Thread Stephen Frost
* daveg ([EMAIL PROTECTED]) wrote:
 The feature that the proposed patch enables is to create pg_dump custom
 format archives for multiple tables with a predicate. No amount of csv or
 xml will do that. Contrived example:

Uh, pg_dump's custom format really isn't particularly special, to be
honest.  Is there some reason you're interested in using it over, as was
suggested, COPY/CSV/etc format?  You could, of course, gzip the output
of COPY (as pg_dump does) if you're concerned about space..

Thanks,

Stephen


signature.asc
Description: Digital signature


Re: [PATCHES] Feature: give pg_dump a WHERE clause expression

2008-06-01 Thread Davy Durham
On Sun, 2008-06-01 at 22:02 -0400, Stephen Frost wrote:
 * Davy Durham ([EMAIL PROTECTED]) wrote:
  To reiterate, it is not possible to use the COPY command to create
  standard SQL INSERT statements that can be conveniently loaded by
  another db. No?
 
 Erm, thankfully, PostgreSQL (what you're loading the data into?) can
 take more than just SQL INSERT statements.
 

No, the database I'm loading into is not PostgreSQL, but that's okay.  I
think that was someone else.

 Of course, on the other hand, you *could* use COPY to create SQL INSERT
 statements through an appropriately crafted query.  PG makes that
 reasonably straight-forward, actually.
 
   Stephen



-- 
Sent via pgsql-patches mailing list (pgsql-patches@postgresql.org)
To make changes to your subscription:
http://www.postgresql.org/mailpref/pgsql-patches


Re: [PATCHES] Feature: give pg_dump a WHERE clause expression

2008-06-01 Thread Tom Lane
Davy Durham [EMAIL PROTECTED] writes:
 To reiterate, it is not possible to use the COPY command to create
 standard SQL INSERT statements that can be conveniently loaded by
 another db. No?

Fair point, but the question here is about how useful this incremental
feature really is compared to its incremental maintenance cost.
It is *possible* to achieve what you want without any pg_dump
changes: create a fresh table via
CREATE TABLE tmp_table AS SELECT * FROM my_table WHERE ...
and then pg_dump that.  So the issue is how often does this problem
come up and is it worth maintaining more code to make it a bit
easier to deal with?  My thought is probably not, and that seems
to be the majority opinion so far.

regards, tom lane

-- 
Sent via pgsql-patches mailing list (pgsql-patches@postgresql.org)
To make changes to your subscription:
http://www.postgresql.org/mailpref/pgsql-patches


Re: [PATCHES] Feature: give pg_dump a WHERE clause expression

2008-06-01 Thread Davy Durham
On Sun, 2008-06-01 at 22:19 -0400, Stephen Frost wrote:

 
 or so.  I suppose it might be interesting to consider an 'insert-format'
 output for COPY, which pg_dump could possibly be refactored to use when
 requested.  It'd be nice if it was easier to have COPY support more
 formats but right now it's kind of a pain.


That sounds also reasonable to me.  It seems like a worthy format that
COPY could output.

And sure.. pg_dump could then be simplified a bit by using this.  Beyond
that, pg_dump would probably most easily let the user specify the very
keyword (or full COPY statement parameters) that COPY would use as
output format rather than implementing flags for everything COPY already
supports.  Perhaps support the existing -d/-D flags for backwards
compatibility.

This makes pg_dump more flexible AND COPY more flexible for use cases
like mine.



-- 
Sent via pgsql-patches mailing list (pgsql-patches@postgresql.org)
To make changes to your subscription:
http://www.postgresql.org/mailpref/pgsql-patches


Re: [PATCHES] Feature: give pg_dump a WHERE clause expression

2008-06-01 Thread Tom Lane
Davy Durham [EMAIL PROTECTED] writes:
 On Sun, 2008-06-01 at 22:19 -0400, Stephen Frost wrote:
 or so.  I suppose it might be interesting to consider an 'insert-format'
 output for COPY, which pg_dump could possibly be refactored to use when
 requested.

 And sure.. pg_dump could then be simplified a bit by using this.

Not really.  pg_dump has to support old server versions, so you won't
get any meaningful simplification by moving functionality out of pg_dump
into the backend; at least not before you've forgotten having made the
change :-(

regards, tom lane

-- 
Sent via pgsql-patches mailing list (pgsql-patches@postgresql.org)
To make changes to your subscription:
http://www.postgresql.org/mailpref/pgsql-patches


[PATCHES] Feature: pg_dump: ability to specify WHERE clause expression for -t/--table option

2008-06-01 Thread Davy Durham
Okay,
  Because I'm hardheaded as well as anxious to implement my own ideas
for the challenge of it :) ...


I've extended the the -t/--table option to optionally accept a WHERE
clause expression following the table pattern.

The user can, for example, run:
pg_dump -t tab1:col115 -t tab2:col125
and it will dump only tab1 WHERE col115 and tab2 WHERE col225

Since the -t/--table option already supports accepting wildcard table
names, the WHERE clause expression applies to all tables matching a
pattern.

The only backwards incompatibility is that if a table name pattern
contains a ':', then the pattern must be quoted otherwise the ':' that
is part of the pattern will be interpreted as a separator between a
pattern and an expression.  If ':' is too common a character to be found
in table patterns, then it can easily be changed (in the pg_dump.sgml
file and in one place with a #define at the top of pg_dump.c).

As before, I have implemented and tested that it works when generating
either COPY statements (the default), or INSERT statements (-d and -D).
These two modes of operation have two different sections of code that
select the data to be dumped.

The code changes should be in conformance to the existing coding style
within pg_dump.

I've made minimal changes to the pg_dump.sgml file as well to affect
the man page.

The patch should be applied from the root of the source tree with a -p1
option to the patch command. The patch is against version 8.3.1 source
code.


Thanks *again* for a great DB,
  Davy


==

P.S.
  This submission is my final response to the previous thread titled: 
Feature: give pg_dump a WHERE clause expression

  Please forgive the submitted patch that I know may never get merged
in.  I merely wanted the final result posted/archived somewhere public
in case any other lurkers were interested for their own purposes.  But
if you're at all curious, try it out.  You might like it :)

  Thanks again for all your feedback.

diff -cr postgresql-8.3.1.orig/doc/src/sgml/ref/pg_dump.sgml postgresql-8.3.1/doc/src/sgml/ref/pg_dump.sgml
*** postgresql-8.3.1.orig/doc/src/sgml/ref/pg_dump.sgml	2008-05-31 17:48:38.0 -0500
--- postgresql-8.3.1/doc/src/sgml/ref/pg_dump.sgml	2008-06-01 23:37:32.0 -0500
***
*** 451,458 
   /varlistentry
  
   varlistentry
!   termoption-t replaceable class=parametertable/replaceable/option/term
!   termoption--table=replaceable class=parametertable/replaceable/option/term
listitem
 para
  Dump only tables (or views or sequences) matching replaceable
--- 451,458 
   /varlistentry
  
   varlistentry
!   termoption-t replaceable class=parametertable[:expression]/replaceable/option/term
!   termoption--table=replaceable class=parametertable[:expression]/replaceable/option/term
listitem
 para
  Dump only tables (or views or sequences) matching replaceable
***
*** 468,473 
--- 468,482 
 /para
  
 para
+ 	If ':' and an expression follow the given table pattern, then it 
+ 	becomes a commandWHERE/command clause expression on the table(s) 
+ 	being dumped by this parameter.  When the expression contains cerain
+ 	characters or spaces, be careful also to quote the entire parameter 
+ 	to prevent the shell from processing special characters or passing
+ 	the parameter as multiple arguments to commandpg_dump/command.
+/para
+ 
+para
  The option-n/ and option-N/ switches have no effect when
  option-t/ is used, because tables selected by option-t/ will
  be dumped regardless of those switches, and non-table objects will not
diff -cr postgresql-8.3.1.orig/src/bin/pg_dump/common.c postgresql-8.3.1/src/bin/pg_dump/common.c
*** postgresql-8.3.1.orig/src/bin/pg_dump/common.c	2008-05-31 17:48:25.0 -0500
--- postgresql-8.3.1/src/bin/pg_dump/common.c	2008-06-01 20:16:01.0 -0500
***
*** 915,927 
   * Support for simple list operations
   */
  
! void
  simple_oid_list_append(SimpleOidList *list, Oid val)
  {
  	SimpleOidListCell *cell;
  
  	cell = (SimpleOidListCell *) pg_malloc(sizeof(SimpleOidListCell));
  	cell-next = NULL;
  	cell-val = val;
  
  	if (list-tail)
--- 915,928 
   * Support for simple list operations
   */
  
! SimpleOidListCell *
  simple_oid_list_append(SimpleOidList *list, Oid val)
  {
  	SimpleOidListCell *cell;
  
  	cell = (SimpleOidListCell *) pg_malloc(sizeof(SimpleOidListCell));
  	cell-next = NULL;
+ 	cell-userData = NULL;
  	cell-val = val;
  
  	if (list-tail)
***
*** 929,937 
  	else
  		list-head = cell;
  	list-tail = cell;
  }
  
! void
  simple_string_list_append(SimpleStringList *list, const char *val)
  {
  	SimpleStringListCell *cell;
--- 930,939 
  	else
  		list-head = cell;
  	list-tail = cell;
+ 	return cell;
  }
  
! SimpleStringListCell *
  simple_string_list_append(SimpleStringList