On Fri, Mar 6, 2015 at 11:07 AM, Jim Nasby <jim.na...@bluetreble.com> wrote:
> On 3/2/15 10:58 AM, Sawada Masahiko wrote:
>>
>> On Wed, Feb 25, 2015 at 4:58 PM, Jim Nasby <jim.na...@bluetreble.com>
>> wrote:
>>>
>>> On 2/24/15 8:28 AM, Sawada Masahiko wrote:
>>>>>
>>>>>
>>>>> According to the above discussion, VACUUM and REINDEX should have
>>>>> trailing options. Tom seems (to me) suggesting that SQL-style
>>>>> (bare word preceded by WITH) options and Jim suggesting '()'
>>>>> style options? (Anyway VACUUM gets the*third additional*  option
>>>>> sytle, but it is the different discussion from this)
>>>
>>>
>>>
>>> Well, almost everything does a trailing WITH. We need to either stick
>>> with
>>> that for consistency, or add leading () as an option to those WITH
>>> commands.
>>>
>>> Does anyone know why those are WITH? Is it ANSI?
>>>
>>> As a refresher, current commands are:
>>>
>>>   VACUUM (ANALYZE, VERBOSE) table1 (col1);
>>>   REINDEX INDEX index1 FORCE;
>>>   COPY table1 FROM 'file.txt' WITH (FORMAT csv);
>>>   CREATE MATERIALIZED VIEW mv1 WITH (storageparam, ...) AS qry WITH DATA;
>>>   CREATE EXTENSION ext1 WITH SCHEMA s1 VERSION v1 FROM over;
>>>   CREATE ROLE role WITH LOGIN;
>>>   GRANT .... WITH GRANT OPTION;
>>>   CREATE VIEW v1 AS qry WITH CASCADED CHECK OPTION;
>>>   ALTER DATABASE db1 WITH CONNECTION LIMIT 50;
>>>   DECLARE c1 INSENSITIVE SCROLL CURSOR WITH HOLD;
>
>
> BTW, I'm fine with Tom's bare-word with WITH idea. That seems to be the most
> consistent with everything else. Is there a problem with doing that? I know
> getting syntax is one of the hard parts of new features, but it seems like
> we reached consensus here...

Attached is latest version patch based on Tom's idea as follows.
REINDEX { INDEX | ... } name WITH ( options [, ...] )

>
>> We have discussed about this option including FORCE option, but I
>> think there are not user who want to use both FORCE and VERBOSE option
>> at same time.
>
>
> I find that very hard to believe... I would expect a primary use case for
> VERBOSE to be "I ran REINDEX, but it doesn't seem to have done anything...
> what's going on?" and that's exactly when you might want to use FORCE.
>

In currently code, nothing happens even if FORCE option is specified.
This option completely exist for backward compatibility.
But this patch add new syntax including FORCE option for now.

Todo
- tab completion
- reindexdb command

Regards,

-------
Sawada Masahiko
diff --git a/doc/src/sgml/ref/reindex.sgml b/doc/src/sgml/ref/reindex.sgml
index 0a4c7d4..a4109aa 100644
--- a/doc/src/sgml/ref/reindex.sgml
+++ b/doc/src/sgml/ref/reindex.sgml
@@ -22,6 +22,12 @@ PostgreSQL documentation
  <refsynopsisdiv>
 <synopsis>
 REINDEX { INDEX | TABLE | SCHEMA | DATABASE | SYSTEM } <replaceable class="PARAMETER">name</replaceable> [ FORCE ]
+REINDEX { INDEX | TABLE | SCHEMA | DATABASE | SYSTEM } <replaceable class="PARAMETER">name</replaceable> WITH ( <replaceable class="PARAMETER">options</replaceable> [, ...] )
+
+<phrase>where <replaceable class="PARAMETER">option</replaceable> can be one of:</phrase>
+
+    FORCE [ <replaceable class="PARAMETER">boolean</replaceable> ]
+    VERBOSE [ <replaceable class="PARAMETER">boolean</replaceable> ]
 </synopsis>
  </refsynopsisdiv>
 
@@ -159,6 +165,29 @@ REINDEX { INDEX | TABLE | SCHEMA | DATABASE | SYSTEM } <replaceable class="PARAM
      </para>
     </listitem>
    </varlistentry>
