Proposal : REINDEX xxx VERBOSE

Started by Sawada Masahikoalmost 11 years ago77 messages
#1Sawada Masahiko
sawada.mshk@gmail.com
1 attachment(s)

Hi all,

Attached patch adds VERBOSE option to REINDEX commands.
The another maintaining commands(VACUUM FULL, CLUSTER) has VERBOSE option,
but REINDEX has not been had it.

Examples is following,

- REINDEX TABLE
[postgres][5432](1)=# REINDEX TABLE VERBOSE hoge;
INFO: index "hoge_idx" was reindexed.
DETAIL: CPU 0.00s/0.00u sec elapsed 0.02 sec.
INFO: index "hoge2_idx" was reindexed.
DETAIL: CPU 0.00s/0.00u sec elapsed 0.00 sec.
REINDEX

- REINDEX SCHEMA
[postgres][5432](1)=# REINDEX SCHEMA VERBOSE s;
INFO: index "hoge_idx" was reindexed.
DETAIL: CPU 0.00s/0.00u sec elapsed 0.00 sec.
INFO: index "hoge2_idx" was reindexed.
DETAIL: CPU 0.00s/0.00u sec elapsed 0.00 sec.
INFO: indexes of whole table "s.hoge" were reindexed
REINDEX

Please give me feedbacks.

Regards,

-------
Sawada Masahiko

Attachments:

000_reindex_verbose_v1.patchapplication/octet-stream; name=000_reindex_verbose_v1.patchDownload
diff --git a/doc/src/sgml/ref/reindex.sgml b/doc/src/sgml/ref/reindex.sgml
index 0a4c7d4..a224111 100644
--- a/doc/src/sgml/ref/reindex.sgml
+++ b/doc/src/sgml/ref/reindex.sgml
@@ -21,7 +21,7 @@ PostgreSQL documentation
 
  <refsynopsisdiv>
 <synopsis>
-REINDEX { INDEX | TABLE | SCHEMA | DATABASE | SYSTEM } <replaceable class="PARAMETER">name</replaceable> [ FORCE ]
+REINDEX { INDEX | TABLE | SCHEMA | DATABASE | SYSTEM } [VERBOSE] <replaceable class="PARAMETER">name</replaceable> [ FORCE ]
 </synopsis>
  </refsynopsisdiv>
 
@@ -81,6 +81,16 @@ REINDEX { INDEX | TABLE | SCHEMA | DATABASE | SYSTEM } <replaceable class="PARAM
   <title>Parameters</title>
 
   <variablelist>
+
+   <varlistentry>
+    <term><literal>VERBOSE</literal></term>
+    <listitem>
+     <para>
+      Prints a progress report as each index is reindexed.
+     </para>
+    </listitem>
+   </varlistentry>
+
    <varlistentry>
     <term><literal>INDEX</literal></term>
     <listitem>
diff --git a/src/backend/catalog/index.c b/src/backend/catalog/index.c
index 9bb9deb..b03b679 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 dc1b37c..ecd8e71 100644
--- a/src/backend/commands/cluster.c
+++ b/src/backend/commands/cluster.c
@@ -1531,7 +1531,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 e859669..bb9b533 100644
--- a/src/backend/commands/indexcmds.c
+++ b/src/backend/commands/indexcmds.c
@@ -1678,7 +1678,7 @@ ChooseIndexColumnNames(List *indexElems)
  *		Recreate a specific index.
  */
 Oid
-ReindexIndex(RangeVar *indexRelation)
+ReindexIndex(RangeVar *indexRelation, bool verbose)
 {
 	Oid			indOid;
 	Oid			heapOid = InvalidOid;
@@ -1689,7 +1689,7 @@ ReindexIndex(RangeVar *indexRelation)
 									  RangeVarCallbackForReindexIndex,
 									  (void *) &heapOid);
 
-	reindex_index(indOid, false, indexRelation->relpersistence);
+	reindex_index(indOid, false, indexRelation->relpersistence, verbose);
 
 	return indOid;
 }
@@ -1758,7 +1758,7 @@ RangeVarCallbackForReindexIndex(const RangeVar *relation,
  *		Recreate all indexes of a table (and of its toast table, if any)
  */
 Oid
-ReindexTable(RangeVar *relation)
+ReindexTable(RangeVar *relation, bool verbose)
 {
 	Oid			heapOid;
 
@@ -1768,7 +1768,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)));
@@ -1785,7 +1786,7 @@ ReindexTable(RangeVar *relation)
  * That means this must not be called within a user transaction block!
  */
 Oid
-ReindexObject(const char *objectName, ReindexObjectType objectKind)
+ReindexObject(const char *objectName, ReindexObjectType objectKind, bool verbose)
 {
 	Oid			objectOid;
 	Relation	relationRelation;
@@ -1797,6 +1798,7 @@ ReindexObject(const char *objectName, ReindexObjectType objectKind)
 	List	   *relids = NIL;
 	ListCell   *l;
 	int	num_keys;
+	int elevel = verbose ? INFO : DEBUG2;
 
 	AssertArg(objectName);
 	Assert(objectKind == REINDEX_OBJECT_SCHEMA ||
@@ -1939,9 +1941,10 @@ ReindexObject(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 66d5083..16a57fd 100644
--- a/src/backend/commands/tablecmds.c
+++ b/src/backend/commands/tablecmds.c
@@ -1218,7 +1218,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);
 		}
 	}
 
diff --git a/src/backend/parser/gram.y b/src/backend/parser/gram.y
index 36dac29..7f82c5f 100644
--- a/src/backend/parser/gram.y
+++ b/src/backend/parser/gram.y
@@ -7318,43 +7318,48 @@ opt_if_exists: IF_P EXISTS						{ $$ = TRUE; }
  *****************************************************************************/
 
 ReindexStmt:
-			REINDEX INDEX qualified_name opt_force
+			REINDEX INDEX opt_verbose qualified_name opt_force
 				{
 					ReindexStmt *n = makeNode(ReindexStmt);
 					n->kind = REINDEX_OBJECT_INDEX;
-					n->relation = $3;
+					n->verbose = $3;
+					n->relation = $4;
 					n->name = NULL;
 					$$ = (Node *)n;
 				}
-			| REINDEX TABLE qualified_name opt_force
+			| REINDEX TABLE opt_verbose qualified_name opt_force
 				{
 					ReindexStmt *n = makeNode(ReindexStmt);
 					n->kind = REINDEX_OBJECT_TABLE;
-					n->relation = $3;
+					n->verbose = $3;
+					n->relation = $4;
 					n->name = NULL;
 					$$ = (Node *)n;
 				}
-			| REINDEX SCHEMA name opt_force
+			| REINDEX SCHEMA opt_verbose name opt_force
 				{
 					ReindexStmt *n = makeNode(ReindexStmt);
 					n->kind = REINDEX_OBJECT_SCHEMA;
-					n->name = $3;
+					n->verbose = $3;
+					n->name = $4;
 					n->relation = NULL;
 					$$ = (Node *)n;
 				}
-			| REINDEX SYSTEM_P name opt_force
+			| REINDEX SYSTEM_P opt_verbose name opt_force
 				{
 					ReindexStmt *n = makeNode(ReindexStmt);
 					n->kind = REINDEX_OBJECT_SYSTEM;
-					n->name = $3;
+					n->verbose = $3;
+					n->name = $4;
 					n->relation = NULL;
 					$$ = (Node *)n;
 				}
-			| REINDEX DATABASE name opt_force
+			| REINDEX DATABASE opt_verbose name opt_force
 				{
 					ReindexStmt *n = makeNode(ReindexStmt);
 					n->kind = REINDEX_OBJECT_DATABASE;
-					n->name = $3;
+					n->verbose = $3;
+					n->name = $4;
 					n->relation = NULL;
 					$$ = (Node *)n;
 				}
diff --git a/src/backend/tcop/utility.c b/src/backend/tcop/utility.c
index 3533cfa..19ebb90 100644
--- a/src/backend/tcop/utility.c
+++ b/src/backend/tcop/utility.c
@@ -750,10 +750,10 @@ standard_ProcessUtility(Node *parsetree,
 				switch (stmt->kind)
 				{
 					case REINDEX_OBJECT_INDEX:
-						ReindexIndex(stmt->relation);
+						ReindexIndex(stmt->relation, stmt->verbose);
 						break;
 					case REINDEX_OBJECT_TABLE:
-						ReindexTable(stmt->relation);
+						ReindexTable(stmt->relation, stmt->verbose);
 						break;
 					case REINDEX_OBJECT_SCHEMA:
 					case REINDEX_OBJECT_SYSTEM:
@@ -768,7 +768,7 @@ standard_ProcessUtility(Node *parsetree,
 						PreventTransactionChain(isTopLevel,
 												(stmt->kind == REINDEX_OBJECT_SCHEMA) ?
 												"REINDEX SCHEMA" : "REINDEX DATABASE");
-						ReindexObject(stmt->name, stmt->kind);
+						ReindexObject(stmt->name, stmt->kind, stmt->verbose);
 						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..5baa8aa 100644
--- a/src/bin/psql/tab-complete.c
+++ b/src/bin/psql/tab-complete.c
@@ -3336,17 +3336,39 @@ psql_completion(const char *text, int start, int end)
 
 		COMPLETE_WITH_LIST(list_REINDEX);
 	}
-	else if (pg_strcasecmp(prev2_wd, "REINDEX") == 0)
+	else if ((pg_strcasecmp(prev2_wd, "REINDEX") == 0 &&
+			  pg_strcasecmp(prev_wd, "TABLE") == 0) ||
+			 (pg_strcasecmp(prev3_wd, "REINDEX") == 0 &&
+			  pg_strcasecmp(prev2_wd, "TABLE") == 0 &&
+			  pg_strcasecmp(prev_wd, "VERBOSE") == 0))
 	{
-		if (pg_strcasecmp(prev_wd, "TABLE") == 0)
-			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 )
-			COMPLETE_WITH_QUERY(Query_for_list_of_schemas);
-		else if (pg_strcasecmp(prev_wd, "SYSTEM") == 0 ||
-				 pg_strcasecmp(prev_wd, "DATABASE") == 0)
-			COMPLETE_WITH_QUERY(Query_for_list_of_databases);
+		COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_tm, "UNION SELECT 'VERBOSE'");
+	}
+	else if ((pg_strcasecmp(prev2_wd, "REINDEX") == 0 &&
+			  pg_strcasecmp(prev_wd, "INDEX") == 0) ||
+			 (pg_strcasecmp(prev3_wd, "REINDEX") == 0 &&
+			  pg_strcasecmp(prev2_wd, "INDEX") == 0 &&
+			  pg_strcasecmp(prev_wd, "VERBOSE") == 0))
+	{
+		COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_indexes, "UNION SELECT 'VERBOSE'");
+	}
+	else if ((pg_strcasecmp(prev2_wd, "REINDEX") == 0 &&
+			  pg_strcasecmp(prev_wd, "SYSTEM") == 0) ||
+			 (pg_strcasecmp(prev3_wd, "REINDEX") == 0 &&
+			  pg_strcasecmp(prev2_wd, "SYSTEM") == 0 &&
+			  pg_strcasecmp(prev_wd, "VERBOSE") == 0))
+	{
+		COMPLETE_WITH_QUERY(Query_for_list_of_databases "UNION SELECT 'VERBOSE'");
+	}
+	else if ((pg_strcasecmp(prev2_wd, "REINDEX") == 0 &&
+			 (pg_strcasecmp(prev_wd, "SCHEMA") == 0 ||
+			  pg_strcasecmp(prev_wd, "DATABASE") == 0)) ||
+			 (pg_strcasecmp(prev3_wd, "REINDEX") == 0 &&
+			  (pg_strcasecmp(prev2_wd, "SCHEMA") == 0 ||
+			   pg_strcasecmp(prev2_wd, "DATABASE") == 0) &&
+			  pg_strcasecmp(prev_wd, "VERBOSE") == 0))
+	{
+		COMPLETE_WITH_QUERY(Query_for_list_of_schemas "UNION SELECT 'VERBOSE'");
 	}
 
 /* SECURITY LABEL */
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 cf586fe..8ebb2d5 100644
--- a/src/include/commands/defrem.h
+++ b/src/include/commands/defrem.h
@@ -28,9 +28,10 @@ extern Oid DefineIndex(Oid relationId,
 			bool check_rights,
 			bool skip_build,
 			bool quiet);
-extern Oid	ReindexIndex(RangeVar *indexRelation);
-extern Oid	ReindexTable(RangeVar *relation);
-extern Oid ReindexObject(const char *databaseName, ReindexObjectType kind);
+extern Oid	ReindexIndex(RangeVar *indexRelation, bool verbose);
+extern Oid	ReindexTable(RangeVar *relation, bool verbose);
+extern Oid ReindexObject(const char *databaseName, ReindexObjectType kind,
+				bool verbose);
 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 b1dfa85..c840e41 100644
--- a/src/include/nodes/parsenodes.h
+++ b/src/include/nodes/parsenodes.h
@@ -2739,6 +2739,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 */
+	bool		verbose;		/* print progress info */
 } ReindexStmt;
 
 /* ----------------------
#2Michael Paquier
michael.paquier@gmail.com
In reply to: Sawada Masahiko (#1)
Re: Proposal : REINDEX xxx VERBOSE

On Mon, Feb 2, 2015 at 8:31 PM, Sawada Masahiko <sawada.mshk@gmail.com> wrote:

Attached patch adds VERBOSE option to REINDEX commands.
Please give me feedbacks.

This could provide useful feedback to users. Now, I think that it may
be better to provide the keyword VERBOSE before the type of object
reindexed as REINDEX [ VERBOSE ] object. In any case, at quick sight,
the table completion for REINDEX is broken with your patch because by
typing REINDEX VERBOSE you would show the list of objects and once
again VERBOSE.
--
Michael

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

#3Sawada Masahiko
sawada.mshk@gmail.com
In reply to: Michael Paquier (#2)
Re: Proposal : REINDEX xxx VERBOSE

On Mon, Feb 2, 2015 at 9:21 PM, Michael Paquier
<michael.paquier@gmail.com> wrote:

On Mon, Feb 2, 2015 at 8:31 PM, Sawada Masahiko <sawada.mshk@gmail.com> wrote:

Attached patch adds VERBOSE option to REINDEX commands.
Please give me feedbacks.

This could provide useful feedback to users.

Thanks.

Now, I think that it may
be better to provide the keyword VERBOSE before the type of object
reindexed as REINDEX [ VERBOSE ] object.

Actually, my first WIP version of patch added VERBOSE word at before
type of object.
I'm feeling difficult about that the position of VERBOSE word in
REINDEX statement.

In any case, at quick sight,
the table completion for REINDEX is broken with your patch because by
typing REINDEX VERBOSE you would show the list of objects and once
again VERBOSE.

I have also rebased the tab-completion source, I think it's not happen.
In my environment, it does not show list of object and VERBOSE again
after typing REINDEX VERBOSE.

Regards,

-------
Sawada Masahiko

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

#4Tom Lane
tgl@sss.pgh.pa.us
In reply to: Sawada Masahiko (#3)
Re: Proposal : REINDEX xxx VERBOSE

Sawada Masahiko <sawada.mshk@gmail.com> writes:

On Mon, Feb 2, 2015 at 9:21 PM, Michael Paquier
<michael.paquier@gmail.com> wrote:

Now, I think that it may
be better to provide the keyword VERBOSE before the type of object
reindexed as REINDEX [ VERBOSE ] object.

Actually, my first WIP version of patch added VERBOSE word at before
type of object.
I'm feeling difficult about that the position of VERBOSE word in
REINDEX statement.

The way that FORCE was added to REINDEX was poorly thought out; let's not
double down on that with another option added without any consideration
for future expansion. I'd be happier if we adopted something similar to
the modern syntax for VACUUM and EXPLAIN, ie, comma-separated options in
parentheses.

regards, tom lane

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

#5Sawada Masahiko
sawada.mshk@gmail.com
In reply to: Tom Lane (#4)
Re: Proposal : REINDEX xxx VERBOSE

On Tue, Feb 3, 2015 at 12:32 AM, Tom Lane <tgl@sss.pgh.pa.us> wrote:

Sawada Masahiko <sawada.mshk@gmail.com> writes:

On Mon, Feb 2, 2015 at 9:21 PM, Michael Paquier
<michael.paquier@gmail.com> wrote:

Now, I think that it may
be better to provide the keyword VERBOSE before the type of object
reindexed as REINDEX [ VERBOSE ] object.

Actually, my first WIP version of patch added VERBOSE word at before
type of object.
I'm feeling difficult about that the position of VERBOSE word in
REINDEX statement.

The way that FORCE was added to REINDEX was poorly thought out; let's not
double down on that with another option added without any consideration
for future expansion. I'd be happier if we adopted something similar to
the modern syntax for VACUUM and EXPLAIN, ie, comma-separated options in
parentheses.

I understood.
I'm imagining new REINDEX syntax are followings.
- REINDEX (INDEX, VERBOSE) hoge_idx;
- REINDEX (TABLE) hoge_table;

i.g., I will add following syntax format,
REINDEX ( { INDEX | TABLE | SCHEMA | SYSTEM | DATABASE } , [VERBOSE] )
name [FORCE];

Thought?

Regards,

-------
Sawada Masahiko

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

#6Fabrízio de Royes Mello
fabriziomello@gmail.com
In reply to: Sawada Masahiko (#5)
Re: Proposal : REINDEX xxx VERBOSE

On Tue, Feb 3, 2015 at 9:09 AM, Sawada Masahiko <sawada.mshk@gmail.com>
wrote:

On Tue, Feb 3, 2015 at 12:32 AM, Tom Lane <tgl@sss.pgh.pa.us> wrote:

Sawada Masahiko <sawada.mshk@gmail.com> writes:

On Mon, Feb 2, 2015 at 9:21 PM, Michael Paquier
<michael.paquier@gmail.com> wrote:

Now, I think that it may
be better to provide the keyword VERBOSE before the type of object
reindexed as REINDEX [ VERBOSE ] object.

Actually, my first WIP version of patch added VERBOSE word at before
type of object.
I'm feeling difficult about that the position of VERBOSE word in
REINDEX statement.

The way that FORCE was added to REINDEX was poorly thought out; let's

not

double down on that with another option added without any consideration
for future expansion. I'd be happier if we adopted something similar to
the modern syntax for VACUUM and EXPLAIN, ie, comma-separated options in
parentheses.

I understood.
I'm imagining new REINDEX syntax are followings.
- REINDEX (INDEX, VERBOSE) hoge_idx;
- REINDEX (TABLE) hoge_table;

i.g., I will add following syntax format,
REINDEX ( { INDEX | TABLE | SCHEMA | SYSTEM | DATABASE } , [VERBOSE] )
name [FORCE];

Thought?

I don't think the keyworks INDEX, TABLE, SCHEMA, SYSTEM and DATABASE are
options... they are part of the command IMHO.

Maybe something like:

REINDEX { INDEX | TABLE | SCHEMA | SYSTEM | DATABASE } [( [ FORCE ],
[VERBOSE] ) ] name;

And maintain the old syntax for compatibility of course.

Regards,

--
Fabrízio de Royes Mello
Consultoria/Coaching PostgreSQL

Show quoted text

Timbira: http://www.timbira.com.br
Blog: http://fabriziomello.github.io
Linkedin: http://br.linkedin.com/in/fabriziomello
Twitter: http://twitter.com/fabriziomello
Github: http://github.com/fabriziomello

#7Tom Lane
tgl@sss.pgh.pa.us
In reply to: Sawada Masahiko (#5)
Re: Proposal : REINDEX xxx VERBOSE

Sawada Masahiko <sawada.mshk@gmail.com> writes:

On Tue, Feb 3, 2015 at 12:32 AM, Tom Lane <tgl@sss.pgh.pa.us> wrote:

The way that FORCE was added to REINDEX was poorly thought out; let's not
double down on that with another option added without any consideration
for future expansion. I'd be happier if we adopted something similar to
the modern syntax for VACUUM and EXPLAIN, ie, comma-separated options in
parentheses.

I understood.
I'm imagining new REINDEX syntax are followings.
- REINDEX (INDEX, VERBOSE) hoge_idx;
- REINDEX (TABLE) hoge_table;

i.g., I will add following syntax format,
REINDEX ( { INDEX | TABLE | SCHEMA | SYSTEM | DATABASE } , [VERBOSE] )
name [FORCE];

Well, the object type is not an optional part of the command. It's
*necessary*. I was thinking more like

REINDEX { INDEX | TABLE | etc } name [ ( option [, option ...] ) ]

option := FORCE | VERBOSE

We'd still keep the historical syntax where you can write FORCE outside
parens, but it'd be deprecated.

Where to insert the parenthesized option list is a judgment call,
but I'd lean to keeping it at the end where FORCE used to be.

regards, tom lane

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

#8Andres Freund
andres@2ndquadrant.com
In reply to: Tom Lane (#7)
Re: Proposal : REINDEX xxx VERBOSE

On 2015-02-03 10:20:03 -0500, Tom Lane wrote:

Sawada Masahiko <sawada.mshk@gmail.com> writes:

On Tue, Feb 3, 2015 at 12:32 AM, Tom Lane <tgl@sss.pgh.pa.us> wrote:

The way that FORCE was added to REINDEX was poorly thought out; let's not
double down on that with another option added without any consideration
for future expansion. I'd be happier if we adopted something similar to
the modern syntax for VACUUM and EXPLAIN, ie, comma-separated options in
parentheses.

I understood.
I'm imagining new REINDEX syntax are followings.
- REINDEX (INDEX, VERBOSE) hoge_idx;
- REINDEX (TABLE) hoge_table;

i.g., I will add following syntax format,
REINDEX ( { INDEX | TABLE | SCHEMA | SYSTEM | DATABASE } , [VERBOSE] )
name [FORCE];

Well, the object type is not an optional part of the command. It's
*necessary*. I was thinking more like

REINDEX { INDEX | TABLE | etc } name [ ( option [, option ...] ) ]

option := FORCE | VERBOSE

We'd still keep the historical syntax where you can write FORCE outside
parens, but it'd be deprecated.

Why would we allow force inside the parens, given it's a backward compat
only thing afaik? Don't get me wrong, I'm not at all against a
extensible syntax, I just don't see a point in further cargo culting
FORCE.

Greetings,

Andres Freund

--
Andres Freund http://www.2ndQuadrant.com/
PostgreSQL Development, 24x7 Support, Training & Services

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

#9Tom Lane
tgl@sss.pgh.pa.us
In reply to: Andres Freund (#8)
Re: Proposal : REINDEX xxx VERBOSE

Andres Freund <andres@2ndquadrant.com> writes:

On 2015-02-03 10:20:03 -0500, Tom Lane wrote:

Well, the object type is not an optional part of the command. It's
*necessary*. I was thinking more like

REINDEX { INDEX | TABLE | etc } name [ ( option [, option ...] ) ]

option := FORCE | VERBOSE

We'd still keep the historical syntax where you can write FORCE outside
parens, but it'd be deprecated.

Why would we allow force inside the parens, given it's a backward compat
only thing afaik? Don't get me wrong, I'm not at all against a
extensible syntax, I just don't see a point in further cargo culting
FORCE.

Ah, I'd forgotten that that option was now a no-op. Yeah, there's no
reason to support it in the new syntax.

regards, tom lane

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

#10Jim Nasby
Jim.Nasby@BlueTreble.com
In reply to: Tom Lane (#7)
Re: Proposal : REINDEX xxx VERBOSE

On 2/3/15 9:20 AM, Tom Lane wrote:

i.g., I will add following syntax format,
REINDEX ( { INDEX | TABLE | SCHEMA | SYSTEM | DATABASE } , [VERBOSE] )
name [FORCE];

Well, the object type is not an optional part of the command. It's
*necessary*. I was thinking more like

REINDEX { INDEX | TABLE | etc } name [ ( option [, option ...] ) ]

VACUUM puts the options before the table name, so ISTM it'd be best to
keep that with REINDEX. Either REINDEX (options) {INDEX | ...} or
REINDEX {INDEX | ...} (options).
--
Jim Nasby, Data Architect, Blue Treble Consulting
Data in Trouble? Get it in Treble! http://BlueTreble.com

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

#11Tom Lane
tgl@sss.pgh.pa.us
In reply to: Jim Nasby (#10)
Re: Proposal : REINDEX xxx VERBOSE

Jim Nasby <Jim.Nasby@bluetreble.com> writes:

On 2/3/15 9:20 AM, Tom Lane wrote:

Well, the object type is not an optional part of the command. It's
*necessary*. I was thinking more like
REINDEX { INDEX | TABLE | etc } name [ ( option [, option ...] ) ]

VACUUM puts the options before the table name, so ISTM it'd be best to
keep that with REINDEX. Either REINDEX (options) {INDEX | ...} or
REINDEX {INDEX | ...} (options).

Well, I really really don't like the first of those. IMO the command name
is "REINDEX INDEX" etc, so sticking something in the middle of that is
bogus.

regards, tom lane

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

#12Fabrízio de Royes Mello
fabriziomello@gmail.com
In reply to: Jim Nasby (#10)
Re: Proposal : REINDEX xxx VERBOSE

On Tue, Feb 3, 2015 at 8:26 PM, Jim Nasby <Jim.Nasby@bluetreble.com> wrote:

On 2/3/15 9:20 AM, Tom Lane wrote:

i.g., I will add following syntax format,
REINDEX ( { INDEX | TABLE | SCHEMA | SYSTEM | DATABASE } , [VERBOSE] )
name [FORCE];

Well, the object type is not an optional part of the command. It's
*necessary*. I was thinking more like

REINDEX { INDEX | TABLE | etc } name [ ( option [, option ...] ) ]

VACUUM puts the options before the table name, so ISTM it'd be best to

keep that with REINDEX. Either REINDEX (options) {INDEX | ...} or REINDEX
{INDEX | ...} (options).

Makes sense... +1

Regards,

--
Fabrízio de Royes Mello
Consultoria/Coaching PostgreSQL

Show quoted text

Timbira: http://www.timbira.com.br
Blog: http://fabriziomello.github.io
Linkedin: http://br.linkedin.com/in/fabriziomello
Twitter: http://twitter.com/fabriziomello
Github: http://github.com/fabriziomello

#13Jim Nasby
Jim.Nasby@BlueTreble.com
In reply to: Tom Lane (#11)
Re: Proposal : REINDEX xxx VERBOSE

On 2/3/15 5:08 PM, Tom Lane wrote:

Jim Nasby <Jim.Nasby@bluetreble.com> writes:

On 2/3/15 9:20 AM, Tom Lane wrote:

Well, the object type is not an optional part of the command. It's
*necessary*. I was thinking more like
REINDEX { INDEX | TABLE | etc } name [ ( option [, option ...] ) ]

VACUUM puts the options before the table name, so ISTM it'd be best to
keep that with REINDEX. Either REINDEX (options) {INDEX | ...} or
REINDEX {INDEX | ...} (options).

Well, I really really don't like the first of those. IMO the command name
is "REINDEX INDEX" etc, so sticking something in the middle of that is
bogus.

Actually, is there a reason we can't just accept all 3? Forcing people
to remember exact ordering of options has always struck me as silly.
--
Jim Nasby, Data Architect, Blue Treble Consulting
Data in Trouble? Get it in Treble! http://BlueTreble.com

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

#14Tom Lane
tgl@sss.pgh.pa.us
In reply to: Jim Nasby (#13)
Re: Proposal : REINDEX xxx VERBOSE

Jim Nasby <Jim.Nasby@BlueTreble.com> writes:

On 2/3/15 5:08 PM, Tom Lane wrote:

Jim Nasby <Jim.Nasby@bluetreble.com> writes:

VACUUM puts the options before the table name, so ISTM it'd be best to
keep that with REINDEX. Either REINDEX (options) {INDEX | ...} or
REINDEX {INDEX | ...} (options).

Well, I really really don't like the first of those. IMO the command name
is "REINDEX INDEX" etc, so sticking something in the middle of that is
bogus.

Actually, is there a reason we can't just accept all 3? Forcing people
to remember exact ordering of options has always struck me as silly.

And that's an even worse idea. Useless "flexibility" in syntax tends to
lead to unfortunate consequences like having to reserve keywords.

regards, tom lane

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

#15Sawada Masahiko
sawada.mshk@gmail.com
In reply to: Tom Lane (#14)
Re: Proposal : REINDEX xxx VERBOSE

On Wed, Feb 4, 2015 at 2:44 PM, Tom Lane <tgl@sss.pgh.pa.us> wrote:

Jim Nasby <Jim.Nasby@BlueTreble.com> writes:

On 2/3/15 5:08 PM, Tom Lane wrote:

Jim Nasby <Jim.Nasby@bluetreble.com> writes:

VACUUM puts the options before the table name, so ISTM it'd be best to
keep that with REINDEX. Either REINDEX (options) {INDEX | ...} or
REINDEX {INDEX | ...} (options).

Well, I really really don't like the first of those. IMO the command name
is "REINDEX INDEX" etc, so sticking something in the middle of that is
bogus.

Actually, is there a reason we can't just accept all 3? Forcing people
to remember exact ordering of options has always struck me as silly.

And that's an even worse idea. Useless "flexibility" in syntax tends to
lead to unfortunate consequences like having to reserve keywords.

As per discussion, it seems to good with
REINDEX { INDEX | TABLE | etc } name [ ( option [, option ...] ) ]
or
REINDEX { INDEX | TABLE | etc } [ (option [, optoin ...] ) ] name
i.g., the options of reindex(VERBOSE and FORCE) are put at before or
after object name.

Because other maintenance command put option at before object name, I
think the latter is better.

Regards,

-------
Sawada Masahiko

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

#16Kyotaro HORIGUCHI
horiguchi.kyotaro@lab.ntt.co.jp
In reply to: Sawada Masahiko (#15)
Re: Proposal : REINDEX xxx VERBOSE

Hello,

As per discussion, it seems to good with
REINDEX { INDEX | TABLE | etc } name [ ( option [, option ...] ) ]
or
REINDEX { INDEX | TABLE | etc } [ (option [, optoin ...] ) ] name
i.g., the options of reindex(VERBOSE and FORCE) are put at before or
after object name.

Because other maintenance command put option at before object name, I
think the latter is better.

The phrase "{INDEX | TABLE |..} name" seems to me indivisible as
target specification. IMHO, the options for VACUUM and so is
placed *just after* command name, not *before* the target.

If this is right, the syntax would be like this.

REINDEX [ (option [, option ...] ) ] {INDEX | TABLE | etc } name

What do you think about this?

regares,

--
Kyotaro Horiguchi
NTT Open Source Software Center

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

#17Tom Lane
tgl@sss.pgh.pa.us
In reply to: Kyotaro HORIGUCHI (#16)
Re: Proposal : REINDEX xxx VERBOSE

Kyotaro HORIGUCHI <horiguchi.kyotaro@lab.ntt.co.jp> writes:

The phrase "{INDEX | TABLE |..} name" seems to me indivisible as
target specification. IMHO, the options for VACUUM and so is
placed *just after* command name, not *before* the target.

If this is right, the syntax would be like this.

REINDEX [ (option [, option ...] ) ] {INDEX | TABLE | etc } name

What do you think about this?

I think this is wrong and ugly. INDEX etc are part of the command name.

regards, tom lane

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

#18David G Johnston
david.g.johnston@gmail.com
In reply to: Tom Lane (#17)
Re: Proposal : REINDEX xxx VERBOSE

Tom Lane-2 wrote

Kyotaro HORIGUCHI &lt;

horiguchi.kyotaro@.co

&gt; writes:

The phrase "{INDEX | TABLE |..} name" seems to me indivisible as
target specification. IMHO, the options for VACUUM and so is
placed *just after* command name, not *before* the target.

If this is right, the syntax would be like this.

REINDEX [ (option [, option ...] ) ] {INDEX | TABLE | etc } name

What do you think about this?

I think this is wrong and ugly. INDEX etc are part of the command name.

I can argue either position...

I lean toward those not being part of the command name because:

The documentation lists only "REINDEX" as a command while "DROP" gets a
separate entry for each type of object it is able to drop; mainly because
the behavior of each command could/does differ based upon the target while
REINDEX will still simply cause indexes to be rebuilt and the modifier's
purposes is to aid in the selection of target indexes.

REINDEX [ ( VERBOSE ) ] { INDEX | TABLE | DATABASE | SYSTEM } name

That said, the entire notes section is written like the writer also believed
that "REINDEX INDEX" is a command in its own right...

VACUUM is a good comparison command and, besides, putting VERBOSE after the
entire thing just doesn't seem right - though that is the only other option
that would work for me. When you read other commands with pre and post
options the wording usually flows reasonably well (IF EXISTS being, for me,
an exception - it reads better after the name, not before, but I
digress...). REINDEX ( VERBOSE ) /target/ reads well to me; I'm already
sold that "TABLE name" and "INDEX name" are target specifiers.

David J.

--
View this message in context: http://postgresql.nabble.com/Proposal-REINDEX-xxx-VERBOSE-tp5836377p5836782.html
Sent from the PostgreSQL - hackers mailing list archive at Nabble.com.

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

#19Robert Haas
robertmhaas@gmail.com
In reply to: Tom Lane (#17)
Re: Proposal : REINDEX xxx VERBOSE

On Wed, Feb 4, 2015 at 8:24 PM, Tom Lane <tgl@sss.pgh.pa.us> wrote:

Kyotaro HORIGUCHI <horiguchi.kyotaro@lab.ntt.co.jp> writes:

The phrase "{INDEX | TABLE |..} name" seems to me indivisible as
target specification. IMHO, the options for VACUUM and so is
placed *just after* command name, not *before* the target.

If this is right, the syntax would be like this.

REINDEX [ (option [, option ...] ) ] {INDEX | TABLE | etc } name

What do you think about this?

I think this is wrong and ugly. INDEX etc are part of the command name.

I don't think so. I think they're part of the target. We have one
manual page is for REINDEX, not five separate reference pages for
REINDEX INDEX, REINDEX TABLE, REINDEX SCHEMA, REINDEX DATABASE, and
REINDEX SYSTEM. If we really wanted to, we could probably even
support this:

REINDEX INDEX foo, TABLE bar, TABLE baz;

We've got a mix of styles for extensible options right now:

EXPLAIN [ ( option [, ...] ) ] statement
COPY table_name [ ( column_name [, ...] ) ]
FROM { 'filename' | PROGRAM 'command' | STDIN }
[ [ WITH ] ( option [, ...] ) ]
VACUUM [ ( { FULL | FREEZE | VERBOSE | ANALYZE } [, ...] ) ] [
table_name [ (column_name [, ...] ) ] ]

So COPY puts the options at the very end, but EXPLAIN and VACUUM put
them right after the command name. I prefer the latter style and
would vote to adopt it here.

--
Robert Haas
EnterpriseDB: http://www.enterprisedb.com
The Enterprise PostgreSQL Company

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

#20Tom Lane
tgl@sss.pgh.pa.us
In reply to: Robert Haas (#19)
Re: Proposal : REINDEX xxx VERBOSE

Robert Haas <robertmhaas@gmail.com> writes:

We've got a mix of styles for extensible options right now:

That we do.

So COPY puts the options at the very end, but EXPLAIN and VACUUM put
them right after the command name. I prefer the latter style and
would vote to adopt it here.

Meh. Options-at-the-end seems by far the most sensible style to me.
The options-right-after-the-keyword style is a mess, both logically
and from a parsing standpoint, and the only reason we have it at all
is historical artifact (ask Bruce about the origins of VACUUM ANALYZE
over a beer sometime).

Still, I can't help noticing that I'm being outvoted. I'll shut up now.

regards, tom lane

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

#21Jim Nasby
Jim.Nasby@BlueTreble.com
In reply to: Tom Lane (#20)
Re: Proposal : REINDEX xxx VERBOSE

On 2/5/15 12:01 PM, Tom Lane wrote:

Robert Haas <robertmhaas@gmail.com> writes:

We've got a mix of styles for extensible options right now:

That we do.

So COPY puts the options at the very end, but EXPLAIN and VACUUM put
them right after the command name. I prefer the latter style and
would vote to adopt it here.

Meh. Options-at-the-end seems by far the most sensible style to me.
The options-right-after-the-keyword style is a mess, both logically
and from a parsing standpoint, and the only reason we have it at all
is historical artifact (ask Bruce about the origins of VACUUM ANALYZE
over a beer sometime).

I suspect at least some of this stems from how command line programs
tend to process options before arguments. I tend to agree with you Tom,
but I think what's more important is that we're consistent. COPY is
already a bit of an oddball because it uses WITH, but both EXPLAIN and
VACUUM use parenthesis immediately after the first verb. Introducing a
parenthesis version that goes at the end instead of the beginning is
just going to make this worse.

If we're going to take a stand on this, we need to do it NOW, before we
have even more commands that use ().

I know you were worried about accepting options anywhere because it
leads to reserved words, but perhaps we could support it just for
EXPLAIN and VACUUM, and then switch to trailing options if people think
that would be better.
--
Jim Nasby, Data Architect, Blue Treble Consulting
Data in Trouble? Get it in Treble! http://BlueTreble.com

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

#22Kyotaro HORIGUCHI
horiguchi.kyotaro@lab.ntt.co.jp
In reply to: Jim Nasby (#21)
Re: Proposal : REINDEX xxx VERBOSE

Hello, I had a look on gram.y and found other syntaxes using WITH
option clause.

At Wed, 11 Feb 2015 14:34:17 -0600, Jim Nasby <Jim.Nasby@BlueTreble.com> wrote in <54DBBCC9.1020206@BlueTreble.com>

I suspect at least some of this stems from how command line programs
tend to process options before arguments. I tend to agree with you
Tom, but I think what's more important is that we're consistent. COPY
is already a bit of an oddball because it uses WITH, but both EXPLAIN
and VACUUM use parenthesis immediately after the first
verb. Introducing a parenthesis version that goes at the end instead
of the beginning is just going to make this worse.

If we're going to take a stand on this, we need to do it NOW, before
we have even more commands that use ().

I know you were worried about accepting options anywhere because it
leads to reserved words, but perhaps we could support it just for
EXPLAIN and VACUUM, and then switch to trailing options if people
think that would be better.

I agree with the direction, but I see two issues here; how many
syntax variants we are allowed to have for one command at a time,
and how far we should/may extend the unified options syntax on
other commands.

Let me put the issues aside for now, VACUUM can have trailing
options naturally but it seems to change, but, IMHO, EXPLAIN
should have the target statement at the tail end. Are you
thinking of syntaxes like following?

VACUUM [FULL] [FREEZE] ... [ANALYZE] [tname [(cname, ...)]
| VACUUM [({FULL [bool]|FREEZE [bool]|...}[,...])] [tname [(cname, ...)]
| VACUUM [tname [(cname, ...)] [[WITH ]({FULL [bool]|FREEZE [bool]|...})]

REINDEX [{INDEX|TABLE|...}] name [[WITH] (VERBOSE [bool]|...)]

EXPLAIN [[WITH] ({ANALYZE [bool]|VERBOSE [bool]|... [,...]})] <statement>

For concrete examples, the lines prefixed by asterisk are in new
syntax.

VACUUM FULL table1;
VACUUM ANALYZE table1 (col1);
VACUUM (ANALYZE, VERBOSE) table1 (col1);
*VACUUM table1 WITH (FREEZE on)
*VACUUM table1 (cola) WITH (ANALYZE)
*VACUUM table1 WITH (ANALYZE)
*VACUUM table1 (FREEZE on)

The fifth example looks quite odd.

REINDEX INDEX index1 FORCE;
*REINDEX TABLE table1 WITH (VERBOSE on);
*REINDEX TABLE table1 (VERBOSE on, FORCE on);

EXPLAIN (ANALYZE) SELECT 1;
*EXPLAIN WITH (ANALYZE) SELECT 1;

The WITH looks a bit uneasy..

COPY table1 FROM 'file.txt' WITH (FORMAT csv);

Returning to the second issue, the following statements have
option list (or single option) preceded (or not preceded) by the
word WITH. The prefixing dollar sign indicates that the syntax is
of SQL standard according to the PostgreSQL
Documentation. Asterisk indicates that the line shows the syntax
if the new policy is applied. Other few statements like DECLARE
looks using WITH as a part of an idiom.

CREATE MATERIALIZED VIEW mv1 WITH (storageparam, ...) AS qry WITH DATA;

This is similar to EXPLAIN in the sense that a query follows
it, but this syntax can have the second WITH follows by DATA.

CREATE EXTENSION ext1 WITH SCHEMA s1 VERSION v1 FROM over;
*CREATE EXTENSION ext1 WITH (SCHEMA s1, VERSION v1, FROM over);

This seems to fit the unification.

CREATE ROLE role WITH LOGIN;
CREATE ROLE role SUPERUSER, LOGIN;
$CREATE ROLE role WITH ADMIN admin;
*CREATE ROLE role WITH (SUPERUSER, LOGIN);
*CREATE ROLE role (SUPERUSER, LOGIN);

This seems meaninglessly too complecated.

GRANT .... WITH GRANT OPTION;
*GRANT .... WITH (GRANT on);

Mmm. Seems no reasoning...

CREATE VIEW v1 AS qry WITH CASCADED CHECK OPTION;
*CREATE VIEW v1 AS qry WITH (CASCADED_CHECK);

Wired syntax?

ALTER DATABASE db1 WITH CONNECTION LIMIT 50;
*ALTER DATABASE db1 WITH (CONNECTION_LIMIT 50);

Hardly looks reasonable..

$DECLARE c1 INSENSITIVE SCROLL CURSOR WITH HOLD;

This cannot have another style.

Mmm... I'm at a loss what is desirable..

regards,

--
Kyotaro Horiguchi
NTT Open Source Software Center

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

#23Jim Nasby
Jim.Nasby@BlueTreble.com
In reply to: Kyotaro HORIGUCHI (#22)
Re: Proposal : REINDEX xxx VERBOSE

On 2/16/15 9:43 PM, Kyotaro HORIGUCHI wrote:

Hello, I had a look on gram.y and found other syntaxes using WITH
option clause.

At Wed, 11 Feb 2015 14:34:17 -0600, Jim Nasby<Jim.Nasby@BlueTreble.com> wrote in<54DBBCC9.1020206@BlueTreble.com>

I suspect at least some of this stems from how command line programs
tend to process options before arguments. I tend to agree with you
Tom, but I think what's more important is that we're consistent. COPY
is already a bit of an oddball because it uses WITH, but both EXPLAIN
and VACUUM use parenthesis immediately after the first
verb. Introducing a parenthesis version that goes at the end instead
of the beginning is just going to make this worse.

If we're going to take a stand on this, we need to do it NOW, before
we have even more commands that use ().

I know you were worried about accepting options anywhere because it
leads to reserved words, but perhaps we could support it just for
EXPLAIN and VACUUM, and then switch to trailing options if people
think that would be better.

I agree with the direction, but I see two issues here; how many
syntax variants we are allowed to have for one command at a time,
and how far we should/may extend the unified options syntax on
other commands.

Let me put the issues aside for now, VACUUM can have trailing
options naturally but it seems to change, but, IMHO, EXPLAIN
should have the target statement at the tail end. Are you
thinking of syntaxes like following?

VACUUM [FULL] [FREEZE] ... [ANALYZE] [tname [(cname, ...)]
| VACUUM [({FULL [bool]|FREEZE [bool]|...}[,...])] [tname [(cname, ...)]
| VACUUM [tname [(cname, ...)] [[WITH ]({FULL [bool]|FREEZE [bool]|...})]

REINDEX [{INDEX|TABLE|...}] name [[WITH] (VERBOSE [bool]|...)]

EXPLAIN [[WITH] ({ANALYZE [bool]|VERBOSE [bool]|... [,...]})] <statement>

For concrete examples, the lines prefixed by asterisk are in new
syntax.

If I could choose only one for explain, I would find it easier to be up
front. That way you do the explain part on one line and just paste the
query after that.

VACUUM FULL table1;
VACUUM ANALYZE table1 (col1);
VACUUM (ANALYZE, VERBOSE) table1 (col1);
*VACUUM table1 WITH (FREEZE on)
*VACUUM table1 (cola) WITH (ANALYZE)
*VACUUM table1 WITH (ANALYZE)
*VACUUM table1 (FREEZE on)

The fifth example looks quite odd.

I don't think we need to allow both () and WITH... I'd say one or the
other, preferably ().
--
Jim Nasby, Data Architect, Blue Treble Consulting
Data in Trouble? Get it in Treble! http://BlueTreble.com

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

#24Sawada Masahiko
sawada.mshk@gmail.com
In reply to: Kyotaro HORIGUCHI (#22)
Re: Proposal : REINDEX xxx VERBOSE

VACUUM [FULL] [FREEZE] ... [ANALYZE] [tname [(cname, ...)]
| VACUUM [({FULL [bool]|FREEZE [bool]|...}[,...])] [tname [(cname, ...)]
| VACUUM [tname [(cname, ...)] [[WITH ]({FULL [bool]|FREEZE [bool]|...})]

REINDEX [{INDEX|TABLE|...}] name [[WITH] (VERBOSE [bool]|...)]

EXPLAIN [[WITH] ({ANALYZE [bool]|VERBOSE [bool]|... [,...]})] <statement>

I don't think "(OptionName [bool])" style like "(VERBOSE on, FORCE
on)" is needed for REINDEX command.
EXPLAIN command has such option style because it has the FORMAT option
can have value excepting ON/TRUE or OFF/FALSE.(e.g., TEXT, XML)
But the value of REINDEX command option can have only ON or OFF.
I think the option name is good enough.

Next, regarding of the location of such option, the several
maintenance command like CLUSTER, VACUUM has option at immediately
after command name.
From consistency perspective, I tend to agree with Robert to put
option at immediately after command name as follows.
REINDEX [(VERBOSE | FORCE)] {INDEX | ...} name;

Btw how long will the FORCE command available?

Regards,

-------
Sawada Masahiko

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

#25Kyotaro HORIGUCHI
horiguchi.kyotaro@lab.ntt.co.jp
In reply to: Jim Nasby (#21)
Re: Proposal : REINDEX xxx VERBOSE

Hello,

I showed an extreme number of examples to include *almost of all*
variations of existing syntax of option specification. And showed
what if all variations could be used for all commands. It was
almost a mess. Sorry for the confusion.

I think the issues at our hands are,

- Options location: at-the-end or right-after-the-keyword?

- FORCE options to be removed?

- Decide whether to allow bare word option if the options are to
be located right after the keyword.

Optinions or thoughts?

====
Rethinking from here.

At Wed, 11 Feb 2015 14:34:17 -0600, Jim Nasby <Jim.Nasby@BlueTreble.com> wrote in <54DBBCC9.1020206@BlueTreble.com>

On 2/5/15 12:01 PM, Tom Lane wrote:

...

Meh. Options-at-the-end seems by far the most sensible style to me.
The options-right-after-the-keyword style is a mess, both logically
and from a parsing standpoint, and the only reason we have it at all
is historical artifact (ask Bruce about the origins of VACUUM ANALYZE
over a beer sometime).

...

I know you were worried about accepting options anywhere because it
leads to reserved words, but perhaps we could support it just for
EXPLAIN and VACUUM, and then switch to trailing options if people
think that would be better.

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)

VACUUM [tname [(cname, ...)]] [({FULL [bool]|FREEZE | [bool]|...})]

=# VACUUM t1 (FULL, FREEZE);

VACUUM [tname [(cname, ...)]] [WITH [FULL [bool]]|[FREEZE | [bool]|...]

=# VACUUM t1 WITH FULL;

IMHO, we are so accustomed to call by the names "VACUUM FULL" or
"VACUUM FREEZE" that the both of them look a bit uneasy.

If the new syntax above is added, REINDEX should have *only* the
trailing style.

REINDEX [{INDEX|TABLE|...}] name [(VERBOSE [bool]|...)]

=# REINDEX TABLE t1 (VERBOSE);

REINDEX [{INDEX|TABLE|...}] name [WITH {VERBOSE [bool]|...}]

=# REINDEX INDEX i_t1_pkey WITH VERBOSE;

Also, both of them seems to be unintuitive..

EXPLAIN.. it seems to be preferred to be as it is..

As the result, it seems the best way to go on the current syntax
for all of those commands.

Optinions?

At Wed, 18 Feb 2015 23:58:15 +0900, Sawada Masahiko <sawada.mshk@gmail.com> wrote in <CAD21AoBkjndQAq2Z-WbScMdHoX257BJj6sUYthwwFs2iL8YDhQ@mail.gmail.com>

From consistency perspective, I tend to agree with Robert to put
option at immediately after command name as follows.
REINDEX [(VERBOSE | FORCE)] {INDEX | ...} name;

I don't object against it if you prefer it. The remaining issue
is the choice between options-at-the-end or this
options-right-after-the-keyword mentioned above. I prefer the
more messy(:-) one..

Btw how long will the FORCE command available?

The options is obsolete since 7.4. I think it should have been
fade away long since and it's the time to remove it. But once the
ancient option removed, the above syntax looks a bit uneasy and
the more messy syntax looks natural.

REINDEX [VERBOSE] {INDEX | ...} name;

That do you think about this?

regards,

At Tue, 17 Feb 2015 12:00:13 -0600, Jim Nasby <Jim.Nasby@BlueTreble.com> wrote in <54E381AD.1090409@BlueTreble.com>

VACUUM [FULL] [FREEZE] ... [ANALYZE] [tname [(cname, ...)]
| VACUUM [({FULL [bool]|FREEZE [bool]|...}[,...])] [tname [(cname, ...)]
| VACUUM [tname [(cname, ...)] [[WITH ]({FULL [bool]|FREEZE
| [bool]|...})]

REINDEX [{INDEX|TABLE|...}] name [[WITH] (VERBOSE [bool]|...)]

EXPLAIN [[WITH] ({ANALYZE [bool]|VERBOSE [bool]|... [,...]})]
<statement>

For concrete examples, the lines prefixed by asterisk are in new
syntax.

If I could choose only one for explain, I would find it easier to be
up front. That way you do the explain part on one line and just paste
the query after that.

..

VACUUM FULL table1;
VACUUM ANALYZE table1 (col1);
VACUUM (ANALYZE, VERBOSE) table1 (col1);
*VACUUM table1 WITH (FREEZE on)
*VACUUM table1 (cola) WITH (ANALYZE)
*VACUUM table1 WITH (ANALYZE)
*VACUUM table1 (FREEZE on)

The fifth example looks quite odd.

I don't think we need to allow both () and WITH... I'd say one or the
other, preferably ().

--
Kyotaro Horiguchi
NTT Open Source Software Center

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

#26Sawada Masahiko
sawada.mshk@gmail.com
In reply to: Kyotaro HORIGUCHI (#25)
Re: Proposal : REINDEX xxx VERBOSE

On Fri, Feb 20, 2015 at 12:24 PM, Kyotaro HORIGUCHI
<horiguchi.kyotaro@lab.ntt.co.jp> wrote:

Hello,

I showed an extreme number of examples to include *almost of all*
variations of existing syntax of option specification. And showed
what if all variations could be used for all commands. It was
almost a mess. Sorry for the confusion.

I think the issues at our hands are,

- Options location: at-the-end or right-after-the-keyword?

- FORCE options to be removed?

- Decide whether to allow bare word option if the options are to
be located right after the keyword.

Optinions or thoughts?

====
Rethinking from here.

At Wed, 11 Feb 2015 14:34:17 -0600, Jim Nasby <Jim.Nasby@BlueTreble.com> wrote in <54DBBCC9.1020206@BlueTreble.com>

On 2/5/15 12:01 PM, Tom Lane wrote:

...

Meh. Options-at-the-end seems by far the most sensible style to me.
The options-right-after-the-keyword style is a mess, both logically
and from a parsing standpoint, and the only reason we have it at all
is historical artifact (ask Bruce about the origins of VACUUM ANALYZE
over a beer sometime).

...

I know you were worried about accepting options anywhere because it
leads to reserved words, but perhaps we could support it just for
EXPLAIN and VACUUM, and then switch to trailing options if people
think that would be better.

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)

VACUUM [tname [(cname, ...)]] [({FULL [bool]|FREEZE | [bool]|...})]

=# VACUUM t1 (FULL, FREEZE);

VACUUM [tname [(cname, ...)]] [WITH [FULL [bool]]|[FREEZE | [bool]|...]

=# VACUUM t1 WITH FULL;

IMHO, we are so accustomed to call by the names "VACUUM FULL" or
"VACUUM FREEZE" that the both of them look a bit uneasy.

If the new syntax above is added, REINDEX should have *only* the
trailing style.

REINDEX [{INDEX|TABLE|...}] name [(VERBOSE [bool]|...)]

=# REINDEX TABLE t1 (VERBOSE);

REINDEX [{INDEX|TABLE|...}] name [WITH {VERBOSE [bool]|...}]

=# REINDEX INDEX i_t1_pkey WITH VERBOSE;

Also, both of them seems to be unintuitive..

EXPLAIN.. it seems to be preferred to be as it is..

As the result, it seems the best way to go on the current syntax
for all of those commands.

Optinions?

At Wed, 18 Feb 2015 23:58:15 +0900, Sawada Masahiko <sawada.mshk@gmail.com> wrote in <CAD21AoBkjndQAq2Z-WbScMdHoX257BJj6sUYthwwFs2iL8YDhQ@mail.gmail.com>

From consistency perspective, I tend to agree with Robert to put
option at immediately after command name as follows.
REINDEX [(VERBOSE | FORCE)] {INDEX | ...} name;

I don't object against it if you prefer it. The remaining issue
is the choice between options-at-the-end or this
options-right-after-the-keyword mentioned above. I prefer the
more messy(:-) one..

Btw how long will the FORCE command available?

The options is obsolete since 7.4. I think it should have been
fade away long since and it's the time to remove it. But once the
ancient option removed, the above syntax looks a bit uneasy and
the more messy syntax looks natural.

REINDEX [VERBOSE] {INDEX | ...} name;

That do you think about this?

Thank you for summarizing them.

I said right-after-the-keyword is looks good to me.
But it's will be possible only if FORCE command is removed.
REINDEX command has FORCE option at the end, so REINDEX probably
should have options at the end.

Regards,

-------
Sawada Masahiko

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

#27Jim Nasby
Jim.Nasby@BlueTreble.com
In reply to: Sawada Masahiko (#26)
Re: Proposal : REINDEX xxx VERBOSE

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;
--
Jim Nasby, Data Architect, Blue Treble Consulting
Data in Trouble? Get it in Treble! http://BlueTreble.com

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

#28Sawada Masahiko
sawada.mshk@gmail.com
In reply to: Jim Nasby (#27)
1 attachment(s)
Re: Proposal : REINDEX xxx VERBOSE

On Wed, Feb 25, 2015 at 4:58 PM, Jim Nasby <Jim.Nasby@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;

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.
Can we think and add new syntax without FORCE option while leaving
current Reindex statement syntax?

As prototype, I attached new version patch has the following syntax.
REINDEX { INDEX | TABLE | ... } relname [ FORCE | VERBOSE];

Regards,

-------
Sawada Masahiko

Attachments:

000_reindex_verbose_v2.patchapplication/octet-stream; name=000_reindex_verbose_v2.patchDownload
diff --git a/doc/src/sgml/ref/reindex.sgml b/doc/src/sgml/ref/reindex.sgml
index 0a4c7d4..a97be82 100644
--- a/doc/src/sgml/ref/reindex.sgml
+++ b/doc/src/sgml/ref/reindex.sgml
@@ -21,7 +21,7 @@ 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> [ FORCE | VERBOSE ]
 </synopsis>
  </refsynopsisdiv>
 
@@ -159,6 +159,15 @@ 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>
   </variablelist>
  </refsect1>
 
diff --git a/src/backend/catalog/index.c b/src/backend/catalog/index.c
index 9bb9deb..b03b679 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 dc1b37c..ecd8e71 100644
--- a/src/backend/commands/cluster.c
+++ b/src/backend/commands/cluster.c
@@ -1531,7 +1531,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 e859669..bb9b533 100644
--- a/src/backend/commands/indexcmds.c
+++ b/src/backend/commands/indexcmds.c
@@ -1678,7 +1678,7 @@ ChooseIndexColumnNames(List *indexElems)
  *		Recreate a specific index.
  */
 Oid
