*** a/doc/src/sgml/ref/reindexdb.sgml
--- b/doc/src/sgml/ref/reindexdb.sgml
***************
*** 104,109 **** PostgreSQL documentation
--- 104,120 ----
       </varlistentry>
  
       <varlistentry>
+       <term><option>-C</></term>
+       <term><option>--concurrently</></term>
+       <listitem>
+        <para>
+         Reindex concurrently.
+         Note that we cannot specify with -s (--system) option.
+        </para>
+       </listitem>
+      </varlistentry>
+ 
+      <varlistentry>
        <term><option><optional>-d</> <replaceable class="parameter">dbname</replaceable></></term>
        <term><option><optional>--dbname=</><replaceable class="parameter">dbname</replaceable></></term>
        <listitem>
*** a/src/bin/scripts/reindexdb.c
--- b/src/bin/scripts/reindexdb.c
***************
*** 13,28 ****
  #include "common.h"
  #include "dumputils.h"
  
  
  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);
  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);
  static void reindex_system_catalogs(const char *dbname,
  						const char *host, const char *port,
--- 13,49 ----
  #include "common.h"
  #include "dumputils.h"
  
+ #define IsToken(c) \
+ 	(IS_HIGHBIT_SET((c)) || isalnum((unsigned char) (c)) || (c) == '_')
  
+ /*
+  * Parsed CREATE INDEX statement. You can rebuild sql using
+  * sprintf(buf, "%s %s ON %s USING %s (%s)%s",
+  *              create, index, table type, columns, options)
+  */
+ typedef struct IndexDef
+ {
+ 	char *create;   /* CREATE INDEX or CREATE UNIQUE INDEX */
+ 	char *index;    /* index name including schema */
+ 	char *table;    /* table name including schema */
+ 	char *type;             /* btree, hash, gist or gin */
+ 	char *columns;  /* column definition */
+ 	char *options;  /* options after columns, before TABLESPACE (e.g. COLLATE) */
+ 	char *tablespace; /* tablespace if specified */
+ 	char *where;    /* WHERE content if specified */
+ } IndexDef;
+ 
+ static void parse_indexdef(IndexDef *stmt, const char *indexdef, const char *indexname, const char *tablename, Oid index, Oid table);
+ static bool reindex_indexes(PGconn *conn, PGresult *res, const char *progname, bool echo);
  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 concurrently);
  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 concurrently,
  					  bool quiet);
  static void reindex_system_catalogs(const char *dbname,
  						const char *host, const char *port,
***************
*** 30,35 **** static void reindex_system_catalogs(const char *dbname,
--- 51,58 ----
  						const char *progname, bool echo);
  static void help(const char *progname);
  
+ 
+ 
  int
  main(int argc, char *argv[])
  {
***************
*** 47,52 **** main(int argc, char *argv[])
--- 70,76 ----
  		{"table", required_argument, NULL, 't'},
  		{"index", required_argument, NULL, 'i'},
  		{"maintenance-db", required_argument, NULL, 2},
+ 		{"concurrently", no_argument, NULL, 'C'},
  		{NULL, 0, NULL, 0}
  	};
  
***************
*** 64,69 **** main(int argc, char *argv[])
--- 88,94 ----
  	bool		alldb = false;
  	bool		echo = false;
  	bool		quiet = false;
+ 	bool		concurrently = false;
  	SimpleStringList indexes = {NULL, NULL};
  	SimpleStringList tables = {NULL, NULL};
  
***************
*** 73,79 **** 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:wWeqd:ast:i:", long_options, &optindex)) != -1)
  	{
  		switch (c)
  		{
--- 98,104 ----
  	handle_help_version_opts(argc, argv, "reindexdb", help);
  
  	/* process command-line options */
! 	while ((c = getopt_long(argc, argv, "h:p:U:wWeqd:ast:i:C", long_options, &optindex)) != -1)
  	{
  		switch (c)
  		{
***************
*** 116,121 **** main(int argc, char *argv[])
--- 141,149 ----
  			case 2:
  				maintenance_db = pg_strdup(optarg);
  				break;
+ 			case 'C':
+ 				concurrently = true;
+ 				break;
  			default:
  				fprintf(stderr, _("Try \"%s --help\" for more information.\n"), progname);
  				exit(1);
***************
*** 166,172 **** main(int argc, char *argv[])
  		}
  
  		reindex_all_databases(maintenance_db, host, port, username,
! 							  prompt_password, progname, echo, quiet);
  	}
  	else if (syscatalog)
  	{
--- 194,200 ----
  		}
  
  		reindex_all_databases(maintenance_db, host, port, username,
! 							  prompt_password, progname, echo, concurrently, quiet);
  	}
  	else if (syscatalog)
  	{
***************
*** 181,186 **** main(int argc, char *argv[])
--- 209,220 ----
  			exit(1);
  		}
  
+ 		if (concurrently)
+ 		{
+ 			fprintf(stderr, _("%s: cannot reindex specific system catalogs and concurrenlty option at the same time\n"),progname);
+ 			exit(1);
+ 		}
+ 
  		if (dbname == NULL)
  		{
  			if (getenv("PGDATABASE"))
***************
*** 213,219 **** 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);
  			}
  		}
  		if (tables.head != NULL)