+
+   <varlistentry>
+    <term><literal>VERBOSE</literal></term>
+    <listitem>
+     <para>
+      Prints a progress report as each index is reindexed.
+     </para>
+    </listitem>
+   </varlistentry>
+
+   <varlistentry>
+    <term><replaceable class="parameter">boolean</replaceable></term>
+    <listitem>
+     <para>
+      Specifies whether the selected option should be turned on or off.
+      You can write <literal>TRUE</literal>, <literal>ON</>, or
+      <literal>1</literal> to enable the option, and <literal>FALSE</literal>,
+      <literal>OFF</>, or <literal>0</literal> to disable it.  The
+      <replaceable class="parameter">boolean</replaceable> value can also
+      be omitted, in which case <literal>TRUE</literal> is assumed.
+     </para>
+    </listitem>
+   </varlistentry>
   </variablelist>
  </refsect1>
 
diff --git a/src/backend/catalog/index.c b/src/backend/catalog/index.c
index f85ed93..786f173 100644
--- a/src/backend/catalog/index.c
+++ b/src/backend/catalog/index.c
@@ -63,6 +63,7 @@
 #include "utils/inval.h"
 #include "utils/lsyscache.h"
 #include "utils/memutils.h"
+#include "utils/pg_rusage.h"
 #include "utils/syscache.h"
 #include "utils/tuplesort.h"
 #include "utils/snapmgr.h"
@@ -3130,13 +3131,18 @@ IndexGetRelation(Oid indexId, bool missing_ok)
  * reindex_index - This routine is used to recreate a single index
  */
 void
-reindex_index(Oid indexId, bool skip_constraint_checks, char persistence)
+reindex_index(Oid indexId, bool skip_constraint_checks, char persistence,
+				bool verbose)
 {
 	Relation	iRel,
 				heapRelation;
 	Oid			heapId;
 	IndexInfo  *indexInfo;
 	volatile bool skipped_constraint = false;
+	int			elevel = verbose ? INFO : DEBUG2;
+	PGRUsage	ru0;
+
+	pg_rusage_init(&ru0);
 
 	/*
 	 * Open and lock the parent heap relation.  ShareLock is sufficient since
@@ -3280,6 +3286,13 @@ reindex_index(Oid indexId, bool skip_constraint_checks, char persistence)
 		heap_close(pg_index, RowExclusiveLock);
 	}
 
+	/* Log what we did */
+	ereport(elevel,
+			(errmsg("index \"%s\" was reindexed.",
+					get_rel_name(indexId)),
+					errdetail("%s.",
+							  pg_rusage_show(&ru0))));
+
 	/* Close rels, but keep locks */
 	index_close(iRel, NoLock);
 	heap_close(heapRelation, NoLock);
@@ -3321,7 +3334,7 @@ reindex_index(Oid indexId, bool skip_constraint_checks, char persistence)
  * index rebuild.
  */
 bool
-reindex_relation(Oid relid, int flags)
+reindex_relation(Oid relid, int flags, bool verbose)
 {
 	Relation	rel;
 	Oid			toast_relid;
@@ -3412,7 +3425,7 @@ reindex_relation(Oid relid, int flags)
 				RelationSetIndexList(rel, doneIndexes, InvalidOid);
 
 			reindex_index(indexOid, !(flags & REINDEX_REL_CHECK_CONSTRAINTS),
-						  persistence);
+						  persistence, verbose);
 
 			CommandCounterIncrement();
 
@@ -3447,7 +3460,7 @@ reindex_relation(Oid relid, int flags)
 	 * still hold the lock on the master table.
 	 */
 	if ((flags & REINDEX_REL_PROCESS_TOAST) && OidIsValid(toast_relid))
-		result |= reindex_relation(toast_relid, flags);
+		result |= reindex_relation(toast_relid, flags, verbose);
 
 	return result;
 }