-ReindexIndex(RangeVar *indexRelation)
+ReindexIndex(RangeVar *indexRelation, bool verbose)
 {
 	Oid			indOid;
 	Oid			heapOid = InvalidOid;
@@ -1689,7 +1689,7 @@ ReindexIndex(RangeVar *indexRelation)
 									  RangeVarCallbackForReindexIndex,
 									  (void *) &heapOid);
 
-	reindex_index(indOid, false, indexRelation->relpersistence);
+	reindex_index(indOid, false, indexRelation->relpersistence, verbose);
 
 	return indOid;
 }
@@ -1758,7 +1758,7 @@ RangeVarCallbackForReindexIndex(const RangeVar *relation,
  *		Recreate all indexes of a table (and of its toast table, if any)
  */
 Oid
-ReindexTable(RangeVar *relation)
+ReindexTable(RangeVar *relation, bool verbose)
 {
 	Oid			heapOid;
 
@@ -1768,7 +1768,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)));
@@ -1785,7 +1786,7 @@ ReindexTable(RangeVar *relation)
  * That means this must not be called within a user transaction block!
  */
 Oid
-ReindexObject(const char *objectName, ReindexObjectType objectKind)
+ReindexObject(const char *objectName, ReindexObjectType objectKind, bool verbose)
 {
 	Oid			objectOid;
 	Relation	relationRelation;
@@ -1797,6 +1798,7 @@ ReindexObject(const char *objectName, ReindexObjectType objectKind)
 	List	   *relids = NIL;
 	ListCell   *l;
 	int	num_keys;
+	int elevel = verbose ? INFO : DEBUG2;
 
 	AssertArg(objectName);
 	Assert(objectKind == REINDEX_OBJECT_SCHEMA ||
@@ -1939,9 +1941,10 @@ ReindexObject(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 66d5083..16a57fd 100644
--- a/src/backend/commands/tablecmds.c
+++ b/src/backend/commands/tablecmds.c
@@ -1218,7 +1218,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);
 		}
 	}
 
diff --git a/src/backend/parser/gram.y b/src/backend/parser/gram.y
index 36dac29..9e3d71b 100644
--- a/src/backend/parser/gram.y
+++ b/src/backend/parser/gram.y
@@ -281,7 +281,7 @@ static Node *makeRecursiveViewSelect(char *relname, List *aliases, Node *query);
 
 %type <ival>	opt_lock lock_type cast_context
 %type <ival>	vacuum_option_list vacuum_option_elem
-%type <boolean>	opt_force opt_or_replace
+%type <boolean>	opt_reindex opt_or_replace
 				opt_grant_grant_option opt_grant_admin_option
 				opt_nowait opt_if_exists opt_with_data
 %type <ival>	opt_nowait_or_skip
@@ -7318,49 +7318,56 @@ opt_if_exists: IF_P EXISTS						{ $$ = TRUE; }
  *****************************************************************************/
 
 ReindexStmt:
-			REINDEX INDEX qualified_name opt_force
+			REINDEX INDEX qualified_name opt_reindex
 				{
 					ReindexStmt *n = makeNode(ReindexStmt);
 					n->kind = REINDEX_OBJECT_INDEX;
 					n->relation = $3;
+					n->verbose = $4;
 					n->name = NULL;
 					$$ = (Node *)n;
 				}
-			| REINDEX TABLE qualified_name opt_force
+			| REINDEX TABLE qualified_name opt_reindex
 				{
 					ReindexStmt *n = makeNode(ReindexStmt);
 					n->kind = REINDEX_OBJECT_TABLE;
 					n->relation = $3;
+					n->verbose = $4;
 					n->name = NULL;
 					$$ = (Node *)n;
 				}
-			| REINDEX SCHEMA name opt_force
+			| REINDEX SCHEMA name opt_reindex
 				{
 					ReindexStmt *n = makeNode(ReindexStmt);
 					n->kind = REINDEX_OBJECT_SCHEMA;
 					n->name = $3;
+					n->verbose = $4;
 					n->relation = NULL;
 					$$ = (Node *)n;
 				}
-			| REINDEX SYSTEM_P name opt_force
+			| REINDEX SYSTEM_P name opt_reindex
 				{
 					ReindexStmt *n = makeNode(ReindexStmt);
 					n->kind = REINDEX_OBJECT_SYSTEM;
 					n->name = $3;
+					n->verbose = $4;
 					n->relation = NULL;
 					$$ = (Node *)n;
 				}
-			| REINDEX DATABASE name opt_force
+			| REINDEX DATABASE name opt_reindex
 				{
 					ReindexStmt *n = makeNode(ReindexStmt);
 					n->kind = REINDEX_OBJECT_DATABASE;
 					n->name = $3;
+					n->verbose = $4;
 					n->relation = NULL;
 					$$ = (Node *)n;
 				}
 		;
 
-opt_force:	FORCE									{  $$ = TRUE; }
+opt_reindex:
+			FORCE									{  $$ = FALSE; }
+			| VERBOSE								{  $$ = TRUE; }
 			| /* EMPTY */							{  $$ = FALSE; }
 		;
 
diff --git a/src/backend/tcop/utility.c b/src/backend/tcop/utility.c
index 3533cfa..19ebb90 100644
--- a/src/backend/tcop/utility.c
+++ b/src/backend/tcop/utility.c
@@ -750,10 +750,10 @@ standard_ProcessUtility(Node *parsetree,
 				switch (stmt->kind)
 				{
 					case REINDEX_OBJECT_INDEX:
-						ReindexIndex(stmt->relation);
+						ReindexIndex(stmt->relation, stmt->verbose);
 						break;
 					case REINDEX_OBJECT_TABLE:
-						ReindexTable(stmt->relation);
+						ReindexTable(stmt->relation, stmt->verbose);
 						break;
 					case REINDEX_OBJECT_SCHEMA:
 					case REINDEX_OBJECT_SYSTEM:
@@ -768,7 +768,7 @@ standard_ProcessUtility(Node *parsetree,
 						PreventTransactionChain(isTopLevel,
 												(stmt->kind == REINDEX_OBJECT_SCHEMA) ?
 												"REINDEX SCHEMA" : "REINDEX DATABASE");
-						ReindexObject(stmt->name, stmt->kind);
+						ReindexObject(stmt->name, stmt->kind, stmt->verbose);
 						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..6d97609 100644
--- a/src/bin/psql/tab-complete.c
+++ b/src/bin/psql/tab-complete.c
@@ -3342,12 +3342,21 @@ 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)
 			COMPLETE_WITH_QUERY(Query_for_list_of_databases);
 	}
+	else if (pg_strcasecmp(prev3_wd, "REINDEX") == 0)
+	{
+		if (pg_strcasecmp(prev2_wd, "TABLE") == 0 ||
+			pg_strcasecmp(prev2_wd, "INDEX") == 0 ||
+			pg_strcasecmp(prev2_wd, "SCHEMA") == 0 ||
+			pg_strcasecmp(prev2_wd, "SYSTEM") == 0 ||
+			pg_strcasecmp(prev2_wd, "DATABASE") == 0)
+			COMPLETE_WITH_CONST("VERBOSE");
+	}
 
 /* SECURITY LABEL */
 	else if (pg_strcasecmp(prev_wd, "SECURITY") == 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 cf586fe..8ebb2d5 100644
--- a/src/include/commands/defrem.h
+++ b/src/include/commands/defrem.h
@@ -28,9 +28,10 @@ extern Oid DefineIndex(Oid relationId,
 			bool check_rights,
 			bool skip_build,
 			bool quiet);
-extern Oid	ReindexIndex(RangeVar *indexRelation);
-extern Oid	ReindexTable(RangeVar *relation);
-extern Oid ReindexObject(const char *databaseName, ReindexObjectType kind);
+extern Oid	ReindexIndex(RangeVar *indexRelation, bool verbose);
+extern Oid	ReindexTable(RangeVar *relation, bool verbose);
+extern Oid ReindexObject(const char *databaseName, ReindexObjectType kind,
+				bool verbose);
 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 b1dfa85..c840e41 100644
--- a/src/include/nodes/parsenodes.h
+++ b/src/include/nodes/parsenodes.h
@@ -2739,6 +2739,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 */
+	bool		verbose;		/* print progress info */
 } ReindexStmt;
 
 /* ----------------------
#29Jim Nasby
Jim.Nasby@BlueTreble.com
In reply to: Sawada Masahiko (#28)
Re: Proposal : REINDEX xxx VERBOSE

On 3/2/15 10:58 AM, Sawada Masahiko wrote:

On Wed, Feb 25, 2015 at 4:58 PM, Jim Nasby <Jim.Nasby@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...

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.
--
Jim Nasby, Data Architect, Blue Treble Consulting
Data in Trouble? Get it in Treble! http://BlueTreble.com

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

#30Sawada Masahiko
sawada.mshk@gmail.com
In reply to: Jim Nasby (#29)
1 attachment(s)
Re: Proposal : REINDEX xxx VERBOSE

On Fri, Mar 6, 2015 at 11:07 AM, Jim Nasby <Jim.Nasby@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.Nasby@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

Attachments:

000_reindex_verbose_v3.patchtext/x-patch; charset=US-ASCII; name=000_reindex_verbose_v3.patchDownload
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;
 
 /* ----------------------
#31Jim Nasby
Jim.Nasby@BlueTreble.com
In reply to: Sawada Masahiko (#30)
Re: Proposal : REINDEX xxx VERBOSE

On 3/9/15 9:43 PM, Sawada Masahiko wrote:

On Fri, Mar 6, 2015 at 11:07 AM, Jim Nasby <Jim.Nasby@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.Nasby@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 [, ...] )

Are the parenthesis necessary? No other WITH option requires them, other
than create table/matview (COPY doesn't actually require them).

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.

I forgot that. There's no reason to support it with the new stuff then.
--
Jim Nasby, Data Architect, Blue Treble Consulting
Data in Trouble? Get it in Treble! http://BlueTreble.com

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

#32Sawada Masahiko
sawada.mshk@gmail.com
In reply to: Jim Nasby (#31)
Re: Proposal : REINDEX xxx VERBOSE

On Tue, Mar 10, 2015 at 5:05 PM, Jim Nasby <Jim.Nasby@bluetreble.com> wrote:

On 3/9/15 9:43 PM, Sawada Masahiko wrote:

On Fri, Mar 6, 2015 at 11:07 AM, Jim Nasby <Jim.Nasby@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.Nasby@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 [, ...] )

Are the parenthesis necessary? No other WITH option requires them, other
than create table/matview (COPY doesn't actually require them).

I was imagining EXPLAIN syntax.
Is there some possibility of supporting multiple options for REINDEX
command in future?
If there is, syntax will be as follows, REINDEX { INDEX | ... } name
WITH VERBOSE, XXX, XXX;
I thought style with parenthesis is better than above style.

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.

I forgot that. There's no reason to support it with the new stuff then.

--
Jim Nasby, Data Architect, Blue Treble Consulting
Data in Trouble? Get it in Treble! http://BlueTreble.com

Regards,

-------
Sawada Masahiko

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

#33Sawada Masahiko
sawada.mshk@gmail.com
In reply to: Jim Nasby (#31)
1 attachment(s)
Re: Proposal : REINDEX xxx VERBOSE

On Tue, Mar 10, 2015 at 5:05 PM, Jim Nasby <Jim.Nasby@bluetreble.com> wrote:

On 3/9/15 9:43 PM, Sawada Masahiko wrote:

On Fri, Mar 6, 2015 at 11:07 AM, Jim Nasby <Jim.Nasby@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.Nasby@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 [, ...] )

Are the parenthesis necessary? No other WITH option requires them, other
than create table/matview (COPY doesn't actually require them).

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.

I forgot that. There's no reason to support it with the new stuff then.

--
Jim Nasby, Data Architect, Blue Treble Consulting
Data in Trouble? Get it in Treble! http://BlueTreble.com

Attached patch is latest version patch changed syntax a little.
This patch adds following syntax for now.
REINDEX { INDEX | ... } name WITH (VERBOSE);

But we are under the discussion regarding parenthesis, so there is
possibility of change.

Regards,

-------
Sawada Masahiko

Attachments:

000_reindex_verbose_v4.patchapplication/octet-stream; name=000_reindex_verbose_v4.patchDownload
diff --git a/doc/src/sgml/ref/reindex.sgml b/doc/src/sgml/ref/reindex.sgml
index 0a4c7d4..e0e37fb 100644
--- a/doc/src/sgml/ref/reindex.sgml
+++ b/doc/src/sgml/ref/reindex.sgml
@@ -22,6 +22,11 @@ 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>
+
+    VERBOSE
 </synopsis>
  </refsynopsisdiv>
 
@@ -159,6 +164,15 @@ 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>
   </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..58e988b 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)
+	{
+		char *opt = (char *) lfirst(lc);
+		if (strcmp(opt, "verbose") == 0)
+			verbose = true;
+		else if (strcmp(opt, "force") == 0)
+		{ /* Nothing to do */ }
+		else
+			ereport(ERROR,
+					(errcode(ERRCODE_INVALID_PARAMETER_VALUE),
+					 errmsg("unrecognized REINDEX option \"%s\"", opt)));
+	}
 
 	/* 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)
+	{
+		char *opt = (char *) lfirst(lc);
+		if (strcmp(opt, "verbose") == 0)
+			verbose = true;
+		else if (strcmp(opt, "force") == 0)
+		{ /* Nothing to do */ }
+		else
+			ereport(ERROR,
+					(errcode(ERRCODE_INVALID_PARAMETER_VALUE),
+					 errmsg("unrecognized REINDEX option \"%s\"", opt)));
+	}
 
 	/* 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)
+	{
+		char *opt = (char *) lfirst(l);
+		if (strcmp(opt, "verbose") == 0)
+		{
+			verbose = true;
+			elevel = INFO;
+		}
+		else if (strcmp(opt, "force") == 0)
+		{ /* Nothing to do */ }
+		else
+			ereport(ERROR,
+					(errcode(ERRCODE_INVALID_PARAMETER_VALUE),
+					 errmsg("unrecognized REINDEX option \"%s\"", opt)));
+	}
+
 	/*
 	 * 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..e13eb2b 100644
--- a/src/backend/parser/gram.y
+++ b/src/backend/parser/gram.y
@@ -456,6 +456,12 @@ 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 <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 +7322,75 @@ 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_name
 				{
-					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_name
+				{
+					$$ = lappend($1, $3);
+				}
+;
+reindex_option_name:
+			VERBOSE 														{ $$ = "verbose"; }
+;
 
 /*****************************************************************************
  *
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;
 
 /* ----------------------
#34Jim Nasby
Jim.Nasby@BlueTreble.com
In reply to: Sawada Masahiko (#32)
Re: Proposal : REINDEX xxx VERBOSE

On 3/11/15 6:33 AM, Sawada Masahiko wrote:

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 [, ...] )

Are the parenthesis necessary? No other WITH option requires them, other
than create table/matview (COPY doesn't actually require them).

I was imagining EXPLAIN syntax.
Is there some possibility of supporting multiple options for REINDEX
command in future?
If there is, syntax will be as follows, REINDEX { INDEX | ... } name
WITH VERBOSE, XXX, XXX;
I thought style with parenthesis is better than above style.

The thing is, ()s are actually an odd-duck. Very little supports it, and
while COPY allows it they're not required. EXPLAIN is a different story,
because that's not WITH; we're actually using () *instead of* WITH.

So because almost all commands that use WITH doen't even accept (), I
don't think this should either. It certainly shouldn't require them,
because unlike EXPLAIN, there's no need to require them.
--
Jim Nasby, Data Architect, Blue Treble Consulting
Data in Trouble? Get it in Treble! http://BlueTreble.com

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

#35Sawada Masahiko
sawada.mshk@gmail.com
In reply to: Jim Nasby (#34)
1 attachment(s)
Re: Proposal : REINDEX xxx VERBOSE

On Thu, Mar 12, 2015 at 6:36 AM, Jim Nasby <Jim.Nasby@bluetreble.com> wrote:

On 3/11/15 6:33 AM, Sawada Masahiko wrote:

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 [, ...] )

Are the parenthesis necessary? No other WITH option requires them, other
than create table/matview (COPY doesn't actually require them).

I was imagining EXPLAIN syntax.
Is there some possibility of supporting multiple options for REINDEX
command in future?
If there is, syntax will be as follows, REINDEX { INDEX | ... } name
WITH VERBOSE, XXX, XXX;
I thought style with parenthesis is better than above style.

The thing is, ()s are actually an odd-duck. Very little supports it, and
while COPY allows it they're not required. EXPLAIN is a different story,
because that's not WITH; we're actually using () *instead of* WITH.

So because almost all commands that use WITH doen't even accept (), I don't
think this should either. It certainly shouldn't require them, because
unlike EXPLAIN, there's no need to require them.

I understood what your point is.
Attached patch is changed syntax, it does not have parenthesis.

Regards,

-------
Sawada Masahiko

Attachments:

000_reindex_verbose_v5.patchtext/x-patch; charset=US-ASCII; name=000_reindex_verbose_v5.patchDownload
diff --git a/doc/src/sgml/ref/reindex.sgml b/doc/src/sgml/ref/reindex.sgml
index 0a4c7d4..3cea35f 100644
--- a/doc/src/sgml/ref/reindex.sgml
+++ b/doc/src/sgml/ref/reindex.sgml
@@ -22,6 +22,11 @@ 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>
+
+    VERBOSE
 </synopsis>
  </refsynopsisdiv>
 
@@ -159,6 +164,15 @@ 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>
   </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..4f0ef08 100644
--- a/src/backend/commands/indexcmds.c
+++ b/src/backend/commands/indexcmds.c
@@ -1681,10 +1681,24 @@ 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)
+	{
+		char *opt = (char *) lfirst(lc);
+		if (strcmp(opt, "verbose") == 0)
+			verbose = true;
+		else
+			ereport(ERROR,
+					(errcode(ERRCODE_INVALID_PARAMETER_VALUE),
+					 errmsg("unrecognized REINDEX option \"%s\"", opt)));
+	}
 
 	/* lock level used here should match index lock reindex_index() */
 	indOid = RangeVarGetRelidExtended(indexRelation, AccessExclusiveLock,
@@ -1692,7 +1706,7 @@ ReindexIndex(RangeVar *indexRelation)
 									  RangeVarCallbackForReindexIndex,
 									  (void *) &heapOid);
 
-	reindex_index(indOid, false, indexRelation->relpersistence);
+	reindex_index(indOid, false, indexRelation->relpersistence, verbose);
 
 	return indOid;
 }