--- 247,253 ----
  			for (cell = indexes.head; cell; cell = cell->next)
  			{
  				reindex_one_database(cell->val, dbname, "INDEX", host, port,
! 								  username, prompt_password, progname, echo, concurrently);
  			}
  		}
  		if (tables.head != NULL)
***************
*** 223,244 **** 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);
  			}
  		}
  		/* reindex database only if neither index nor table is specified */
  		if (indexes.head == NULL && tables.head == NULL)
  			reindex_one_database(dbname, dbname, "DATABASE", host, port,
! 								 username, prompt_password, progname, echo);
  	}
  
  	exit(0);
  }
  
  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)
  {
  	PQExpBufferData sql;
  
--- 257,659 ----
  			for (cell = tables.head; cell; cell = cell->next)
  			{
  				reindex_one_database(cell->val, dbname, "TABLE", host, port,
! 								  username, prompt_password, progname, echo, concurrently);
  			}
  		}
  		/* reindex database only if neither index nor table is specified */
  		if (indexes.head == NULL && tables.head == NULL)
  			reindex_one_database(dbname, dbname, "DATABASE", host, port,
! 								 username, prompt_password, progname, echo, concurrently);
  	}
  
  	exit(0);
  }
  
+ static Oid
+ getoid(PGresult *res, int row, int col)
+ {
+ 	if (PQgetisnull(res, row, col))
+ 		return InvalidOid;
+ 	else
+ 		return (Oid)strtoul(PQgetvalue(res, row, col), NULL, 10);
+ }
+ 
+ static char *
+ getstr(PGresult *res, int row, int col)
+ {
+ 	if (PQgetisnull(res, row, col))
+ 		return NULL;
+ 	else
+ 		return PQgetvalue(res, row, col);
+ }
+ 
+ static char *
+ parse_error(Oid index)
+ {
+ 	fprintf(stderr, "unexpected index definition: %d", index);
+ 	return NULL;
+ }
+ 
+ /*
+  * Skip until 'end' character found. The 'end' character is replaced with \0.
+  * Returns the next character of the 'end', or NULL if 'end' is not found.
+  */
+ static char *
+ skip_until(Oid index, char *sql, char end)
+ {
+ 	char    instr = 0;
+ 	int             nopen = 0;
+ 
+ 	for (; *sql && (nopen > 0 || instr != 0 || *sql != end); sql++)
+ 	{
+ 		if (instr)
+ 		{
+ 			if (sql[0] == instr)
+ 			{
+ 				if (sql[1] == instr)
+ 					sql++;
+ 				else
+ 					instr = 0;
+ 			}
+ 			else if (sql[0] == '\\')
+ 				sql++;  /* next char is always string */
+ 		}
+ 		else
+ 		{
+ 			switch (sql[0])
+ 			{
+ 			case '(':
+ 				nopen++;
+ 				break;
+ 			case ')':
+ 				nopen--;
+ 				break;
+ 			case '\'':
+ 			case '"':
+ 				instr = sql[0];
+ 			break;
+ 			}
+ 		}
+ 	}
+ 
+ 	if (nopen == 0 && instr == 0)
+ 	{
+ 		if (*sql)
+ 		{
+ 			*sql = '\0';
+ 			return sql + 1;
+ 		}
+ 		else
+ 			return NULL;
+ 	}
+ 
+ 	/* error */
+ 	return parse_error(index);
+ }
+ 
+ static char *
+ skip_const(Oid index, char *sql, const char *arg1, const char *arg2)
+ {
+ 	size_t  len;
+ 
+ 	if ((arg1 && strncmp(sql, arg1, (len = strlen(arg1))) == 0) ||
+ 		(arg2 && strncmp(sql, arg2, (len = strlen(arg2))) == 0))
+ 	{
+ 		sql[len] = '\0';
+ 		return sql + len + 1;
+ 	}
+ 
+ 	/* error */
+ 	return parse_error(index);
+ }
+ 
+ static char *
+ skip_ident(Oid index, char *sql)
+ {
+ 	while (*sql && isspace((unsigned char) *sql))
+ 		sql++;
+ 
+ 	if (*sql == '"')
+ 	{
+ 		sql++;
+ 		for (;;)
+ 		{
+ 			char *end = strchr(sql, '"');
+ 			if (end == NULL)
+ 				return parse_error(index);
+ 			else if (end[1] != '"')
+ 			{
+ 				end[1] = '\0';
+ 				return end + 2;
+ 			}
+ 			else    /* escaped quote ("") */
+ 				sql = end + 2;
+ 		}
+ 	}
+ 	else
+ 	{
+ 		while (*sql && IsToken(*sql))
+ 			sql++;
+ 		*sql = '\0';
+ 		return sql + 1;
+ 	}
+ 
+ 	/* error */
+ 	return parse_error(index);
+ }
+ 
+ static char *
+ skip_until_const(Oid index, char *sql, const char *what)
+ {
+ 	char *pos;
+ 
+ 	if ((pos = strstr(sql, what)))
+ 	{
+ 		size_t  len;
+ 
+ 		len = strlen(what);
+ 		pos[-1] = '\0';
+ 		return pos + len + 1;
+ 	}
+ 
+ 	/* error */
+ 	return parse_error(index);
+ }
+ 
+ /*
+  * Aquire lock to table
+  * In this function, the transaction is began with READ COMMITTED isolation level.
+  * Note that we try to aquire lock only once.
+  * XXX : To optinal wait_time
+  */
+ static bool
+ aquire_lock(PGconn *conn, const char *lock_query, const char *progname, bool echo)
+ {
+ 	PQExpBufferData sql;
+ 	int wait_time = 60;
+ 	bool ret = false;
+ 
+ 	initPQExpBuffer(&sql);
+ 
+ 	appendPQExpBuffer(&sql, "BEGIN ISOLATION LEVEL READ COMMITTED");
+ 	executeCommand(conn, sql.data, progname, echo);
+ 
+ 	resetPQExpBuffer(&sql);
+ 	appendPQExpBuffer(&sql, "SET statement_timeout TO %d", wait_time);
+ 	executeCommand(conn, sql.data, progname, echo);
+ 
+ 	/* Aquire lock */
+ 	ret = executeMaintenanceCommand(conn, lock_query, echo);
+ 
+ 	executeCommand(conn, "RESET statement_timeout", progname, echo);
+ 	return ret;
+ }
+ 
+ /*
+  * Swapping old index and new index
+  * We swap value of relfilenode in pg_class actually.
+  */
+ static bool
+ swap_index(PGconn *conn, const Oid index, const char *progname, bool echo)
+ {
+ 	PQExpBufferData sql;
+ 	PGresult *res  = NULL;
+ 	Oid tmpindex_oid, orig_filenode, tmp_filenode;;
+ 
+ 	initPQExpBuffer(&sql);
+ 
+ 	/* Get oid of new index */
+ 	appendPQExpBuffer(&sql,
+ 					  "SELECT pgc.oid FROM pg_class pgc "
+ 					  "WHERE pgc.relname = 'index_%d' "
+ 					  "AND pgc.relkind = 'i'", index);
+ 	res = executeQuery(conn, sql.data, progname, echo);
+ 	Assert(PQntuples(res) == 1);
+ 
+ 	tmpindex_oid = getoid(res, 0, 0);
+ 
+ 	/* Get each value of relfilenode */
+ 	resetPQExpBuffer(&sql);
+ 	appendPQExpBuffer(&sql,
+ 					 "SELECT pgc.oid, pgc.relfilenode "
+ 					 "FROM pg_Class pgc "
+ 					 "WHERE pgc.oid = %u OR pgc.oid = %u", index, tmpindex_oid);
+ 	res = executeQuery(conn, sql.data, progname, echo);
+ 	Assert(PQntuples(res) == 2);
+ 
+ 	orig_filenode = (getoid(res, 0, 0) == index) ? getoid(res, 0, 1) : getoid(res, 1,1);
+ 	tmp_filenode = (getoid(res, 0, 0) == tmpindex_oid) ? getoid(res, 0, 1) : getoid(res, 1, 1);
+ 
+ 	if (!(aquire_lock(conn, "LOCK TABLE pg_class IN ROW EXCLUSIVE MODE", progname, echo)))
+ 	{
+ 		fprintf(stderr, _("aquire_lock failed in connection for pa_class"));
+ 		return false;
+ 	}
+ 
+ 
+ 	resetPQExpBuffer(&sql);
+ 	appendPQExpBuffer(&sql,
+ 					  "UPDATE pg_class SET relfilenode = %u WHERE oid = %u", tmp_filenode, index);
+ 	executeCommand(conn, sql.data, progname, echo);
+ 	resetPQExpBuffer(&sql);
+ 	appendPQExpBuffer(&sql,
+ 					  "UPDATE pg_class SET relfilenode = %u WHERE oid = %u", orig_filenode, tmpindex_oid);
+ 	executeCommand(conn, sql.data, progname, echo);
+ 
+ 	PQclear(res);
+ 	termPQExpBuffer(&sql);
+ 
+ 	return true;
+ }
+ 
+ static void
+ parse_indexdef(IndexDef *stmt, const char *indexdef, const char *indexname, const char *tablename, Oid index, Oid table)
+ {
+ 
+ 	const char *limit = strchr(indexdef, '\0');
+ 	char *orig = (char*)indexdef;
+ 
+ 	/* CREATE [UNIQUE] INDEX */
+ 	stmt->create = orig;
+ 	orig = skip_const(index, orig, "CREATE INDEX", "CREATE UNIQUE INDEX");
+ 	/* index */
+ 	stmt->index = orig;
+ 	orig = skip_const(index, orig, indexname, NULL);
+ 	/* ON */
+ 	orig = skip_const(index, orig, "ON", NULL);
+ 	/* table */
+ 	stmt->table = orig;
+ 	orig = skip_until(index, orig, ' ');
+ 	/* USING */
+ 	orig = skip_const(index, orig, "USING", NULL);
+ 	/* type */
+ 	stmt->type = orig;
+ 	orig = skip_ident(index, orig);
+ 	/* (columns) */
+ 	if ((orig = strchr(orig, '(')) == NULL)
+ 		parse_error(index);
+ 
+ 	orig++;
+ 	stmt->columns = orig;
+ 	if ((orig = skip_until(index, orig, ')')) == NULL)
+ 		parse_error(index);
+ 
+ 	/* options */
+ 	stmt->options = orig;
+ 	stmt->tablespace = NULL;
+ 	stmt->where = NULL;
+ 
+ 	/* Is there a tablespace? Note that apparently there is never, but
+ 	 * if there was one it would appear here. */
+ 	if (orig< limit && strstr(orig, "TABLESPACE"))
+ 	{
+ 		orig = skip_until_const(index, orig, "TABLESPACE");
+ 		stmt->tablespace = orig;
+ 		orig = skip_ident(index, orig);
+ 	}
+ 
+ 	/* Note: assuming WHERE is the only clause allowed after TABLESPACE */
+ 	if (orig < limit && strstr(orig, "WHERE"))
+ 	{
+ 		orig = skip_until_const(index, orig, "WHERE");
+ 		stmt->where = orig;
+ 	}
+ }
+ 
+ static bool
+ reindex_indexes(PGconn *conn, PGresult *res, const char *progname, bool echo)
+ {
+ 	PGresult *res2 = NULL;
+ 	PQExpBufferData sql;
+ 	int num = PQntuples(res);
+ 	int i = 0;
+ 	Oid indexoid, tableoid;
+ 	char *schemaname, *tablename, *indexname, *indexdef;
+ 	bool ret = false;
+ 
+ 	initPQExpBuffer(&sql);
+ 
+ 	for (i = 0; i < num; i++)
+ 	{
+ 		IndexDef stmt;
+ 
+ 		indexoid   = getoid(res, i, 0);
+ 		indexname  = getstr(res, i, 1);
+ 		tableoid   = getoid(res, i, 2);
+ 		tablename  = getstr(res, i, 3);
+ 		schemaname = getstr(res, i, 4);
+ 		indexdef   = getstr(res, i, 5);
+ 
+ 		/* Check if new index exist already */
+ 		appendPQExpBuffer(&sql,
+ 						  "SELECT oid FROM pg_class pgc "
+ 						  "WHERE relname = 'index_%u'", indexoid);
+ 		res2 = executeQuery(conn, sql.data, progname, echo);
+ 		resetPQExpBuffer(&sql);
+ 
+ 		if (PQntuples(res2) > 0)
+ 		{
+ 			fprintf(stderr,
+ 					_("%s: \"%s\".\"index_%u\" already exists, skip reindexing concurrently")
+ 					, progname, schemaname, indexoid);
+ 			PQclear(res2);
+ 			continue;
+ 		}
+ 
+ 		parse_indexdef(&stmt, indexdef, indexname, tablename, indexoid, tableoid);
+ 
+ 		appendPQExpBuffer(&sql, "%s CONCURRENTLY index_%u ON %s USING %s (%s)%s",
+ 						 stmt.create, indexoid, stmt.table, stmt.type, stmt.columns, stmt.options);
+ 
+ 		if (stmt.tablespace)
+ 			appendPQExpBuffer(&sql, " TABLESPACE %s",
+ 							 stmt.tablespace);
+ 		if (stmt.where)
+ 			appendPQExpBuffer(&sql, " WHERE %s", stmt.where);
+ 
+ 		/* Create index concurrently */
+ 		if(!executeMaintenanceCommand(conn, sql.data, echo ))
+ 		{
+ 			fprintf(stderr,
+ 					_("%s: Cannot create index concurrently \"%s\".\"index_%u\""),
+ 					  progname, schemaname, indexoid);
+ 			ret = false;
+ 			break;
+ 		}
+ 
+ 		resetPQExpBuffer(&sql);
+ 		appendPQExpBuffer(&sql, "LOCK TABLE %s IN ACCESS EXCLUSIVE MODE",
+ 						 stmt.table);
+ 
+ 		/* Aquire ACCESS EXCLUSIVE LOCK for table */
+ 		if (!(aquire_lock(conn, sql.data, progname, echo)))
+ 		{
+ 			fprintf(stderr, "aquire_lock() failed in connection for %s",
+ 				 tablename);
+ 			goto drop_idx;
+ 		}
+ 
+ 		ret = swap_index(conn, indexoid, progname, echo);
+ 		executeCommand(conn, "COMMIT", progname, echo);
+ 
+ drop_idx:
+ 		PQclear(res2);
+ 		resetPQExpBuffer(&sql);
+ 		appendPQExpBuffer(&sql, "DROP INDEX %s.index_%u", schemaname, indexoid);
+ 		executeMaintenanceCommand(conn, sql.data, echo);
+ 		resetPQExpBuffer(&sql);
+ 	}
+ 
+ 	termPQExpBuffer(&sql);
+ 	return ret;
+ 
+ }
+ 
  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 concurrently)
  {
  	PQExpBufferData sql;
  
***************
*** 246,276 **** reindex_one_database(const char *name, const char *dbname, const char *type,
  
  	initPQExpBuffer(&sql);
  
- 	appendPQExpBufferStr(&sql, "REINDEX");
- 	if (strcmp(type, "TABLE") == 0)
- 		appendPQExpBuffer(&sql, " TABLE %s", name);
- 	else if (strcmp(type, "INDEX") == 0)
- 		appendPQExpBuffer(&sql, " INDEX %s", name);
- 	else if (strcmp(type, "DATABASE") == 0)
- 		appendPQExpBuffer(&sql, " DATABASE %s", fmtId(name));
- 	appendPQExpBufferStr(&sql, ";");
- 
  	conn = connectDatabase(dbname, host, port, username, prompt_password,
  						   progname, false);
  
! 	if (!executeMaintenanceCommand(conn, sql.data, echo))
  	{
  		if (strcmp(type, "TABLE") == 0)
! 			fprintf(stderr, _("%s: reindexing of table \"%s\" in database \"%s\" failed: %s"),
! 					progname, name, dbname, PQerrorMessage(conn));
! 		if (strcmp(type, "INDEX") == 0)
! 			fprintf(stderr, _("%s: reindexing of index \"%s\" in database \"%s\" failed: %s"),
! 					progname, name, dbname, PQerrorMessage(conn));
! 		else
! 			fprintf(stderr, _("%s: reindexing of database \"%s\" failed: %s"),
! 					progname, dbname, PQerrorMessage(conn));
! 		PQfinish(conn);
! 		exit(1);
  	}
  
  	PQfinish(conn);
--- 661,734 ----
  
  	initPQExpBuffer(&sql);
  
  	conn = connectDatabase(dbname, host, port, username, prompt_password,
  						   progname, false);
  
! 	if (!concurrently)
  	{
+ 		appendPQExpBufferStr(&sql, "REINDEX");
  		if (strcmp(type, "TABLE") == 0)
! 			appendPQExpBuffer(&sql, " TABLE %s", name);
! 		else if (strcmp(type, "INDEX") == 0)
! 			appendPQExpBuffer(&sql, " INDEX %s", name);
! 		else if (strcmp(type, "DATABASE") == 0)
! 			appendPQExpBuffer(&sql, " DATABASE %s", fmtId(name));
! 		appendPQExpBufferStr(&sql, ";");
! 
! 
! 		if (!executeMaintenanceCommand(conn, sql.data, echo))
! 		{
! 			if (strcmp(type, "TABLE") == 0)
! 				fprintf(stderr, _("%s: reindexing of table \"%s\" in database \"%s\" failed: %s"),
! 						progname, name, dbname, PQerrorMessage(conn));
! 			if (strcmp(type, "INDEX") == 0)
! 				fprintf(stderr, _("%s: reindexing of index \"%s\" in database \"%s\" failed: %s"),
! 						progname, name, dbname, PQerrorMessage(conn));
! 			else
! 				fprintf(stderr, _("%s: reindexing of database \"%s\" failed: %s"),
! 						progname, dbname, PQerrorMessage(conn));
! 			PQfinish(conn);
! 			exit(1);
! 		}
! 	}
! 	else
! 	{
! 		PGresult *res = NULL;
! 
! 		/* We get informations are neccesary to swap index */
! 		appendPQExpBufferStr(&sql,
! 							 "SELECT pgind.indexrelid, pgc1.relname, pgc2.oid,"
! 							 " pgc2.relname, nsp.nspname, inddef.indexdef "
! 							 "FROM pg_class pgc1, pg_class pgc2, pg_index pgind, "
! 							 "pg_namespace nsp, pg_indexes inddef "
! 							 "WHERE pgc1.oid = pgind.indexrelid AND pgc2.oid = pgind.indrelid "
! 							 "AND pgc2.relnamespace = nsp.oid AND inddef.schemaname = nsp.nspname "
! 							 "AND inddef.indexname = pgc1.relname AND pgind.indisvalid "
! 							 "AND nsp.nspname NOT IN ('pg_catalog', 'information_schema') "	);
! 		if (strcmp(type, "TABLE") == 0)
! 			appendPQExpBuffer(&sql, "AND pgc2.relname = '%s' ", name);
! 		else if (strcmp(type, "INDEX") == 0)
! 			appendPQExpBuffer(&sql, "AND pgc1.relname = '%s' ", name);
! 
! 		appendPQExpBufferStr(&sql, "ORDER BY nsp.nspname, pgc1.relname");
! 
! 		res = executeQuery(conn, sql.data, progname, echo);
! 
! 		if (PQntuples(res) == 0)
! 		{
! 			if (strcmp(type, "DATABASE") == 0 || strcmp(type, "TABLE") == 0)
! 				fprintf(stderr,
! 						_("%s : \"%s\" \"%s\" dose not have any index\n"),
! 						progname, name, type);
! 			else
! 				fprintf(stderr,
! 						_("%s: \"%s\" INDEX dose not exist\n"),
! 						progname, name);
! 			PQfinish(conn);
! 			termPQExpBuffer(&sql);
! 			exit(1);
! 		}
! 		reindex_indexes(conn, res, progname, echo);
  	}
  
  	PQfinish(conn);
***************
*** 281,287 **** 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)
  {
  	PGconn	   *conn;
  	PGresult   *result;
--- 739,745 ----
  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 concurrently, bool quiet)
  {
  	PGconn	   *conn;
  	PGresult   *result;
***************
*** 303,309 **** reindex_all_databases(const char *maintenance_db,
  		}
  
  		reindex_one_database(dbname, dbname, "DATABASE", host, port, username,
! 							 prompt_password, progname, echo);
  	}
  
  	PQclear(result);
--- 761,767 ----
  		}
  
  		reindex_one_database(dbname, dbname, "DATABASE", host, port, username,
! 							 prompt_password, progname, echo, concurrently);
  	}
  
  	PQclear(result);
***************
*** 343,348 **** help(const char *progname)
--- 801,807 ----
  	printf(_("  %s [OPTION]... [DBNAME]\n"), progname);
  	printf(_("\nOptions:\n"));
  	printf(_("  -a, --all                 reindex all databases\n"));
+ 	printf(_("  -C, --concurrently        reindex concurrently\n"));
  	printf(_("  -d, --dbname=DBNAME       database to reindex\n"));
  	printf(_("  -e, --echo                show the commands being sent to the server\n"));
  	printf(_("  -i, --index=INDEX         recreate specific index(es) only\n"));