diff --git a/src/backend/commands/cluster.c b/src/backend/commands/cluster.c
index 3febdd5..34ffaba 100644
--- a/src/backend/commands/cluster.c
+++ b/src/backend/commands/cluster.c
@@ -1532,7 +1532,7 @@ finish_heap_swap(Oid OIDOldHeap, Oid OIDNewHeap,
 	else if (newrelpersistence == RELPERSISTENCE_PERMANENT)
 		reindex_flags |= REINDEX_REL_FORCE_INDEXES_PERMANENT;
 
-	reindex_relation(OIDOldHeap, reindex_flags);
+	reindex_relation(OIDOldHeap, reindex_flags, false);
 
 	/*
 	 * If the relation being rebuild is pg_class, swap_relation_files()
diff --git a/src/backend/commands/indexcmds.c b/src/backend/commands/indexcmds.c
index 1c1d0da..24ec705 100644
--- a/src/backend/commands/indexcmds.c
+++ b/src/backend/commands/indexcmds.c
@@ -1681,10 +1681,26 @@ ChooseIndexColumnNames(List *indexElems)
  *		Recreate a specific index.
  */
 Oid
-ReindexIndex(RangeVar *indexRelation)
+ReindexIndex(RangeVar *indexRelation, List *options)
 {
 	Oid			indOid;
 	Oid			heapOid = InvalidOid;
+	bool		verbose = false;
+	ListCell	*lc;
+
+	/* Parse list of options */
+	foreach(lc, options)
+	{
+		DefElem *opt = (DefElem *) lfirst(lc);
+		if (strcmp(opt->defname, "verbose") == 0)
+			verbose = defGetBoolean(opt);
+		else if (strcmp(opt->defname, "force") == 0)
+		{ /* Nothing to do */ }
+		else
+			ereport(ERROR,
+					(errcode(ERRCODE_INVALID_PARAMETER_VALUE),
+					 errmsg("unrecognized REINDEX option \"%s\"", opt->defname)));
+	}
 
 	/* lock level used here should match index lock reindex_index() */
 	indOid = RangeVarGetRelidExtended(indexRelation, AccessExclusiveLock,
@@ -1692,7 +1708,7 @@ ReindexIndex(RangeVar *indexRelation)
 									  RangeVarCallbackForReindexIndex,
 									  (void *) &heapOid);
 
-	reindex_index(indOid, false, indexRelation->relpersistence);
+	reindex_index(indOid, false, indexRelation->relpersistence, verbose);
 
 	return indOid;
 }
@@ -1761,9 +1777,25 @@ RangeVarCallbackForReindexIndex(const RangeVar *relation,
  *		Recreate all indexes of a table (and of its toast table, if any)
  */
 Oid
-ReindexTable(RangeVar *relation)
+ReindexTable(RangeVar *relation, List *options)
 {
 	Oid			heapOid;
+	bool		verbose = false;
+	ListCell	*lc;
+
+	/* Parse list of options */
+	foreach(lc, options)
+	{
+		DefElem *opt = (DefElem *) lfirst(lc);
+		if (strcmp(opt->defname, "verbose") == 0)
+			verbose = defGetBoolean(opt);
+		else if (strcmp(opt->defname, "force") == 0)
+		{ /* Nothing to do */ }
+		else
+			ereport(ERROR,
+					(errcode(ERRCODE_INVALID_PARAMETER_VALUE),
+					 errmsg("unrecognized REINDEX option \"%s\"", opt->defname)));
+	}
 
 	/* The lock level used here should match reindex_relation(). */
 	heapOid = RangeVarGetRelidExtended(relation, ShareLock, false, false,
@@ -1771,7 +1803,8 @@ ReindexTable(RangeVar *relation)
 
 	if (!reindex_relation(heapOid,
 						  REINDEX_REL_PROCESS_TOAST |
-						  REINDEX_REL_CHECK_CONSTRAINTS))
+						  REINDEX_REL_CHECK_CONSTRAINTS,
+						  verbose))
 		ereport(NOTICE,
 				(errmsg("table \"%s\" has no indexes",
 						relation->relname)));
@@ -1788,7 +1821,7 @@ ReindexTable(RangeVar *relation)
  * That means this must not be called within a user transaction block!
  */
 void
-ReindexMultipleTables(const char *objectName, ReindexObjectType objectKind)
+ReindexMultipleTables(const char *objectName, ReindexObjectType objectKind, List *options)
 {
 	Oid			objectOid;
 	Relation	relationRelation;
@@ -1800,12 +1833,31 @@ ReindexMultipleTables(const char *objectName, ReindexObjectType objectKind)
 	List	   *relids = NIL;
 	ListCell   *l;
 	int			num_keys;
+	bool		verbose;
+	int			elevel = DEBUG2;
 
 	AssertArg(objectName);
 	Assert(objectKind == REINDEX_OBJECT_SCHEMA ||
 		   objectKind == REINDEX_OBJECT_SYSTEM ||
 		   objectKind == REINDEX_OBJECT_DATABASE);
 
+	/* Parse list of options */
+	foreach(l, options)
+	{
+		DefElem *opt = (DefElem *) lfirst(l);
+		if (strcmp(opt->defname, "verbose") == 0)
+		{
+			verbose = defGetBoolean(opt);
+			elevel = INFO;
+		}
+		else if (strcmp(opt->defname, "force") == 0)
+		{ /* Nothing to do */ }
+		else
+			ereport(ERROR,
+					(errcode(ERRCODE_INVALID_PARAMETER_VALUE),
+					 errmsg("unrecognized REINDEX option \"%s\"", opt->defname)));
+	}
+
 	/*
 	 * Get OID of object to reindex, being the database currently being used
 	 * by session for a database or for system catalogs, or the schema defined
@@ -1924,9 +1976,10 @@ ReindexMultipleTables(const char *objectName, ReindexObjectType objectKind)
 		PushActiveSnapshot(GetTransactionSnapshot());
 		if (reindex_relation(relid,
 							 REINDEX_REL_PROCESS_TOAST |
-							 REINDEX_REL_CHECK_CONSTRAINTS))
-			ereport(DEBUG1,
-					(errmsg("table \"%s.%s\" was reindexed",
+							 REINDEX_REL_CHECK_CONSTRAINTS,
+							 verbose))
+			ereport(elevel,
+					(errmsg("indexes of whole table \"%s.%s\" were reindexed",
 							get_namespace_name(get_rel_namespace(relid)),
 							get_rel_name(relid))));
 		PopActiveSnapshot();
diff --git a/src/backend/commands/tablecmds.c b/src/backend/commands/tablecmds.c
index 6536778..792fc00 100644
--- a/src/backend/commands/tablecmds.c
+++ b/src/backend/commands/tablecmds.c
@@ -1225,7 +1225,7 @@ ExecuteTruncate(TruncateStmt *stmt)
 			/*
 			 * Reconstruct the indexes to match, and we're done.
 			 */
-			reindex_relation(heap_relid, REINDEX_REL_PROCESS_TOAST);
+			reindex_relation(heap_relid, REINDEX_REL_PROCESS_TOAST, false);
 		}
 
 		pgstat_count_truncate(rel);
diff --git a/src/backend/parser/gram.y b/src/backend/parser/gram.y
index 581f7a1..1c8970f 100644
--- a/src/backend/parser/gram.y
+++ b/src/backend/parser/gram.y
@@ -456,6 +456,14 @@ static Node *makeRecursiveViewSelect(char *relname, List *aliases, Node *query);
 %type <node>	explain_option_arg
 %type <defelt>	explain_option_elem
 %type <list>	explain_option_list
+
+%type <str>		reindex_option_name
+%type <node>	reindex_option_arg
+%type <defelt>	reindex_option_elem
+%type <ival>	reindex_target_type
+%type <ival>	reindex_target_multitable
+%type <list>	reindex_option_list
+
 %type <node>	copy_generic_opt_arg copy_generic_opt_arg_list_item
 %type <defelt>	copy_generic_opt_elem
 %type <list>	copy_generic_opt_list copy_generic_opt_arg_list
@@ -7316,57 +7324,87 @@ opt_if_exists: IF_P EXISTS						{ $$ = TRUE; }
  *		QUERY:
  *
  *		REINDEX type <name> [FORCE]
+ *		REINDEX type <name> WITH ( options )
  *
  * FORCE no longer does anything, but we accept it for backwards compatibility
  *****************************************************************************/
 
 ReindexStmt:
-			REINDEX INDEX qualified_name opt_force
+			REINDEX reindex_target_type qualified_name opt_force
 				{
 					ReindexStmt *n = makeNode(ReindexStmt);
-					n->kind = REINDEX_OBJECT_INDEX;
+					n->kind = $2;
 					n->relation = $3;
 					n->name = NULL;
+					n->options = NULL;
 					$$ = (Node *)n;
 				}
-			| REINDEX TABLE qualified_name opt_force
+			| REINDEX reindex_target_type qualified_name WITH '(' reindex_option_list ')'
 				{
 					ReindexStmt *n = makeNode(ReindexStmt);
-					n->kind = REINDEX_OBJECT_TABLE;
+					n->kind = $2;
 					n->relation = $3;
 					n->name = NULL;
+					n->options = $6;
 					$$ = (Node *)n;
 				}
-			| REINDEX SCHEMA name opt_force
+			| REINDEX reindex_target_multitable name opt_force
 				{
 					ReindexStmt *n = makeNode(ReindexStmt);
-					n->kind = REINDEX_OBJECT_SCHEMA;
+					n->kind = $2;
 					n->name = $3;
 					n->relation = NULL;
+					n->options = NULL;
 					$$ = (Node *)n;
 				}
-			| REINDEX SYSTEM_P name opt_force
+			| REINDEX reindex_target_multitable name WITH '(' reindex_option_list ')'
 				{
 					ReindexStmt *n = makeNode(ReindexStmt);
-					n->kind = REINDEX_OBJECT_SYSTEM;
+					n->kind = $2;
 					n->name = $3;
 					n->relation = NULL;
+				    n->options = $6;
 					$$ = (Node *)n;
 				}
-			| REINDEX DATABASE name opt_force
+		;
+reindex_target_type:
+			INDEX { $$ = REINDEX_OBJECT_INDEX; }
+			| TABLE { $$ = REINDEX_OBJECT_TABLE; }
+;
+reindex_target_multitable:
+			SCHEMA { $$ = REINDEX_OBJECT_SCHEMA; }
+			| SYSTEM_P { $$ = REINDEX_OBJECT_SYSTEM; }
+			| DATABASE { $$ = REINDEX_OBJECT_DATABASE; }
+;
+opt_force:
+			FORCE                                                           {  $$ = TRUE; }
+			| /* EMPTY */                                                   {  $$ = FALSE; }
+;
+reindex_option_list:
+			reindex_option_elem
 				{
-					ReindexStmt *n = makeNode(ReindexStmt);
-					n->kind = REINDEX_OBJECT_DATABASE;
-					n->name = $3;
-					n->relation = NULL;
-					$$ = (Node *)n;
+					$$ = list_make1($1);
 				}
-		;
-
-opt_force:	FORCE									{  $$ = TRUE; }
-			| /* EMPTY */							{  $$ = FALSE; }
-		;
-
+			| reindex_option_list ',' reindex_option_elem
+				{
+					$$ = lappend($1, $3);
+				}
+;
+reindex_option_elem:
+			reindex_option_name reindex_option_arg
+			{
+				$$ = makeDefElem($1, $2);
+			}
+;
+reindex_option_name:
+			VERBOSE 				{ $$ = "verbose"; }
+			| FORCE					{ $$ = "force"; }
+;
+reindex_option_arg:
+			opt_boolean_or_string 	{ $$ = (Node *) makeString($1); }
+			| NumericOnly			{ $$ = (Node *) $1; }
+			| /* EMPTY */ 			{ $$ = NULL; }
+;
 
 /*****************************************************************************
  *
diff --git a/src/backend/tcop/utility.c b/src/backend/tcop/utility.c
index 126e38d..0b41701 100644
--- a/src/backend/tcop/utility.c
+++ b/src/backend/tcop/utility.c
@@ -737,10 +737,10 @@ standard_ProcessUtility(Node *parsetree,
 				switch (stmt->kind)
 				{
 					case REINDEX_OBJECT_INDEX:
-						ReindexIndex(stmt->relation);
+						ReindexIndex(stmt->relation, stmt->options);
 						break;
 					case REINDEX_OBJECT_TABLE:
-						ReindexTable(stmt->relation);
+						ReindexTable(stmt->relation, stmt->options);
 						break;
 					case REINDEX_OBJECT_SCHEMA:
 					case REINDEX_OBJECT_SYSTEM:
@@ -756,7 +756,7 @@ standard_ProcessUtility(Node *parsetree,
 												(stmt->kind == REINDEX_OBJECT_SCHEMA) ? "REINDEX SCHEMA" :
 												(stmt->kind == REINDEX_OBJECT_SYSTEM) ? "REINDEX SYSTEM" :
 												"REINDEX DATABASE");
-						ReindexMultipleTables(stmt->name, stmt->kind);
+						ReindexMultipleTables(stmt->name, stmt->kind, stmt->options);
 						break;
 					default:
 						elog(ERROR, "unrecognized object type: %d",
diff --git a/src/bin/psql/tab-complete.c b/src/bin/psql/tab-complete.c
index e39a07c..d3835c8 100644
--- a/src/bin/psql/tab-complete.c
+++ b/src/bin/psql/tab-complete.c
@@ -3342,7 +3342,7 @@ psql_completion(const char *text, int start, int end)
 			COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_tm, NULL);
 		else if (pg_strcasecmp(prev_wd, "INDEX") == 0)
 			COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_indexes, NULL);
-		else if (pg_strcasecmp(prev_wd, "SCHEMA") == 0 )
+		else if (pg_strcasecmp(prev_wd, "SCHEMA") == 0)
 			COMPLETE_WITH_QUERY(Query_for_list_of_schemas);
 		else if (pg_strcasecmp(prev_wd, "SYSTEM") == 0 ||
 				 pg_strcasecmp(prev_wd, "DATABASE") == 0)
diff --git a/src/include/catalog/index.h b/src/include/catalog/index.h
index e7cc7a0..48f8660 100644
--- a/src/include/catalog/index.h
+++ b/src/include/catalog/index.h
@@ -112,7 +112,7 @@ extern void validate_index(Oid heapId, Oid indexId, Snapshot snapshot);
 extern void index_set_state_flags(Oid indexId, IndexStateFlagsAction action);
 
 extern void reindex_index(Oid indexId, bool skip_constraint_checks,
-			  char relpersistence);
+						  char relpersistence, bool verbose);
 
 /* Flag bits for reindex_relation(): */
 #define REINDEX_REL_PROCESS_TOAST			0x01
@@ -121,7 +121,7 @@ extern void reindex_index(Oid indexId, bool skip_constraint_checks,
 #define REINDEX_REL_FORCE_INDEXES_UNLOGGED	0x08
 #define REINDEX_REL_FORCE_INDEXES_PERMANENT	0x10
 
-extern bool reindex_relation(Oid relid, int flags);
+extern bool reindex_relation(Oid relid, int flags, bool verbose);
 
 extern bool ReindexIsProcessingHeap(Oid heapOid);
 extern bool ReindexIsProcessingIndex(Oid indexOid);
diff --git a/src/include/commands/defrem.h b/src/include/commands/defrem.h
index a9c6783..0b5d023 100644
--- a/src/include/commands/defrem.h
+++ b/src/include/commands/defrem.h
@@ -29,9 +29,9 @@ extern ObjectAddress DefineIndex(Oid relationId,
 			bool check_rights,
 			bool skip_build,
 			bool quiet);
-extern Oid	ReindexIndex(RangeVar *indexRelation);
-extern Oid	ReindexTable(RangeVar *relation);
-extern void ReindexMultipleTables(const char *objectName, ReindexObjectType objectKind);
+extern Oid	ReindexIndex(RangeVar *indexRelation, List *options);
+extern Oid	ReindexTable(RangeVar *relation, List *optionsc);
+extern void ReindexMultipleTables(const char *objectName, ReindexObjectType objectKind, List *options);
 extern char *makeObjectName(const char *name1, const char *name2,
 			   const char *label);
 extern char *ChooseRelationName(const char *name1, const char *name2,
diff --git a/src/include/nodes/parsenodes.h b/src/include/nodes/parsenodes.h
index ac13302..fb98fa7 100644
--- a/src/include/nodes/parsenodes.h
+++ b/src/include/nodes/parsenodes.h
@@ -2747,6 +2747,7 @@ typedef struct ReindexStmt
 	ReindexObjectType	kind;	/* REINDEX_OBJECT_INDEX, REINDEX_OBJECT_TABLE, etc. */
 	RangeVar   *relation;		/* Table or index to reindex */
 	const char *name;			/* name of database to reindex */
+	List	   *options;		/* list of options */
 } ReindexStmt;
 
 /* ----------------------
-- 
Sent via pgsql-hackers mailing list (pgsql-hackers@postgresql.org)
To make changes to your subscription:
http://www.postgresql.org/mailpref/pgsql-hackers

Reply via email to