@@ -1761,9 +1775,23 @@ 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)
+	{
+		char *opt = (char *) lfirst(lc);
+		if (strcmp(opt, "verbose") == 0)
+			verbose = true;
+		else
+			ereport(ERROR,
+					(errcode(ERRCODE_INVALID_PARAMETER_VALUE),
+					 errmsg("unrecognized REINDEX option \"%s\"", opt)));
+	}
 
 	/* The lock level used here should match reindex_relation(). */
 	heapOid = RangeVarGetRelidExtended(relation, ShareLock, false, false,
@@ -1771,7 +1799,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 +1817,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 +1829,29 @@ 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)
+	{
+		char *opt = (char *) lfirst(l);
+		if (strcmp(opt, "verbose") == 0)
+		{
+			verbose = true;
+			elevel = INFO;
+		}
+		else
+			ereport(ERROR,
+					(errcode(ERRCODE_INVALID_PARAMETER_VALUE),
+					 errmsg("unrecognized REINDEX option \"%s\"", opt)));
+	}
+
 	/*
 	 * 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 +1970,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 623e6bf..6359b6f 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 cf0d317..382ebcd 100644
--- a/src/backend/parser/gram.y
+++ b/src/backend/parser/gram.y
@@ -457,6 +457,12 @@ 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 <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
@@ -7295,57 +7301,75 @@ 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 = $5;
 					$$ = (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 = $5;
 					$$ = (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_name
 				{
-					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_name
+				{
+					$$ = lappend($1, $3);
+				}
+;
+reindex_option_name:
+			VERBOSE 														{ $$ = "verbose"; }
+;
 
 /*****************************************************************************
  *
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..46c8365 100644
--- a/src/bin/psql/tab-complete.c
+++ b/src/bin/psql/tab-complete.c
@@ -3342,12 +3342,32 @@ 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)
 			COMPLETE_WITH_QUERY(Query_for_list_of_databases);
 	}
+	else if (pg_strcasecmp(prev3_wd, "REINDEX") == 0)
+	{
+		if (pg_strcasecmp(prev2_wd, "TABLE") == 0 ||
+			 pg_strcasecmp(prev2_wd, "INDEX") == 0 ||
+			 pg_strcasecmp(prev2_wd, "SCHEMA") == 0 ||
+			 pg_strcasecmp(prev2_wd, "SYSTEM") == 0 ||
+			 pg_strcasecmp(prev2_wd, "DATABASE") == 0)
+			COMPLETE_WITH_CONST("WITH");
+	}
+	else if (pg_strcasecmp(prev4_wd, "REINDEX") == 0)
+	{
+		if ((pg_strcasecmp(prev3_wd, "TABLE") == 0 ||
+			 pg_strcasecmp(prev3_wd, "INDEX") == 0 ||
+			 pg_strcasecmp(prev3_wd, "SCHEMA") == 0 ||
+			 pg_strcasecmp(prev3_wd, "SYSTEM") == 0 ||
+			 pg_strcasecmp(prev3_wd, "DATABASE") == 0) &&
+			pg_strcasecmp(prev_wd, "WITH") == 0)
+			COMPLETE_WITH_CONST("VERBOSE");
+	}
+
 
 /* SECURITY LABEL */
 	else if (pg_strcasecmp(prev_wd, "SECURITY") == 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 38ed661..d66fd3b 100644
--- a/src/include/nodes/parsenodes.h
+++ b/src/include/nodes/parsenodes.h
@@ -2764,6 +2764,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;
 
 /* ----------------------
#36Kyotaro HORIGUCHI
horiguchi.kyotaro@lab.ntt.co.jp
In reply to: Sawada Masahiko (#35)
Re: Proposal : REINDEX xxx VERBOSE

Hello, I have some trivial comments about the latest patch.

At Thu, 12 Mar 2015 21:15:14 +0900, Sawada Masahiko <sawada.mshk@gmail.com> wrote in <CAD21AoBxPCpPvKQmvJMUh+p=2pfAu03gKJQ2R2zY47XHsH205Q@mail.gmail.com>
sawada.mshk> On Thu, Mar 12, 2015 at 6:36 AM, Jim Nasby <Jim.Nasby@bluetreble.com> wrote:

Are the parenthesis necessary? No other WITH option requires them, other
than create table/matview (COPY doesn't actually require them).

I was imagining EXPLAIN syntax.
Is there some possibility of supporting multiple options for REINDEX
command in future?
If there is, syntax will be as follows, REINDEX { INDEX | ... } name
WITH VERBOSE, XXX, XXX;
I thought style with parenthesis is better than above style.

The thing is, ()s are actually an odd-duck. Very little supports it, and
while COPY allows it they're not required. EXPLAIN is a different story,
because that's not WITH; we're actually using () *instead of* WITH.

So because almost all commands that use WITH doen't even accept (), I don't
think this should either. It certainly shouldn't require them, because
unlike EXPLAIN, there's no need to require them.

I understood what your point is.
Attached patch is changed syntax, it does not have parenthesis.

As I looked into the code to find what the syntax would be, I
found some points which would be better to be fixed.

In gram.y the options is a list of cstring but it is not necesary
to be a list because there's only one kind of option now.

If you prefer it to be a list, I have a comment for the way to
make string list in gram.y. You stored bare cstring in the
options list but I think it is not the preferable form. I suppose
the followings are preferable. Corresponding fixes are needed in
ReindexTable, ReindexIndex, ReindexMultipleTables.

$$ = list_make1(makeString($1);
....
$$ = lappend($1, list_make1(makeString($3));

In equalfuncs.c, _equalReindexStmt forgets to compare the member
options. _copyReindexStmt also forgets to copy it. The way you
constructed the options list prevents them from doing their jobs
using prepared methods. Comparing and copying the member "option"
is needed even if it becomes a simple string.

regards,

--
Kyotaro Horiguchi
NTT Open Source Software Center

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

#37Robert Haas
robertmhaas@gmail.com
In reply to: Jim Nasby (#34)
Re: Proposal : REINDEX xxx VERBOSE

On Wed, Mar 11, 2015 at 5:36 PM, Jim Nasby <Jim.Nasby@bluetreble.com> wrote:

The thing is, ()s are actually an odd-duck. Very little supports it, and
while COPY allows it they're not required. EXPLAIN is a different story,
because that's not WITH; we're actually using () *instead of* WITH.

Generally, I think the commands that don't have () are the older ones,
and those that do have it are the newer ones: EXPLAIN, VERBOSE, the
newest of our three COPY syntaxes, CREATE MATERIALIZED VIEW, foreign
data wrappers, servers, and foreign tables. The older stuff like
CREATE DATABASE and REINDEX that uses ad-hoc syntax instead is a real
pain in the neck: every time you want to add an option, you've got to
add new parser rules and keywords, which is bad for the overall
efficiency of parsing. So I think this argument is exactly backwards:
parenthesized options are the newer, better way to do this sort of
thing.

--
Robert Haas
EnterpriseDB: http://www.enterprisedb.com
The Enterprise PostgreSQL Company

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

#38Jim Nasby
Jim.Nasby@BlueTreble.com
In reply to: Robert Haas (#37)
Re: Proposal : REINDEX xxx VERBOSE

On 3/13/15 6:48 AM, Robert Haas wrote:

On Wed, Mar 11, 2015 at 5:36 PM, Jim Nasby <Jim.Nasby@bluetreble.com> wrote:

The thing is, ()s are actually an odd-duck. Very little supports it, and
while COPY allows it they're not required. EXPLAIN is a different story,
because that's not WITH; we're actually using () *instead of* WITH.

Generally, I think the commands that don't have () are the older ones,
and those that do have it are the newer ones: EXPLAIN, VERBOSE, the
newest of our three COPY syntaxes, CREATE MATERIALIZED VIEW, foreign
data wrappers, servers, and foreign tables. The older stuff like
CREATE DATABASE and REINDEX that uses ad-hoc syntax instead is a real
pain in the neck: every time you want to add an option, you've got to
add new parser rules and keywords, which is bad for the overall
efficiency of parsing. So I think this argument is exactly backwards:
parenthesized options are the newer, better way to do this sort of
thing.

Yeah, that doesn't sound like a good tradeoff compared to making people
type some extra ()s. :(

We should at least support ()s on the other commands though, so that
we're consistent.
--
Jim Nasby, Data Architect, Blue Treble Consulting
Data in Trouble? Get it in Treble! http://BlueTreble.com

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

#39Robert Haas
robertmhaas@gmail.com
In reply to: Jim Nasby (#38)
Re: Proposal : REINDEX xxx VERBOSE

On Fri, Mar 13, 2015 at 8:57 AM, Jim Nasby <Jim.Nasby@bluetreble.com> wrote:

Yeah, that doesn't sound like a good tradeoff compared to making people type
some extra ()s. :(

We should at least support ()s on the other commands though, so that we're
consistent.

I think we've been moving slowly in that direction, but it's not this
patch's job to accelerate that transition.

--
Robert Haas
EnterpriseDB: http://www.enterprisedb.com
The Enterprise PostgreSQL Company

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

#40Sawada Masahiko
sawada.mshk@gmail.com
In reply to: Kyotaro HORIGUCHI (#36)
1 attachment(s)
Re: Proposal : REINDEX xxx VERBOSE

On Fri, Mar 13, 2015 at 5:10 PM, Kyotaro HORIGUCHI
<horiguchi.kyotaro@lab.ntt.co.jp> wrote:

Hello, I have some trivial comments about the latest patch.

At Thu, 12 Mar 2015 21:15:14 +0900, Sawada Masahiko <sawada.mshk@gmail.com> wrote in <CAD21AoBxPCpPvKQmvJMUh+p=2pfAu03gKJQ2R2zY47XHsH205Q@mail.gmail.com>
sawada.mshk> On Thu, Mar 12, 2015 at 6:36 AM, Jim Nasby <Jim.Nasby@bluetreble.com> wrote:

Are the parenthesis necessary? No other WITH option requires them, other
than create table/matview (COPY doesn't actually require them).

I was imagining EXPLAIN syntax.
Is there some possibility of supporting multiple options for REINDEX
command in future?
If there is, syntax will be as follows, REINDEX { INDEX | ... } name
WITH VERBOSE, XXX, XXX;
I thought style with parenthesis is better than above style.

The thing is, ()s are actually an odd-duck. Very little supports it, and
while COPY allows it they're not required. EXPLAIN is a different story,
because that's not WITH; we're actually using () *instead of* WITH.

So because almost all commands that use WITH doen't even accept (), I don't
think this should either. It certainly shouldn't require them, because
unlike EXPLAIN, there's no need to require them.

I understood what your point is.
Attached patch is changed syntax, it does not have parenthesis.

As I looked into the code to find what the syntax would be, I
found some points which would be better to be fixed.

In gram.y the options is a list of cstring but it is not necesary
to be a list because there's only one kind of option now.

If you prefer it to be a list, I have a comment for the way to
make string list in gram.y. You stored bare cstring in the
options list but I think it is not the preferable form. I suppose
the followings are preferable. Corresponding fixes are needed in
ReindexTable, ReindexIndex, ReindexMultipleTables.

$$ = list_make1(makeString($1);
....
$$ = lappend($1, list_make1(makeString($3));

In equalfuncs.c, _equalReindexStmt forgets to compare the member
options. _copyReindexStmt also forgets to copy it. The way you
constructed the options list prevents them from doing their jobs
using prepared methods. Comparing and copying the member "option"
is needed even if it becomes a simple string.

I revised patch, and changed gram.y as I don't use the list.
So this patch adds new syntax,
REINDEX { INDEX | ... } name WITH VERBOSE;

Also documentation is updated.
Please give me feedbacks.

Regards,

-------
Sawada Masahiko

Attachments:

000_reindex_verbose_v6.patchtext/x-patch; charset=US-ASCII; name=000_reindex_verbose_v6.patchDownload
diff --git a/doc/src/sgml/ref/reindex.sgml b/doc/src/sgml/ref/reindex.sgml
index 0a4c7d4..27be1a4 100644
--- a/doc/src/sgml/ref/reindex.sgml
+++ b/doc/src/sgml/ref/reindex.sgml
@@ -22,6 +22,7 @@ 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 VERBOSE
 </synopsis>
  </refsynopsisdiv>
 
@@ -159,6 +160,15 @@ 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>
   </variablelist>
  </refsect1>
 
diff --git a/src/backend/catalog/index.c b/src/backend/catalog/index.c
index 351dcb2..fc44495 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"
@@ -3133,13 +3134,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
@@ -3283,6 +3289,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);
@@ -3324,7 +3337,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;
@@ -3415,7 +3428,7 @@ reindex_relation(Oid relid, int flags)
 				RelationSetIndexList(rel, doneIndexes, InvalidOid);
 
 			reindex_index(indexOid, !(flags & REINDEX_REL_CHECK_CONSTRAINTS),
-						  persistence);
+						  persistence, verbose);
 
 			CommandCounterIncrement();
 
@@ -3450,7 +3463,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 99acd4a..a42a508 100644
--- a/src/backend/commands/indexcmds.c
+++ b/src/backend/commands/indexcmds.c
@@ -1681,7 +1681,7 @@ ChooseIndexColumnNames(List *indexElems)
  *		Recreate a specific index.
  */
 Oid
-ReindexIndex(RangeVar *indexRelation)
+ReindexIndex(RangeVar *indexRelation, bool verbose)
 {
 	Oid			indOid;
 	Oid			heapOid = InvalidOid;
@@ -1706,7 +1706,7 @@ ReindexIndex(RangeVar *indexRelation)
 	persistence = irel->rd_rel->relpersistence;
 	index_close(irel, NoLock);
 
-	reindex_index(indOid, false, persistence);
+	reindex_index(indOid, false, persistence, verbose);
 
 	return indOid;
 }
@@ -1775,7 +1775,7 @@ RangeVarCallbackForReindexIndex(const RangeVar *relation,
  *		Recreate all indexes of a table (and of its toast table, if any)
  */
 Oid
-ReindexTable(RangeVar *relation)
+ReindexTable(RangeVar *relation, bool verbose)
 {
 	Oid			heapOid;
 
@@ -1785,7 +1785,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)));
@@ -1802,7 +1803,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, bool verbose)
 {
 	Oid			objectOid;
 	Relation	relationRelation;
@@ -1814,6 +1815,7 @@ ReindexMultipleTables(const char *objectName, ReindexObjectType objectKind)
 	List	   *relids = NIL;
 	ListCell   *l;
 	int			num_keys;
+	int			elevel = verbose ? INFO : DEBUG2;
 
 	AssertArg(objectName);
 	Assert(objectKind == REINDEX_OBJECT_SCHEMA ||
@@ -1938,9 +1940,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 06e4332..4f90a9e 100644
--- a/src/backend/commands/tablecmds.c
+++ b/src/backend/commands/tablecmds.c
@@ -1226,7 +1226,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/nodes/equalfuncs.c b/src/backend/nodes/equalfuncs.c
index 190e50a..cecd0c5 100644
--- a/src/backend/nodes/equalfuncs.c
+++ b/src/backend/nodes/equalfuncs.c
@@ -1896,6 +1896,7 @@ _equalReindexStmt(const ReindexStmt *a, const ReindexStmt *b)
 	COMPARE_SCALAR_FIELD(kind);
 	COMPARE_NODE_FIELD(relation);
 	COMPARE_STRING_FIELD(name);
+	COMPARE_SCALAR_FIELD(verbose);
 
 	return true;
 }
diff --git a/src/backend/parser/gram.y b/src/backend/parser/gram.y
index 88ec83c..1b456c1 100644
--- a/src/backend/parser/gram.y
+++ b/src/backend/parser/gram.y
@@ -457,6 +457,11 @@ 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 <ival>	reindex_target_type
+%type <ival>	reindex_target_multitable
+
 %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
@@ -7302,57 +7307,62 @@ 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->verbose = false;
 					$$ = (Node *)n;
 				}
-			| REINDEX TABLE qualified_name opt_force
+			| REINDEX reindex_target_type qualified_name WITH opt_verbose
 				{
 					ReindexStmt *n = makeNode(ReindexStmt);
-					n->kind = REINDEX_OBJECT_TABLE;
+					n->kind = $2;
 					n->relation = $3;
 					n->name = NULL;
+					n->verbose = $5;
 					$$ = (Node *)n;
 				}
-			| REINDEX SCHEMA name opt_force
-				{
-					ReindexStmt *n = makeNode(ReindexStmt);
-					n->kind = REINDEX_OBJECT_SCHEMA;
-					n->name = $3;
-					n->relation = NULL;
-					$$ = (Node *)n;
-				}
-			| REINDEX SYSTEM_P name opt_force
+			| REINDEX reindex_target_multitable name opt_force
 				{
 					ReindexStmt *n = makeNode(ReindexStmt);
-					n->kind = REINDEX_OBJECT_SYSTEM;
+					n->kind = $2;
 					n->name = $3;
 					n->relation = NULL;
+					n->verbose = false;
 					$$ = (Node *)n;
 				}
-			| REINDEX DATABASE name opt_force
+			| REINDEX reindex_target_multitable name WITH opt_verbose
 				{
 					ReindexStmt *n = makeNode(ReindexStmt);
-					n->kind = REINDEX_OBJECT_DATABASE;
+					n->kind = $2;
 					n->name = $3;
 					n->relation = NULL;
+				    n->verbose = $5;
 					$$ = (Node *)n;
 				}
 		;
-
-opt_force:	FORCE									{  $$ = TRUE; }
-			| /* EMPTY */							{  $$ = FALSE; }
-		;
-
+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; }
+;
 
 /*****************************************************************************
  *
diff --git a/src/backend/tcop/utility.c b/src/backend/tcop/utility.c
index fd09d3a..ecec81d 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->verbose);
 						break;
 					case REINDEX_OBJECT_TABLE:
-						ReindexTable(stmt->relation);
+						ReindexTable(stmt->relation, stmt->verbose);
 						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->verbose);
 						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 38fde39..a7109b5 100644
--- a/src/bin/psql/tab-complete.c
+++ b/src/bin/psql/tab-complete.c
@@ -3344,12 +3344,32 @@ 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)
 			COMPLETE_WITH_QUERY(Query_for_list_of_databases);
 	}
+	else if (pg_strcasecmp(prev3_wd, "REINDEX") == 0)
+	{
+		if (pg_strcasecmp(prev2_wd, "TABLE") == 0 ||
+			 pg_strcasecmp(prev2_wd, "INDEX") == 0 ||
+			 pg_strcasecmp(prev2_wd, "SCHEMA") == 0 ||
+			 pg_strcasecmp(prev2_wd, "SYSTEM") == 0 ||
+			 pg_strcasecmp(prev2_wd, "DATABASE") == 0)
+			COMPLETE_WITH_CONST("WITH");
+	}
+	else if (pg_strcasecmp(prev4_wd, "REINDEX") == 0)
+	{
+		if ((pg_strcasecmp(prev3_wd, "TABLE") == 0 ||
+			 pg_strcasecmp(prev3_wd, "INDEX") == 0 ||
+			 pg_strcasecmp(prev3_wd, "SCHEMA") == 0 ||
+			 pg_strcasecmp(prev3_wd, "SYSTEM") == 0 ||
+			 pg_strcasecmp(prev3_wd, "DATABASE") == 0) &&
+			pg_strcasecmp(prev_wd, "WITH") == 0)
+			COMPLETE_WITH_CONST("VERBOSE");
+	}
+
 
 /* SECURITY LABEL */
 	else if (pg_strcasecmp(prev_wd, "SECURITY") == 0)
diff --git a/src/include/catalog/index.h b/src/include/catalog/index.h
index a04def9..0662f46 100644
--- a/src/include/catalog/index.h
+++ b/src/include/catalog/index.h
@@ -113,7 +113,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
@@ -122,7 +122,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 595f93f..fce0b41 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, bool verbose);
+extern Oid	ReindexTable(RangeVar *relation, bool verbose );
+extern void ReindexMultipleTables(const char *objectName, ReindexObjectType objectKind, bool verbose);
 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 0e257ac..ee1921f 100644
--- a/src/include/nodes/parsenodes.h
+++ b/src/include/nodes/parsenodes.h
@@ -2750,6 +2750,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 */
+	bool	   verbose;		/* print progress info */
 } ReindexStmt;
 
 /* ----------------------
#41Fabrízio de Royes Mello
fabriziomello@gmail.com
In reply to: Sawada Masahiko (#40)
Re: Proposal : REINDEX xxx VERBOSE

On Mon, Apr 6, 2015 at 10:21 AM, Sawada Masahiko <sawada.mshk@gmail.com>
wrote:

On Fri, Mar 13, 2015 at 5:10 PM, Kyotaro HORIGUCHI
<horiguchi.kyotaro@lab.ntt.co.jp> wrote:

Hello, I have some trivial comments about the latest patch.

At Thu, 12 Mar 2015 21:15:14 +0900, Sawada Masahiko <

sawada.mshk@gmail.com> wrote in <CAD21AoBxPCpPvKQmvJMUh+p=
2pfAu03gKJQ2R2zY47XHsH205Q@mail.gmail.com>

sawada.mshk> On Thu, Mar 12, 2015 at 6:36 AM, Jim Nasby <

Jim.Nasby@bluetreble.com> wrote:

Are the parenthesis necessary? No other WITH option requires

them, other

than create table/matview (COPY doesn't actually require them).

I was imagining EXPLAIN syntax.
Is there some possibility of supporting multiple options for REINDEX
command in future?
If there is, syntax will be as follows, REINDEX { INDEX | ... } name
WITH VERBOSE, XXX, XXX;
I thought style with parenthesis is better than above style.

The thing is, ()s are actually an odd-duck. Very little supports it,

and

while COPY allows it they're not required. EXPLAIN is a different

story,

because that's not WITH; we're actually using () *instead of* WITH.

So because almost all commands that use WITH doen't even accept (),

I don't

think this should either. It certainly shouldn't require them,

because

unlike EXPLAIN, there's no need to require them.

I understood what your point is.
Attached patch is changed syntax, it does not have parenthesis.

As I looked into the code to find what the syntax would be, I
found some points which would be better to be fixed.

In gram.y the options is a list of cstring but it is not necesary
to be a list because there's only one kind of option now.

If you prefer it to be a list, I have a comment for the way to
make string list in gram.y. You stored bare cstring in the
options list but I think it is not the preferable form. I suppose
the followings are preferable. Corresponding fixes are needed in
ReindexTable, ReindexIndex, ReindexMultipleTables.

$ = list_make1(makeString($1);
....
$ = lappend($1, list_make1(makeString($3));

In equalfuncs.c, _equalReindexStmt forgets to compare the member
options. _copyReindexStmt also forgets to copy it. The way you
constructed the options list prevents them from doing their jobs
using prepared methods. Comparing and copying the member "option"
is needed even if it becomes a simple string.

I revised patch, and changed gram.y as I don't use the list.
So this patch adds new syntax,
REINDEX { INDEX | ... } name WITH VERBOSE;

Also documentation is updated.
Please give me feedbacks.

Some notes:

1) There are a trailing space in src/backend/parser/gram.y:

-           | REINDEX DATABASE name opt_force
+           | REINDEX reindex_target_multitable name WITH opt_verbose
                {
                    ReindexStmt *n = makeNode(ReindexStmt);
-                   n->kind = REINDEX_OBJECT_DATABASE;
+                   n->kind = $2;
                    n->name = $3;
                    n->relation = NULL;
+                   n->verbose = $5;
                    $$ = (Node *)n;
                }
        ;

2) The documentation was updated and is according the behaviour.

3) psql autocomplete is ok.

4) Lack of regression tests. I think you should add some regression like
that:

fabrizio=# \set VERBOSITY terse
fabrizio=# create table reindex_verbose(id integer primary key);
CREATE TABLE
fabrizio=# reindex table reindex_verbose with verbose;
INFO: index "reindex_verbose_pkey" was reindexed.
REINDEX

5) Code style and organization is ok

6) You should add the new field ReindexStmt->verbose to
src/backend/nodes/copyfuncs.c

Regards,

--
Fabrízio de Royes Mello
Consultoria/Coaching PostgreSQL

Show quoted text

Timbira: http://www.timbira.com.br
Blog: http://fabriziomello.github.io
Linkedin: http://br.linkedin.com/in/fabriziomello
Twitter: http://twitter.com/fabriziomello
Github: http://github.com/fabriziomello

#42Sawada Masahiko
sawada.mshk@gmail.com
In reply to: Fabrízio de Royes Mello (#41)
1 attachment(s)
Re: Proposal : REINDEX xxx VERBOSE

On Tue, Apr 7, 2015 at 9:32 AM, Fabrízio de Royes Mello
<fabriziomello@gmail.com> wrote:

On Mon, Apr 6, 2015 at 10:21 AM, Sawada Masahiko <sawada.mshk@gmail.com>
wrote:

On Fri, Mar 13, 2015 at 5:10 PM, Kyotaro HORIGUCHI
<horiguchi.kyotaro@lab.ntt.co.jp> wrote:

Hello, I have some trivial comments about the latest patch.

At Thu, 12 Mar 2015 21:15:14 +0900, Sawada Masahiko
<sawada.mshk@gmail.com> wrote in
<CAD21AoBxPCpPvKQmvJMUh+p=2pfAu03gKJQ2R2zY47XHsH205Q@mail.gmail.com>
sawada.mshk> On Thu, Mar 12, 2015 at 6:36 AM, Jim Nasby
<Jim.Nasby@bluetreble.com> wrote:

Are the parenthesis necessary? No other WITH option requires them,
other
than create table/matview (COPY doesn't actually require them).

I was imagining EXPLAIN syntax.
Is there some possibility of supporting multiple options for REINDEX
command in future?
If there is, syntax will be as follows, REINDEX { INDEX | ... } name
WITH VERBOSE, XXX, XXX;
I thought style with parenthesis is better than above style.

The thing is, ()s are actually an odd-duck. Very little supports it,
and
while COPY allows it they're not required. EXPLAIN is a different
story,
because that's not WITH; we're actually using () *instead of* WITH.

So because almost all commands that use WITH doen't even accept (), I
don't
think this should either. It certainly shouldn't require them,
because
unlike EXPLAIN, there's no need to require them.

I understood what your point is.
Attached patch is changed syntax, it does not have parenthesis.

As I looked into the code to find what the syntax would be, I
found some points which would be better to be fixed.

In gram.y the options is a list of cstring but it is not necesary
to be a list because there's only one kind of option now.

If you prefer it to be a list, I have a comment for the way to
make string list in gram.y. You stored bare cstring in the
options list but I think it is not the preferable form. I suppose
the followings are preferable. Corresponding fixes are needed in
ReindexTable, ReindexIndex, ReindexMultipleTables.

$ = list_make1(makeString($1);
....
$ = lappend($1, list_make1(makeString($3));

In equalfuncs.c, _equalReindexStmt forgets to compare the member
options. _copyReindexStmt also forgets to copy it. The way you
constructed the options list prevents them from doing their jobs
using prepared methods. Comparing and copying the member "option"
is needed even if it becomes a simple string.

I revised patch, and changed gram.y as I don't use the list.
So this patch adds new syntax,
REINDEX { INDEX | ... } name WITH VERBOSE;

Also documentation is updated.
Please give me feedbacks.

Some notes:

1) There are a trailing space in src/backend/parser/gram.y:

-           | REINDEX DATABASE name opt_force
+           | REINDEX reindex_target_multitable name WITH opt_verbose
{
ReindexStmt *n = makeNode(ReindexStmt);
-                   n->kind = REINDEX_OBJECT_DATABASE;
+                   n->kind = $2;
n->name = $3;
n->relation = NULL;
+                   n->verbose = $5;
$$ = (Node *)n;
}
;

2) The documentation was updated and is according the behaviour.

3) psql autocomplete is ok.

4) Lack of regression tests. I think you should add some regression like
that:

fabrizio=# \set VERBOSITY terse
fabrizio=# create table reindex_verbose(id integer primary key);
CREATE TABLE
fabrizio=# reindex table reindex_verbose with verbose;
INFO: index "reindex_verbose_pkey" was reindexed.
REINDEX

5) Code style and organization is ok

6) You should add the new field ReindexStmt->verbose to
src/backend/nodes/copyfuncs.c

Regards,

Thank you for your reviewing.
I modified the patch and attached latest version patch(v7).
Please have a look it.

Regards,

-------
Sawada Masahiko

Attachments:

000_reindex_verbose_v7.patchtext/x-patch; charset=US-ASCII; name=000_reindex_verbose_v7.patchDownload
diff --git a/doc/src/sgml/ref/reindex.sgml b/doc/src/sgml/ref/reindex.sgml
index 0a4c7d4..27be1a4 100644
--- a/doc/src/sgml/ref/reindex.sgml
+++ b/doc/src/sgml/ref/reindex.sgml
@@ -22,6 +22,7 @@ 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 VERBOSE
 </synopsis>
  </refsynopsisdiv>
 
@@ -159,6 +160,15 @@ 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>
   </variablelist>
  </refsect1>
 
diff --git a/src/backend/catalog/index.c b/src/backend/catalog/index.c
index 351dcb2..fc44495 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"
@@ -3133,13 +3134,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
@@ -3283,6 +3289,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);
@@ -3324,7 +3337,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;
@@ -3415,7 +3428,7 @@ reindex_relation(Oid relid, int flags)
 				RelationSetIndexList(rel, doneIndexes, InvalidOid);
 
 			reindex_index(indexOid, !(flags & REINDEX_REL_CHECK_CONSTRAINTS),
-						  persistence);
+						  persistence, verbose);
 
 			CommandCounterIncrement();
 
@@ -3450,7 +3463,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 99acd4a..a42a508 100644
--- a/src/backend/commands/indexcmds.c
+++ b/src/backend/commands/indexcmds.c
@@ -1681,7 +1681,7 @@ ChooseIndexColumnNames(List *indexElems)
  *		Recreate a specific index.
  */
 Oid
-ReindexIndex(RangeVar *indexRelation)
+ReindexIndex(RangeVar *indexRelation, bool verbose)
 {
 	Oid			indOid;
 	Oid			heapOid = InvalidOid;
@@ -1706,7 +1706,7 @@ ReindexIndex(RangeVar *indexRelation)
 	persistence = irel->rd_rel->relpersistence;
 	index_close(irel, NoLock);
 
-	reindex_index(indOid, false, persistence);
+	reindex_index(indOid, false, persistence, verbose);
 
 	return indOid;
 }
@@ -1775,7 +1775,7 @@ RangeVarCallbackForReindexIndex(const RangeVar *relation,
  *		Recreate all indexes of a table (and of its toast table, if any)
  */
 Oid
-ReindexTable(RangeVar *relation)
+ReindexTable(RangeVar *relation, bool verbose)
 {
 	Oid			heapOid;
 
@@ -1785,7 +1785,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)));
@@ -1802,7 +1803,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, bool verbose)
 {
 	Oid			objectOid;
 	Relation	relationRelation;
@@ -1814,6 +1815,7 @@ ReindexMultipleTables(const char *objectName, ReindexObjectType objectKind)
 	List	   *relids = NIL;
 	ListCell   *l;
 	int			num_keys;
+	int			elevel = verbose ? INFO : DEBUG2;
 
 	AssertArg(objectName);
 	Assert(objectKind == REINDEX_OBJECT_SCHEMA ||
@@ -1938,9 +1940,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 06e4332..4f90a9e 100644
--- a/src/backend/commands/tablecmds.c
+++ b/src/backend/commands/tablecmds.c
@@ -1226,7 +1226,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/nodes/copyfuncs.c b/src/backend/nodes/copyfuncs.c
index 029761e..5b87c3f 100644
--- a/src/backend/nodes/copyfuncs.c
+++ b/src/backend/nodes/copyfuncs.c
@@ -3763,6 +3763,7 @@ _copyReindexStmt(const ReindexStmt *from)
 	COPY_SCALAR_FIELD(kind);
 	COPY_NODE_FIELD(relation);
 	COPY_STRING_FIELD(name);
+	COPY_SCALAR_FIELD(verbose);
 
 	return newnode;
 }
diff --git a/src/backend/nodes/equalfuncs.c b/src/backend/nodes/equalfuncs.c
index 190e50a..cecd0c5 100644
--- a/src/backend/nodes/equalfuncs.c
+++ b/src/backend/nodes/equalfuncs.c
@@ -1896,6 +1896,7 @@ _equalReindexStmt(const ReindexStmt *a, const ReindexStmt *b)
 	COMPARE_SCALAR_FIELD(kind);
 	COMPARE_NODE_FIELD(relation);
 	COMPARE_STRING_FIELD(name);
+	COMPARE_SCALAR_FIELD(verbose);
 
 	return true;
 }
diff --git a/src/backend/parser/gram.y b/src/backend/parser/gram.y
index 88ec83c..f4c88af 100644
--- a/src/backend/parser/gram.y
+++ b/src/backend/parser/gram.y
@@ -457,6 +457,10 @@ 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 <ival>	reindex_target_type
+%type <ival>	reindex_target_multitable
+
 %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
@@ -7302,57 +7306,62 @@ opt_if_exists: IF_P EXISTS						{ $$ = TRUE; }
  *		QUERY:
  *
  *		REINDEX type <name> [FORCE]
+ *		REINDEX type <name> WITH VERBOSE
  *
  * 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->verbose = false;
 					$$ = (Node *)n;
 				}
-			| REINDEX TABLE qualified_name opt_force
+			| REINDEX reindex_target_type qualified_name WITH opt_verbose
 				{
 					ReindexStmt *n = makeNode(ReindexStmt);
-					n->kind = REINDEX_OBJECT_TABLE;
+					n->kind = $2;
 					n->relation = $3;
 					n->name = NULL;
+					n->verbose = $5;
 					$$ = (Node *)n;
 				}
-			| REINDEX SCHEMA name opt_force
-				{
-					ReindexStmt *n = makeNode(ReindexStmt);
-					n->kind = REINDEX_OBJECT_SCHEMA;
-					n->name = $3;
-					n->relation = NULL;
-					$$ = (Node *)n;
-				}
-			| REINDEX SYSTEM_P name opt_force
+			| REINDEX reindex_target_multitable name opt_force
 				{
 					ReindexStmt *n = makeNode(ReindexStmt);
-					n->kind = REINDEX_OBJECT_SYSTEM;
+					n->kind = $2;
 					n->name = $3;
 					n->relation = NULL;
+					n->verbose = false;
 					$$ = (Node *)n;
 				}
-			| REINDEX DATABASE name opt_force
+			| REINDEX reindex_target_multitable name WITH opt_verbose
 				{
 					ReindexStmt *n = makeNode(ReindexStmt);
-					n->kind = REINDEX_OBJECT_DATABASE;
+					n->kind = $2;
 					n->name = $3;
 					n->relation = NULL;
+				    n->verbose = $5;
 					$$ = (Node *)n;
 				}
 		;
-
-opt_force:	FORCE									{  $$ = TRUE; }
-			| /* EMPTY */							{  $$ = FALSE; }
-		;
-
+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; }
+;
 
 /*****************************************************************************
  *
diff --git a/src/backend/tcop/utility.c b/src/backend/tcop/utility.c
index fd09d3a..ecec81d 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->verbose);
 						break;
 					case REINDEX_OBJECT_TABLE:
-						ReindexTable(stmt->relation);
+						ReindexTable(stmt->relation, stmt->verbose);
 						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->verbose);
 						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 38fde39..a7109b5 100644
--- a/src/bin/psql/tab-complete.c
+++ b/src/bin/psql/tab-complete.c
@@ -3344,12 +3344,32 @@ 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)
 			COMPLETE_WITH_QUERY(Query_for_list_of_databases);
 	}
+	else if (pg_strcasecmp(prev3_wd, "REINDEX") == 0)
+	{
+		if (pg_strcasecmp(prev2_wd, "TABLE") == 0 ||
+			 pg_strcasecmp(prev2_wd, "INDEX") == 0 ||
+			 pg_strcasecmp(prev2_wd, "SCHEMA") == 0 ||
+			 pg_strcasecmp(prev2_wd, "SYSTEM") == 0 ||
+			 pg_strcasecmp(prev2_wd, "DATABASE") == 0)
+			COMPLETE_WITH_CONST("WITH");
+	}
+	else if (pg_strcasecmp(prev4_wd, "REINDEX") == 0)
+	{
+		if ((pg_strcasecmp(prev3_wd, "TABLE") == 0 ||
+			 pg_strcasecmp(prev3_wd, "INDEX") == 0 ||
+			 pg_strcasecmp(prev3_wd, "SCHEMA") == 0 ||
+			 pg_strcasecmp(prev3_wd, "SYSTEM") == 0 ||
+			 pg_strcasecmp(prev3_wd, "DATABASE") == 0) &&
+			pg_strcasecmp(prev_wd, "WITH") == 0)
+			COMPLETE_WITH_CONST("VERBOSE");
+	}
+
 
 /* SECURITY LABEL */
 	else if (pg_strcasecmp(prev_wd, "SECURITY") == 0)
diff --git a/src/include/catalog/index.h b/src/include/catalog/index.h
index a04def9..0662f46 100644
--- a/src/include/catalog/index.h
+++ b/src/include/catalog/index.h
@@ -113,7 +113,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
@@ -122,7 +122,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 595f93f..fce0b41 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, bool verbose);
+extern Oid	ReindexTable(RangeVar *relation, bool verbose );
+extern void ReindexMultipleTables(const char *objectName, ReindexObjectType objectKind, bool verbose);
 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 0e257ac..ee1921f 100644
--- a/src/include/nodes/parsenodes.h
+++ b/src/include/nodes/parsenodes.h
@@ -2750,6 +2750,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 */
+	bool	   verbose;		/* print progress info */
 } ReindexStmt;
 
 /* ----------------------
diff --git a/src/test/regress/expected/create_index.out b/src/test/regress/expected/create_index.out
index abe64e5..7bd2f5a 100644
--- a/src/test/regress/expected/create_index.out
+++ b/src/test/regress/expected/create_index.out
@@ -2832,6 +2832,14 @@ explain (costs off)
 (2 rows)
 
 --
+-- REINDEX WITH VERBOSE
+--
+CREATE TABLE reindex_verbose(id integer primary key);
+\set VERBOSITY terse
+REINDEX TABLE reindex_verbose WITH VERBOSE;
+INFO:  index "reindex_verbose_pkey" was reindexed.
+DROP TABLE reindex_verbose;
+--
 -- REINDEX SCHEMA
 --
 REINDEX SCHEMA schema_to_reindex; -- failure, schema does not exist
diff --git a/src/test/regress/sql/create_index.sql b/src/test/regress/sql/create_index.sql
index f779fa0..65d52b8 100644
--- a/src/test/regress/sql/create_index.sql
+++ b/src/test/regress/sql/create_index.sql
@@ -966,6 +966,14 @@ explain (costs off)
   select * from tenk1 where (thousand, tenthous) in ((1,1001), (null,null));
 
 --
+-- REINDEX WITH VERBOSE
+--
+CREATE TABLE reindex_verbose(id integer primary key);
+\set VERBOSITY terse
+REINDEX TABLE reindex_verbose WITH VERBOSE;
+DROP TABLE reindex_verbose;
+
+--
 -- REINDEX SCHEMA
 --
 REINDEX SCHEMA schema_to_reindex; -- failure, schema does not exist
#43Fabrízio de Royes Mello
fabriziomello@gmail.com
In reply to: Sawada Masahiko (#42)
1 attachment(s)
Re: Proposal : REINDEX xxx VERBOSE

On Tue, Apr 7, 2015 at 7:22 AM, Sawada Masahiko <sawada.mshk@gmail.com>
wrote:

Thank you for your reviewing.
I modified the patch and attached latest version patch(v7).
Please have a look it.

Looks good to me. Attached patch (v8) just fix a tab indentation in gram.y.

Regards,

--
Fabrízio de Royes Mello
Consultoria/Coaching PostgreSQL

Show quoted text

Timbira: http://www.timbira.com.br
Blog: http://fabriziomello.github.io
Linkedin: http://br.linkedin.com/in/fabriziomello
Twitter: http://twitter.com/fabriziomello
Github: http://github.com/fabriziomello

Attachments:

000_reindex_verbose_v8.patchtext/x-diff; charset=US-ASCII; name=000_reindex_verbose_v8.patchDownload
diff --git a/doc/src/sgml/ref/reindex.sgml b/doc/src/sgml/ref/reindex.sgml
index 0a4c7d4..27be1a4 100644
--- a/doc/src/sgml/ref/reindex.sgml
+++ b/doc/src/sgml/ref/reindex.sgml
@@ -22,6 +22,7 @@ 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 VERBOSE
 </synopsis>
  </refsynopsisdiv>
 
@@ -159,6 +160,15 @@ 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>
   </variablelist>
  </refsect1>
 
diff --git a/src/backend/catalog/index.c b/src/backend/catalog/index.c
index 351dcb2..fc44495 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"
@@ -3133,13 +3134,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
@@ -3283,6 +3289,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);
@@ -3324,7 +3337,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;
@@ -3415,7 +3428,7 @@ reindex_relation(Oid relid, int flags)
 				RelationSetIndexList(rel, doneIndexes, InvalidOid);
 
 			reindex_index(indexOid, !(flags & REINDEX_REL_CHECK_CONSTRAINTS),
-						  persistence);
+						  persistence, verbose);
 
 			CommandCounterIncrement();
 
@@ -3450,7 +3463,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 99acd4a..a42a508 100644
--- a/src/backend/commands/indexcmds.c
+++ b/src/backend/commands/indexcmds.c
@@ -1681,7 +1681,7 @@ ChooseIndexColumnNames(List *indexElems)
  *		Recreate a specific index.
  */
 Oid
-ReindexIndex(RangeVar *indexRelation)
+ReindexIndex(RangeVar *indexRelation, bool verbose)
 {
 	Oid			indOid;
 	Oid			heapOid = InvalidOid;
@@ -1706,7 +1706,7 @@ ReindexIndex(RangeVar *indexRelation)
 	persistence = irel->rd_rel->relpersistence;
 	index_close(irel, NoLock);
 
-	reindex_index(indOid, false, persistence);
+	reindex_index(indOid, false, persistence, verbose);
 
 	return indOid;
 }
@@ -1775,7 +1775,7 @@ RangeVarCallbackForReindexIndex(const RangeVar *relation,
  *		Recreate all indexes of a table (and of its toast table, if any)
  */
 Oid
-ReindexTable(RangeVar *relation)
+ReindexTable(RangeVar *relation, bool verbose)
 {
 	Oid			heapOid;
 
@@ -1785,7 +1785,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)));
@@ -1802,7 +1803,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, bool verbose)
 {
 	Oid			objectOid;
 	Relation	relationRelation;
@@ -1814,6 +1815,7 @@ ReindexMultipleTables(const char *objectName, ReindexObjectType objectKind)
 	List	   *relids = NIL;
 	ListCell   *l;
 	int			num_keys;
+	int			elevel = verbose ? INFO : DEBUG2;
 
 	AssertArg(objectName);
 	Assert(objectKind == REINDEX_OBJECT_SCHEMA ||
@@ -1938,9 +1940,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 06e4332..4f90a9e 100644
--- a/src/backend/commands/tablecmds.c
+++ b/src/backend/commands/tablecmds.c
@@ -1226,7 +1226,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/nodes/copyfuncs.c b/src/backend/nodes/copyfuncs.c
index 029761e..5b87c3f 100644
--- a/src/backend/nodes/copyfuncs.c
+++ b/src/backend/nodes/copyfuncs.c
@@ -3763,6 +3763,7 @@ _copyReindexStmt(const ReindexStmt *from)
 	COPY_SCALAR_FIELD(kind);
 	COPY_NODE_FIELD(relation);
 	COPY_STRING_FIELD(name);
+	COPY_SCALAR_FIELD(verbose);
 
 	return newnode;
 }
diff --git a/src/backend/nodes/equalfuncs.c b/src/backend/nodes/equalfuncs.c
index 190e50a..cecd0c5 100644
--- a/src/backend/nodes/equalfuncs.c
+++ b/src/backend/nodes/equalfuncs.c
@@ -1896,6 +1896,7 @@ _equalReindexStmt(const ReindexStmt *a, const ReindexStmt *b)
 	COMPARE_SCALAR_FIELD(kind);
 	COMPARE_NODE_FIELD(relation);
 	COMPARE_STRING_FIELD(name);
+	COMPARE_SCALAR_FIELD(verbose);
 
 	return true;
 }
diff --git a/src/backend/parser/gram.y b/src/backend/parser/gram.y
index 88ec83c..a6fccb2 100644
--- a/src/backend/parser/gram.y
+++ b/src/backend/parser/gram.y
@@ -457,6 +457,10 @@ 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 <ival>	reindex_target_type
+%type <ival>	reindex_target_multitable
+
 %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
@@ -7302,57 +7306,62 @@ opt_if_exists: IF_P EXISTS						{ $$ = TRUE; }
  *		QUERY:
  *
  *		REINDEX type <name> [FORCE]
+ *		REINDEX type <name> WITH VERBOSE
  *
  * 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->verbose = false;
 					$$ = (Node *)n;
 				}
-			| REINDEX TABLE qualified_name opt_force
+			| REINDEX reindex_target_type qualified_name WITH opt_verbose
 				{
 					ReindexStmt *n = makeNode(ReindexStmt);
-					n->kind = REINDEX_OBJECT_TABLE;
+					n->kind = $2;
 					n->relation = $3;
 					n->name = NULL;
+					n->verbose = $5;
 					$$ = (Node *)n;
 				}
-			| REINDEX SCHEMA name opt_force
-				{
-					ReindexStmt *n = makeNode(ReindexStmt);
-					n->kind = REINDEX_OBJECT_SCHEMA;
-					n->name = $3;
-					n->relation = NULL;
-					$$ = (Node *)n;
-				}
-			| REINDEX SYSTEM_P name opt_force
+			| REINDEX reindex_target_multitable name opt_force
 				{
 					ReindexStmt *n = makeNode(ReindexStmt);
-					n->kind = REINDEX_OBJECT_SYSTEM;
+					n->kind = $2;
 					n->name = $3;
 					n->relation = NULL;
+					n->verbose = false;
 					$$ = (Node *)n;
 				}
-			| REINDEX DATABASE name opt_force
+			| REINDEX reindex_target_multitable name WITH opt_verbose
 				{
 					ReindexStmt *n = makeNode(ReindexStmt);
-					n->kind = REINDEX_OBJECT_DATABASE;
+					n->kind = $2;
 					n->name = $3;
 					n->relation = NULL;
+					n->verbose = $5;
 					$$ = (Node *)n;
 				}
 		;
-
-opt_force:	FORCE									{  $$ = TRUE; }
-			| /* EMPTY */							{  $$ = FALSE; }
-		;
-
+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; }
+;
 
 /*****************************************************************************
  *
diff --git a/src/backend/tcop/utility.c b/src/backend/tcop/utility.c
index fd09d3a..ecec81d 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->verbose);
 						break;
 					case REINDEX_OBJECT_TABLE:
-						ReindexTable(stmt->relation);
+						ReindexTable(stmt->relation, stmt->verbose);
 						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->verbose);
 						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 38fde39..a7109b5 100644
--- a/src/bin/psql/tab-complete.c
+++ b/src/bin/psql/tab-complete.c
@@ -3344,12 +3344,32 @@ 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)
 			COMPLETE_WITH_QUERY(Query_for_list_of_databases);
 	}
+	else if (pg_strcasecmp(prev3_wd, "REINDEX") == 0)
+	{
+		if (pg_strcasecmp(prev2_wd, "TABLE") == 0 ||
+			 pg_strcasecmp(prev2_wd, "INDEX") == 0 ||
+			 pg_strcasecmp(prev2_wd, "SCHEMA") == 0 ||
+			 pg_strcasecmp(prev2_wd, "SYSTEM") == 0 ||
+			 pg_strcasecmp(prev2_wd, "DATABASE") == 0)
+			COMPLETE_WITH_CONST("WITH");
+	}
+	else if (pg_strcasecmp(prev4_wd, "REINDEX") == 0)
+	{
+		if ((pg_strcasecmp(prev3_wd, "TABLE") == 0 ||
+			 pg_strcasecmp(prev3_wd, "INDEX") == 0 ||
+			 pg_strcasecmp(prev3_wd, "SCHEMA") == 0 ||
+			 pg_strcasecmp(prev3_wd, "SYSTEM") == 0 ||
+			 pg_strcasecmp(prev3_wd, "DATABASE") == 0) &&
+			pg_strcasecmp(prev_wd, "WITH") == 0)
+			COMPLETE_WITH_CONST("VERBOSE");
+	}
+
 
 /* SECURITY LABEL */
 	else if (pg_strcasecmp(prev_wd, "SECURITY") == 0)
diff --git a/src/include/catalog/index.h b/src/include/catalog/index.h
index a04def9..0662f46 100644
--- a/src/include/catalog/index.h
+++ b/src/include/catalog/index.h
@@ -113,7 +113,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
@@ -122,7 +122,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 595f93f..fce0b41 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, bool verbose);
+extern Oid	ReindexTable(RangeVar *relation, bool verbose );
+extern void ReindexMultipleTables(const char *objectName, ReindexObjectType objectKind, bool verbose);
 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 0e257ac..ee1921f 100644
--- a/src/include/nodes/parsenodes.h
+++ b/src/include/nodes/parsenodes.h
@@ -2750,6 +2750,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 */
+	bool	   verbose;		/* print progress info */
 } ReindexStmt;
 
 /* ----------------------
diff --git a/src/test/regress/expected/create_index.out b/src/test/regress/expected/create_index.out
index abe64e5..7bd2f5a 100644
--- a/src/test/regress/expected/create_index.out
+++ b/src/test/regress/expected/create_index.out
@@ -2832,6 +2832,14 @@ explain (costs off)
 (2 rows)
 
 --
+-- REINDEX WITH VERBOSE
+--
+CREATE TABLE reindex_verbose(id integer primary key);
+\set VERBOSITY terse
+REINDEX TABLE reindex_verbose WITH VERBOSE;
+INFO:  index "reindex_verbose_pkey" was reindexed.
+DROP TABLE reindex_verbose;
+--
 -- REINDEX SCHEMA
 --
 REINDEX SCHEMA schema_to_reindex; -- failure, schema does not exist
diff --git a/src/test/regress/sql/create_index.sql b/src/test/regress/sql/create_index.sql
index f779fa0..65d52b8 100644
--- a/src/test/regress/sql/create_index.sql
+++ b/src/test/regress/sql/create_index.sql
@@ -966,6 +966,14 @@ explain (costs off)
   select * from tenk1 where (thousand, tenthous) in ((1,1001), (null,null));
 
 --
+-- REINDEX WITH VERBOSE
+--
+CREATE TABLE reindex_verbose(id integer primary key);
+\set VERBOSITY terse
+REINDEX TABLE reindex_verbose WITH VERBOSE;
+DROP TABLE reindex_verbose;
+
+--
 -- REINDEX SCHEMA
 --
 REINDEX SCHEMA schema_to_reindex; -- failure, schema does not exist
#44Sawada Masahiko
sawada.mshk@gmail.com
In reply to: Fabrízio de Royes Mello (#43)
Re: Proposal : REINDEX xxx VERBOSE

On Tue, Apr 7, 2015 at 10:12 PM, Fabrízio de Royes Mello
<fabriziomello@gmail.com> wrote:

On Tue, Apr 7, 2015 at 7:22 AM, Sawada Masahiko <sawada.mshk@gmail.com>
wrote:

Thank you for your reviewing.
I modified the patch and attached latest version patch(v7).
Please have a look it.

Looks good to me. Attached patch (v8) just fix a tab indentation in gram.y.

I had forgotten fix a tab indentation, sorry.
Thank you for reviewing!
It looks good to me too.
Can this patch be marked as "Ready for Committer"?

Regards,

-------
Sawada Masahiko

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

#45Fabrízio de Royes Mello
fabriziomello@gmail.com
In reply to: Sawada Masahiko (#44)
Re: Proposal : REINDEX xxx VERBOSE

On Tue, Apr 7, 2015 at 1:04 PM, Sawada Masahiko <sawada.mshk@gmail.com>
wrote:

On Tue, Apr 7, 2015 at 10:12 PM, Fabrízio de Royes Mello
<fabriziomello@gmail.com> wrote:

On Tue, Apr 7, 2015 at 7:22 AM, Sawada Masahiko <sawada.mshk@gmail.com>
wrote:

Thank you for your reviewing.
I modified the patch and attached latest version patch(v7).
Please have a look it.

Looks good to me. Attached patch (v8) just fix a tab indentation in

gram.y.

I had forgotten fix a tab indentation, sorry.
Thank you for reviewing!
It looks good to me too.
Can this patch be marked as "Ready for Committer"?

+1

--
Fabrízio de Royes Mello
Consultoria/Coaching PostgreSQL

Show quoted text

Timbira: http://www.timbira.com.br
Blog: http://fabriziomello.github.io
Linkedin: http://br.linkedin.com/in/fabriziomello
Twitter: http://twitter.com/fabriziomello
Github: http://github.com/fabriziomello

#46Sawada Masahiko
sawada.mshk@gmail.com
In reply to: Fabrízio de Royes Mello (#45)
Re: Proposal : REINDEX xxx VERBOSE

On Wed, Apr 8, 2015 at 1:11 AM, Fabrízio de Royes Mello
<fabriziomello@gmail.com> wrote:

On Tue, Apr 7, 2015 at 1:04 PM, Sawada Masahiko <sawada.mshk@gmail.com>
wrote:

On Tue, Apr 7, 2015 at 10:12 PM, Fabrízio de Royes Mello
<fabriziomello@gmail.com> wrote:

On Tue, Apr 7, 2015 at 7:22 AM, Sawada Masahiko <sawada.mshk@gmail.com>
wrote:

Thank you for your reviewing.
I modified the patch and attached latest version patch(v7).
Please have a look it.

Looks good to me. Attached patch (v8) just fix a tab indentation in
gram.y.

I had forgotten fix a tab indentation, sorry.
Thank you for reviewing!
It looks good to me too.
Can this patch be marked as "Ready for Committer"?

+1

Changed status to "Ready for Committer".
Thank you for final reviewing!

Regards,

-------
Sawada Masahiko

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

#47Fujii Masao
masao.fujii@gmail.com
In reply to: Sawada Masahiko (#46)
Re: Proposal : REINDEX xxx VERBOSE

On Wed, Apr 8, 2015 at 1:57 AM, Sawada Masahiko <sawada.mshk@gmail.com> wrote:

On Wed, Apr 8, 2015 at 1:11 AM, Fabrízio de Royes Mello
<fabriziomello@gmail.com> wrote:

On Tue, Apr 7, 2015 at 1:04 PM, Sawada Masahiko <sawada.mshk@gmail.com>
wrote:

On Tue, Apr 7, 2015 at 10:12 PM, Fabrízio de Royes Mello
<fabriziomello@gmail.com> wrote:

On Tue, Apr 7, 2015 at 7:22 AM, Sawada Masahiko <sawada.mshk@gmail.com>
wrote:

Thank you for your reviewing.
I modified the patch and attached latest version patch(v7).
Please have a look it.

Looks good to me. Attached patch (v8) just fix a tab indentation in
gram.y.

I had forgotten fix a tab indentation, sorry.
Thank you for reviewing!
It looks good to me too.
Can this patch be marked as "Ready for Committer"?

+1

Changed status to "Ready for Committer".

The patch adds new syntax like "REINDEX ... WITH VERBOSE", i.e., () is not
added after WITH clause. Did we reach the consensus about this syntax?
The last email from Robert just makes me think that () should be added
into the syntax.

Regards,

--
Fujii Masao

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

#48Sawada Masahiko
sawada.mshk@gmail.com
In reply to: Fujii Masao (#47)
Re: Proposal : REINDEX xxx VERBOSE

On Wed, Apr 8, 2015 at 1:09 PM, Fujii Masao <masao.fujii@gmail.com> wrote:

On Wed, Apr 8, 2015 at 1:57 AM, Sawada Masahiko <sawada.mshk@gmail.com> wrote:

On Wed, Apr 8, 2015 at 1:11 AM, Fabrízio de Royes Mello
<fabriziomello@gmail.com> wrote:

On Tue, Apr 7, 2015 at 1:04 PM, Sawada Masahiko <sawada.mshk@gmail.com>
wrote:

On Tue, Apr 7, 2015 at 10:12 PM, Fabrízio de Royes Mello
<fabriziomello@gmail.com> wrote:

On Tue, Apr 7, 2015 at 7:22 AM, Sawada Masahiko <sawada.mshk@gmail.com>
wrote:

Thank you for your reviewing.
I modified the patch and attached latest version patch(v7).
Please have a look it.

Looks good to me. Attached patch (v8) just fix a tab indentation in
gram.y.

I had forgotten fix a tab indentation, sorry.
Thank you for reviewing!
It looks good to me too.
Can this patch be marked as "Ready for Committer"?

+1

Changed status to "Ready for Committer".

The patch adds new syntax like "REINDEX ... WITH VERBOSE", i.e., () is not
added after WITH clause. Did we reach the consensus about this syntax?
The last email from Robert just makes me think that () should be added
into the syntax.

Thank you for taking time for this patch!

This was quite complicated issue since we already have a lot of style
command currently.
We can think many of style from various perspective: kind of DDL, new
or old command, maintenance command. And each command has each its
story.
I believe we have reached the consensus with this style at least once
(please see previous discussion), but we might needs to discuss
more...

Regards,

-------
Sawada Masahiko

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

#49Fujii Masao
masao.fujii@gmail.com
In reply to: Sawada Masahiko (#48)
Re: Proposal : REINDEX xxx VERBOSE

On Wed, Apr 8, 2015 at 10:53 PM, Sawada Masahiko <sawada.mshk@gmail.com> wrote:

On Wed, Apr 8, 2015 at 1:09 PM, Fujii Masao <masao.fujii@gmail.com> wrote:

On Wed, Apr 8, 2015 at 1:57 AM, Sawada Masahiko <sawada.mshk@gmail.com> wrote:

On Wed, Apr 8, 2015 at 1:11 AM, Fabrízio de Royes Mello
<fabriziomello@gmail.com> wrote:

On Tue, Apr 7, 2015 at 1:04 PM, Sawada Masahiko <sawada.mshk@gmail.com>
wrote:

On Tue, Apr 7, 2015 at 10:12 PM, Fabrízio de Royes Mello
<fabriziomello@gmail.com> wrote:

On Tue, Apr 7, 2015 at 7:22 AM, Sawada Masahiko <sawada.mshk@gmail.com>
wrote:

Thank you for your reviewing.
I modified the patch and attached latest version patch(v7).
Please have a look it.

Looks good to me. Attached patch (v8) just fix a tab indentation in
gram.y.

I had forgotten fix a tab indentation, sorry.
Thank you for reviewing!
It looks good to me too.
Can this patch be marked as "Ready for Committer"?

+1

Changed status to "Ready for Committer".

The patch adds new syntax like "REINDEX ... WITH VERBOSE", i.e., () is not
added after WITH clause. Did we reach the consensus about this syntax?
The last email from Robert just makes me think that () should be added
into the syntax.

Thank you for taking time for this patch!

I removed the FORCE option from REINDEX, so you would need to update the patch.

This was quite complicated issue since we already have a lot of style
command currently.
We can think many of style from various perspective: kind of DDL, new
or old command, maintenance command. And each command has each its
story.
I believe we have reached the consensus with this style at least once
(please see previous discussion), but we might needs to discuss
more...

Okay, another question is that; WITH must be required whenever the options
are specified? Or should it be abbreviatable?

Regards,

--
Fujii Masao

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

#50Sawada Masahiko
sawada.mshk@gmail.com
In reply to: Fujii Masao (#49)
Re: Proposal : REINDEX xxx VERBOSE

On Thu, Apr 9, 2015 at 1:14 PM, Fujii Masao <masao.fujii@gmail.com> wrote:

On Wed, Apr 8, 2015 at 10:53 PM, Sawada Masahiko <sawada.mshk@gmail.com> wrote:

On Wed, Apr 8, 2015 at 1:09 PM, Fujii Masao <masao.fujii@gmail.com> wrote:

On Wed, Apr 8, 2015 at 1:57 AM, Sawada Masahiko <sawada.mshk@gmail.com> wrote:

On Wed, Apr 8, 2015 at 1:11 AM, Fabrízio de Royes Mello
<fabriziomello@gmail.com> wrote:

On Tue, Apr 7, 2015 at 1:04 PM, Sawada Masahiko <sawada.mshk@gmail.com>
wrote:

On Tue, Apr 7, 2015 at 10:12 PM, Fabrízio de Royes Mello
<fabriziomello@gmail.com> wrote:

On Tue, Apr 7, 2015 at 7:22 AM, Sawada Masahiko <sawada.mshk@gmail.com>
wrote:

Thank you for your reviewing.
I modified the patch and attached latest version patch(v7).
Please have a look it.

Looks good to me. Attached patch (v8) just fix a tab indentation in
gram.y.

I had forgotten fix a tab indentation, sorry.
Thank you for reviewing!
It looks good to me too.
Can this patch be marked as "Ready for Committer"?

+1

Changed status to "Ready for Committer".

The patch adds new syntax like "REINDEX ... WITH VERBOSE", i.e., () is not
added after WITH clause. Did we reach the consensus about this syntax?
The last email from Robert just makes me think that () should be added
into the syntax.

Thank you for taking time for this patch!

I removed the FORCE option from REINDEX, so you would need to update the patch.

Thanks.
I will change the patch with this change.

This was quite complicated issue since we already have a lot of style
command currently.
We can think many of style from various perspective: kind of DDL, new
or old command, maintenance command. And each command has each its
story.
I believe we have reached the consensus with this style at least once
(please see previous discussion), but we might needs to discuss
more...

Okay, another question is that; WITH must be required whenever the options
are specified? Or should it be abbreviatable?

In previous discussion, the WITH clause is always required by VERBOSE
option. I don't think to enable us to abbreviate WITH clause for now.
Also, at this time that FORCE option is removed, we could bring back
idea is to put VERBOSE at after object name like CLUSTER. (INDEX,
TABLE, etc.)

Regards,

-------
Sawada Masahiko

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

#51Sawada Masahiko
sawada.mshk@gmail.com
In reply to: Sawada Masahiko (#50)
1 attachment(s)
Re: Proposal : REINDEX xxx VERBOSE

On Fri, Apr 10, 2015 at 2:52 AM, Sawada Masahiko <sawada.mshk@gmail.com> wrote:

On Thu, Apr 9, 2015 at 1:14 PM, Fujii Masao <masao.fujii@gmail.com> wrote:

On Wed, Apr 8, 2015 at 10:53 PM, Sawada Masahiko <sawada.mshk@gmail.com> wrote:

On Wed, Apr 8, 2015 at 1:09 PM, Fujii Masao <masao.fujii@gmail.com> wrote:

On Wed, Apr 8, 2015 at 1:57 AM, Sawada Masahiko <sawada.mshk@gmail.com> wrote:

On Wed, Apr 8, 2015 at 1:11 AM, Fabrízio de Royes Mello
<fabriziomello@gmail.com> wrote:

On Tue, Apr 7, 2015 at 1:04 PM, Sawada Masahiko <sawada.mshk@gmail.com>
wrote:

On Tue, Apr 7, 2015 at 10:12 PM, Fabrízio de Royes Mello
<fabriziomello@gmail.com> wrote:

On Tue, Apr 7, 2015 at 7:22 AM, Sawada Masahiko <sawada.mshk@gmail.com>
wrote:

Thank you for your reviewing.
I modified the patch and attached latest version patch(v7).
Please have a look it.

Looks good to me. Attached patch (v8) just fix a tab indentation in
gram.y.

I had forgotten fix a tab indentation, sorry.
Thank you for reviewing!
It looks good to me too.
Can this patch be marked as "Ready for Committer"?

+1

Changed status to "Ready for Committer".

The patch adds new syntax like "REINDEX ... WITH VERBOSE", i.e., () is not
added after WITH clause. Did we reach the consensus about this syntax?
The last email from Robert just makes me think that () should be added
into the syntax.

Thank you for taking time for this patch!

I removed the FORCE option from REINDEX, so you would need to update the patch.

Thanks.
I will change the patch with this change.

This was quite complicated issue since we already have a lot of style
command currently.
We can think many of style from various perspective: kind of DDL, new
or old command, maintenance command. And each command has each its
story.
I believe we have reached the consensus with this style at least once
(please see previous discussion), but we might needs to discuss
more...

Okay, another question is that; WITH must be required whenever the options
are specified? Or should it be abbreviatable?

In previous discussion, the WITH clause is always required by VERBOSE
option. I don't think to enable us to abbreviate WITH clause for now.
Also, at this time that FORCE option is removed, we could bring back
idea is to put VERBOSE at after object name like CLUSTER. (INDEX,
TABLE, etc.)

Attached v10 patch is latest version patch.
The syntax is,
REINDEX { INDEX | ... } name [ WITH ] [ VERBOSE ]

That is, WITH clause is optional.

Regards,

-------
Sawada Masahiko

Attachments:

000_reindex_verbose_v10.patchtext/x-diff; charset=US-ASCII; name=000_reindex_verbose_v10.patchDownload
diff --git a/doc/src/sgml/ref/reindex.sgml b/doc/src/sgml/ref/reindex.sgml
index 998340c..2e8db5a 100644
--- a/doc/src/sgml/ref/reindex.sgml
+++ b/doc/src/sgml/ref/reindex.sgml
@@ -21,7 +21,7 @@ PostgreSQL documentation
 
  <refsynopsisdiv>
 <synopsis>
-REINDEX { INDEX | TABLE | SCHEMA | DATABASE | SYSTEM } <replaceable class="PARAMETER">name</replaceable>
+REINDEX { INDEX | TABLE | SCHEMA | DATABASE | SYSTEM } <replaceable class="PARAMETER">name</replaceable> [ WITH ] [ VERBOSE ]
 </synopsis>
  </refsynopsisdiv>
 
@@ -150,6 +150,15 @@ 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>
   </variablelist>
  </refsect1>
 
diff --git a/src/backend/catalog/index.c b/src/backend/catalog/index.c
index ac3b785..27364ec 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"
@@ -3133,13 +3134,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
@@ -3283,6 +3289,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);
@@ -3324,7 +3337,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;
@@ -3415,7 +3428,7 @@ reindex_relation(Oid relid, int flags)
 				RelationSetIndexList(rel, doneIndexes, InvalidOid);
 
 			reindex_index(indexOid, !(flags & REINDEX_REL_CHECK_CONSTRAINTS),
-						  persistence);
+						  persistence, verbose);
 
 			CommandCounterIncrement();
 
@@ -3450,7 +3463,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 351d48e..5d44bda 100644
--- a/src/backend/commands/indexcmds.c
+++ b/src/backend/commands/indexcmds.c
@@ -1681,7 +1681,7 @@ ChooseIndexColumnNames(List *indexElems)
  *		Recreate a specific index.
  */
 Oid
-ReindexIndex(RangeVar *indexRelation)
+ReindexIndex(RangeVar *indexRelation, bool verbose)
 {
 	Oid			indOid;
 	Oid			heapOid = InvalidOid;
@@ -1706,7 +1706,7 @@ ReindexIndex(RangeVar *indexRelation)
 	persistence = irel->rd_rel->relpersistence;
 	index_close(irel, NoLock);
 
-	reindex_index(indOid, false, persistence);
+	reindex_index(indOid, false, persistence, verbose);
 
 	return indOid;
 }
@@ -1775,7 +1775,7 @@ RangeVarCallbackForReindexIndex(const RangeVar *relation,
  *		Recreate all indexes of a table (and of its toast table, if any)
  */
 Oid
-ReindexTable(RangeVar *relation)
+ReindexTable(RangeVar *relation, bool verbose)
 {
 	Oid			heapOid;
 
@@ -1785,7 +1785,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)));
@@ -1802,7 +1803,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, bool verbose)
 {
 	Oid			objectOid;
 	Relation	relationRelation;
@@ -1814,6 +1815,7 @@ ReindexMultipleTables(const char *objectName, ReindexObjectType objectKind)
 	List	   *relids = NIL;
 	ListCell   *l;
 	int			num_keys;
+	int			elevel = verbose ? INFO : DEBUG2;
 
 	AssertArg(objectName);
 	Assert(objectKind == REINDEX_OBJECT_SCHEMA ||
@@ -1938,9 +1940,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 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 5d84285..7ef9f51 100644
--- a/src/backend/commands/tablecmds.c
+++ b/src/backend/commands/tablecmds.c
@@ -1234,7 +1234,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/nodes/copyfuncs.c b/src/backend/nodes/copyfuncs.c
index 1685efe..6b1d119 100644
--- a/src/backend/nodes/copyfuncs.c
+++ b/src/backend/nodes/copyfuncs.c
@@ -3778,6 +3778,7 @@ _copyReindexStmt(const ReindexStmt *from)
 	COPY_SCALAR_FIELD(kind);
 	COPY_NODE_FIELD(relation);
 	COPY_STRING_FIELD(name);
+	COPY_SCALAR_FIELD(verbose);
 
 	return newnode;
 }
diff --git a/src/backend/nodes/equalfuncs.c b/src/backend/nodes/equalfuncs.c
index 578ead5..ef816cc 100644
--- a/src/backend/nodes/equalfuncs.c
+++ b/src/backend/nodes/equalfuncs.c
@@ -1908,6 +1908,7 @@ _equalReindexStmt(const ReindexStmt *a, const ReindexStmt *b)
 	COMPARE_SCALAR_FIELD(kind);
 	COMPARE_NODE_FIELD(relation);
 	COMPARE_STRING_FIELD(name);
+	COMPARE_SCALAR_FIELD(verbose);
 
 	return true;
 }
diff --git a/src/backend/parser/gram.y b/src/backend/parser/gram.y
index 962a69d..27974b8 100644
--- a/src/backend/parser/gram.y
+++ b/src/backend/parser/gram.y
@@ -459,6 +459,10 @@ 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 <ival>	reindex_target_type
+%type <ival>	reindex_target_multitable
+
 %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
@@ -7383,51 +7387,56 @@ DropTransformStmt: DROP TRANSFORM opt_if_exists FOR Typename LANGUAGE name opt_d
  *
  *		QUERY:
  *
- *		REINDEX type <name>
+ *		REINDEX type <name> [WITH] [VERBOSE]
  *****************************************************************************/
 
 ReindexStmt:
-			REINDEX INDEX qualified_name
+			REINDEX reindex_target_type qualified_name WITH opt_verbose
 				{
 					ReindexStmt *n = makeNode(ReindexStmt);
-					n->kind = REINDEX_OBJECT_INDEX;
+					n->kind = $2;
 					n->relation = $3;
 					n->name = NULL;
+					n->verbose = $5;
 					$$ = (Node *)n;
 				}
-			| REINDEX TABLE qualified_name
+			| REINDEX reindex_target_type qualified_name opt_verbose
 				{
 					ReindexStmt *n = makeNode(ReindexStmt);
-					n->kind = REINDEX_OBJECT_TABLE;
+					n->kind = $2;
 					n->relation = $3;
 					n->name = NULL;
+					n->verbose = $4;
 					$$ = (Node *)n;
 				}
-			| REINDEX SCHEMA name
-				{
-					ReindexStmt *n = makeNode(ReindexStmt);
-					n->kind = REINDEX_OBJECT_SCHEMA;
-					n->name = $3;
-					n->relation = NULL;
-					$$ = (Node *)n;
-				}
-			| REINDEX SYSTEM_P name
+			| REINDEX reindex_target_multitable name WITH opt_verbose
 				{
 					ReindexStmt *n = makeNode(ReindexStmt);
-					n->kind = REINDEX_OBJECT_SYSTEM;
+					n->kind = $2;
 					n->name = $3;
 					n->relation = NULL;
+					n->verbose = $5;
 					$$ = (Node *)n;
 				}
-			| REINDEX DATABASE name
+			| REINDEX reindex_target_multitable name opt_verbose
 				{
 					ReindexStmt *n = makeNode(ReindexStmt);
-					n->kind = REINDEX_OBJECT_DATABASE;
+					n->kind = $2;
 					n->name = $3;
 					n->relation = NULL;
+					n->verbose = $4;
 					$$ = (Node *)n;
 				}
 		;
+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; }
+;
 
 
 /*****************************************************************************
diff --git a/src/backend/tcop/utility.c b/src/backend/tcop/utility.c
index 31e9d4c..98c3b29 100644
--- a/src/backend/tcop/utility.c
+++ b/src/backend/tcop/utility.c
@@ -738,10 +738,10 @@ standard_ProcessUtility(Node *parsetree,
 				switch (stmt->kind)
 				{
 					case REINDEX_OBJECT_INDEX:
-						ReindexIndex(stmt->relation);
+						ReindexIndex(stmt->relation, stmt->verbose);
 						break;
 					case REINDEX_OBJECT_TABLE:
-						ReindexTable(stmt->relation);
+						ReindexTable(stmt->relation, stmt->verbose);
 						break;
 					case REINDEX_OBJECT_SCHEMA:
 					case REINDEX_OBJECT_SYSTEM:
@@ -757,7 +757,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->verbose);
 						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 750e29d..d46d04d 100644
--- a/src/bin/psql/tab-complete.c
+++ b/src/bin/psql/tab-complete.c
@@ -3346,12 +3346,36 @@ 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)
 			COMPLETE_WITH_QUERY(Query_for_list_of_databases);
 	}
+	else if (pg_strcasecmp(prev3_wd, "REINDEX") == 0)
+	{
+		if (pg_strcasecmp(prev2_wd, "TABLE") == 0 ||
+			 pg_strcasecmp(prev2_wd, "INDEX") == 0 ||
+			 pg_strcasecmp(prev2_wd, "SCHEMA") == 0 ||
+			 pg_strcasecmp(prev2_wd, "SYSTEM") == 0 ||
+			 pg_strcasecmp(prev2_wd, "DATABASE") == 0)
+		{
+			static const char *const list_REINDEX_option[] = 
+				{"WITH", "VERBOSE", NULL};
+			COMPLETE_WITH_LIST(list_REINDEX_option);
+		}
+	}
+	else if (pg_strcasecmp(prev4_wd, "REINDEX") == 0)
+	{
+		if ((pg_strcasecmp(prev3_wd, "TABLE") == 0 ||
+			 pg_strcasecmp(prev3_wd, "INDEX") == 0 ||
+			 pg_strcasecmp(prev3_wd, "SCHEMA") == 0 ||
+			 pg_strcasecmp(prev3_wd, "SYSTEM") == 0 ||
+			 pg_strcasecmp(prev3_wd, "DATABASE") == 0) &&
+			pg_strcasecmp(prev_wd, "WITH") == 0)
+			COMPLETE_WITH_CONST("VERBOSE");
+	}
+
 
 /* SECURITY LABEL */
 	else if (pg_strcasecmp(prev_wd, "SECURITY") == 0)
diff --git a/src/include/catalog/index.h b/src/include/catalog/index.h
index a04def9..0662f46 100644
--- a/src/include/catalog/index.h
+++ b/src/include/catalog/index.h
@@ -113,7 +113,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
@@ -122,7 +122,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 335f09c..a1d334f 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, bool verbose);
+extern Oid	ReindexTable(RangeVar *relation, bool verbose );
+extern void ReindexMultipleTables(const char *objectName, ReindexObjectType objectKind, bool verbose);
 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 852eb4f..3db9c6c 100644
--- a/src/include/nodes/parsenodes.h
+++ b/src/include/nodes/parsenodes.h
@@ -2760,6 +2760,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 */
+	bool	   verbose;		/* print progress info */
 } ReindexStmt;
 
 /* ----------------------
diff --git a/src/test/regress/expected/create_index.out b/src/test/regress/expected/create_index.out
index abe64e5..d062148 100644
--- a/src/test/regress/expected/create_index.out
+++ b/src/test/regress/expected/create_index.out
@@ -2832,6 +2832,16 @@ explain (costs off)
 (2 rows)
 
 --
+-- REINDEX [ WITH ] VERBOSE
+--
+CREATE TABLE reindex_verbose(id integer primary key);
+\set VERBOSITY terse
+REINDEX TABLE reindex_verbose WITH VERBOSE;
+INFO:  index "reindex_verbose_pkey" was reindexed.
+REINDEX TABLE reindex_verbose VERBOSE;
+INFO:  index "reindex_verbose_pkey" was reindexed.
+DROP TABLE reindex_verbose;
+--
 -- REINDEX SCHEMA
 --
 REINDEX SCHEMA schema_to_reindex; -- failure, schema does not exist
diff --git a/src/test/regress/sql/create_index.sql b/src/test/regress/sql/create_index.sql
index f779fa0..ae103bf 100644
--- a/src/test/regress/sql/create_index.sql
+++ b/src/test/regress/sql/create_index.sql
@@ -966,6 +966,15 @@ explain (costs off)
   select * from tenk1 where (thousand, tenthous) in ((1,1001), (null,null));
 
 --
+-- REINDEX [ WITH ] VERBOSE
+--
+CREATE TABLE reindex_verbose(id integer primary key);
+\set VERBOSITY terse
+REINDEX TABLE reindex_verbose WITH VERBOSE;
+REINDEX TABLE reindex_verbose VERBOSE;
+DROP TABLE reindex_verbose;
+
+--
 -- REINDEX SCHEMA
 --
 REINDEX SCHEMA schema_to_reindex; -- failure, schema does not exist
#52Robert Haas
robertmhaas@gmail.com
In reply to: Sawada Masahiko (#51)
Re: Proposal : REINDEX xxx VERBOSE

On Thu, Apr 30, 2015 at 6:37 AM, Sawada Masahiko <sawada.mshk@gmail.com> wrote:

Attached v10 patch is latest version patch.
The syntax is,
REINDEX { INDEX | ... } name [ WITH ] [ VERBOSE ]

That is, WITH clause is optional.

I thought we agreed on moving this earlier in the command:

/messages/by-id/18569.1423159294@sss.pgh.pa.us

--
Robert Haas
EnterpriseDB: http://www.enterprisedb.com
The Enterprise PostgreSQL Company

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

#53Sawada Masahiko
sawada.mshk@gmail.com
In reply to: Robert Haas (#52)
1 attachment(s)
Re: Proposal : REINDEX xxx VERBOSE

On Thu, Apr 30, 2015 at 8:39 PM, Robert Haas <robertmhaas@gmail.com> wrote:

On Thu, Apr 30, 2015 at 6:37 AM, Sawada Masahiko <sawada.mshk@gmail.com> wrote:

Attached v10 patch is latest version patch.
The syntax is,
REINDEX { INDEX | ... } name [ WITH ] [ VERBOSE ]

That is, WITH clause is optional.

I thought we agreed on moving this earlier in the command:

/messages/by-id/18569.1423159294@sss.pgh.pa.us

Oh, I see.
Attached patch is modified syntax as
REINDEX [VERBOSE] { INDEX | ... } name

Thought?

Regards,

-------
Sawada Masahiko

Attachments:

000_reindex_verbose_v11.patchapplication/octet-stream; name=000_reindex_verbose_v11.patchDownload
diff --git a/doc/src/sgml/ref/reindex.sgml b/doc/src/sgml/ref/reindex.sgml
index 998340c..c9c6996 100644
--- a/doc/src/sgml/ref/reindex.sgml
+++ b/doc/src/sgml/ref/reindex.sgml
@@ -21,7 +21,7 @@ PostgreSQL documentation
 
  <refsynopsisdiv>
 <synopsis>
-REINDEX { INDEX | TABLE | SCHEMA | DATABASE | SYSTEM } <replaceable class="PARAMETER">name</replaceable>
+REINDEX [ VERBOSE ] { INDEX | TABLE | SCHEMA | DATABASE | SYSTEM } <replaceable class="PARAMETER">name</replaceable>
 </synopsis>
  </refsynopsisdiv>
 
@@ -150,6 +150,15 @@ 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>
   </variablelist>
  </refsect1>
 
diff --git a/src/backend/catalog/index.c b/src/backend/catalog/index.c
index ac3b785..27364ec 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"
@@ -3133,13 +3134,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
@@ -3283,6 +3289,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);
@@ -3324,7 +3337,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;
@@ -3415,7 +3428,7 @@ reindex_relation(Oid relid, int flags)
 				RelationSetIndexList(rel, doneIndexes, InvalidOid);
 
 			reindex_index(indexOid, !(flags & REINDEX_REL_CHECK_CONSTRAINTS),
-						  persistence);
+						  persistence, verbose);
 
 			CommandCounterIncrement();
 
@@ -3450,7 +3463,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 351d48e..5d44bda 100644
--- a/src/backend/commands/indexcmds.c
+++ b/src/backend/commands/indexcmds.c
@@ -1681,7 +1681,7 @@ ChooseIndexColumnNames(List *indexElems)
  *		Recreate a specific index.
  */
 Oid
-ReindexIndex(RangeVar *indexRelation)
+ReindexIndex(RangeVar *indexRelation, bool verbose)
 {
 	Oid			indOid;
 	Oid			heapOid = InvalidOid;
@@ -1706,7 +1706,7 @@ ReindexIndex(RangeVar *indexRelation)
 	persistence = irel->rd_rel->relpersistence;
 	index_close(irel, NoLock);
 
-	reindex_index(indOid, false, persistence);
+	reindex_index(indOid, false, persistence, verbose);
 
 	return indOid;
 }
@@ -1775,7 +1775,7 @@ RangeVarCallbackForReindexIndex(const RangeVar *relation,
  *		Recreate all indexes of a table (and of its toast table, if any)
  */
 Oid
-ReindexTable(RangeVar *relation)
+ReindexTable(RangeVar *relation, bool verbose)
 {
 	Oid			heapOid;
 
@@ -1785,7 +1785,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)));
@@ -1802,7 +1803,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, bool verbose)
 {
 	Oid			objectOid;
 	Relation	relationRelation;
@@ -1814,6 +1815,7 @@ ReindexMultipleTables(const char *objectName, ReindexObjectType objectKind)
 	List	   *relids = NIL;
 	ListCell   *l;
 	int			num_keys;
+	int			elevel = verbose ? INFO : DEBUG2;
 
 	AssertArg(objectName);
 	Assert(objectKind == REINDEX_OBJECT_SCHEMA ||
@@ -1938,9 +1940,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 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 5d84285..7ef9f51 100644
--- a/src/backend/commands/tablecmds.c
+++ b/src/backend/commands/tablecmds.c
@@ -1234,7 +1234,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/nodes/copyfuncs.c b/src/backend/nodes/copyfuncs.c
index 1685efe..6b1d119 100644
--- a/src/backend/nodes/copyfuncs.c
+++ b/src/backend/nodes/copyfuncs.c
@@ -3778,6 +3778,7 @@ _copyReindexStmt(const ReindexStmt *from)
 	COPY_SCALAR_FIELD(kind);
 	COPY_NODE_FIELD(relation);
 	COPY_STRING_FIELD(name);
+	COPY_SCALAR_FIELD(verbose);
 
 	return newnode;
 }
diff --git a/src/backend/nodes/equalfuncs.c b/src/backend/nodes/equalfuncs.c
index 578ead5..ef816cc 100644
--- a/src/backend/nodes/equalfuncs.c
+++ b/src/backend/nodes/equalfuncs.c
@@ -1908,6 +1908,7 @@ _equalReindexStmt(const ReindexStmt *a, const ReindexStmt *b)
 	COMPARE_SCALAR_FIELD(kind);
 	COMPARE_NODE_FIELD(relation);
 	COMPARE_STRING_FIELD(name);
+	COMPARE_SCALAR_FIELD(verbose);
 
 	return true;
 }
diff --git a/src/backend/parser/gram.y b/src/backend/parser/gram.y
index 962a69d..697401e 100644
--- a/src/backend/parser/gram.y
+++ b/src/backend/parser/gram.y
@@ -459,6 +459,10 @@ 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 <ival>	reindex_target_type
+%type <ival>	reindex_target_multitable
+
 %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
@@ -7383,51 +7387,38 @@ DropTransformStmt: DROP TRANSFORM opt_if_exists FOR Typename LANGUAGE name opt_d
  *
  *		QUERY:
  *
- *		REINDEX type <name>
+ *		REINDEX [ VERBOSE ] type <name>
  *****************************************************************************/
 
 ReindexStmt:
-			REINDEX INDEX qualified_name
-				{
-					ReindexStmt *n = makeNode(ReindexStmt);
-					n->kind = REINDEX_OBJECT_INDEX;
-					n->relation = $3;
-					n->name = NULL;
-					$$ = (Node *)n;
-				}
-			| REINDEX TABLE qualified_name
+			REINDEX opt_verbose reindex_target_type qualified_name
 				{
 					ReindexStmt *n = makeNode(ReindexStmt);
-					n->kind = REINDEX_OBJECT_TABLE;
-					n->relation = $3;
+					n->kind = $3;
+					n->relation = $4;
 					n->name = NULL;
+					n->verbose = $2;
 					$$ = (Node *)n;
 				}
-			| REINDEX SCHEMA name
-				{
-					ReindexStmt *n = makeNode(ReindexStmt);
-					n->kind = REINDEX_OBJECT_SCHEMA;
-					n->name = $3;
-					n->relation = NULL;
-					$$ = (Node *)n;
-				}
-			| REINDEX SYSTEM_P name
-				{
-					ReindexStmt *n = makeNode(ReindexStmt);
-					n->kind = REINDEX_OBJECT_SYSTEM;
-					n->name = $3;
-					n->relation = NULL;
-					$$ = (Node *)n;
-				}
-			| REINDEX DATABASE name
+			| REINDEX opt_verbose reindex_target_multitable name
 				{
 					ReindexStmt *n = makeNode(ReindexStmt);
-					n->kind = REINDEX_OBJECT_DATABASE;
-					n->name = $3;
+					n->kind = $3;
+					n->name = $4;
 					n->relation = NULL;
+					n->verbose = $2;
 					$$ = (Node *)n;
 				}
 		;
+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; }
+;
 
 
 /*****************************************************************************
diff --git a/src/backend/tcop/utility.c b/src/backend/tcop/utility.c
index 31e9d4c..98c3b29 100644
--- a/src/backend/tcop/utility.c
+++ b/src/backend/tcop/utility.c
@@ -738,10 +738,10 @@ standard_ProcessUtility(Node *parsetree,
 				switch (stmt->kind)
 				{
 					case REINDEX_OBJECT_INDEX:
-						ReindexIndex(stmt->relation);
+						ReindexIndex(stmt->relation, stmt->verbose);
 						break;
 					case REINDEX_OBJECT_TABLE:
-						ReindexTable(stmt->relation);
+						ReindexTable(stmt->relation, stmt->verbose);
 						break;
 					case REINDEX_OBJECT_SCHEMA:
 					case REINDEX_OBJECT_SYSTEM:
@@ -757,7 +757,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->verbose);
 						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 750e29d..befce0a 100644
--- a/src/bin/psql/tab-complete.c
+++ b/src/bin/psql/tab-complete.c
@@ -3335,6 +3335,14 @@ psql_completion(const char *text, int start, int end)
 /* REINDEX */
 	else if (pg_strcasecmp(prev_wd, "REINDEX") == 0)
 	{
+		static const char *const list_REINDEX_and_option[] =
+			{"TABLE", "INDEX", "SYSTEM", "SCHEMA", "DATABASE", "VERBOSE", NULL};
+
+		COMPLETE_WITH_LIST(list_REINDEX_and_option);
+	}
+	else if (pg_strcasecmp(prev2_wd, "REINDEX") == 0 &&
+			 pg_strcasecmp(prev_wd, "VERBOSE") == 0)
+	{
 		static const char *const list_REINDEX[] =
 			{"TABLE", "INDEX", "SYSTEM", "SCHEMA", "DATABASE", NULL};
 
@@ -3346,13 +3354,27 @@ 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)
+			COMPLETE_WITH_QUERY(Query_for_list_of_databases);
+	}
+	else if (pg_strcasecmp(prev3_wd, "REINDEX") == 0 &&
+			 pg_strcasecmp(prev2_wd, "VERBOSE") == 0)
+	{
+		if (pg_strcasecmp(prev_wd, "TABLE") == 0)
+			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)
 			COMPLETE_WITH_QUERY(Query_for_list_of_schemas);
 		else if (pg_strcasecmp(prev_wd, "SYSTEM") == 0 ||
 				 pg_strcasecmp(prev_wd, "DATABASE") == 0)
 			COMPLETE_WITH_QUERY(Query_for_list_of_databases);
 	}
 
+
 /* SECURITY LABEL */
 	else if (pg_strcasecmp(prev_wd, "SECURITY") == 0)
 		COMPLETE_WITH_CONST("LABEL");
diff --git a/src/include/catalog/index.h b/src/include/catalog/index.h
index a04def9..0662f46 100644
--- a/src/include/catalog/index.h
+++ b/src/include/catalog/index.h
@@ -113,7 +113,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
@@ -122,7 +122,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 335f09c..a1d334f 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, bool verbose);
+extern Oid	ReindexTable(RangeVar *relation, bool verbose );
+extern void ReindexMultipleTables(const char *objectName, ReindexObjectType objectKind, bool verbose);
 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 852eb4f..3db9c6c 100644
--- a/src/include/nodes/parsenodes.h
+++ b/src/include/nodes/parsenodes.h
@@ -2760,6 +2760,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 */
+	bool	   verbose;		/* print progress info */
 } ReindexStmt;
 
 /* ----------------------
diff --git a/src/test/regress/expected/create_index.out b/src/test/regress/expected/create_index.out
index abe64e5..9f90bd4 100644
--- a/src/test/regress/expected/create_index.out
+++ b/src/test/regress/expected/create_index.out
@@ -2832,6 +2832,14 @@ explain (costs off)
 (2 rows)
 
 --
+-- REINDEX VERBOSE
+--
+CREATE TABLE reindex_verbose(id integer primary key);
+\set VERBOSITY terse
+REINDEX VERBOSE TABLE reindex_verbose;
+INFO:  index "reindex_verbose_pkey" was reindexed.
+DROP TABLE reindex_verbose;
+--
 -- REINDEX SCHEMA
 --
 REINDEX SCHEMA schema_to_reindex; -- failure, schema does not exist
diff --git a/src/test/regress/sql/create_index.sql b/src/test/regress/sql/create_index.sql
index f779fa0..7f116f9 100644
--- a/src/test/regress/sql/create_index.sql
+++ b/src/test/regress/sql/create_index.sql
@@ -966,6 +966,14 @@ explain (costs off)
   select * from tenk1 where (thousand, tenthous) in ((1,1001), (null,null));
 
 --
+-- REINDEX VERBOSE
+--
+CREATE TABLE reindex_verbose(id integer primary key);
+\set VERBOSITY terse
+REINDEX VERBOSE TABLE reindex_verbose;
+DROP TABLE reindex_verbose;
+
+--
 -- REINDEX SCHEMA
 --
 REINDEX SCHEMA schema_to_reindex; -- failure, schema does not exist
#54Fabrízio de Royes Mello
fabriziomello@gmail.com
In reply to: Sawada Masahiko (#53)
Re: Proposal : REINDEX xxx VERBOSE

On Thu, Apr 30, 2015 at 10:15 AM, Sawada Masahiko <sawada.mshk@gmail.com>
wrote:

On Thu, Apr 30, 2015 at 8:39 PM, Robert Haas <robertmhaas@gmail.com>

wrote:

On Thu, Apr 30, 2015 at 6:37 AM, Sawada Masahiko <sawada.mshk@gmail.com>

wrote:

Attached v10 patch is latest version patch.
The syntax is,
REINDEX { INDEX | ... } name [ WITH ] [ VERBOSE ]

That is, WITH clause is optional.

I thought we agreed on moving this earlier in the command:

/messages/by-id/18569.1423159294@sss.pgh.pa.us

Oh, I see.
Attached patch is modified syntax as
REINDEX [VERBOSE] { INDEX | ... } name

Thought?

Looks good to me.

Regards,

--
Fabrízio de Royes Mello
Consultoria/Coaching PostgreSQL

Show quoted text

Timbira: http://www.timbira.com.br
Blog: http://fabriziomello.github.io
Linkedin: http://br.linkedin.com/in/fabriziomello
Twitter: http://twitter.com/fabriziomello
Github: http://github.com/fabriziomello

#55Robert Haas
robertmhaas@gmail.com
In reply to: Sawada Masahiko (#53)
Re: Proposal : REINDEX xxx VERBOSE

On Thu, Apr 30, 2015 at 9:15 AM, Sawada Masahiko <sawada.mshk@gmail.com> wrote:

On Thu, Apr 30, 2015 at 8:39 PM, Robert Haas <robertmhaas@gmail.com> wrote:

On Thu, Apr 30, 2015 at 6:37 AM, Sawada Masahiko <sawada.mshk@gmail.com> wrote:

Attached v10 patch is latest version patch.
The syntax is,
REINDEX { INDEX | ... } name [ WITH ] [ VERBOSE ]

That is, WITH clause is optional.

I thought we agreed on moving this earlier in the command:

/messages/by-id/18569.1423159294@sss.pgh.pa.us

Oh, I see.
Attached patch is modified syntax as
REINDEX [VERBOSE] { INDEX | ... } name

Thought?

I thought what we agreed on was:

REINDEX (flexible options) { INDEX | ... } name

The argument wasn't about whether to use flexible options, but where
in the command to put them.

--
Robert Haas
EnterpriseDB: http://www.enterprisedb.com
The Enterprise PostgreSQL Company

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

#56Sawada Masahiko
sawada.mshk@gmail.com
In reply to: Robert Haas (#55)
Re: Proposal : REINDEX xxx VERBOSE

On Fri, May 1, 2015 at 1:38 AM, Robert Haas <robertmhaas@gmail.com> wrote:

On Thu, Apr 30, 2015 at 9:15 AM, Sawada Masahiko <sawada.mshk@gmail.com> wrote:

On Thu, Apr 30, 2015 at 8:39 PM, Robert Haas <robertmhaas@gmail.com> wrote:

On Thu, Apr 30, 2015 at 6:37 AM, Sawada Masahiko <sawada.mshk@gmail.com> wrote:

Attached v10 patch is latest version patch.
The syntax is,
REINDEX { INDEX | ... } name [ WITH ] [ VERBOSE ]

That is, WITH clause is optional.

I thought we agreed on moving this earlier in the command:

/messages/by-id/18569.1423159294@sss.pgh.pa.us

Oh, I see.
Attached patch is modified syntax as
REINDEX [VERBOSE] { INDEX | ... } name

Thought?

I thought what we agreed on was:

REINDEX (flexible options) { INDEX | ... } name

The argument wasn't about whether to use flexible options, but where
in the command to put them.

VACUUM has both syntax: with parentheses and without parentheses.
I think we should have both syntax for REINDEX like VACUUM does
because it would be pain to put parentheses whenever we want to do
REINDEX.
Are the parentheses optional in REINDEX command?

And CLUSTER should have syntax like that in future?

Regards,

-------
Sawada Masahiko

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

#57Robert Haas
robertmhaas@gmail.com
In reply to: Sawada Masahiko (#56)
Re: Proposal : REINDEX xxx VERBOSE

On Thu, Apr 30, 2015 at 11:05 PM, Sawada Masahiko <sawada.mshk@gmail.com> wrote:

VACUUM has both syntax: with parentheses and without parentheses.
I think we should have both syntax for REINDEX like VACUUM does
because it would be pain to put parentheses whenever we want to do
REINDEX.
Are the parentheses optional in REINDEX command?

No. The unparenthesized VACUUM syntax was added back before we
realized that that kind of syntax is a terrible idea. It requires
every option to be a keyword, and those keywords have to be in a fixed
order. I believe the intention is to keep the old VACUUM syntax
around for backward-compatibility, but not to extend it. Same for
EXPLAIN and COPY.

I agree that it would be nice if the grammar problems could be solved
without adding parentheses. But there was a period during which many
good ideas for new EXPLAIN options died on the vine because we were
using an inextensible syntax for EXPLAIN options. I'm not keen to
repeat that experience.

--
Robert Haas
EnterpriseDB: http://www.enterprisedb.com
The Enterprise PostgreSQL Company

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

#58Sawada Masahiko
sawada.mshk@gmail.com
In reply to: Robert Haas (#57)
Re: Proposal : REINDEX xxx VERBOSE

On Fri, May 1, 2015 at 9:04 PM, Robert Haas <robertmhaas@gmail.com> wrote:

On Thu, Apr 30, 2015 at 11:05 PM, Sawada Masahiko <sawada.mshk@gmail.com> wrote:

VACUUM has both syntax: with parentheses and without parentheses.
I think we should have both syntax for REINDEX like VACUUM does
because it would be pain to put parentheses whenever we want to do
REINDEX.
Are the parentheses optional in REINDEX command?

No. The unparenthesized VACUUM syntax was added back before we
realized that that kind of syntax is a terrible idea. It requires
every option to be a keyword, and those keywords have to be in a fixed
order. I believe the intention is to keep the old VACUUM syntax
around for backward-compatibility, but not to extend it. Same for
EXPLAIN and COPY.

REINDEX will have only one option VERBOSE for now.
Even we're in a situation like that it's not clear to be added newly
additional option to REINDEX now, we should need to put parenthesis?
Also I'm not sure that both implementation and documentation regarding
VERBOSE option should be optional.

Regards,

-------
Sawada Masahiko

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

#59Robert Haas
robertmhaas@gmail.com
In reply to: Sawada Masahiko (#58)
Re: Proposal : REINDEX xxx VERBOSE

On Tue, May 5, 2015 at 11:10 AM, Sawada Masahiko <sawada.mshk@gmail.com> wrote:

On Fri, May 1, 2015 at 9:04 PM, Robert Haas <robertmhaas@gmail.com> wrote:

On Thu, Apr 30, 2015 at 11:05 PM, Sawada Masahiko <sawada.mshk@gmail.com> wrote:

VACUUM has both syntax: with parentheses and without parentheses.
I think we should have both syntax for REINDEX like VACUUM does
because it would be pain to put parentheses whenever we want to do
REINDEX.
Are the parentheses optional in REINDEX command?

No. The unparenthesized VACUUM syntax was added back before we
realized that that kind of syntax is a terrible idea. It requires
every option to be a keyword, and those keywords have to be in a fixed
order. I believe the intention is to keep the old VACUUM syntax
around for backward-compatibility, but not to extend it. Same for
EXPLAIN and COPY.

REINDEX will have only one option VERBOSE for now.
Even we're in a situation like that it's not clear to be added newly
additional option to REINDEX now, we should need to put parenthesis?

In my opinion, yes. The whole point of a flexible options syntax is
that we can add new options without changing the grammar. That
involves some compromise on the syntax, which doesn't bother me a bit.
Our previous experiments with this for EXPLAIN and COPY and VACUUM
have worked out quite well, and I see no reason for pessimism here.

Also I'm not sure that both implementation and documentation regarding
VERBOSE option should be optional.

I don't know what this means.

--
Robert Haas
EnterpriseDB: http://www.enterprisedb.com
The Enterprise PostgreSQL Company

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

#60Sawada Masahiko
sawada.mshk@gmail.com
In reply to: Robert Haas (#59)

On Wed, May 6, 2015 at 5:42 AM, Robert Haas <robertmhaas@gmail.com
<javascript:;>> wrote:

On Tue, May 5, 2015 at 11:10 AM, Sawada Masahiko <sawada.mshk@gmail.com

<javascript:;>> wrote:

On Fri, May 1, 2015 at 9:04 PM, Robert Haas <robertmhaas@gmail.com

<javascript:;>> wrote:

On Thu, Apr 30, 2015 at 11:05 PM, Sawada Masahiko <sawada.mshk@gmail.com

<javascript:;>> wrote:

VACUUM has both syntax: with parentheses and without parentheses.
I think we should have both syntax for REINDEX like VACUUM does
because it would be pain to put parentheses whenever we want to do
REINDEX.
Are the parentheses optional in REINDEX command?

No. The unparenthesized VACUUM syntax was added back before we
realized that that kind of syntax is a terrible idea. It requires
every option to be a keyword, and those keywords have to be in a fixed
order. I believe the intention is to keep the old VACUUM syntax
around for backward-compatibility, but not to extend it. Same for
EXPLAIN and COPY.

REINDEX will have only one option VERBOSE for now.
Even we're in a situation like that it's not clear to be added newly
additional option to REINDEX now, we should need to put parenthesis?

In my opinion, yes. The whole point of a flexible options syntax is
that we can add new options without changing the grammar. That
involves some compromise on the syntax, which doesn't bother me a bit.
Our previous experiments with this for EXPLAIN and COPY and VACUUM
have worked out quite well, and I see no reason for pessimism here.

I agree that flexible option syntax does not need to change grammar
whenever we add new options.
Attached patch is changed based on your suggestion.
And the patch for reindexdb is also attached.
Please feedbacks.

Also I'm not sure that both implementation and documentation regarding
VERBOSE option should be optional.

I don't know what this means.

Sorry for confusing you.
Please ignore this.

Regards,

-------
Sawada Masahiko

--
Regards,

-------
Sawada Masahiko

#61Sawada Masahiko
sawada.mshk@gmail.com
In reply to: Sawada Masahiko (#60)
2 attachment(s)
Re: Proposal : REINDEX xxx VERBOSE

On 5/7/15, Sawada Masahiko <sawada.mshk@gmail.com> wrote:

On Wed, May 6, 2015 at 5:42 AM, Robert Haas <robertmhaas@gmail.com
<javascript:;>> wrote:

On Tue, May 5, 2015 at 11:10 AM, Sawada Masahiko <sawada.mshk@gmail.com

<javascript:;>> wrote:

On Fri, May 1, 2015 at 9:04 PM, Robert Haas <robertmhaas@gmail.com

<javascript:;>> wrote:

On Thu, Apr 30, 2015 at 11:05 PM, Sawada Masahiko
<sawada.mshk@gmail.com

<javascript:;>> wrote:

VACUUM has both syntax: with parentheses and without parentheses.
I think we should have both syntax for REINDEX like VACUUM does
because it would be pain to put parentheses whenever we want to do
REINDEX.
Are the parentheses optional in REINDEX command?

No. The unparenthesized VACUUM syntax was added back before we
realized that that kind of syntax is a terrible idea. It requires
every option to be a keyword, and those keywords have to be in a fixed
order. I believe the intention is to keep the old VACUUM syntax
around for backward-compatibility, but not to extend it. Same for
EXPLAIN and COPY.

REINDEX will have only one option VERBOSE for now.
Even we're in a situation like that it's not clear to be added newly
additional option to REINDEX now, we should need to put parenthesis?

In my opinion, yes. The whole point of a flexible options syntax is
that we can add new options without changing the grammar. That
involves some compromise on the syntax, which doesn't bother me a bit.
Our previous experiments with this for EXPLAIN and COPY and VACUUM
have worked out quite well, and I see no reason for pessimism here.

I agree that flexible option syntax does not need to change grammar
whenever we add new options.
Attached patch is changed based on your suggestion.
And the patch for reindexdb is also attached.
Please feedbacks.

Also I'm not sure that both implementation and documentation regarding
VERBOSE option should be optional.

I don't know what this means.

Sorry for confusing you.
Please ignore this.

Sorry, I forgot attach files.

Regards,

-------
Sawada Masahiko

Attachments:

000_reindex_verbose_v12.patchtext/x-patch; charset=US-ASCII; name=000_reindex_verbose_v12.patchDownload
diff --git a/doc/src/sgml/ref/reindex.sgml b/doc/src/sgml/ref/reindex.sgml
index 998340c..703b760 100644
--- a/doc/src/sgml/ref/reindex.sgml
+++ b/doc/src/sgml/ref/reindex.sgml
@@ -21,7 +21,7 @@ PostgreSQL documentation
 
  <refsynopsisdiv>
 <synopsis>
-REINDEX { INDEX | TABLE | SCHEMA | DATABASE | SYSTEM } <replaceable class="PARAMETER">name</replaceable>
+REINDEX [ ( { VERBOSE } [, ...] ) ] { INDEX | TABLE | SCHEMA | DATABASE | SYSTEM } <replaceable class="PARAMETER">name</replaceable>
 </synopsis>
  </refsynopsisdiv>
 
@@ -150,6 +150,15 @@ 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>
   </variablelist>
  </refsect1>
 
diff --git a/src/backend/catalog/index.c b/src/backend/catalog/index.c
index ac3b785..c04b907 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"
@@ -3133,13 +3134,22 @@ 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,
+				uint8 options)
 {
 	Relation	iRel,
 				heapRelation;
 	Oid			heapId;
 	IndexInfo  *indexInfo;
 	volatile bool skipped_constraint = false;
+	int			elevel = DEBUG2;
+	PGRUsage	ru0;
+
+	pg_rusage_init(&ru0);
+
+	/* Set option(s) */
+	if (options & REINDEXOPT_VERBOSE)
+		elevel = INFO;
 
 	/*
 	 * Open and lock the parent heap relation.  ShareLock is sufficient since
@@ -3283,6 +3293,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);
@@ -3324,7 +3341,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, uint8 options)
 {
 	Relation	rel;
 	Oid			toast_relid;
@@ -3415,7 +3432,7 @@ reindex_relation(Oid relid, int flags)
 				RelationSetIndexList(rel, doneIndexes, InvalidOid);
 
 			reindex_index(indexOid, !(flags & REINDEX_REL_CHECK_CONSTRAINTS),
-						  persistence);
+						  persistence, options);
 
 			CommandCounterIncrement();
 
@@ -3450,7 +3467,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, options);
 
 	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 351d48e..fa63611 100644
--- a/src/backend/commands/indexcmds.c
+++ b/src/backend/commands/indexcmds.c
@@ -1681,7 +1681,7 @@ ChooseIndexColumnNames(List *indexElems)
  *		Recreate a specific index.
  */
 Oid
-ReindexIndex(RangeVar *indexRelation)
+ReindexIndex(RangeVar *indexRelation, uint8 options)
 {
 	Oid			indOid;
 	Oid			heapOid = InvalidOid;
@@ -1706,7 +1706,7 @@ ReindexIndex(RangeVar *indexRelation)
 	persistence = irel->rd_rel->relpersistence;
 	index_close(irel, NoLock);
 
-	reindex_index(indOid, false, persistence);
+	reindex_index(indOid, false, persistence, options);
 
 	return indOid;
 }
@@ -1775,7 +1775,7 @@ RangeVarCallbackForReindexIndex(const RangeVar *relation,
  *		Recreate all indexes of a table (and of its toast table, if any)
  */
 Oid
-ReindexTable(RangeVar *relation)
+ReindexTable(RangeVar *relation, uint8 options)
 {
 	Oid			heapOid;
 
@@ -1785,7 +1785,8 @@ ReindexTable(RangeVar *relation)
 
 	if (!reindex_relation(heapOid,
 						  REINDEX_REL_PROCESS_TOAST |
-						  REINDEX_REL_CHECK_CONSTRAINTS))
+						  REINDEX_REL_CHECK_CONSTRAINTS,
+						  options))
 		ereport(NOTICE,
 				(errmsg("table \"%s\" has no indexes",
 						relation->relname)));
@@ -1802,7 +1803,8 @@ 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,
+					  uint8 options)
 {
 	Oid			objectOid;
 	Relation	relationRelation;
@@ -1814,12 +1816,17 @@ ReindexMultipleTables(const char *objectName, ReindexObjectType objectKind)
 	List	   *relids = NIL;
 	ListCell   *l;
 	int			num_keys;
+	int			elevel = DEBUG2;
 
 	AssertArg(objectName);
 	Assert(objectKind == REINDEX_OBJECT_SCHEMA ||
 		   objectKind == REINDEX_OBJECT_SYSTEM ||
 		   objectKind == REINDEX_OBJECT_DATABASE);
 
+	/* Set option(s) */
+	if (options & REINDEXOPT_VERBOSE)
+		elevel = INFO;
+
 	/*
 	 * 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
@@ -1938,9 +1945,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,
+							 options))
+			ereport(elevel,
+					(errmsg("indexes of 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 299d8cc..925ad5d 100644
--- a/src/backend/commands/tablecmds.c
+++ b/src/backend/commands/tablecmds.c
@@ -1234,7 +1234,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/nodes/copyfuncs.c b/src/backend/nodes/copyfuncs.c
index 805045d..dc4409c 100644
--- a/src/backend/nodes/copyfuncs.c
+++ b/src/backend/nodes/copyfuncs.c
@@ -3783,6 +3783,7 @@ _copyReindexStmt(const ReindexStmt *from)
 	COPY_SCALAR_FIELD(kind);
 	COPY_NODE_FIELD(relation);
 	COPY_STRING_FIELD(name);
+	COPY_SCALAR_FIELD(options);
 
 	return newnode;
 }
diff --git a/src/backend/nodes/equalfuncs.c b/src/backend/nodes/equalfuncs.c
index 578ead5..a89afd6 100644
--- a/src/backend/nodes/equalfuncs.c
+++ b/src/backend/nodes/equalfuncs.c
@@ -1908,6 +1908,7 @@ _equalReindexStmt(const ReindexStmt *a, const ReindexStmt *b)
 	COMPARE_SCALAR_FIELD(kind);
 	COMPARE_NODE_FIELD(relation);
 	COMPARE_STRING_FIELD(name);
+	COMPARE_SCALAR_FIELD(options);
 
 	return true;
 }
diff --git a/src/backend/parser/gram.y b/src/backend/parser/gram.y
index 0180530..8a0e569 100644
--- a/src/backend/parser/gram.y
+++ b/src/backend/parser/gram.y
@@ -459,6 +459,10 @@ 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 <ival>	reindex_target_type reindex_target_multitable
+%type <ival>	reindex_option_list reindex_option_elem
+
 %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
@@ -7383,52 +7387,63 @@ DropTransformStmt: DROP TRANSFORM opt_if_exists FOR Typename LANGUAGE name opt_d
  *
  *		QUERY:
  *
- *		REINDEX type <name>
+ *		REINDEX [ (options) ] type <name>
  *****************************************************************************/
 
 ReindexStmt:
-			REINDEX INDEX qualified_name
+			REINDEX reindex_target_type qualified_name
 				{
 					ReindexStmt *n = makeNode(ReindexStmt);
-					n->kind = REINDEX_OBJECT_INDEX;
+					n->kind = $2;
 					n->relation = $3;
 					n->name = NULL;
+					n->options = 0;
 					$$ = (Node *)n;
 				}
-			| REINDEX TABLE qualified_name
+			| REINDEX reindex_target_multitable name
 				{
 					ReindexStmt *n = makeNode(ReindexStmt);
-					n->kind = REINDEX_OBJECT_TABLE;
-					n->relation = $3;
-					n->name = NULL;
-					$$ = (Node *)n;
-				}
-			| REINDEX SCHEMA name
-				{
-					ReindexStmt *n = makeNode(ReindexStmt);
-					n->kind = REINDEX_OBJECT_SCHEMA;
+					n->kind = $2;
 					n->name = $3;
 					n->relation = NULL;
+					n->options = 0;
 					$$ = (Node *)n;
 				}
-			| REINDEX SYSTEM_P name
+			| REINDEX '(' reindex_option_list ')' reindex_target_type qualified_name
 				{
 					ReindexStmt *n = makeNode(ReindexStmt);
-					n->kind = REINDEX_OBJECT_SYSTEM;
-					n->name = $3;
-					n->relation = NULL;
+					n->kind = $5;
+					n->relation = $6;
+					n->name = NULL;
+					n->options = $3;
 					$$ = (Node *)n;
 				}
-			| REINDEX DATABASE name
+			| REINDEX '(' reindex_option_list ')' reindex_target_multitable name
 				{
 					ReindexStmt *n = makeNode(ReindexStmt);
-					n->kind = REINDEX_OBJECT_DATABASE;
-					n->name = $3;
+					n->kind = $5;
+					n->name = $6;
 					n->relation = NULL;
+					n->options = $3;
 					$$ = (Node *)n;
 				}
 		;
-
+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; }
+		;
+reindex_option_list:
+			reindex_option_elem								{ $$ = $1; }
+			| reindex_option_list ',' reindex_option_elem	{ $$ = $1 | $3; }
+		;
+reindex_option_elem:
+			VERBOSE	{ $$ = REINDEXOPT_VERBOSE; }
+		;
 
 /*****************************************************************************
  *
diff --git a/src/backend/tcop/utility.c b/src/backend/tcop/utility.c
index 59f09dc..6bae061 100644
--- a/src/backend/tcop/utility.c
+++ b/src/backend/tcop/utility.c
@@ -762,10 +762,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:
@@ -781,7 +781,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 750e29d..55b0df5 100644
--- a/src/bin/psql/tab-complete.c
+++ b/src/bin/psql/tab-complete.c
@@ -3335,7 +3335,6 @@ psql_completion(const char *text, int start, int end)
 /* REINDEX */
 	else if (pg_strcasecmp(prev_wd, "REINDEX") == 0)
 	{
-		static const char *const list_REINDEX[] =
 			{"TABLE", "INDEX", "SYSTEM", "SCHEMA", "DATABASE", NULL};
 
 		COMPLETE_WITH_LIST(list_REINDEX);
@@ -3346,13 +3345,14 @@ 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)
 			COMPLETE_WITH_QUERY(Query_for_list_of_databases);
 	}
 
+
 /* SECURITY LABEL */
 	else if (pg_strcasecmp(prev_wd, "SECURITY") == 0)
 		COMPLETE_WITH_CONST("LABEL");
diff --git a/src/include/catalog/index.h b/src/include/catalog/index.h
index a04def9..994a2f2 100644
--- a/src/include/catalog/index.h
+++ b/src/include/catalog/index.h
@@ -113,7 +113,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, uint8 options);
 
 /* Flag bits for reindex_relation(): */
 #define REINDEX_REL_PROCESS_TOAST			0x01
@@ -122,7 +122,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, uint8 options);
 
 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 335f09c..80b3d30 100644
--- a/src/include/commands/defrem.h
+++ b/src/include/commands/defrem.h
@@ -29,9 +29,10 @@ 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, uint8 options);
+extern Oid	ReindexTable(RangeVar *relation, uint8 options);
+extern void ReindexMultipleTables(const char *objectName, ReindexObjectType objectKind,
+								  uint8 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 852eb4f..aae328c 100644
--- a/src/include/nodes/parsenodes.h
+++ b/src/include/nodes/parsenodes.h
@@ -2745,6 +2745,11 @@ typedef struct ConstraintsSetStmt
  *		REINDEX Statement
  * ----------------------
  */
+typedef enum ReindexOption
+{
+	REINDEXOPT_VERBOSE = 1 << 0	/* pint progress info */
+} ReindexOption;
+
 typedef enum ReindexObjectType
 {
 	REINDEX_OBJECT_INDEX,	/* index */
@@ -2760,6 +2765,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 */
+	uint8		options;		/* ReindexOption flags*/
 } ReindexStmt;
 
 /* ----------------------
diff --git a/src/test/regress/expected/create_index.out b/src/test/regress/expected/create_index.out
index abe64e5..cba11b4 100644
--- a/src/test/regress/expected/create_index.out
+++ b/src/test/regress/expected/create_index.out
@@ -2832,6 +2832,14 @@ explain (costs off)
 (2 rows)
 
 --
+-- REINDEX (VERBOSE)
+--
+CREATE TABLE reindex_verbose(id integer primary key);
+\set VERBOSITY terse
+REINDEX (VERBOSE) TABLE reindex_verbose;
+INFO:  index "reindex_verbose_pkey" was reindexed.
+DROP TABLE reindex_verbose;
+--
 -- REINDEX SCHEMA
 --
 REINDEX SCHEMA schema_to_reindex; -- failure, schema does not exist
diff --git a/src/test/regress/sql/create_index.sql b/src/test/regress/sql/create_index.sql
index f779fa0..6333a30 100644
--- a/src/test/regress/sql/create_index.sql
+++ b/src/test/regress/sql/create_index.sql
@@ -966,6 +966,14 @@ explain (costs off)
   select * from tenk1 where (thousand, tenthous) in ((1,1001), (null,null));
 
 --
+-- REINDEX (VERBOSE)
+--
+CREATE TABLE reindex_verbose(id integer primary key);
+\set VERBOSITY terse
+REINDEX (VERBOSE) TABLE reindex_verbose;
+DROP TABLE reindex_verbose;
+
+--
 -- REINDEX SCHEMA
 --
 REINDEX SCHEMA schema_to_reindex; -- failure, schema does not exist
001_reindexdb_verbose_option_v1.patchtext/x-patch; charset=US-ASCII; name=001_reindexdb_verbose_option_v1.patchDownload
diff --git a/src/bin/scripts/reindexdb.c b/src/bin/scripts/reindexdb.c
index 778d72a..fdb79f1 100644
--- a/src/bin/scripts/reindexdb.c
+++ b/src/bin/scripts/reindexdb.c
@@ -18,16 +18,16 @@ static void reindex_one_database(const char *name, const char *dbname,
 					 const char *type, const char *host,
 					 const char *port, const char *username,
 					 enum trivalue prompt_password, const char *progname,
-					 bool echo);
+					 bool echo, bool verbose);
 static void reindex_all_databases(const char *maintenance_db,
 					  const char *host, const char *port,
 					  const char *username, enum trivalue prompt_password,
 					  const char *progname, bool echo,
-					  bool quiet);
+					  bool quiet, bool verbose);
 static void reindex_system_catalogs(const char *dbname,
 						const char *host, const char *port,
 						const char *username, enum trivalue prompt_password,
-						const char *progname, bool echo);
+						const char *progname, bool echo, bool verbose);
 static void help(const char *progname);
 
 int
@@ -47,6 +47,7 @@ main(int argc, char *argv[])
 		{"system", no_argument, NULL, 's'},
 		{"table", required_argument, NULL, 't'},
 		{"index", required_argument, NULL, 'i'},
+		{"verbose", no_argument, NULL, 'v'},
 		{"maintenance-db", required_argument, NULL, 2},
 		{NULL, 0, NULL, 0}
 	};
@@ -65,6 +66,7 @@ main(int argc, char *argv[])
 	bool		alldb = false;
 	bool		echo = false;
 	bool		quiet = false;
+	bool		verbose = false;
 	SimpleStringList indexes = {NULL, NULL};
 	SimpleStringList tables = {NULL, NULL};
 	SimpleStringList schemas = {NULL, NULL};
@@ -118,6 +120,9 @@ main(int argc, char *argv[])
 			case 'i':
 				simple_string_list_append(&indexes, optarg);
 				break;
+			case 'v':
+				verbose = true;
+				break;
 			case 2:
 				maintenance_db = pg_strdup(optarg);
 				break;
@@ -176,7 +181,7 @@ main(int argc, char *argv[])
 		}
 
 		reindex_all_databases(maintenance_db, host, port, username,
-							  prompt_password, progname, echo, quiet);
+							  prompt_password, progname, echo, quiet, verbose);
 	}
 	else if (syscatalog)
 	{
@@ -207,7 +212,7 @@ main(int argc, char *argv[])
 		}
 
 		reindex_system_catalogs(dbname, host, port, username, prompt_password,
-								progname, echo);
+								progname, echo, verbose);
 	}
 	else
 	{
@@ -228,7 +233,7 @@ main(int argc, char *argv[])
 			for (cell = schemas.head; cell; cell = cell->next)
 			{
 				reindex_one_database(cell->val, dbname, "SCHEMA", host, port,
-								   username, prompt_password, progname, echo);
+								   username, prompt_password, progname, echo, verbose);
 			}
 		}
 
@@ -239,7 +244,7 @@ main(int argc, char *argv[])
 			for (cell = indexes.head; cell; cell = cell->next)
 			{
 				reindex_one_database(cell->val, dbname, "INDEX", host, port,
-								  username, prompt_password, progname, echo);
+								  username, prompt_password, progname, echo, verbose);
 			}
 		}
 		if (tables.head != NULL)
@@ -249,13 +254,13 @@ main(int argc, char *argv[])
 			for (cell = tables.head; cell; cell = cell->next)
 			{
 				reindex_one_database(cell->val, dbname, "TABLE", host, port,
-								  username, prompt_password, progname, echo);
+								  username, prompt_password, progname, echo, verbose);
 			}
 		}
 		/* reindex database only if neither index nor table nor schema is specified */
 		if (indexes.head == NULL && tables.head == NULL && schemas.head == NULL)
 			reindex_one_database(dbname, dbname, "DATABASE", host, port,
-								 username, prompt_password, progname, echo);
+								 username, prompt_password, progname, echo, verbose);
 	}
 
 	exit(0);
@@ -264,7 +269,8 @@ main(int argc, char *argv[])
 static void
 reindex_one_database(const char *name, const char *dbname, const char *type,
 					 const char *host, const char *port, const char *username,
-			  enum trivalue prompt_password, const char *progname, bool echo)
+					 enum trivalue prompt_password, const char *progname, bool echo,
+					 bool verbose)
 {
 	PQExpBufferData sql;
 
@@ -273,6 +279,10 @@ reindex_one_database(const char *name, const char *dbname, const char *type,
 	initPQExpBuffer(&sql);
 
 	appendPQExpBufferStr(&sql, "REINDEX");
+
+	if (verbose)
+		appendPQExpBufferStr(&sql, " (VERBOSE) ");
+
 	if (strcmp(type, "TABLE") == 0)
 		appendPQExpBuffer(&sql, " TABLE %s", name);
 	else if (strcmp(type, "INDEX") == 0)
@@ -312,7 +322,7 @@ static void
 reindex_all_databases(const char *maintenance_db,
 					  const char *host, const char *port,
 					  const char *username, enum trivalue prompt_password,
-					  const char *progname, bool echo, bool quiet)
+					  const char *progname, bool echo, bool quiet, bool verbose)
 {
 	PGconn	   *conn;
 	PGresult   *result;
@@ -334,7 +344,7 @@ reindex_all_databases(const char *maintenance_db,
 		}
 
 		reindex_one_database(dbname, dbname, "DATABASE", host, port, username,
-							 prompt_password, progname, echo);
+							 prompt_password, progname, echo, verbose);
 	}
 
 	PQclear(result);
@@ -343,7 +353,7 @@ reindex_all_databases(const char *maintenance_db,
 static void
 reindex_system_catalogs(const char *dbname, const char *host, const char *port,
 						const char *username, enum trivalue prompt_password,
-						const char *progname, bool echo)
+						const char *progname, bool echo, bool verbose)
 {
 	PQExpBufferData sql;
 
@@ -351,7 +361,12 @@ reindex_system_catalogs(const char *dbname, const char *host, const char *port,
 
 	initPQExpBuffer(&sql);
 
-	appendPQExpBuffer(&sql, "REINDEX SYSTEM %s;", dbname);
+	appendPQExpBuffer(&sql, "REINDEX");
+
+	if (verbose)
+		appendPQExpBuffer(&sql, " (VERBOSE) ");
+
+	appendPQExpBuffer(&sql, " SYSTEM %s;", dbname);
 
 	conn = connectDatabase(dbname, host, port, username, prompt_password,
 						   progname, false);
@@ -380,6 +395,7 @@ help(const char *progname)
 	printf(_("  -q, --quiet               don't write any messages\n"));
 	printf(_("  -s, --system              reindex system catalogs\n"));
 	printf(_("  -S, --schema=SCHEMA       recreate specific schema(s) only\n"));
+	printf(_("  -v, --verbose			  write a lot of output\n"));
 	printf(_("  -t, --table=TABLE         reindex specific table(s) only\n"));
 	printf(_("  -V, --version             output version information, then exit\n"));
 	printf(_("  -?, --help                show this help, then exit\n"));
#62Fabrízio de Royes Mello
fabriziomello@gmail.com
In reply to: Sawada Masahiko (#61)
2 attachment(s)
Re: Proposal : REINDEX xxx VERBOSE

On Thu, May 7, 2015 at 7:55 PM, Sawada Masahiko <sawada.mshk@gmail.com>
wrote:

On 5/7/15, Sawada Masahiko <sawada.mshk@gmail.com> wrote:

On Wed, May 6, 2015 at 5:42 AM, Robert Haas <robertmhaas@gmail.com
<javascript:;>> wrote:

On Tue, May 5, 2015 at 11:10 AM, Sawada Masahiko <sawada.mshk@gmail.com

<javascript:;>> wrote:

On Fri, May 1, 2015 at 9:04 PM, Robert Haas <robertmhaas@gmail.com

<javascript:;>> wrote:

On Thu, Apr 30, 2015 at 11:05 PM, Sawada Masahiko
<sawada.mshk@gmail.com

<javascript:;>> wrote:

VACUUM has both syntax: with parentheses and without parentheses.
I think we should have both syntax for REINDEX like VACUUM does
because it would be pain to put parentheses whenever we want to do
REINDEX.
Are the parentheses optional in REINDEX command?

No. The unparenthesized VACUUM syntax was added back before we
realized that that kind of syntax is a terrible idea. It requires
every option to be a keyword, and those keywords have to be in a

fixed

order. I believe the intention is to keep the old VACUUM syntax
around for backward-compatibility, but not to extend it. Same for
EXPLAIN and COPY.

REINDEX will have only one option VERBOSE for now.
Even we're in a situation like that it's not clear to be added newly
additional option to REINDEX now, we should need to put parenthesis?

In my opinion, yes. The whole point of a flexible options syntax is
that we can add new options without changing the grammar. That
involves some compromise on the syntax, which doesn't bother me a bit.
Our previous experiments with this for EXPLAIN and COPY and VACUUM
have worked out quite well, and I see no reason for pessimism here.

I agree that flexible option syntax does not need to change grammar
whenever we add new options.
Attached patch is changed based on your suggestion.
And the patch for reindexdb is also attached.
Please feedbacks.

Also I'm not sure that both implementation and documentation regarding
VERBOSE option should be optional.

I don't know what this means.

Sorry for confusing you.
Please ignore this.

Sorry, I forgot attach files.

I applied the two patches to master and I got some errors when compile:

tab-complete.c: In function ‘psql_completion’:
tab-complete.c:3338:12: warning: left-hand operand of comma expression has
no effect [-Wunused-value]
{"TABLE", "INDEX", "SYSTEM", "SCHEMA", "DATABASE", NULL};
^
tab-complete.c:3338:21: warning: left-hand operand of comma expression has
no effect [-Wunused-value]
{"TABLE", "INDEX", "SYSTEM", "SCHEMA", "DATABASE", NULL};
^
tab-complete.c:3338:31: warning: left-hand operand of comma expression has
no effect [-Wunused-value]
{"TABLE", "INDEX", "SYSTEM", "SCHEMA", "DATABASE", NULL};
^
tab-complete.c:3338:41: warning: left-hand operand of comma expression has
no effect [-Wunused-value]
{"TABLE", "INDEX", "SYSTEM", "SCHEMA", "DATABASE", NULL};
^
tab-complete.c:3338:53: warning: left-hand operand of comma expression has
no effect [-Wunused-value]
{"TABLE", "INDEX", "SYSTEM", "SCHEMA", "DATABASE", NULL};
^
tab-complete.c:3338:5: warning: statement with no effect [-Wunused-value]
{"TABLE", "INDEX", "SYSTEM", "SCHEMA", "DATABASE", NULL};
^
tab-complete.c:3338:59: error: expected ‘;’ before ‘}’ token
{"TABLE", "INDEX", "SYSTEM", "SCHEMA", "DATABASE", NULL};
^
tab-complete.c:3340:22: error: ‘list_REINDEX’ undeclared (first use in this
function)
COMPLETE_WITH_LIST(list_REINDEX);
^
tab-complete.c:169:22: note: in definition of macro ‘COMPLETE_WITH_LIST’
completion_charpp = list; \
^
tab-complete.c:3340:22: note: each undeclared identifier is reported only
once for each function it appears in
COMPLETE_WITH_LIST(list_REINDEX);
^
tab-complete.c:169:22: note: in definition of macro ‘COMPLETE_WITH_LIST’
completion_charpp = list; \
^
make[3]: *** [tab-complete.o] Error 1
make[3]: *** Waiting for unfinished jobs....
make[2]: *** [install-psql-recurse] Error 2
make[2]: *** Waiting for unfinished jobs....
make[1]: *** [install-bin-recurse] Error 2
make: *** [install-src-recurse] Error 2

Looking at the code I think you remove one line accidentally from
tab-complete.c:

$ git diff src/bin/psql/tab-complete.c
diff --git a/src/bin/psql/tab-complete.c b/src/bin/psql/tab-complete.c
index 750e29d..55b0df5 100644
--- a/src/bin/psql/tab-complete.c
+++ b/src/bin/psql/tab-complete.c
@@ -3335,7 +3335,6 @@ psql_completion(const char *text, int start, int end)
 /* REINDEX */
    else if (pg_strcasecmp(prev_wd, "REINDEX") == 0)
    {
-       static const char *const list_REINDEX[] =
            {"TABLE", "INDEX", "SYSTEM", "SCHEMA", "DATABASE", NULL};

COMPLETE_WITH_LIST(list_REINDEX);

The attached fix it and now seems good to me.

Regards,

--
Fabrízio de Royes Mello
Consultoria/Coaching PostgreSQL

Show quoted text

Timbira: http://www.timbira.com.br
Blog: http://fabriziomello.github.io
Linkedin: http://br.linkedin.com/in/fabriziomello
Twitter: http://twitter.com/fabriziomello
Github: http://github.com/fabriziomello

Attachments:

000_reindex_verbose_v13.patchtext/x-diff; charset=US-ASCII; name=000_reindex_verbose_v13.patchDownload
diff --git a/doc/src/sgml/ref/reindex.sgml b/doc/src/sgml/ref/reindex.sgml
index 998340c..703b760 100644
--- a/doc/src/sgml/ref/reindex.sgml
+++ b/doc/src/sgml/ref/reindex.sgml
@@ -21,7 +21,7 @@ PostgreSQL documentation
 
  <refsynopsisdiv>
 <synopsis>
-REINDEX { INDEX | TABLE | SCHEMA | DATABASE | SYSTEM } <replaceable class="PARAMETER">name</replaceable>
+REINDEX [ ( { VERBOSE } [, ...] ) ] { INDEX | TABLE | SCHEMA | DATABASE | SYSTEM } <replaceable class="PARAMETER">name</replaceable>
 </synopsis>
  </refsynopsisdiv>
 
@@ -150,6 +150,15 @@ 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>
   </variablelist>
  </refsect1>
 
diff --git a/src/backend/catalog/index.c b/src/backend/catalog/index.c
index 8c8a9ea..d8da0e8 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"
@@ -3184,13 +3185,22 @@ 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,
+				uint8 options)
 {
 	Relation	iRel,
 				heapRelation;
 	Oid			heapId;
 	IndexInfo  *indexInfo;
 	volatile bool skipped_constraint = false;
+	int			elevel = DEBUG2;
+	PGRUsage	ru0;
+
+	pg_rusage_init(&ru0);
+
+	/* Set option(s) */
+	if (options & REINDEXOPT_VERBOSE)
+		elevel = INFO;
 
 	/*
 	 * Open and lock the parent heap relation.  ShareLock is sufficient since
@@ -3334,6 +3344,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);
@@ -3375,7 +3392,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, uint8 options)
 {
 	Relation	rel;
 	Oid			toast_relid;
@@ -3466,7 +3483,7 @@ reindex_relation(Oid relid, int flags)
 				RelationSetIndexList(rel, doneIndexes, InvalidOid);
 
 			reindex_index(indexOid, !(flags & REINDEX_REL_CHECK_CONSTRAINTS),
-						  persistence);
+						  persistence, options);
 
 			CommandCounterIncrement();
 
@@ -3501,7 +3518,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, options);
 
 	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 351d48e..fa63611 100644
--- a/src/backend/commands/indexcmds.c
+++ b/src/backend/commands/indexcmds.c
@@ -1681,7 +1681,7 @@ ChooseIndexColumnNames(List *indexElems)
  *		Recreate a specific index.
  */
 Oid
-ReindexIndex(RangeVar *indexRelation)
+ReindexIndex(RangeVar *indexRelation, uint8 options)
 {
 	Oid			indOid;
 	Oid			heapOid = InvalidOid;
@@ -1706,7 +1706,7 @@ ReindexIndex(RangeVar *indexRelation)
 	persistence = irel->rd_rel->relpersistence;
 	index_close(irel, NoLock);
 
-	reindex_index(indOid, false, persistence);
+	reindex_index(indOid, false, persistence, options);
 
 	return indOid;
 }
@@ -1775,7 +1775,7 @@ RangeVarCallbackForReindexIndex(const RangeVar *relation,
  *		Recreate all indexes of a table (and of its toast table, if any)
  */
 Oid
-ReindexTable(RangeVar *relation)
+ReindexTable(RangeVar *relation, uint8 options)
 {
 	Oid			heapOid;
 
@@ -1785,7 +1785,8 @@ ReindexTable(RangeVar *relation)
 
 	if (!reindex_relation(heapOid,
 						  REINDEX_REL_PROCESS_TOAST |
-						  REINDEX_REL_CHECK_CONSTRAINTS))
+						  REINDEX_REL_CHECK_CONSTRAINTS,
+						  options))
 		ereport(NOTICE,
 				(errmsg("table \"%s\" has no indexes",
 						relation->relname)));
@@ -1802,7 +1803,8 @@ 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,
+					  uint8 options)
 {
 	Oid			objectOid;
 	Relation	relationRelation;
@@ -1814,12 +1816,17 @@ ReindexMultipleTables(const char *objectName, ReindexObjectType objectKind)
 	List	   *relids = NIL;
 	ListCell   *l;
 	int			num_keys;
+	int			elevel = DEBUG2;
 
 	AssertArg(objectName);
 	Assert(objectKind == REINDEX_OBJECT_SCHEMA ||
 		   objectKind == REINDEX_OBJECT_SYSTEM ||
 		   objectKind == REINDEX_OBJECT_DATABASE);
 
+	/* Set option(s) */
+	if (options & REINDEXOPT_VERBOSE)
+		elevel = INFO;
+
 	/*
 	 * 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
@@ -1938,9 +1945,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,
+							 options))
+			ereport(elevel,
+					(errmsg("indexes of 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 299d8cc..925ad5d 100644
--- a/src/backend/commands/tablecmds.c
+++ b/src/backend/commands/tablecmds.c
@@ -1234,7 +1234,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/nodes/copyfuncs.c b/src/backend/nodes/copyfuncs.c
index a3139d3..c70f418 100644
--- a/src/backend/nodes/copyfuncs.c
+++ b/src/backend/nodes/copyfuncs.c
@@ -3856,6 +3856,7 @@ _copyReindexStmt(const ReindexStmt *from)
 	COPY_SCALAR_FIELD(kind);
 	COPY_NODE_FIELD(relation);
 	COPY_STRING_FIELD(name);
+	COPY_SCALAR_FIELD(options);
 
 	return newnode;
 }
diff --git a/src/backend/nodes/equalfuncs.c b/src/backend/nodes/equalfuncs.c
index 7c86e91..d086261 100644
--- a/src/backend/nodes/equalfuncs.c
+++ b/src/backend/nodes/equalfuncs.c
@@ -1935,6 +1935,7 @@ _equalReindexStmt(const ReindexStmt *a, const ReindexStmt *b)
 	COMPARE_SCALAR_FIELD(kind);
 	COMPARE_NODE_FIELD(relation);
 	COMPARE_STRING_FIELD(name);
+	COMPARE_SCALAR_FIELD(options);
 
 	return true;
 }
diff --git a/src/backend/parser/gram.y b/src/backend/parser/gram.y
index 7a4c073..112021b 100644
--- a/src/backend/parser/gram.y
+++ b/src/backend/parser/gram.y
@@ -463,6 +463,10 @@ 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 <ival>	reindex_target_type reindex_target_multitable
+%type <ival>	reindex_option_list reindex_option_elem
+
 %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
@@ -7387,52 +7391,63 @@ DropTransformStmt: DROP TRANSFORM opt_if_exists FOR Typename LANGUAGE name opt_d
  *
  *		QUERY:
  *
- *		REINDEX type <name>
+ *		REINDEX [ (options) ] type <name>
  *****************************************************************************/
 
 ReindexStmt:
-			REINDEX INDEX qualified_name
+			REINDEX reindex_target_type qualified_name
 				{
 					ReindexStmt *n = makeNode(ReindexStmt);
-					n->kind = REINDEX_OBJECT_INDEX;
+					n->kind = $2;
 					n->relation = $3;
 					n->name = NULL;
+					n->options = 0;
 					$$ = (Node *)n;
 				}
-			| REINDEX TABLE qualified_name
+			| REINDEX reindex_target_multitable name
 				{
 					ReindexStmt *n = makeNode(ReindexStmt);
-					n->kind = REINDEX_OBJECT_TABLE;
-					n->relation = $3;
-					n->name = NULL;
-					$$ = (Node *)n;
-				}
-			| REINDEX SCHEMA name
-				{
-					ReindexStmt *n = makeNode(ReindexStmt);
-					n->kind = REINDEX_OBJECT_SCHEMA;
+					n->kind = $2;
 					n->name = $3;
 					n->relation = NULL;
+					n->options = 0;
 					$$ = (Node *)n;
 				}
-			| REINDEX SYSTEM_P name
+			| REINDEX '(' reindex_option_list ')' reindex_target_type qualified_name
 				{
 					ReindexStmt *n = makeNode(ReindexStmt);
-					n->kind = REINDEX_OBJECT_SYSTEM;
-					n->name = $3;
-					n->relation = NULL;
+					n->kind = $5;
+					n->relation = $6;
+					n->name = NULL;
+					n->options = $3;
 					$$ = (Node *)n;
 				}
-			| REINDEX DATABASE name
+			| REINDEX '(' reindex_option_list ')' reindex_target_multitable name
 				{
 					ReindexStmt *n = makeNode(ReindexStmt);
-					n->kind = REINDEX_OBJECT_DATABASE;
-					n->name = $3;
+					n->kind = $5;
+					n->name = $6;
 					n->relation = NULL;
+					n->options = $3;
 					$$ = (Node *)n;
 				}
 		;
-
+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; }
+		;
+reindex_option_list:
+			reindex_option_elem								{ $$ = $1; }
+			| reindex_option_list ',' reindex_option_elem	{ $$ = $1 | $3; }
+		;
+reindex_option_elem:
+			VERBOSE	{ $$ = REINDEXOPT_VERBOSE; }
+		;
 
 /*****************************************************************************
  *
diff --git a/src/backend/tcop/utility.c b/src/backend/tcop/utility.c
index 59f09dc..6bae061 100644
--- a/src/backend/tcop/utility.c
+++ b/src/backend/tcop/utility.c
@@ -762,10 +762,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:
@@ -781,7 +781,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 750e29d..4884a3d 100644
--- a/src/bin/psql/tab-complete.c
+++ b/src/bin/psql/tab-complete.c
@@ -3346,7 +3346,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 06f3820..f2429fd 100644
--- a/src/include/catalog/index.h
+++ b/src/include/catalog/index.h
@@ -115,7 +115,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, uint8 options);
 
 /* Flag bits for reindex_relation(): */
 #define REINDEX_REL_PROCESS_TOAST			0x01
@@ -124,7 +124,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, uint8 options);
 
 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 335f09c..80b3d30 100644
--- a/src/include/commands/defrem.h
+++ b/src/include/commands/defrem.h
@@ -29,9 +29,10 @@ 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, uint8 options);
+extern Oid	ReindexTable(RangeVar *relation, uint8 options);
+extern void ReindexMultipleTables(const char *objectName, ReindexObjectType objectKind,
+								  uint8 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 91ca9c6..49ba23e 100644
--- a/src/include/nodes/parsenodes.h
+++ b/src/include/nodes/parsenodes.h
@@ -2782,6 +2782,11 @@ typedef struct ConstraintsSetStmt
  *		REINDEX Statement
  * ----------------------
  */
+typedef enum ReindexOption
+{
+	REINDEXOPT_VERBOSE = 1 << 0	/* pint progress info */
+} ReindexOption;
+
 typedef enum ReindexObjectType
 {
 	REINDEX_OBJECT_INDEX,	/* index */
@@ -2797,6 +2802,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 */
+	uint8		options;		/* ReindexOption flags*/
 } ReindexStmt;
 
 /* ----------------------
diff --git a/src/test/regress/expected/create_index.out b/src/test/regress/expected/create_index.out
index abe64e5..cba11b4 100644
--- a/src/test/regress/expected/create_index.out
+++ b/src/test/regress/expected/create_index.out
@@ -2832,6 +2832,14 @@ explain (costs off)
 (2 rows)
 
 --
+-- REINDEX (VERBOSE)
+--
+CREATE TABLE reindex_verbose(id integer primary key);
+\set VERBOSITY terse
+REINDEX (VERBOSE) TABLE reindex_verbose;
+INFO:  index "reindex_verbose_pkey" was reindexed.
+DROP TABLE reindex_verbose;
+--
 -- REINDEX SCHEMA
 --
 REINDEX SCHEMA schema_to_reindex; -- failure, schema does not exist
diff --git a/src/test/regress/sql/create_index.sql b/src/test/regress/sql/create_index.sql
index f779fa0..6333a30 100644
--- a/src/test/regress/sql/create_index.sql
+++ b/src/test/regress/sql/create_index.sql
@@ -966,6 +966,14 @@ explain (costs off)
   select * from tenk1 where (thousand, tenthous) in ((1,1001), (null,null));
 
 --
+-- REINDEX (VERBOSE)
+--
+CREATE TABLE reindex_verbose(id integer primary key);
+\set VERBOSITY terse
+REINDEX (VERBOSE) TABLE reindex_verbose;
+DROP TABLE reindex_verbose;
+
+--
 -- REINDEX SCHEMA
 --
 REINDEX SCHEMA schema_to_reindex; -- failure, schema does not exist
001_reindexdb_verbose_option_v1.patchtext/x-diff; charset=US-ASCII; name=001_reindexdb_verbose_option_v1.patchDownload
diff --git a/src/bin/scripts/reindexdb.c b/src/bin/scripts/reindexdb.c
index 778d72a..fdb79f1 100644
--- a/src/bin/scripts/reindexdb.c
+++ b/src/bin/scripts/reindexdb.c
@@ -18,16 +18,16 @@ static void reindex_one_database(const char *name, const char *dbname,
 					 const char *type, const char *host,
 					 const char *port, const char *username,
 					 enum trivalue prompt_password, const char *progname,
-					 bool echo);
+					 bool echo, bool verbose);
 static void reindex_all_databases(const char *maintenance_db,
 					  const char *host, const char *port,
 					  const char *username, enum trivalue prompt_password,
 					  const char *progname, bool echo,
-					  bool quiet);
+					  bool quiet, bool verbose);
 static void reindex_system_catalogs(const char *dbname,
 						const char *host, const char *port,
 						const char *username, enum trivalue prompt_password,
-						const char *progname, bool echo);
+						const char *progname, bool echo, bool verbose);
 static void help(const char *progname);
 
 int
@@ -47,6 +47,7 @@ main(int argc, char *argv[])
 		{"system", no_argument, NULL, 's'},
 		{"table", required_argument, NULL, 't'},
 		{"index", required_argument, NULL, 'i'},
+		{"verbose", no_argument, NULL, 'v'},
 		{"maintenance-db", required_argument, NULL, 2},
 		{NULL, 0, NULL, 0}
 	};
@@ -65,6 +66,7 @@ main(int argc, char *argv[])
 	bool		alldb = false;
 	bool		echo = false;
 	bool		quiet = false;
+	bool		verbose = false;
 	SimpleStringList indexes = {NULL, NULL};
 	SimpleStringList tables = {NULL, NULL};
 	SimpleStringList schemas = {NULL, NULL};
@@ -118,6 +120,9 @@ main(int argc, char *argv[])
 			case 'i':
 				simple_string_list_append(&indexes, optarg);
 				break;
+			case 'v':
+				verbose = true;
+				break;
 			case 2:
 				maintenance_db = pg_strdup(optarg);
 				break;
@@ -176,7 +181,7 @@ main(int argc, char *argv[])
 		}
 
 		reindex_all_databases(maintenance_db, host, port, username,
-							  prompt_password, progname, echo, quiet);
+							  prompt_password, progname, echo, quiet, verbose);
 	}
 	else if (syscatalog)
 	{
@@ -207,7 +212,7 @@ main(int argc, char *argv[])
 		}
 
 		reindex_system_catalogs(dbname, host, port, username, prompt_password,
-								progname, echo);
+								progname, echo, verbose);
 	}
 	else
 	{
@@ -228,7 +233,7 @@ main(int argc, char *argv[])
 			for (cell = schemas.head; cell; cell = cell->next)
 			{
 				reindex_one_database(cell->val, dbname, "SCHEMA", host, port,
-								   username, prompt_password, progname, echo);
+								   username, prompt_password, progname, echo, verbose);
 			}
 		}
 
@@ -239,7 +244,7 @@ main(int argc, char *argv[])
 			for (cell = indexes.head; cell; cell = cell->next)
 			{
 				reindex_one_database(cell->val, dbname, "INDEX", host, port,
-								  username, prompt_password, progname, echo);
+								  username, prompt_password, progname, echo, verbose);
 			}
 		}
 		if (tables.head != NULL)
@@ -249,13 +254,13 @@ main(int argc, char *argv[])
 			for (cell = tables.head; cell; cell = cell->next)
 			{
 				reindex_one_database(cell->val, dbname, "TABLE", host, port,
-								  username, prompt_password, progname, echo);
+								  username, prompt_password, progname, echo, verbose);
 			}
 		}
 		/* reindex database only if neither index nor table nor schema is specified */
 		if (indexes.head == NULL && tables.head == NULL && schemas.head == NULL)
 			reindex_one_database(dbname, dbname, "DATABASE", host, port,
-								 username, prompt_password, progname, echo);
+								 username, prompt_password, progname, echo, verbose);
 	}
 
 	exit(0);
@@ -264,7 +269,8 @@ main(int argc, char *argv[])
 static void
 reindex_one_database(const char *name, const char *dbname, const char *type,
 					 const char *host, const char *port, const char *username,
-			  enum trivalue prompt_password, const char *progname, bool echo)
+					 enum trivalue prompt_password, const char *progname, bool echo,
+					 bool verbose)
 {
 	PQExpBufferData sql;
 
@@ -273,6 +279,10 @@ reindex_one_database(const char *name, const char *dbname, const char *type,
 	initPQExpBuffer(&sql);
 
 	appendPQExpBufferStr(&sql, "REINDEX");
+
+	if (verbose)
+		appendPQExpBufferStr(&sql, " (VERBOSE) ");
+
 	if (strcmp(type, "TABLE") == 0)
 		appendPQExpBuffer(&sql, " TABLE %s", name);
 	else if (strcmp(type, "INDEX") == 0)
@@ -312,7 +322,7 @@ static void
 reindex_all_databases(const char *maintenance_db,
 					  const char *host, const char *port,
 					  const char *username, enum trivalue prompt_password,
-					  const char *progname, bool echo, bool quiet)
+					  const char *progname, bool echo, bool quiet, bool verbose)
 {
 	PGconn	   *conn;
 	PGresult   *result;
@@ -334,7 +344,7 @@ reindex_all_databases(const char *maintenance_db,
 		}
 
 		reindex_one_database(dbname, dbname, "DATABASE", host, port, username,
-							 prompt_password, progname, echo);
+							 prompt_password, progname, echo, verbose);
 	}
 
 	PQclear(result);
@@ -343,7 +353,7 @@ reindex_all_databases(const char *maintenance_db,
 static void
 reindex_system_catalogs(const char *dbname, const char *host, const char *port,
 						const char *username, enum trivalue prompt_password,
-						const char *progname, bool echo)
+						const char *progname, bool echo, bool verbose)
 {
 	PQExpBufferData sql;
 
@@ -351,7 +361,12 @@ reindex_system_catalogs(const char *dbname, const char *host, const char *port,
 
 	initPQExpBuffer(&sql);
 
-	appendPQExpBuffer(&sql, "REINDEX SYSTEM %s;", dbname);
+	appendPQExpBuffer(&sql, "REINDEX");
+
+	if (verbose)
+		appendPQExpBuffer(&sql, " (VERBOSE) ");
+
+	appendPQExpBuffer(&sql, " SYSTEM %s;", dbname);
 
 	conn = connectDatabase(dbname, host, port, username, prompt_password,
 						   progname, false);
@@ -380,6 +395,7 @@ help(const char *progname)
 	printf(_("  -q, --quiet               don't write any messages\n"));
 	printf(_("  -s, --system              reindex system catalogs\n"));
 	printf(_("  -S, --schema=SCHEMA       recreate specific schema(s) only\n"));
+	printf(_("  -v, --verbose			  write a lot of output\n"));
 	printf(_("  -t, --table=TABLE         reindex specific table(s) only\n"));
 	printf(_("  -V, --version             output version information, then exit\n"));
 	printf(_("  -?, --help                show this help, then exit\n"));
#63Fabrízio de Royes Mello
fabriziomello@gmail.com
In reply to: Fabrízio de Royes Mello (#62)
Re: Proposal : REINDEX xxx VERBOSE

On Fri, May 8, 2015 at 4:23 PM, Fabrízio de Royes Mello <
fabriziomello@gmail.com> wrote:

On Thu, May 7, 2015 at 7:55 PM, Sawada Masahiko <sawada.mshk@gmail.com>

wrote:

On 5/7/15, Sawada Masahiko <sawada.mshk@gmail.com> wrote:

On Wed, May 6, 2015 at 5:42 AM, Robert Haas <robertmhaas@gmail.com
<javascript:;>> wrote:

On Tue, May 5, 2015 at 11:10 AM, Sawada Masahiko <

sawada.mshk@gmail.com

<javascript:;>> wrote:

On Fri, May 1, 2015 at 9:04 PM, Robert Haas <robertmhaas@gmail.com

<javascript:;>> wrote:

On Thu, Apr 30, 2015 at 11:05 PM, Sawada Masahiko
<sawada.mshk@gmail.com

<javascript:;>> wrote:

VACUUM has both syntax: with parentheses and without parentheses.
I think we should have both syntax for REINDEX like VACUUM does
because it would be pain to put parentheses whenever we want to do
REINDEX.
Are the parentheses optional in REINDEX command?

No. The unparenthesized VACUUM syntax was added back before we
realized that that kind of syntax is a terrible idea. It requires
every option to be a keyword, and those keywords have to be in a

fixed

order. I believe the intention is to keep the old VACUUM syntax
around for backward-compatibility, but not to extend it. Same for
EXPLAIN and COPY.

REINDEX will have only one option VERBOSE for now.
Even we're in a situation like that it's not clear to be added newly
additional option to REINDEX now, we should need to put parenthesis?

In my opinion, yes. The whole point of a flexible options syntax is
that we can add new options without changing the grammar. That
involves some compromise on the syntax, which doesn't bother me a

bit.

Our previous experiments with this for EXPLAIN and COPY and VACUUM
have worked out quite well, and I see no reason for pessimism here.

I agree that flexible option syntax does not need to change grammar
whenever we add new options.
Attached patch is changed based on your suggestion.
And the patch for reindexdb is also attached.
Please feedbacks.

Also I'm not sure that both implementation and documentation

regarding

VERBOSE option should be optional.

I don't know what this means.

Sorry for confusing you.
Please ignore this.

Sorry, I forgot attach files.

I applied the two patches to master and I got some errors when compile:

tab-complete.c: In function ‘psql_completion’:
tab-complete.c:3338:12: warning: left-hand operand of comma expression

has no effect [-Wunused-value]

{"TABLE", "INDEX", "SYSTEM", "SCHEMA", "DATABASE", NULL};
^
tab-complete.c:3338:21: warning: left-hand operand of comma expression

has no effect [-Wunused-value]

{"TABLE", "INDEX", "SYSTEM", "SCHEMA", "DATABASE", NULL};
^
tab-complete.c:3338:31: warning: left-hand operand of comma expression

has no effect [-Wunused-value]

{"TABLE", "INDEX", "SYSTEM", "SCHEMA", "DATABASE", NULL};
^
tab-complete.c:3338:41: warning: left-hand operand of comma expression

has no effect [-Wunused-value]

{"TABLE", "INDEX", "SYSTEM", "SCHEMA", "DATABASE", NULL};
^
tab-complete.c:3338:53: warning: left-hand operand of comma expression

has no effect [-Wunused-value]

{"TABLE", "INDEX", "SYSTEM", "SCHEMA", "DATABASE", NULL};
^
tab-complete.c:3338:5: warning: statement with no effect [-Wunused-value]
{"TABLE", "INDEX", "SYSTEM", "SCHEMA", "DATABASE", NULL};
^
tab-complete.c:3338:59: error: expected ‘;’ before ‘}’ token
{"TABLE", "INDEX", "SYSTEM", "SCHEMA", "DATABASE", NULL};
^
tab-complete.c:3340:22: error: ‘list_REINDEX’ undeclared (first use in

this function)

COMPLETE_WITH_LIST(list_REINDEX);
^
tab-complete.c:169:22: note: in definition of macro ‘COMPLETE_WITH_LIST’
completion_charpp = list; \
^
tab-complete.c:3340:22: note: each undeclared identifier is reported only

once for each function it appears in

COMPLETE_WITH_LIST(list_REINDEX);
^
tab-complete.c:169:22: note: in definition of macro ‘COMPLETE_WITH_LIST’
completion_charpp = list; \
^
make[3]: *** [tab-complete.o] Error 1
make[3]: *** Waiting for unfinished jobs....
make[2]: *** [install-psql-recurse] Error 2
make[2]: *** Waiting for unfinished jobs....
make[1]: *** [install-bin-recurse] Error 2
make: *** [install-src-recurse] Error 2

Looking at the code I think you remove one line accidentally from

tab-complete.c:

$ git diff src/bin/psql/tab-complete.c
diff --git a/src/bin/psql/tab-complete.c b/src/bin/psql/tab-complete.c
index 750e29d..55b0df5 100644
--- a/src/bin/psql/tab-complete.c
+++ b/src/bin/psql/tab-complete.c
@@ -3335,7 +3335,6 @@ psql_completion(const char *text, int start, int

end)

/* REINDEX */
else if (pg_strcasecmp(prev_wd, "REINDEX") == 0)
{
- static const char *const list_REINDEX[] =
{"TABLE", "INDEX", "SYSTEM", "SCHEMA", "DATABASE", NULL};

COMPLETE_WITH_LIST(list_REINDEX);

The attached fix it and now seems good to me.

Just one last note. IMHO we should add a regression to src/bin/scripts/
090_reindexdb.pl.

Regards,

--
Fabrízio de Royes Mello
Consultoria/Coaching PostgreSQL

Show quoted text

Timbira: http://www.timbira.com.br
Blog: http://fabriziomello.github.io
Linkedin: http://br.linkedin.com/in/fabriziomello
Twitter: http://twitter.com/fabriziomello
Github: http://github.com/fabriziomello

#64Sawada Masahiko
sawada.mshk@gmail.com
In reply to: Fabrízio de Royes Mello (#63)
1 attachment(s)
Re: Proposal : REINDEX xxx VERBOSE

On Sat, May 9, 2015 at 4:26 AM, Fabrízio de Royes Mello
<fabriziomello@gmail.com> wrote:

On Fri, May 8, 2015 at 4:23 PM, Fabrízio de Royes Mello
<fabriziomello@gmail.com> wrote:

On Thu, May 7, 2015 at 7:55 PM, Sawada Masahiko <sawada.mshk@gmail.com>
wrote:

On 5/7/15, Sawada Masahiko <sawada.mshk@gmail.com> wrote:

On Wed, May 6, 2015 at 5:42 AM, Robert Haas <robertmhaas@gmail.com
<javascript:;>> wrote:

On Tue, May 5, 2015 at 11:10 AM, Sawada Masahiko
<sawada.mshk@gmail.com

<javascript:;>> wrote:

On Fri, May 1, 2015 at 9:04 PM, Robert Haas <robertmhaas@gmail.com

<javascript:;>> wrote:

On Thu, Apr 30, 2015 at 11:05 PM, Sawada Masahiko
<sawada.mshk@gmail.com

<javascript:;>> wrote:

VACUUM has both syntax: with parentheses and without parentheses.
I think we should have both syntax for REINDEX like VACUUM does
because it would be pain to put parentheses whenever we want to do
REINDEX.
Are the parentheses optional in REINDEX command?

No. The unparenthesized VACUUM syntax was added back before we
realized that that kind of syntax is a terrible idea. It requires
every option to be a keyword, and those keywords have to be in a
fixed
order. I believe the intention is to keep the old VACUUM syntax
around for backward-compatibility, but not to extend it. Same for
EXPLAIN and COPY.

REINDEX will have only one option VERBOSE for now.
Even we're in a situation like that it's not clear to be added newly
additional option to REINDEX now, we should need to put parenthesis?

In my opinion, yes. The whole point of a flexible options syntax is
that we can add new options without changing the grammar. That
involves some compromise on the syntax, which doesn't bother me a
bit.
Our previous experiments with this for EXPLAIN and COPY and VACUUM
have worked out quite well, and I see no reason for pessimism here.

I agree that flexible option syntax does not need to change grammar
whenever we add new options.
Attached patch is changed based on your suggestion.
And the patch for reindexdb is also attached.
Please feedbacks.

Also I'm not sure that both implementation and documentation
regarding
VERBOSE option should be optional.

I don't know what this means.

Sorry for confusing you.
Please ignore this.

Sorry, I forgot attach files.

I applied the two patches to master and I got some errors when compile:

tab-complete.c: In function ‘psql_completion’:
tab-complete.c:3338:12: warning: left-hand operand of comma expression has
no effect [-Wunused-value]
{"TABLE", "INDEX", "SYSTEM", "SCHEMA", "DATABASE", NULL};
^
tab-complete.c:3338:21: warning: left-hand operand of comma expression has
no effect [-Wunused-value]
{"TABLE", "INDEX", "SYSTEM", "SCHEMA", "DATABASE", NULL};
^
tab-complete.c:3338:31: warning: left-hand operand of comma expression has
no effect [-Wunused-value]
{"TABLE", "INDEX", "SYSTEM", "SCHEMA", "DATABASE", NULL};
^
tab-complete.c:3338:41: warning: left-hand operand of comma expression has
no effect [-Wunused-value]
{"TABLE", "INDEX", "SYSTEM", "SCHEMA", "DATABASE", NULL};
^
tab-complete.c:3338:53: warning: left-hand operand of comma expression has
no effect [-Wunused-value]
{"TABLE", "INDEX", "SYSTEM", "SCHEMA", "DATABASE", NULL};
^
tab-complete.c:3338:5: warning: statement with no effect [-Wunused-value]
{"TABLE", "INDEX", "SYSTEM", "SCHEMA", "DATABASE", NULL};
^
tab-complete.c:3338:59: error: expected ‘;’ before ‘}’ token
{"TABLE", "INDEX", "SYSTEM", "SCHEMA", "DATABASE", NULL};
^
tab-complete.c:3340:22: error: ‘list_REINDEX’ undeclared (first use in
this function)
COMPLETE_WITH_LIST(list_REINDEX);
^
tab-complete.c:169:22: note: in definition of macro ‘COMPLETE_WITH_LIST’
completion_charpp = list; \
^
tab-complete.c:3340:22: note: each undeclared identifier is reported only
once for each function it appears in
COMPLETE_WITH_LIST(list_REINDEX);
^
tab-complete.c:169:22: note: in definition of macro ‘COMPLETE_WITH_LIST’
completion_charpp = list; \
^
make[3]: *** [tab-complete.o] Error 1
make[3]: *** Waiting for unfinished jobs....
make[2]: *** [install-psql-recurse] Error 2
make[2]: *** Waiting for unfinished jobs....
make[1]: *** [install-bin-recurse] Error 2
make: *** [install-src-recurse] Error 2

Looking at the code I think you remove one line accidentally from
tab-complete.c:

$ git diff src/bin/psql/tab-complete.c
diff --git a/src/bin/psql/tab-complete.c b/src/bin/psql/tab-complete.c
index 750e29d..55b0df5 100644
--- a/src/bin/psql/tab-complete.c
+++ b/src/bin/psql/tab-complete.c
@@ -3335,7 +3335,6 @@ psql_completion(const char *text, int start, int
end)
/* REINDEX */
else if (pg_strcasecmp(prev_wd, "REINDEX") == 0)
{
-       static const char *const list_REINDEX[] =
{"TABLE", "INDEX", "SYSTEM", "SCHEMA", "DATABASE", NULL};

COMPLETE_WITH_LIST(list_REINDEX);

The attached fix it and now seems good to me.

Just one last note. IMHO we should add a regression to
src/bin/scripts/090_reindexdb.pl.

Thank you for your patch!
(Sorry for attaching the patch still has compile error..)

- 000_reindex_verbose_v13.patch
Looks good to me.

- 001_reindexdb_verbose_option_v1.patch
I noticed a bug in reindexdb patch, so fixed version is attached.
The regression test for reindexdb is added as well.

Regards,

-------
Sawada Masahiko

Attachments:

001_reindexdb_verbose_option_v2.patchtext/x-diff; charset=US-ASCII; name=001_reindexdb_verbose_option_v2.patchDownload
diff --git a/src/bin/scripts/reindexdb.c b/src/bin/scripts/reindexdb.c
index 778d72a..547d0f8 100644
--- a/src/bin/scripts/reindexdb.c
+++ b/src/bin/scripts/reindexdb.c
@@ -18,16 +18,16 @@ static void reindex_one_database(const char *name, const char *dbname,
 					 const char *type, const char *host,
 					 const char *port, const char *username,
 					 enum trivalue prompt_password, const char *progname,
-					 bool echo);
+					 bool echo, bool verbose);
 static void reindex_all_databases(const char *maintenance_db,
 					  const char *host, const char *port,
 					  const char *username, enum trivalue prompt_password,
 					  const char *progname, bool echo,
-					  bool quiet);
+					  bool quiet, bool verbose);
 static void reindex_system_catalogs(const char *dbname,
 						const char *host, const char *port,
 						const char *username, enum trivalue prompt_password,
-						const char *progname, bool echo);
+						const char *progname, bool echo, bool verbose);
 static void help(const char *progname);
 
 int
@@ -47,6 +47,7 @@ main(int argc, char *argv[])
 		{"system", no_argument, NULL, 's'},
 		{"table", required_argument, NULL, 't'},
 		{"index", required_argument, NULL, 'i'},
+		{"verbose", no_argument, NULL, 'v'},
 		{"maintenance-db", required_argument, NULL, 2},
 		{NULL, 0, NULL, 0}
 	};
@@ -65,6 +66,7 @@ main(int argc, char *argv[])
 	bool		alldb = false;
 	bool		echo = false;
 	bool		quiet = false;
+	bool		verbose = false;
 	SimpleStringList indexes = {NULL, NULL};
 	SimpleStringList tables = {NULL, NULL};
 	SimpleStringList schemas = {NULL, NULL};
@@ -75,7 +77,7 @@ main(int argc, char *argv[])
 	handle_help_version_opts(argc, argv, "reindexdb", help);
 
 	/* process command-line options */
-	while ((c = getopt_long(argc, argv, "h:p:U:wWeqS:d:ast:i:", long_options, &optindex)) != -1)
+	while ((c = getopt_long(argc, argv, "h:p:U:wWeqS:d:ast:i:v", long_options, &optindex)) != -1)
 	{
 		switch (c)
 		{
@@ -118,6 +120,9 @@ main(int argc, char *argv[])
 			case 'i':
 				simple_string_list_append(&indexes, optarg);
 				break;
+			case 'v':
+				verbose = true;
+				break;
 			case 2:
 				maintenance_db = pg_strdup(optarg);
 				break;
@@ -176,7 +181,7 @@ main(int argc, char *argv[])
 		}
 
 		reindex_all_databases(maintenance_db, host, port, username,
-							  prompt_password, progname, echo, quiet);
+							  prompt_password, progname, echo, quiet, verbose);
 	}
 	else if (syscatalog)
 	{
@@ -207,7 +212,7 @@ main(int argc, char *argv[])
 		}
 
 		reindex_system_catalogs(dbname, host, port, username, prompt_password,
-								progname, echo);
+								progname, echo, verbose);
 	}
 	else
 	{
@@ -228,7 +233,7 @@ main(int argc, char *argv[])
 			for (cell = schemas.head; cell; cell = cell->next)
 			{
 				reindex_one_database(cell->val, dbname, "SCHEMA", host, port,
-								   username, prompt_password, progname, echo);
+								   username, prompt_password, progname, echo, verbose);
 			}
 		}
 
@@ -239,7 +244,7 @@ main(int argc, char *argv[])
 			for (cell = indexes.head; cell; cell = cell->next)
 			{
 				reindex_one_database(cell->val, dbname, "INDEX", host, port,
-								  username, prompt_password, progname, echo);
+								  username, prompt_password, progname, echo, verbose);
 			}
 		}
 		if (tables.head != NULL)
@@ -249,13 +254,13 @@ main(int argc, char *argv[])
 			for (cell = tables.head; cell; cell = cell->next)
 			{
 				reindex_one_database(cell->val, dbname, "TABLE", host, port,
-								  username, prompt_password, progname, echo);
+								  username, prompt_password, progname, echo, verbose);
 			}
 		}
 		/* reindex database only if neither index nor table nor schema is specified */
 		if (indexes.head == NULL && tables.head == NULL && schemas.head == NULL)
 			reindex_one_database(dbname, dbname, "DATABASE", host, port,
-								 username, prompt_password, progname, echo);
+								 username, prompt_password, progname, echo, verbose);
 	}
 
 	exit(0);
@@ -264,7 +269,8 @@ main(int argc, char *argv[])
 static void
 reindex_one_database(const char *name, const char *dbname, const char *type,
 					 const char *host, const char *port, const char *username,
-			  enum trivalue prompt_password, const char *progname, bool echo)
+					 enum trivalue prompt_password, const char *progname, bool echo,
+					 bool verbose)
 {
 	PQExpBufferData sql;
 
@@ -273,6 +279,10 @@ reindex_one_database(const char *name, const char *dbname, const char *type,
 	initPQExpBuffer(&sql);
 
 	appendPQExpBufferStr(&sql, "REINDEX");
+
+	if (verbose)
+		appendPQExpBufferStr(&sql, " (VERBOSE)");
+
 	if (strcmp(type, "TABLE") == 0)
 		appendPQExpBuffer(&sql, " TABLE %s", name);
 	else if (strcmp(type, "INDEX") == 0)
@@ -312,7 +322,7 @@ static void
 reindex_all_databases(const char *maintenance_db,
 					  const char *host, const char *port,
 					  const char *username, enum trivalue prompt_password,
-					  const char *progname, bool echo, bool quiet)
+					  const char *progname, bool echo, bool quiet, bool verbose)
 {
 	PGconn	   *conn;
 	PGresult   *result;
@@ -334,7 +344,7 @@ reindex_all_databases(const char *maintenance_db,
 		}
 
 		reindex_one_database(dbname, dbname, "DATABASE", host, port, username,
-							 prompt_password, progname, echo);
+							 prompt_password, progname, echo, verbose);
 	}
 
 	PQclear(result);
@@ -343,7 +353,7 @@ reindex_all_databases(const char *maintenance_db,
 static void
 reindex_system_catalogs(const char *dbname, const char *host, const char *port,
 						const char *username, enum trivalue prompt_password,
-						const char *progname, bool echo)
+						const char *progname, bool echo, bool verbose)
 {
 	PQExpBufferData sql;
 
@@ -351,7 +361,12 @@ reindex_system_catalogs(const char *dbname, const char *host, const char *port,
 
 	initPQExpBuffer(&sql);
 
-	appendPQExpBuffer(&sql, "REINDEX SYSTEM %s;", dbname);
+	appendPQExpBuffer(&sql, "REINDEX");
+
+	if (verbose)
+		appendPQExpBuffer(&sql, " (VERBOSE)");
+
+	appendPQExpBuffer(&sql, " SYSTEM %s;", dbname);
 
 	conn = connectDatabase(dbname, host, port, username, prompt_password,
 						   progname, false);
@@ -380,6 +395,7 @@ help(const char *progname)
 	printf(_("  -q, --quiet               don't write any messages\n"));
 	printf(_("  -s, --system              reindex system catalogs\n"));
 	printf(_("  -S, --schema=SCHEMA       recreate specific schema(s) only\n"));
+	printf(_("  -v, --verbose			  write a lot of output\n"));
 	printf(_("  -t, --table=TABLE         reindex specific table(s) only\n"));
 	printf(_("  -V, --version             output version information, then exit\n"));
 	printf(_("  -?, --help                show this help, then exit\n"));
diff --git a/src/bin/scripts/t/090_reindexdb.pl b/src/bin/scripts/t/090_reindexdb.pl
index d5bce43..42628c2 100644
--- a/src/bin/scripts/t/090_reindexdb.pl
+++ b/src/bin/scripts/t/090_reindexdb.pl
@@ -1,7 +1,7 @@
 use strict;
 use warnings;
 use TestLib;
-use Test::More tests => 18;
+use Test::More tests => 20;
 
 program_help_ok('reindexdb');
 program_version_ok('reindexdb');
@@ -35,3 +35,7 @@ issues_sql_like(
 	[ 'reindexdb', '-s', 'postgres' ],
 	qr/statement: REINDEX SYSTEM postgres;/,
 	'reindex system tables');
+issues_sql_like(
+	[ 'reindexdb', '-v', '-t', 'test1', 'postgres' ],
+	qr/statement: REINDEX \(VERBOSE\) TABLE test1;/,
+	'reindex with verbose output');
#65Sawada Masahiko
sawada.mshk@gmail.com
In reply to: Sawada Masahiko (#64)
1 attachment(s)
Re: Proposal : REINDEX xxx VERBOSE

On Sun, May 10, 2015 at 2:23 AM, Sawada Masahiko <sawada.mshk@gmail.com> wrote:

On Sat, May 9, 2015 at 4:26 AM, Fabrízio de Royes Mello
<fabriziomello@gmail.com> wrote:

On Fri, May 8, 2015 at 4:23 PM, Fabrízio de Royes Mello
<fabriziomello@gmail.com> wrote:

On Thu, May 7, 2015 at 7:55 PM, Sawada Masahiko <sawada.mshk@gmail.com>
wrote:

On 5/7/15, Sawada Masahiko <sawada.mshk@gmail.com> wrote:

On Wed, May 6, 2015 at 5:42 AM, Robert Haas <robertmhaas@gmail.com
<javascript:;>> wrote:

On Tue, May 5, 2015 at 11:10 AM, Sawada Masahiko
<sawada.mshk@gmail.com

<javascript:;>> wrote:

On Fri, May 1, 2015 at 9:04 PM, Robert Haas <robertmhaas@gmail.com

<javascript:;>> wrote:

On Thu, Apr 30, 2015 at 11:05 PM, Sawada Masahiko
<sawada.mshk@gmail.com

<javascript:;>> wrote:

VACUUM has both syntax: with parentheses and without parentheses.
I think we should have both syntax for REINDEX like VACUUM does
because it would be pain to put parentheses whenever we want to do
REINDEX.
Are the parentheses optional in REINDEX command?

No. The unparenthesized VACUUM syntax was added back before we
realized that that kind of syntax is a terrible idea. It requires
every option to be a keyword, and those keywords have to be in a
fixed
order. I believe the intention is to keep the old VACUUM syntax
around for backward-compatibility, but not to extend it. Same for
EXPLAIN and COPY.

REINDEX will have only one option VERBOSE for now.
Even we're in a situation like that it's not clear to be added newly
additional option to REINDEX now, we should need to put parenthesis?

In my opinion, yes. The whole point of a flexible options syntax is
that we can add new options without changing the grammar. That
involves some compromise on the syntax, which doesn't bother me a
bit.
Our previous experiments with this for EXPLAIN and COPY and VACUUM
have worked out quite well, and I see no reason for pessimism here.

I agree that flexible option syntax does not need to change grammar
whenever we add new options.
Attached patch is changed based on your suggestion.
And the patch for reindexdb is also attached.
Please feedbacks.

Also I'm not sure that both implementation and documentation
regarding
VERBOSE option should be optional.

I don't know what this means.

Sorry for confusing you.
Please ignore this.

Sorry, I forgot attach files.

I applied the two patches to master and I got some errors when compile:

tab-complete.c: In function ‘psql_completion’:
tab-complete.c:3338:12: warning: left-hand operand of comma expression has
no effect [-Wunused-value]
{"TABLE", "INDEX", "SYSTEM", "SCHEMA", "DATABASE", NULL};
^
tab-complete.c:3338:21: warning: left-hand operand of comma expression has
no effect [-Wunused-value]
{"TABLE", "INDEX", "SYSTEM", "SCHEMA", "DATABASE", NULL};
^
tab-complete.c:3338:31: warning: left-hand operand of comma expression has
no effect [-Wunused-value]
{"TABLE", "INDEX", "SYSTEM", "SCHEMA", "DATABASE", NULL};
^
tab-complete.c:3338:41: warning: left-hand operand of comma expression has
no effect [-Wunused-value]
{"TABLE", "INDEX", "SYSTEM", "SCHEMA", "DATABASE", NULL};
^
tab-complete.c:3338:53: warning: left-hand operand of comma expression has
no effect [-Wunused-value]
{"TABLE", "INDEX", "SYSTEM", "SCHEMA", "DATABASE", NULL};
^
tab-complete.c:3338:5: warning: statement with no effect [-Wunused-value]
{"TABLE", "INDEX", "SYSTEM", "SCHEMA", "DATABASE", NULL};
^
tab-complete.c:3338:59: error: expected ‘;’ before ‘}’ token
{"TABLE", "INDEX", "SYSTEM", "SCHEMA", "DATABASE", NULL};
^
tab-complete.c:3340:22: error: ‘list_REINDEX’ undeclared (first use in
this function)
COMPLETE_WITH_LIST(list_REINDEX);
^
tab-complete.c:169:22: note: in definition of macro ‘COMPLETE_WITH_LIST’
completion_charpp = list; \
^
tab-complete.c:3340:22: note: each undeclared identifier is reported only
once for each function it appears in
COMPLETE_WITH_LIST(list_REINDEX);
^
tab-complete.c:169:22: note: in definition of macro ‘COMPLETE_WITH_LIST’
completion_charpp = list; \
^
make[3]: *** [tab-complete.o] Error 1
make[3]: *** Waiting for unfinished jobs....
make[2]: *** [install-psql-recurse] Error 2
make[2]: *** Waiting for unfinished jobs....
make[1]: *** [install-bin-recurse] Error 2
make: *** [install-src-recurse] Error 2

Looking at the code I think you remove one line accidentally from
tab-complete.c:

$ git diff src/bin/psql/tab-complete.c
diff --git a/src/bin/psql/tab-complete.c b/src/bin/psql/tab-complete.c
index 750e29d..55b0df5 100644
--- a/src/bin/psql/tab-complete.c
+++ b/src/bin/psql/tab-complete.c
@@ -3335,7 +3335,6 @@ psql_completion(const char *text, int start, int
end)
/* REINDEX */
else if (pg_strcasecmp(prev_wd, "REINDEX") == 0)
{
-       static const char *const list_REINDEX[] =
{"TABLE", "INDEX", "SYSTEM", "SCHEMA", "DATABASE", NULL};

COMPLETE_WITH_LIST(list_REINDEX);

The attached fix it and now seems good to me.

Just one last note. IMHO we should add a regression to
src/bin/scripts/090_reindexdb.pl.

Thank you for your patch!
(Sorry for attaching the patch still has compile error..)

- 000_reindex_verbose_v13.patch
Looks good to me.

- 001_reindexdb_verbose_option_v1.patch
I noticed a bug in reindexdb patch, so fixed version is attached.
The regression test for reindexdb is added as well.

I forgot to add documentation patch.
The latest version patch is attached.
(the latest version of REINDEX VERBOSE patch is v13 Fabrizio attached)

Regards,

-------
Sawada Masahiko

Attachments:

001_reindexdb_verbose_option_v3.patchtext/x-diff; charset=US-ASCII; name=001_reindexdb_verbose_option_v3.patchDownload
diff --git a/doc/src/sgml/ref/reindexdb.sgml b/doc/src/sgml/ref/reindexdb.sgml
index b5b449c..951dbbb 100644
--- a/doc/src/sgml/ref/reindexdb.sgml
+++ b/doc/src/sgml/ref/reindexdb.sgml
@@ -24,6 +24,13 @@ PostgreSQL documentation
    <command>reindexdb</command>
    <arg rep="repeat"><replaceable>connection-option</replaceable></arg>
 
+   <arg choice="opt">
+    <group choice="plain">
+     <arg choice="plain"><option>--verbose</option></arg>
+     <arg choice="plain"><option>-v</option></arg>
+    </group>
+   </arg>
+   
    <arg choice="plain" rep="repeat">
     <arg choice="opt">
      <group choice="plain">
@@ -60,6 +67,14 @@ PostgreSQL documentation
   <cmdsynopsis>
    <command>reindexdb</command>
    <arg rep="repeat"><replaceable>connection-option</replaceable></arg>
+
+   <arg choice="opt">
+    <group choice="plain">
+     <arg choice="plain"><option>--verbose</option></arg>
+     <arg choice="plain"><option>-v</option></arg>
+    </group>
+   </arg>
+
    <group choice="plain">
     <arg choice="plain"><option>--all</option></arg>
     <arg choice="plain"><option>-a</option></arg>
@@ -69,6 +84,14 @@ PostgreSQL documentation
   <cmdsynopsis>
    <command>reindexdb</command>
    <arg rep="repeat"><replaceable>connection-option</replaceable></arg>
+
+   <arg choice="opt">
+    <group choice="plain">
+     <arg choice="plain"><option>--verbose</option></arg>
+     <arg choice="plain"><option>-v</option></arg>
+    </group>
+   </arg>
+
    <group choice="plain">
     <arg choice="plain"><option>--system</option></arg>
     <arg choice="plain"><option>-s</option></arg>
@@ -196,6 +219,16 @@ PostgreSQL documentation
      </varlistentry>
 
     <varlistentry>
+     <term><option>-v</></term>
+     <term><option>--verbose</></term>
+     <listitem>
+      <para>
+       Print detailed information during processing.
+      </para>
+     </listitem>
+    </varlistentry>
+
+    <varlistentry>
       <term><option>-V</></term>
       <term><option>--version</></term>
       <listitem>
diff --git a/src/bin/scripts/reindexdb.c b/src/bin/scripts/reindexdb.c
index 778d72a..547d0f8 100644
--- a/src/bin/scripts/reindexdb.c
+++ b/src/bin/scripts/reindexdb.c
@@ -18,16 +18,16 @@ static void reindex_one_database(const char *name, const char *dbname,
 					 const char *type, const char *host,
 					 const char *port, const char *username,
 					 enum trivalue prompt_password, const char *progname,
-					 bool echo);
+					 bool echo, bool verbose);
 static void reindex_all_databases(const char *maintenance_db,
 					  const char *host, const char *port,
 					  const char *username, enum trivalue prompt_password,
 					  const char *progname, bool echo,
-					  bool quiet);
+					  bool quiet, bool verbose);
 static void reindex_system_catalogs(const char *dbname,
 						const char *host, const char *port,
 						const char *username, enum trivalue prompt_password,
-						const char *progname, bool echo);
+						const char *progname, bool echo, bool verbose);
 static void help(const char *progname);
 
 int
@@ -47,6 +47,7 @@ main(int argc, char *argv[])
 		{"system", no_argument, NULL, 's'},
 		{"table", required_argument, NULL, 't'},
 		{"index", required_argument, NULL, 'i'},
+		{"verbose", no_argument, NULL, 'v'},
 		{"maintenance-db", required_argument, NULL, 2},
 		{NULL, 0, NULL, 0}
 	};
@@ -65,6 +66,7 @@ main(int argc, char *argv[])
 	bool		alldb = false;
 	bool		echo = false;
 	bool		quiet = false;
+	bool		verbose = false;
 	SimpleStringList indexes = {NULL, NULL};
 	SimpleStringList tables = {NULL, NULL};
 	SimpleStringList schemas = {NULL, NULL};
@@ -75,7 +77,7 @@ main(int argc, char *argv[])
 	handle_help_version_opts(argc, argv, "reindexdb", help);
 
 	/* process command-line options */
-	while ((c = getopt_long(argc, argv, "h:p:U:wWeqS:d:ast:i:", long_options, &optindex)) != -1)
+	while ((c = getopt_long(argc, argv, "h:p:U:wWeqS:d:ast:i:v", long_options, &optindex)) != -1)
 	{
 		switch (c)
 		{
@@ -118,6 +120,9 @@ main(int argc, char *argv[])
 			case 'i':
 				simple_string_list_append(&indexes, optarg);
 				break;
+			case 'v':
+				verbose = true;
+				break;
 			case 2:
 				maintenance_db = pg_strdup(optarg);
 				break;
@@ -176,7 +181,7 @@ main(int argc, char *argv[])
 		}
 
 		reindex_all_databases(maintenance_db, host, port, username,
-							  prompt_password, progname, echo, quiet);
+							  prompt_password, progname, echo, quiet, verbose);
 	}
 	else if (syscatalog)
 	{
@@ -207,7 +212,7 @@ main(int argc, char *argv[])
 		}
 
 		reindex_system_catalogs(dbname, host, port, username, prompt_password,
-								progname, echo);
+								progname, echo, verbose);
 	}
 	else
 	{
@@ -228,7 +233,7 @@ main(int argc, char *argv[])
 			for (cell = schemas.head; cell; cell = cell->next)
 			{
 				reindex_one_database(cell->val, dbname, "SCHEMA", host, port,
-								   username, prompt_password, progname, echo);
+								   username, prompt_password, progname, echo, verbose);
 			}
 		}
 
@@ -239,7 +244,7 @@ main(int argc, char *argv[])
 			for (cell = indexes.head; cell; cell = cell->next)
 			{
 				reindex_one_database(cell->val, dbname, "INDEX", host, port,
-								  username, prompt_password, progname, echo);
+								  username, prompt_password, progname, echo, verbose);
 			}
 		}
 		if (tables.head != NULL)
@@ -249,13 +254,13 @@ main(int argc, char *argv[])
 			for (cell = tables.head; cell; cell = cell->next)
 			{
 				reindex_one_database(cell->val, dbname, "TABLE", host, port,
-								  username, prompt_password, progname, echo);
+								  username, prompt_password, progname, echo, verbose);
 			}
 		}
 		/* reindex database only if neither index nor table nor schema is specified */
 		if (indexes.head == NULL && tables.head == NULL && schemas.head == NULL)
 			reindex_one_database(dbname, dbname, "DATABASE", host, port,
-								 username, prompt_password, progname, echo);
+								 username, prompt_password, progname, echo, verbose);
 	}
 
 	exit(0);
@@ -264,7 +269,8 @@ main(int argc, char *argv[])
 static void
 reindex_one_database(const char *name, const char *dbname, const char *type,
 					 const char *host, const char *port, const char *username,
-			  enum trivalue prompt_password, const char *progname, bool echo)
+					 enum trivalue prompt_password, const char *progname, bool echo,
+					 bool verbose)
 {
 	PQExpBufferData sql;
 
@@ -273,6 +279,10 @@ reindex_one_database(const char *name, const char *dbname, const char *type,
 	initPQExpBuffer(&sql);
 
 	appendPQExpBufferStr(&sql, "REINDEX");
+
+	if (verbose)
+		appendPQExpBufferStr(&sql, " (VERBOSE)");
+
 	if (strcmp(type, "TABLE") == 0)
 		appendPQExpBuffer(&sql, " TABLE %s", name);
 	else if (strcmp(type, "INDEX") == 0)
@@ -312,7 +322,7 @@ static void
 reindex_all_databases(const char *maintenance_db,
 					  const char *host, const char *port,
 					  const char *username, enum trivalue prompt_password,
-					  const char *progname, bool echo, bool quiet)
+					  const char *progname, bool echo, bool quiet, bool verbose)
 {
 	PGconn	   *conn;
 	PGresult   *result;
@@ -334,7 +344,7 @@ reindex_all_databases(const char *maintenance_db,
 		}
 
 		reindex_one_database(dbname, dbname, "DATABASE", host, port, username,
-							 prompt_password, progname, echo);
+							 prompt_password, progname, echo, verbose);
 	}
 
 	PQclear(result);
@@ -343,7 +353,7 @@ reindex_all_databases(const char *maintenance_db,
 static void
 reindex_system_catalogs(const char *dbname, const char *host, const char *port,
 						const char *username, enum trivalue prompt_password,
-						const char *progname, bool echo)
+						const char *progname, bool echo, bool verbose)
 {
 	PQExpBufferData sql;
 
@@ -351,7 +361,12 @@ reindex_system_catalogs(const char *dbname, const char *host, const char *port,
 
 	initPQExpBuffer(&sql);
 
-	appendPQExpBuffer(&sql, "REINDEX SYSTEM %s;", dbname);
+	appendPQExpBuffer(&sql, "REINDEX");
+
+	if (verbose)
+		appendPQExpBuffer(&sql, " (VERBOSE)");
+
+	appendPQExpBuffer(&sql, " SYSTEM %s;", dbname);
 
 	conn = connectDatabase(dbname, host, port, username, prompt_password,
 						   progname, false);
@@ -380,6 +395,7 @@ help(const char *progname)
 	printf(_("  -q, --quiet               don't write any messages\n"));
 	printf(_("  -s, --system              reindex system catalogs\n"));
 	printf(_("  -S, --schema=SCHEMA       recreate specific schema(s) only\n"));
+	printf(_("  -v, --verbose			  write a lot of output\n"));
 	printf(_("  -t, --table=TABLE         reindex specific table(s) only\n"));
 	printf(_("  -V, --version             output version information, then exit\n"));
 	printf(_("  -?, --help                show this help, then exit\n"));
diff --git a/src/bin/scripts/t/090_reindexdb.pl b/src/bin/scripts/t/090_reindexdb.pl
index d5bce43..42628c2 100644
--- a/src/bin/scripts/t/090_reindexdb.pl
+++ b/src/bin/scripts/t/090_reindexdb.pl
@@ -1,7 +1,7 @@
 use strict;
 use warnings;
 use TestLib;
-use Test::More tests => 18;
+use Test::More tests => 20;
 
 program_help_ok('reindexdb');
 program_version_ok('reindexdb');
@@ -35,3 +35,7 @@ issues_sql_like(
 	[ 'reindexdb', '-s', 'postgres' ],
 	qr/statement: REINDEX SYSTEM postgres;/,
 	'reindex system tables');
+issues_sql_like(
+	[ 'reindexdb', '-v', '-t', 'test1', 'postgres' ],
+	qr/statement: REINDEX \(VERBOSE\) TABLE test1;/,
+	'reindex with verbose output');
#66Robert Haas
robertmhaas@gmail.com
In reply to: Sawada Masahiko (#61)
Re: Proposal : REINDEX xxx VERBOSE

On Thu, May 7, 2015 at 6:55 PM, Sawada Masahiko <sawada.mshk@gmail.com> wrote:

Sorry, I forgot attach files.

Review comments:

- Customarily we use int, rather than uint8, for flags variables. I
think we should do that here also.

- reindex_index() emits a log message either way, but at DEBUG2 level
without VERBOSE and at the INFO level with it. I think we should skip
it altogether without VERBOSE. i.e. if (options & REINDEXOPT_VERBOSE)
ereport(...)

- The errmsg() in that function should not end with a period.

- The 000 patch makes a pointless whitespace change to tab-complete.c.

- Instead of an enumerated type (ReindexOption) just use #define to
define the flag value.

Apart from those fairly minor issues, I think this looks pretty solid.

--
Robert Haas
EnterpriseDB: http://www.enterprisedb.com
The Enterprise PostgreSQL Company

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

#67Sawada Masahiko
sawada.mshk@gmail.com
In reply to: Robert Haas (#66)
1 attachment(s)
Re: Proposal : REINDEX xxx VERBOSE

On Thu, May 14, 2015 at 12:28 AM, Robert Haas <robertmhaas@gmail.com> wrote:

On Thu, May 7, 2015 at 6:55 PM, Sawada Masahiko <sawada.mshk@gmail.com> wrote:

Sorry, I forgot attach files.

Review comments:

- Customarily we use int, rather than uint8, for flags variables. I
think we should do that here also.

- reindex_index() emits a log message either way, but at DEBUG2 level
without VERBOSE and at the INFO level with it. I think we should skip
it altogether without VERBOSE. i.e. if (options & REINDEXOPT_VERBOSE)
ereport(...)

- The errmsg() in that function should not end with a period.

- The 000 patch makes a pointless whitespace change to tab-complete.c.

- Instead of an enumerated type (ReindexOption) just use #define to
define the flag value.

Apart from those fairly minor issues, I think this looks pretty solid.

Thank you for reviwing..
All fixed.

Regards,

-------
Sawada Masahiko

Attachments:

000_reindex_verbose_v14.patchapplication/octet-stream; name=000_reindex_verbose_v14.patchDownload
diff --git a/doc/src/sgml/ref/reindex.sgml b/doc/src/sgml/ref/reindex.sgml
index 998340c..703b760 100644
--- a/doc/src/sgml/ref/reindex.sgml
+++ b/doc/src/sgml/ref/reindex.sgml
@@ -21,7 +21,7 @@ PostgreSQL documentation
 
  <refsynopsisdiv>
 <synopsis>
-REINDEX { INDEX | TABLE | SCHEMA | DATABASE | SYSTEM } <replaceable class="PARAMETER">name</replaceable>
+REINDEX [ ( { VERBOSE } [, ...] ) ] { INDEX | TABLE | SCHEMA | DATABASE | SYSTEM } <replaceable class="PARAMETER">name</replaceable>
 </synopsis>
  </refsynopsisdiv>
 
@@ -150,6 +150,15 @@ 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>
   </variablelist>
  </refsect1>
 
diff --git a/src/backend/catalog/index.c b/src/backend/catalog/index.c
index 8c8a9ea..bac9fbe 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"
@@ -3184,13 +3185,17 @@ 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,
+				int options)
 {
 	Relation	iRel,
 				heapRelation;
 	Oid			heapId;
 	IndexInfo  *indexInfo;
 	volatile bool skipped_constraint = false;
+	PGRUsage	ru0;
+
+	pg_rusage_init(&ru0);
 
 	/*
 	 * Open and lock the parent heap relation.  ShareLock is sufficient since
@@ -3334,6 +3339,14 @@ reindex_index(Oid indexId, bool skip_constraint_checks, char persistence)
 		heap_close(pg_index, RowExclusiveLock);
 	}
 
+	/* Log what we did */
+	if (options & REINDEXOPT_VERBOSE)
+		ereport(INFO,
+				(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);
@@ -3375,7 +3388,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, int options)
 {
 	Relation	rel;
 	Oid			toast_relid;
@@ -3466,7 +3479,7 @@ reindex_relation(Oid relid, int flags)
 				RelationSetIndexList(rel, doneIndexes, InvalidOid);
 
 			reindex_index(indexOid, !(flags & REINDEX_REL_CHECK_CONSTRAINTS),
-						  persistence);
+						  persistence, options);
 
 			CommandCounterIncrement();
 
@@ -3501,7 +3514,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, options);
 
 	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 351d48e..d056e85 100644
--- a/src/backend/commands/indexcmds.c
+++ b/src/backend/commands/indexcmds.c
@@ -1681,7 +1681,7 @@ ChooseIndexColumnNames(List *indexElems)
  *		Recreate a specific index.
  */
 Oid
-ReindexIndex(RangeVar *indexRelation)
+ReindexIndex(RangeVar *indexRelation, int options)
 {
 	Oid			indOid;
 	Oid			heapOid = InvalidOid;
@@ -1706,7 +1706,7 @@ ReindexIndex(RangeVar *indexRelation)
 	persistence = irel->rd_rel->relpersistence;
 	index_close(irel, NoLock);
 
-	reindex_index(indOid, false, persistence);
+	reindex_index(indOid, false, persistence, options);
 
 	return indOid;
 }
@@ -1775,7 +1775,7 @@ RangeVarCallbackForReindexIndex(const RangeVar *relation,
  *		Recreate all indexes of a table (and of its toast table, if any)
  */
 Oid
-ReindexTable(RangeVar *relation)
+ReindexTable(RangeVar *relation, int options)
 {
 	Oid			heapOid;
 
@@ -1785,7 +1785,8 @@ ReindexTable(RangeVar *relation)
 
 	if (!reindex_relation(heapOid,
 						  REINDEX_REL_PROCESS_TOAST |
-						  REINDEX_REL_CHECK_CONSTRAINTS))
+						  REINDEX_REL_CHECK_CONSTRAINTS,
+						  options))
 		ereport(NOTICE,
 				(errmsg("table \"%s\" has no indexes",
 						relation->relname)));
@@ -1802,7 +1803,8 @@ 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,
+					  int options)
 {
 	Oid			objectOid;
 	Relation	relationRelation;
@@ -1938,11 +1940,13 @@ 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",
-							get_namespace_name(get_rel_namespace(relid)),
-							get_rel_name(relid))));
+							 REINDEX_REL_CHECK_CONSTRAINTS,
+							 options))
+			if (options & REINDEXOPT_VERBOSE)
+				ereport(INFO,
+						(errmsg("indexes of table \"%s.%s\" were reindexed",
+								get_namespace_name(get_rel_namespace(relid)),
+								get_rel_name(relid))));
 		PopActiveSnapshot();
 		CommitTransactionCommand();
 	}
diff --git a/src/backend/commands/tablecmds.c b/src/backend/commands/tablecmds.c
index 0a6b069..4c756a7 100644
--- a/src/backend/commands/tablecmds.c
+++ b/src/backend/commands/tablecmds.c
@@ -1234,7 +1234,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/nodes/copyfuncs.c b/src/backend/nodes/copyfuncs.c
index 76b63af..25839ee 100644
--- a/src/backend/nodes/copyfuncs.c
+++ b/src/backend/nodes/copyfuncs.c
@@ -3856,6 +3856,7 @@ _copyReindexStmt(const ReindexStmt *from)
 	COPY_SCALAR_FIELD(kind);
 	COPY_NODE_FIELD(relation);
 	COPY_STRING_FIELD(name);
+	COPY_SCALAR_FIELD(options);
 
 	return newnode;
 }
diff --git a/src/backend/nodes/equalfuncs.c b/src/backend/nodes/equalfuncs.c
index e032142..c4b3615 100644
--- a/src/backend/nodes/equalfuncs.c
+++ b/src/backend/nodes/equalfuncs.c
@@ -1935,6 +1935,7 @@ _equalReindexStmt(const ReindexStmt *a, const ReindexStmt *b)
 	COMPARE_SCALAR_FIELD(kind);
 	COMPARE_NODE_FIELD(relation);
 	COMPARE_STRING_FIELD(name);
+	COMPARE_SCALAR_FIELD(options);
 
 	return true;
 }
diff --git a/src/backend/parser/gram.y b/src/backend/parser/gram.y
index e71d926..2dce878 100644
--- a/src/backend/parser/gram.y
+++ b/src/backend/parser/gram.y
@@ -463,6 +463,10 @@ 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 <ival>	reindex_target_type reindex_target_multitable
+%type <ival>	reindex_option_list reindex_option_elem
+
 %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
@@ -7387,52 +7391,63 @@ DropTransformStmt: DROP TRANSFORM opt_if_exists FOR Typename LANGUAGE name opt_d
  *
  *		QUERY:
  *
- *		REINDEX type <name>
+ *		REINDEX [ (options) ] type <name>
  *****************************************************************************/
 
 ReindexStmt:
-			REINDEX INDEX qualified_name
+			REINDEX reindex_target_type qualified_name
 				{
 					ReindexStmt *n = makeNode(ReindexStmt);
-					n->kind = REINDEX_OBJECT_INDEX;
+					n->kind = $2;
 					n->relation = $3;
 					n->name = NULL;
+					n->options = 0;
 					$$ = (Node *)n;
 				}
-			| REINDEX TABLE qualified_name
+			| REINDEX reindex_target_multitable name
 				{
 					ReindexStmt *n = makeNode(ReindexStmt);
-					n->kind = REINDEX_OBJECT_TABLE;
-					n->relation = $3;
-					n->name = NULL;
-					$$ = (Node *)n;
-				}
-			| REINDEX SCHEMA name
-				{
-					ReindexStmt *n = makeNode(ReindexStmt);
-					n->kind = REINDEX_OBJECT_SCHEMA;
+					n->kind = $2;
 					n->name = $3;
 					n->relation = NULL;
+					n->options = 0;
 					$$ = (Node *)n;
 				}
-			| REINDEX SYSTEM_P name
+			| REINDEX '(' reindex_option_list ')' reindex_target_type qualified_name
 				{
 					ReindexStmt *n = makeNode(ReindexStmt);
-					n->kind = REINDEX_OBJECT_SYSTEM;
-					n->name = $3;
-					n->relation = NULL;
+					n->kind = $5;
+					n->relation = $6;
+					n->name = NULL;
+					n->options = $3;
 					$$ = (Node *)n;
 				}
-			| REINDEX DATABASE name
+			| REINDEX '(' reindex_option_list ')' reindex_target_multitable name
 				{
 					ReindexStmt *n = makeNode(ReindexStmt);
-					n->kind = REINDEX_OBJECT_DATABASE;
-					n->name = $3;
+					n->kind = $5;
+					n->name = $6;
 					n->relation = NULL;
+					n->options = $3;
 					$$ = (Node *)n;
 				}
 		;
-
+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; }
+		;
+reindex_option_list:
+			reindex_option_elem								{ $$ = $1; }
+			| reindex_option_list ',' reindex_option_elem	{ $$ = $1 | $3; }
+		;
+reindex_option_elem:
+			VERBOSE	{ $$ = REINDEXOPT_VERBOSE; }
+		;
 
 /*****************************************************************************
  *
diff --git a/src/backend/tcop/utility.c b/src/backend/tcop/utility.c
index 78bfd34..a95eff1 100644
--- a/src/backend/tcop/utility.c
+++ b/src/backend/tcop/utility.c
@@ -762,10 +762,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:
@@ -781,7 +781,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/include/catalog/index.h b/src/include/catalog/index.h
index 06f3820..e961d37 100644
--- a/src/include/catalog/index.h
+++ b/src/include/catalog/index.h
@@ -115,7 +115,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, int options);
 
 /* Flag bits for reindex_relation(): */
 #define REINDEX_REL_PROCESS_TOAST			0x01
@@ -124,7 +124,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, int options);
 
 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 c3a1748..d625725 100644
--- a/src/include/commands/defrem.h
+++ b/src/include/commands/defrem.h
@@ -29,9 +29,10 @@ 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, int options);
+extern Oid	ReindexTable(RangeVar *relation, int options);
+extern void ReindexMultipleTables(const char *objectName, ReindexObjectType objectKind,
+								  int 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 556c1c5..1500ee6 100644
--- a/src/include/nodes/parsenodes.h
+++ b/src/include/nodes/parsenodes.h
@@ -2782,6 +2782,10 @@ typedef struct ConstraintsSetStmt
  *		REINDEX Statement
  * ----------------------
  */
+
+/* Reindex options */
+#define REINDEXOPT_VERBOSE 1 << 0 /* print progress info */
+
 typedef enum ReindexObjectType
 {
 	REINDEX_OBJECT_INDEX,	/* index */
@@ -2797,6 +2801,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 */
+	int			options;		/* ReindexOption flags*/
 } ReindexStmt;
 
 /* ----------------------
diff --git a/src/test/regress/expected/create_index.out b/src/test/regress/expected/create_index.out
index abe64e5..cba11b4 100644
--- a/src/test/regress/expected/create_index.out
+++ b/src/test/regress/expected/create_index.out
@@ -2832,6 +2832,14 @@ explain (costs off)
 (2 rows)
 
 --
+-- REINDEX (VERBOSE)
+--
+CREATE TABLE reindex_verbose(id integer primary key);
+\set VERBOSITY terse
+REINDEX (VERBOSE) TABLE reindex_verbose;
+INFO:  index "reindex_verbose_pkey" was reindexed.
+DROP TABLE reindex_verbose;
+--
 -- REINDEX SCHEMA
 --
 REINDEX SCHEMA schema_to_reindex; -- failure, schema does not exist
diff --git a/src/test/regress/sql/create_index.sql b/src/test/regress/sql/create_index.sql
index f779fa0..6333a30 100644
--- a/src/test/regress/sql/create_index.sql
+++ b/src/test/regress/sql/create_index.sql
@@ -966,6 +966,14 @@ explain (costs off)
   select * from tenk1 where (thousand, tenthous) in ((1,1001), (null,null));
 
 --
+-- REINDEX (VERBOSE)
+--
+CREATE TABLE reindex_verbose(id integer primary key);
+\set VERBOSITY terse
+REINDEX (VERBOSE) TABLE reindex_verbose;
+DROP TABLE reindex_verbose;
+
+--
 -- REINDEX SCHEMA
 --
 REINDEX SCHEMA schema_to_reindex; -- failure, schema does not exist
#68Alvaro Herrera
alvherre@2ndquadrant.com
In reply to: Sawada Masahiko (#67)
Re: Proposal : REINDEX xxx VERBOSE

Uh, are we really using INFO to log this? I thought that was a
discouraged level to use anymore. Why not NOTICE?

Also, when multiple tables are reindexed, do we emit lines for each
index, or only for each table? If we're going to emit a line for each
index in the single-table mode, it seems more sensible to do the same
for the multi-table forms also.

--
�lvaro Herrera http://www.2ndQuadrant.com/
PostgreSQL Development, 24x7 Support, Remote DBA, Training & Services

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

#69Sawada Masahiko
sawada.mshk@gmail.com
In reply to: Alvaro Herrera (#68)
1 attachment(s)
Re: Proposal : REINDEX xxx VERBOSE

On Thu, May 14, 2015 at 3:10 AM, Alvaro Herrera
<alvherre@2ndquadrant.com> wrote:

Uh, are we really using INFO to log this? I thought that was a
discouraged level to use anymore. Why not NOTICE?

I think it should be INFO level because it is a information of REINDEX
command,such as progress of itself, CPU usage and so on. it would be
overkill if we output the logs as NOTICE level, and verbose outputs of
other maintenance command are emitted as INFO level.

Also, when multiple tables are reindexed, do we emit lines for each
index, or only for each table? If we're going to emit a line for each
index in the single-table mode, it seems more sensible to do the same
for the multi-table forms also.

I agree that we emit lines for each table when we do reindex multiple tables.
The latest patch is attached.

Regards,

-------
Sawada Masahiko

Attachments:

000_reindex_verbose_v15.patchapplication/octet-stream; name=000_reindex_verbose_v15.patchDownload
diff --git a/doc/src/sgml/ref/reindex.sgml b/doc/src/sgml/ref/reindex.sgml
index 998340c..703b760 100644
--- a/doc/src/sgml/ref/reindex.sgml
+++ b/doc/src/sgml/ref/reindex.sgml
@@ -21,7 +21,7 @@ PostgreSQL documentation
 
  <refsynopsisdiv>
 <synopsis>
-REINDEX { INDEX | TABLE | SCHEMA | DATABASE | SYSTEM } <replaceable class="PARAMETER">name</replaceable>
+REINDEX [ ( { VERBOSE } [, ...] ) ] { INDEX | TABLE | SCHEMA | DATABASE | SYSTEM } <replaceable class="PARAMETER">name</replaceable>
 </synopsis>
  </refsynopsisdiv>
 
@@ -150,6 +150,15 @@ 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>
   </variablelist>
  </refsect1>
 
diff --git a/src/backend/catalog/index.c b/src/backend/catalog/index.c
index 8c8a9ea..879d5a2 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"
@@ -3184,13 +3185,17 @@ 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,
+				int options)
 {
 	Relation	iRel,
 				heapRelation;
 	Oid			heapId;
 	IndexInfo  *indexInfo;
 	volatile bool skipped_constraint = false;
+	PGRUsage	ru0;
+
+	pg_rusage_init(&ru0);
 
 	/*
 	 * Open and lock the parent heap relation.  ShareLock is sufficient since
@@ -3334,6 +3339,15 @@ reindex_index(Oid indexId, bool skip_constraint_checks, char persistence)
 		heap_close(pg_index, RowExclusiveLock);
 	}
 
+	/* Log what we did */
+	if (options & REINDEXOPT_VERBOSE)
+		ereport(INFO,
+				(errmsg("index \"%s.%s\" was reindexed",
+						get_namespace_name(get_rel_namespace(indexId)),
+						get_rel_name(indexId)),
+				 errdetail("%s.",
+						   pg_rusage_show(&ru0))));
+
 	/* Close rels, but keep locks */
 	index_close(iRel, NoLock);
 	heap_close(heapRelation, NoLock);
@@ -3375,7 +3389,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, int options)
 {
 	Relation	rel;
 	Oid			toast_relid;
@@ -3466,7 +3480,7 @@ reindex_relation(Oid relid, int flags)
 				RelationSetIndexList(rel, doneIndexes, InvalidOid);
 
 			reindex_index(indexOid, !(flags & REINDEX_REL_CHECK_CONSTRAINTS),
-						  persistence);
+						  persistence, options);
 
 			CommandCounterIncrement();
 
@@ -3501,7 +3515,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, options);
 
 	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 351d48e..e089484 100644
--- a/src/backend/commands/indexcmds.c
+++ b/src/backend/commands/indexcmds.c
@@ -47,6 +47,7 @@
 #include "utils/inval.h"
 #include "utils/lsyscache.h"
 #include "utils/memutils.h"
+#include "utils/pg_rusage.h"
 #include "utils/snapmgr.h"
 #include "utils/syscache.h"
 #include "utils/tqual.h"
@@ -1681,7 +1682,7 @@ ChooseIndexColumnNames(List *indexElems)
  *		Recreate a specific index.
  */
 Oid
-ReindexIndex(RangeVar *indexRelation)
+ReindexIndex(RangeVar *indexRelation, int options)
 {
 	Oid			indOid;
 	Oid			heapOid = InvalidOid;
@@ -1706,7 +1707,7 @@ ReindexIndex(RangeVar *indexRelation)
 	persistence = irel->rd_rel->relpersistence;
 	index_close(irel, NoLock);
 
-	reindex_index(indOid, false, persistence);
+	reindex_index(indOid, false, persistence, options);
 
 	return indOid;
 }
@@ -1775,7 +1776,7 @@ RangeVarCallbackForReindexIndex(const RangeVar *relation,
  *		Recreate all indexes of a table (and of its toast table, if any)
  */
 Oid
-ReindexTable(RangeVar *relation)
+ReindexTable(RangeVar *relation, int options)
 {
 	Oid			heapOid;
 
@@ -1785,7 +1786,8 @@ ReindexTable(RangeVar *relation)
 
 	if (!reindex_relation(heapOid,
 						  REINDEX_REL_PROCESS_TOAST |
-						  REINDEX_REL_CHECK_CONSTRAINTS))
+						  REINDEX_REL_CHECK_CONSTRAINTS,
+						  options))
 		ereport(NOTICE,
 				(errmsg("table \"%s\" has no indexes",
 						relation->relname)));
@@ -1802,7 +1804,8 @@ 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,
+					  int options)
 {
 	Oid			objectOid;
 	Relation	relationRelation;
@@ -1932,17 +1935,28 @@ ReindexMultipleTables(const char *objectName, ReindexObjectType objectKind)
 	foreach(l, relids)
 	{
 		Oid			relid = lfirst_oid(l);
+		PGRUsage	ru0;
 
 		StartTransactionCommand();
 		/* functions in indexes may want a snapshot set */
 		PushActiveSnapshot(GetTransactionSnapshot());
+
+		pg_rusage_init(&ru0);
+
 		if (reindex_relation(relid,
 							 REINDEX_REL_PROCESS_TOAST |
-							 REINDEX_REL_CHECK_CONSTRAINTS))
-			ereport(DEBUG1,
-					(errmsg("table \"%s.%s\" was reindexed",
-							get_namespace_name(get_rel_namespace(relid)),
-							get_rel_name(relid))));
+							 REINDEX_REL_CHECK_CONSTRAINTS,
+							 0))
+
+
+			if (options & REINDEXOPT_VERBOSE)
+				ereport(INFO,
+						(errmsg("indexes of table \"%s.%s\" were reindexed",
+								get_namespace_name(get_rel_namespace(relid)),
+								get_rel_name(relid)),
+						 errdetail("%s.",
+								   pg_rusage_show(&ru0))));
+
 		PopActiveSnapshot();
 		CommitTransactionCommand();
 	}
diff --git a/src/backend/commands/tablecmds.c b/src/backend/commands/tablecmds.c
index 0a6b069..4c756a7 100644
--- a/src/backend/commands/tablecmds.c
+++ b/src/backend/commands/tablecmds.c
@@ -1234,7 +1234,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/nodes/copyfuncs.c b/src/backend/nodes/copyfuncs.c
index 76b63af..25839ee 100644
--- a/src/backend/nodes/copyfuncs.c
+++ b/src/backend/nodes/copyfuncs.c
@@ -3856,6 +3856,7 @@ _copyReindexStmt(const ReindexStmt *from)
 	COPY_SCALAR_FIELD(kind);
 	COPY_NODE_FIELD(relation);
 	COPY_STRING_FIELD(name);
+	COPY_SCALAR_FIELD(options);
 
 	return newnode;
 }
diff --git a/src/backend/nodes/equalfuncs.c b/src/backend/nodes/equalfuncs.c
index e032142..c4b3615 100644
--- a/src/backend/nodes/equalfuncs.c
+++ b/src/backend/nodes/equalfuncs.c
@@ -1935,6 +1935,7 @@ _equalReindexStmt(const ReindexStmt *a, const ReindexStmt *b)
 	COMPARE_SCALAR_FIELD(kind);
 	COMPARE_NODE_FIELD(relation);
 	COMPARE_STRING_FIELD(name);
+	COMPARE_SCALAR_FIELD(options);
 
 	return true;
 }
diff --git a/src/backend/parser/gram.y b/src/backend/parser/gram.y
index e71d926..2dce878 100644
--- a/src/backend/parser/gram.y
+++ b/src/backend/parser/gram.y
@@ -463,6 +463,10 @@ 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 <ival>	reindex_target_type reindex_target_multitable
+%type <ival>	reindex_option_list reindex_option_elem
+
 %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
@@ -7387,52 +7391,63 @@ DropTransformStmt: DROP TRANSFORM opt_if_exists FOR Typename LANGUAGE name opt_d
  *
  *		QUERY:
  *
- *		REINDEX type <name>
+ *		REINDEX [ (options) ] type <name>
  *****************************************************************************/
 
 ReindexStmt:
-			REINDEX INDEX qualified_name
+			REINDEX reindex_target_type qualified_name
 				{
 					ReindexStmt *n = makeNode(ReindexStmt);
-					n->kind = REINDEX_OBJECT_INDEX;
+					n->kind = $2;
 					n->relation = $3;
 					n->name = NULL;
+					n->options = 0;
 					$$ = (Node *)n;
 				}
-			| REINDEX TABLE qualified_name
+			| REINDEX reindex_target_multitable name
 				{
 					ReindexStmt *n = makeNode(ReindexStmt);
-					n->kind = REINDEX_OBJECT_TABLE;
-					n->relation = $3;
-					n->name = NULL;
-					$$ = (Node *)n;
-				}
-			| REINDEX SCHEMA name
-				{
-					ReindexStmt *n = makeNode(ReindexStmt);
-					n->kind = REINDEX_OBJECT_SCHEMA;
+					n->kind = $2;
 					n->name = $3;
 					n->relation = NULL;
+					n->options = 0;
 					$$ = (Node *)n;
 				}
-			| REINDEX SYSTEM_P name
+			| REINDEX '(' reindex_option_list ')' reindex_target_type qualified_name
 				{
 					ReindexStmt *n = makeNode(ReindexStmt);
-					n->kind = REINDEX_OBJECT_SYSTEM;
-					n->name = $3;
-					n->relation = NULL;
+					n->kind = $5;
+					n->relation = $6;
+					n->name = NULL;
+					n->options = $3;
 					$$ = (Node *)n;
 				}
-			| REINDEX DATABASE name
+			| REINDEX '(' reindex_option_list ')' reindex_target_multitable name
 				{
 					ReindexStmt *n = makeNode(ReindexStmt);
-					n->kind = REINDEX_OBJECT_DATABASE;
-					n->name = $3;
+					n->kind = $5;
+					n->name = $6;
 					n->relation = NULL;
+					n->options = $3;
 					$$ = (Node *)n;
 				}
 		;
-
+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; }
+		;
+reindex_option_list:
+			reindex_option_elem								{ $$ = $1; }
+			| reindex_option_list ',' reindex_option_elem	{ $$ = $1 | $3; }
+		;
+reindex_option_elem:
+			VERBOSE	{ $$ = REINDEXOPT_VERBOSE; }
+		;
 
 /*****************************************************************************
  *
diff --git a/src/backend/tcop/utility.c b/src/backend/tcop/utility.c
index 78bfd34..a95eff1 100644
--- a/src/backend/tcop/utility.c
+++ b/src/backend/tcop/utility.c
@@ -762,10 +762,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:
@@ -781,7 +781,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/include/catalog/index.h b/src/include/catalog/index.h
index 06f3820..e961d37 100644
--- a/src/include/catalog/index.h
+++ b/src/include/catalog/index.h
@@ -115,7 +115,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, int options);
 
 /* Flag bits for reindex_relation(): */
 #define REINDEX_REL_PROCESS_TOAST			0x01
@@ -124,7 +124,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, int options);
 
 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 c3a1748..d625725 100644
--- a/src/include/commands/defrem.h
+++ b/src/include/commands/defrem.h
@@ -29,9 +29,10 @@ 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, int options);
+extern Oid	ReindexTable(RangeVar *relation, int options);
+extern void ReindexMultipleTables(const char *objectName, ReindexObjectType objectKind,
+								  int 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 556c1c5..1500ee6 100644
--- a/src/include/nodes/parsenodes.h
+++ b/src/include/nodes/parsenodes.h
@@ -2782,6 +2782,10 @@ typedef struct ConstraintsSetStmt
  *		REINDEX Statement
  * ----------------------
  */
+
+/* Reindex options */
+#define REINDEXOPT_VERBOSE 1 << 0 /* print progress info */
+
 typedef enum ReindexObjectType
 {
 	REINDEX_OBJECT_INDEX,	/* index */
@@ -2797,6 +2801,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 */
+	int			options;		/* ReindexOption flags*/
 } ReindexStmt;
 
 /* ----------------------
diff --git a/src/test/regress/expected/create_index.out b/src/test/regress/expected/create_index.out
index abe64e5..68d233e 100644
--- a/src/test/regress/expected/create_index.out
+++ b/src/test/regress/expected/create_index.out
@@ -2832,6 +2832,14 @@ explain (costs off)
 (2 rows)
 
 --
+-- REINDEX (VERBOSE)
+--
+CREATE TABLE reindex_verbose(id integer primary key);
+\set VERBOSITY terse
+REINDEX (VERBOSE) TABLE reindex_verbose;
+INFO:  index "public.reindex_verbose_pkey" was reindexed
+DROP TABLE reindex_verbose;
+--
 -- REINDEX SCHEMA
 --
 REINDEX SCHEMA schema_to_reindex; -- failure, schema does not exist
diff --git a/src/test/regress/sql/create_index.sql b/src/test/regress/sql/create_index.sql
index f779fa0..6333a30 100644
--- a/src/test/regress/sql/create_index.sql
+++ b/src/test/regress/sql/create_index.sql
@@ -966,6 +966,14 @@ explain (costs off)
   select * from tenk1 where (thousand, tenthous) in ((1,1001), (null,null));
 
 --
+-- REINDEX (VERBOSE)
+--
+CREATE TABLE reindex_verbose(id integer primary key);
+\set VERBOSITY terse
+REINDEX (VERBOSE) TABLE reindex_verbose;
+DROP TABLE reindex_verbose;
+
+--
 -- REINDEX SCHEMA
 --
 REINDEX SCHEMA schema_to_reindex; -- failure, schema does not exist
#70Robert Haas
robertmhaas@gmail.com
In reply to: Alvaro Herrera (#68)
Re: Proposal : REINDEX xxx VERBOSE

On Wed, May 13, 2015 at 2:10 PM, Alvaro Herrera
<alvherre@2ndquadrant.com> wrote:

Uh, are we really using INFO to log this? I thought that was a
discouraged level to use anymore. Why not NOTICE?

Well, as Masahiko-san points out, VACUUM uses INFO. I can't see any
good reason to make this different.

Also, when multiple tables are reindexed, do we emit lines for each
index, or only for each table? If we're going to emit a line for each
index in the single-table mode, it seems more sensible to do the same
for the multi-table forms also.

Hmm, yeah, I agree with that. I thought the patch worked that way,
but I see now that it doesn't. I think that should be changed.

--
Robert Haas
EnterpriseDB: http://www.enterprisedb.com
The Enterprise PostgreSQL Company

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

#71Alvaro Herrera
alvherre@2ndquadrant.com
In reply to: Robert Haas (#70)
Re: Proposal : REINDEX xxx VERBOSE

Robert Haas wrote:

On Wed, May 13, 2015 at 2:10 PM, Alvaro Herrera
<alvherre@2ndquadrant.com> wrote:

Uh, are we really using INFO to log this? I thought that was a
discouraged level to use anymore. Why not NOTICE?

Well, as Masahiko-san points out, VACUUM uses INFO. I can't see any
good reason to make this different.

I was misremembering the INFO situation. Here's one item in the
archives I found in a very quick search, which says that INFO is the
right thing to use:
/messages/by-id/24874.1231183906@sss.pgh.pa.us

Cheers

--
�lvaro Herrera http://www.2ndQuadrant.com/
PostgreSQL Development, 24x7 Support, Remote DBA, Training & Services

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

#72Sawada Masahiko
sawada.mshk@gmail.com
In reply to: Robert Haas (#70)
Re: Proposal : REINDEX xxx VERBOSE

On Thu, May 14, 2015 at 4:53 AM, Robert Haas <robertmhaas@gmail.com> wrote:

On Wed, May 13, 2015 at 2:10 PM, Alvaro Herrera
<alvherre@2ndquadrant.com> wrote:

Uh, are we really using INFO to log this? I thought that was a
discouraged level to use anymore. Why not NOTICE?

Well, as Masahiko-san points out, VACUUM uses INFO. I can't see any
good reason to make this different.

Also, when multiple tables are reindexed, do we emit lines for each
index, or only for each table? If we're going to emit a line for each
index in the single-table mode, it seems more sensible to do the same
for the multi-table forms also.

Hmm, yeah, I agree with that. I thought the patch worked that way,
but I see now that it doesn't. I think that should be changed.

The v15 patch emits a line for each table when reindexing multiple
tables, and emits a line for each index when reindexing single table.
But v14 patch emits a line for each index, regardless of reindex target.
Should I change back to v14 patch?

Regards,

-------
Sawada Masahiko

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

#73Fabrízio de Royes Mello
fabriziomello@gmail.com
In reply to: Sawada Masahiko (#67)
Re: Proposal : REINDEX xxx VERBOSE

On Wed, May 13, 2015 at 2:49 PM, Sawada Masahiko <sawada.mshk@gmail.com>
wrote:

On Thu, May 14, 2015 at 12:28 AM, Robert Haas <robertmhaas@gmail.com>

wrote:

On Thu, May 7, 2015 at 6:55 PM, Sawada Masahiko <sawada.mshk@gmail.com>

wrote:

Sorry, I forgot attach files.

Review comments:

- Customarily we use int, rather than uint8, for flags variables. I
think we should do that here also.

- reindex_index() emits a log message either way, but at DEBUG2 level
without VERBOSE and at the INFO level with it. I think we should skip
it altogether without VERBOSE. i.e. if (options & REINDEXOPT_VERBOSE)
ereport(...)

- The errmsg() in that function should not end with a period.

- The 000 patch makes a pointless whitespace change to tab-complete.c.

- Instead of an enumerated type (ReindexOption) just use #define to
define the flag value.

Apart from those fairly minor issues, I think this looks pretty solid.

Thank you for reviwing..
All fixed.

IMHO we don't need "pg_rusage_init(&ru0)" if the verbose options is not
setted. Maybe change:

+
+ pg_rusage_init(&ru0);

to

+
+    if (options & REINDEXOPT_VERBOSE)
+        pg_rusage_init(&ru0);

Regards,

--
Fabrízio de Royes Mello
Consultoria/Coaching PostgreSQL

Show quoted text

Timbira: http://www.timbira.com.br
Blog: http://fabriziomello.github.io
Linkedin: http://br.linkedin.com/in/fabriziomello
Twitter: http://twitter.com/fabriziomello
Github: http://github.com/fabriziomello

#74Robert Haas
robertmhaas@gmail.com
In reply to: Sawada Masahiko (#72)
Re: Proposal : REINDEX xxx VERBOSE

On Wed, May 13, 2015 at 8:25 PM, Sawada Masahiko <sawada.mshk@gmail.com> wrote:

The v15 patch emits a line for each table when reindexing multiple
tables, and emits a line for each index when reindexing single table.
But v14 patch emits a line for each index, regardless of reindex target.
Should I change back to v14 patch?

Uh, maybe. What made you change it?

--
Robert Haas
EnterpriseDB: http://www.enterprisedb.com
The Enterprise PostgreSQL Company

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

#75Sawada Masahiko
sawada.mshk@gmail.com
In reply to: Robert Haas (#74)
1 attachment(s)
Re: Proposal : REINDEX xxx VERBOSE

On Thu, May 14, 2015 at 9:58 AM, Robert Haas <robertmhaas@gmail.com> wrote:

On Wed, May 13, 2015 at 8:25 PM, Sawada Masahiko <sawada.mshk@gmail.com> wrote:

The v15 patch emits a line for each table when reindexing multiple
tables, and emits a line for each index when reindexing single table.
But v14 patch emits a line for each index, regardless of reindex target.
Should I change back to v14 patch?

Uh, maybe. What made you change it?

I thought that the users who want to reindex multiple tables are
interested in the time to reindex whole table takes.
But I think it seems sensible to emit a line for each index even when
reindex multiple tables.
The v16 patch is based on v14 and a few modified is attached.

Regards,

-------
Sawada Masahiko

Attachments:

000_reindex_verbose_v16.patchtext/x-diff; charset=US-ASCII; name=000_reindex_verbose_v16.patchDownload
diff --git a/doc/src/sgml/ref/reindex.sgml b/doc/src/sgml/ref/reindex.sgml
index 998340c..703b760 100644
--- a/doc/src/sgml/ref/reindex.sgml
+++ b/doc/src/sgml/ref/reindex.sgml
@@ -21,7 +21,7 @@ PostgreSQL documentation
 
  <refsynopsisdiv>
 <synopsis>
-REINDEX { INDEX | TABLE | SCHEMA | DATABASE | SYSTEM } <replaceable class="PARAMETER">name</replaceable>
+REINDEX [ ( { VERBOSE } [, ...] ) ] { INDEX | TABLE | SCHEMA | DATABASE | SYSTEM } <replaceable class="PARAMETER">name</replaceable>
 </synopsis>
  </refsynopsisdiv>
 
@@ -150,6 +150,15 @@ 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>
   </variablelist>
  </refsect1>
 
diff --git a/src/backend/catalog/index.c b/src/backend/catalog/index.c
index 8c8a9ea..bac9fbe 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"
@@ -3184,13 +3185,17 @@ 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,
+				int options)
 {
 	Relation	iRel,
 				heapRelation;
 	Oid			heapId;
 	IndexInfo  *indexInfo;
 	volatile bool skipped_constraint = false;
+	PGRUsage	ru0;
+
+	pg_rusage_init(&ru0);
 
 	/*
 	 * Open and lock the parent heap relation.  ShareLock is sufficient since
@@ -3334,6 +3339,14 @@ reindex_index(Oid indexId, bool skip_constraint_checks, char persistence)
 		heap_close(pg_index, RowExclusiveLock);
 	}
 
+	/* Log what we did */
+	if (options & REINDEXOPT_VERBOSE)
+		ereport(INFO,
+				(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);
@@ -3375,7 +3388,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, int options)
 {
 	Relation	rel;
 	Oid			toast_relid;
@@ -3466,7 +3479,7 @@ reindex_relation(Oid relid, int flags)
 				RelationSetIndexList(rel, doneIndexes, InvalidOid);
 
 			reindex_index(indexOid, !(flags & REINDEX_REL_CHECK_CONSTRAINTS),
-						  persistence);
+						  persistence, options);
 
 			CommandCounterIncrement();
 
@@ -3501,7 +3514,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, options);
 
 	return result;
 }
diff --git a/src/backend/commands/cluster.c b/src/backend/commands/cluster.c
index 3febdd5..7ab4874 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, 0);
 
 	/*
 	 * 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 351d48e..7340a1f 100644
--- a/src/backend/commands/indexcmds.c
+++ b/src/backend/commands/indexcmds.c
@@ -1681,7 +1681,7 @@ ChooseIndexColumnNames(List *indexElems)
  *		Recreate a specific index.
  */
 Oid
-ReindexIndex(RangeVar *indexRelation)
+ReindexIndex(RangeVar *indexRelation, int options)
 {
 	Oid			indOid;
 	Oid			heapOid = InvalidOid;
@@ -1706,7 +1706,7 @@ ReindexIndex(RangeVar *indexRelation)
 	persistence = irel->rd_rel->relpersistence;
 	index_close(irel, NoLock);
 
-	reindex_index(indOid, false, persistence);
+	reindex_index(indOid, false, persistence, options);
 
 	return indOid;
 }
@@ -1775,7 +1775,7 @@ RangeVarCallbackForReindexIndex(const RangeVar *relation,
  *		Recreate all indexes of a table (and of its toast table, if any)
  */
 Oid
-ReindexTable(RangeVar *relation)
+ReindexTable(RangeVar *relation, int options)
 {
 	Oid			heapOid;
 
@@ -1785,7 +1785,8 @@ ReindexTable(RangeVar *relation)
 
 	if (!reindex_relation(heapOid,
 						  REINDEX_REL_PROCESS_TOAST |
-						  REINDEX_REL_CHECK_CONSTRAINTS))
+						  REINDEX_REL_CHECK_CONSTRAINTS,
+						  options))
 		ereport(NOTICE,
 				(errmsg("table \"%s\" has no indexes",
 						relation->relname)));
@@ -1802,7 +1803,8 @@ 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,
+					  int options)
 {
 	Oid			objectOid;
 	Relation	relationRelation;
@@ -1938,11 +1940,14 @@ 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",
-							get_namespace_name(get_rel_namespace(relid)),
-							get_rel_name(relid))));
+							 REINDEX_REL_CHECK_CONSTRAINTS,
+							 options))
+
+			if (options & REINDEXOPT_VERBOSE)
+				ereport(INFO,
+						(errmsg("table \"%s.%s\" was reindexed",
+								get_namespace_name(get_rel_namespace(relid)),
+								get_rel_name(relid))));
 		PopActiveSnapshot();
 		CommitTransactionCommand();
 	}
diff --git a/src/backend/commands/tablecmds.c b/src/backend/commands/tablecmds.c
index 0a6b069..33ea387 100644
--- a/src/backend/commands/tablecmds.c
+++ b/src/backend/commands/tablecmds.c
@@ -1234,7 +1234,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, 0);
 		}
 
 		pgstat_count_truncate(rel);
diff --git a/src/backend/nodes/copyfuncs.c b/src/backend/nodes/copyfuncs.c
index 76b63af..25839ee 100644
--- a/src/backend/nodes/copyfuncs.c
+++ b/src/backend/nodes/copyfuncs.c
@@ -3856,6 +3856,7 @@ _copyReindexStmt(const ReindexStmt *from)
 	COPY_SCALAR_FIELD(kind);
 	COPY_NODE_FIELD(relation);
 	COPY_STRING_FIELD(name);
+	COPY_SCALAR_FIELD(options);
 
 	return newnode;
 }
diff --git a/src/backend/nodes/equalfuncs.c b/src/backend/nodes/equalfuncs.c
index e032142..c4b3615 100644
--- a/src/backend/nodes/equalfuncs.c
+++ b/src/backend/nodes/equalfuncs.c
@@ -1935,6 +1935,7 @@ _equalReindexStmt(const ReindexStmt *a, const ReindexStmt *b)
 	COMPARE_SCALAR_FIELD(kind);
 	COMPARE_NODE_FIELD(relation);
 	COMPARE_STRING_FIELD(name);
+	COMPARE_SCALAR_FIELD(options);
 
 	return true;
 }
diff --git a/src/backend/parser/gram.y b/src/backend/parser/gram.y
index e71d926..2dce878 100644
--- a/src/backend/parser/gram.y
+++ b/src/backend/parser/gram.y
@@ -463,6 +463,10 @@ 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 <ival>	reindex_target_type reindex_target_multitable
+%type <ival>	reindex_option_list reindex_option_elem
+
 %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
@@ -7387,52 +7391,63 @@ DropTransformStmt: DROP TRANSFORM opt_if_exists FOR Typename LANGUAGE name opt_d
  *
  *		QUERY:
  *
- *		REINDEX type <name>
+ *		REINDEX [ (options) ] type <name>
  *****************************************************************************/
 
 ReindexStmt:
-			REINDEX INDEX qualified_name
+			REINDEX reindex_target_type qualified_name
 				{
 					ReindexStmt *n = makeNode(ReindexStmt);
-					n->kind = REINDEX_OBJECT_INDEX;
+					n->kind = $2;
 					n->relation = $3;
 					n->name = NULL;
+					n->options = 0;
 					$$ = (Node *)n;
 				}
-			| REINDEX TABLE qualified_name
+			| REINDEX reindex_target_multitable name
 				{
 					ReindexStmt *n = makeNode(ReindexStmt);
-					n->kind = REINDEX_OBJECT_TABLE;
-					n->relation = $3;
-					n->name = NULL;
-					$$ = (Node *)n;
-				}
-			| REINDEX SCHEMA name
-				{
-					ReindexStmt *n = makeNode(ReindexStmt);
-					n->kind = REINDEX_OBJECT_SCHEMA;
+					n->kind = $2;
 					n->name = $3;
 					n->relation = NULL;
+					n->options = 0;
 					$$ = (Node *)n;
 				}
-			| REINDEX SYSTEM_P name
+			| REINDEX '(' reindex_option_list ')' reindex_target_type qualified_name
 				{
 					ReindexStmt *n = makeNode(ReindexStmt);
-					n->kind = REINDEX_OBJECT_SYSTEM;
-					n->name = $3;
-					n->relation = NULL;
+					n->kind = $5;
+					n->relation = $6;
+					n->name = NULL;
+					n->options = $3;
 					$$ = (Node *)n;
 				}
-			| REINDEX DATABASE name
+			| REINDEX '(' reindex_option_list ')' reindex_target_multitable name
 				{
 					ReindexStmt *n = makeNode(ReindexStmt);
-					n->kind = REINDEX_OBJECT_DATABASE;
-					n->name = $3;
+					n->kind = $5;
+					n->name = $6;
 					n->relation = NULL;
+					n->options = $3;
 					$$ = (Node *)n;
 				}
 		;
-
+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; }
+		;
+reindex_option_list:
+			reindex_option_elem								{ $$ = $1; }
+			| reindex_option_list ',' reindex_option_elem	{ $$ = $1 | $3; }
+		;
+reindex_option_elem:
+			VERBOSE	{ $$ = REINDEXOPT_VERBOSE; }
+		;
 
 /*****************************************************************************
  *
diff --git a/src/backend/tcop/utility.c b/src/backend/tcop/utility.c
index 78bfd34..a95eff1 100644
--- a/src/backend/tcop/utility.c
+++ b/src/backend/tcop/utility.c
@@ -762,10 +762,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:
@@ -781,7 +781,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/include/catalog/index.h b/src/include/catalog/index.h
index 06f3820..e961d37 100644
--- a/src/include/catalog/index.h
+++ b/src/include/catalog/index.h
@@ -115,7 +115,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, int options);
 
 /* Flag bits for reindex_relation(): */
 #define REINDEX_REL_PROCESS_TOAST			0x01
@@ -124,7 +124,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, int options);
 
 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 c3a1748..d625725 100644
--- a/src/include/commands/defrem.h
+++ b/src/include/commands/defrem.h
@@ -29,9 +29,10 @@ 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, int options);
+extern Oid	ReindexTable(RangeVar *relation, int options);
+extern void ReindexMultipleTables(const char *objectName, ReindexObjectType objectKind,
+								  int 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 556c1c5..1500ee6 100644
--- a/src/include/nodes/parsenodes.h
+++ b/src/include/nodes/parsenodes.h
@@ -2782,6 +2782,10 @@ typedef struct ConstraintsSetStmt
  *		REINDEX Statement
  * ----------------------
  */
+
+/* Reindex options */
+#define REINDEXOPT_VERBOSE 1 << 0 /* print progress info */
+
 typedef enum ReindexObjectType
 {
 	REINDEX_OBJECT_INDEX,	/* index */
@@ -2797,6 +2801,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 */
+	int			options;		/* ReindexOption flags*/
 } ReindexStmt;
 
 /* ----------------------
diff --git a/src/test/regress/expected/create_index.out b/src/test/regress/expected/create_index.out
index abe64e5..cba11b4 100644
--- a/src/test/regress/expected/create_index.out
+++ b/src/test/regress/expected/create_index.out
@@ -2832,6 +2832,14 @@ explain (costs off)
 (2 rows)
 
 --
+-- REINDEX (VERBOSE)
+--
+CREATE TABLE reindex_verbose(id integer primary key);
+\set VERBOSITY terse
+REINDEX (VERBOSE) TABLE reindex_verbose;
+INFO:  index "reindex_verbose_pkey" was reindexed.
+DROP TABLE reindex_verbose;
+--
 -- REINDEX SCHEMA
 --
 REINDEX SCHEMA schema_to_reindex; -- failure, schema does not exist
diff --git a/src/test/regress/sql/create_index.sql b/src/test/regress/sql/create_index.sql
index f779fa0..6333a30 100644
--- a/src/test/regress/sql/create_index.sql
+++ b/src/test/regress/sql/create_index.sql
@@ -966,6 +966,14 @@ explain (costs off)
   select * from tenk1 where (thousand, tenthous) in ((1,1001), (null,null));
 
 --
+-- REINDEX (VERBOSE)
+--
+CREATE TABLE reindex_verbose(id integer primary key);
+\set VERBOSITY terse
+REINDEX (VERBOSE) TABLE reindex_verbose;
+DROP TABLE reindex_verbose;
+
+--
 -- REINDEX SCHEMA
 --
 REINDEX SCHEMA schema_to_reindex; -- failure, schema does not exist
#76Fujii Masao
masao.fujii@gmail.com
In reply to: Sawada Masahiko (#75)
Re: Proposal : REINDEX xxx VERBOSE

On Thu, May 14, 2015 at 4:30 PM, Sawada Masahiko <sawada.mshk@gmail.com> wrote:

On Thu, May 14, 2015 at 9:58 AM, Robert Haas <robertmhaas@gmail.com> wrote:

On Wed, May 13, 2015 at 8:25 PM, Sawada Masahiko <sawada.mshk@gmail.com> wrote:

The v15 patch emits a line for each table when reindexing multiple
tables, and emits a line for each index when reindexing single table.
But v14 patch emits a line for each index, regardless of reindex target.
Should I change back to v14 patch?

Uh, maybe. What made you change it?

I thought that the users who want to reindex multiple tables are
interested in the time to reindex whole table takes.
But I think it seems sensible to emit a line for each index even when
reindex multiple tables.
The v16 patch is based on v14 and a few modified is attached.

Thanks for updating the patch!

The regression test failed because you forgot to remove the trailng period
from the verbose message in the "expected file" of the regression test.
I just fixed it and push the patch.

Regards,

--
Fujii Masao

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

#77Fujii Masao
masao.fujii@gmail.com
In reply to: Sawada Masahiko (#64)
Re: Proposal : REINDEX xxx VERBOSE

On Sun, May 10, 2015 at 2:23 AM, Sawada Masahiko <sawada.mshk@gmail.com> wrote:

On Sat, May 9, 2015 at 4:26 AM, Fabrízio de Royes Mello
<fabriziomello@gmail.com> wrote:

On Fri, May 8, 2015 at 4:23 PM, Fabrízio de Royes Mello
<fabriziomello@gmail.com> wrote:

On Thu, May 7, 2015 at 7:55 PM, Sawada Masahiko <sawada.mshk@gmail.com>
wrote:

On 5/7/15, Sawada Masahiko <sawada.mshk@gmail.com> wrote:

On Wed, May 6, 2015 at 5:42 AM, Robert Haas <robertmhaas@gmail.com
<javascript:;>> wrote:

On Tue, May 5, 2015 at 11:10 AM, Sawada Masahiko
<sawada.mshk@gmail.com

<javascript:;>> wrote:

On Fri, May 1, 2015 at 9:04 PM, Robert Haas <robertmhaas@gmail.com

<javascript:;>> wrote:

On Thu, Apr 30, 2015 at 11:05 PM, Sawada Masahiko
<sawada.mshk@gmail.com

<javascript:;>> wrote:

VACUUM has both syntax: with parentheses and without parentheses.
I think we should have both syntax for REINDEX like VACUUM does
because it would be pain to put parentheses whenever we want to do
REINDEX.
Are the parentheses optional in REINDEX command?

No. The unparenthesized VACUUM syntax was added back before we
realized that that kind of syntax is a terrible idea. It requires
every option to be a keyword, and those keywords have to be in a
fixed
order. I believe the intention is to keep the old VACUUM syntax
around for backward-compatibility, but not to extend it. Same for
EXPLAIN and COPY.

REINDEX will have only one option VERBOSE for now.
Even we're in a situation like that it's not clear to be added newly
additional option to REINDEX now, we should need to put parenthesis?

In my opinion, yes. The whole point of a flexible options syntax is
that we can add new options without changing the grammar. That
involves some compromise on the syntax, which doesn't bother me a
bit.
Our previous experiments with this for EXPLAIN and COPY and VACUUM
have worked out quite well, and I see no reason for pessimism here.

I agree that flexible option syntax does not need to change grammar
whenever we add new options.
Attached patch is changed based on your suggestion.
And the patch for reindexdb is also attached.
Please feedbacks.

Also I'm not sure that both implementation and documentation
regarding
VERBOSE option should be optional.

I don't know what this means.

Sorry for confusing you.
Please ignore this.

Sorry, I forgot attach files.

I applied the two patches to master and I got some errors when compile:

tab-complete.c: In function ‘psql_completion’:
tab-complete.c:3338:12: warning: left-hand operand of comma expression has
no effect [-Wunused-value]
{"TABLE", "INDEX", "SYSTEM", "SCHEMA", "DATABASE", NULL};
^
tab-complete.c:3338:21: warning: left-hand operand of comma expression has
no effect [-Wunused-value]
{"TABLE", "INDEX", "SYSTEM", "SCHEMA", "DATABASE", NULL};
^
tab-complete.c:3338:31: warning: left-hand operand of comma expression has
no effect [-Wunused-value]
{"TABLE", "INDEX", "SYSTEM", "SCHEMA", "DATABASE", NULL};
^
tab-complete.c:3338:41: warning: left-hand operand of comma expression has
no effect [-Wunused-value]
{"TABLE", "INDEX", "SYSTEM", "SCHEMA", "DATABASE", NULL};
^
tab-complete.c:3338:53: warning: left-hand operand of comma expression has
no effect [-Wunused-value]
{"TABLE", "INDEX", "SYSTEM", "SCHEMA", "DATABASE", NULL};
^
tab-complete.c:3338:5: warning: statement with no effect [-Wunused-value]
{"TABLE", "INDEX", "SYSTEM", "SCHEMA", "DATABASE", NULL};
^
tab-complete.c:3338:59: error: expected ‘;’ before ‘}’ token
{"TABLE", "INDEX", "SYSTEM", "SCHEMA", "DATABASE", NULL};
^
tab-complete.c:3340:22: error: ‘list_REINDEX’ undeclared (first use in
this function)
COMPLETE_WITH_LIST(list_REINDEX);
^
tab-complete.c:169:22: note: in definition of macro ‘COMPLETE_WITH_LIST’
completion_charpp = list; \
^
tab-complete.c:3340:22: note: each undeclared identifier is reported only
once for each function it appears in
COMPLETE_WITH_LIST(list_REINDEX);
^
tab-complete.c:169:22: note: in definition of macro ‘COMPLETE_WITH_LIST’
completion_charpp = list; \
^
make[3]: *** [tab-complete.o] Error 1
make[3]: *** Waiting for unfinished jobs....
make[2]: *** [install-psql-recurse] Error 2
make[2]: *** Waiting for unfinished jobs....
make[1]: *** [install-bin-recurse] Error 2
make: *** [install-src-recurse] Error 2

Looking at the code I think you remove one line accidentally from
tab-complete.c:

$ git diff src/bin/psql/tab-complete.c
diff --git a/src/bin/psql/tab-complete.c b/src/bin/psql/tab-complete.c
index 750e29d..55b0df5 100644
--- a/src/bin/psql/tab-complete.c
+++ b/src/bin/psql/tab-complete.c
@@ -3335,7 +3335,6 @@ psql_completion(const char *text, int start, int
end)
/* REINDEX */
else if (pg_strcasecmp(prev_wd, "REINDEX") == 0)
{
-       static const char *const list_REINDEX[] =
{"TABLE", "INDEX", "SYSTEM", "SCHEMA", "DATABASE", NULL};

COMPLETE_WITH_LIST(list_REINDEX);

The attached fix it and now seems good to me.

Just one last note. IMHO we should add a regression to
src/bin/scripts/090_reindexdb.pl.

Thank you for your patch!
(Sorry for attaching the patch still has compile error..)

- 000_reindex_verbose_v13.patch
Looks good to me.

- 001_reindexdb_verbose_option_v1.patch
I noticed a bug in reindexdb patch, so fixed version is attached.
The regression test for reindexdb is added as well.

Pushed.

Regards,

--
Fujii Masao

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