Proposal : REINDEX SCHEMA
Hi all,
Attached WIP patch adds new syntax REINEX SCHEMA which does reindexing
all table of specified schema.
There are syntax dose reindexing specified index, per table and per database,
but we can not do reindexing per schema for now.
So we must use reindexdb command if we want to do.
This new syntax supports it as SQL command.
This use similar logic as REINDEX DATABASE, but we can use it in
transaction block.
Here is some example,
-- Table information
[postgres][5432](1)=# \d n1.hoge
Table "n1.hoge"
Column | Type | Modifiers
--------+---------+-----------
col | integer | not null
Indexes:
"hoge_pkey" PRIMARY KEY, btree (col)
[postgres][5432](1)=# \d n2.hoge
Table "n2.hoge"
Column | Type | Modifiers
--------+---------+-----------
col | integer |
[postgres][5432](1)=# \d n3.hoge
Did not find any relation named "n3.hoge".
-- Do reindexing
[postgres][5432](1)=# reindex schema n1;
NOTICE: table "n1.hoge" was reindexed
REINDEX
[postgres][5432](1)=# reindex schema n2;
REINDEX
[postgres][5432](1)=# reindex schema n3;
NOTICE: schema"n3" does not hava any table
REINDEX
Please review and comment.
Regards,
-------
Sawada Masahiko
Attachments:
reindex_schema_v1.patchapplication/octet-stream; name=reindex_schema_v1.patchDownload
*** a/doc/src/sgml/ref/reindex.sgml
--- b/doc/src/sgml/ref/reindex.sgml
***************
*** 21,27 **** PostgreSQL documentation
<refsynopsisdiv>
<synopsis>
! REINDEX { INDEX | TABLE | DATABASE | SYSTEM } <replaceable class="PARAMETER">name</replaceable> [ FORCE ]
</synopsis>
</refsynopsisdiv>
--- 21,27 ----
<refsynopsisdiv>
<synopsis>
! REINDEX { INDEX | TABLE | SCHEMA | DATABASE | SYSTEM } <replaceable class="PARAMETER">name</replaceable> [ FORCE ]
</synopsis>
</refsynopsisdiv>
***************
*** 101,106 **** REINDEX { INDEX | TABLE | DATABASE | SYSTEM } <replaceable class="PARAMETER">nam
--- 101,116 ----
</varlistentry>
<varlistentry>
+ <term><literal>SCHEMA</literal></term>
+ <listitem>
+ <para>
+ Recreate all indexes of all tables of the specified schema. If the table has a
+ secondary <quote>TOAST</> table, that is reindexed as well.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
<term><literal>DATABASE</literal></term>
<listitem>
<para>
*** a/src/backend/catalog/index.c
--- b/src/backend/catalog/index.c
***************
*** 3402,3407 **** reindex_relation(Oid relid, int flags)
--- 3402,3465 ----
return result;
}
+ /*
+ * reindex_schema - This routine is used to recreate all indexes
+ * of all relation of a namespace
+ */
+ bool
+ reindex_schema(Oid schemaOid)
+ {
+ ScanKeyData key[2];
+ HeapScanDesc scan;
+ HeapTuple tuple;
+ Relation relationRelation;
+ List *relids = NULL;
+ ListCell *l;
+
+ AssertArg(schemaOid);
+
+ ScanKeyInit(&key[0],
+ Anum_pg_class_relnamespace,
+ BTEqualStrategyNumber, F_OIDEQ,
+ ObjectIdGetDatum(schemaOid));
+ ScanKeyInit(&key[1],
+ Anum_pg_class_relkind,
+ BTEqualStrategyNumber, F_CHAREQ,
+ 'r');
+
+ /*
+ * Scan pg_class by relnamespace to build a list of the relations we need to reindex.
+ */
+ relationRelation = heap_open(RelationRelationId, AccessShareLock);
+ scan = heap_beginscan_catalog(relationRelation, 2, key);
+
+ while ((tuple = heap_getnext(scan, ForwardScanDirection)) != NULL)
+ {
+ relids = lappend_oid(relids, HeapTupleGetOid(tuple));
+ }
+
+ heap_endscan(scan);
+ heap_close(relationRelation, AccessShareLock);
+
+ if (relids == NULL)
+ /* The schema does not have any table */
+ return false;
+
+ /* now reindex each relation by using reindex_relation */
+ foreach(l, relids)
+ {
+ Oid relid = lfirst_oid(l);
+ if (reindex_relation(relid,
+ REINDEX_REL_PROCESS_TOAST |
+ REINDEX_REL_CHECK_CONSTRAINTS))
+ ereport(NOTICE,
+ (errmsg("table \"%s.%s\" was reindexed",
+ get_namespace_name(schemaOid),
+ get_rel_name(relid))));
+ }
+
+ return true;
+ }
/* ----------------------------------------------------------------
* System index reindexing support
*** a/src/backend/commands/indexcmds.c
--- b/src/backend/commands/indexcmds.c
***************
*** 1769,1774 **** ReindexTable(RangeVar *relation)
--- 1769,1789 ----
return heapOid;
}
+ Oid
+ ReindexSchema(RangeVar *schema)
+ {
+ Oid heapOid;
+
+ heapOid = get_namespace_oid(schema->relname, false);
+
+ if (!reindex_schema(heapOid))
+ ereport(NOTICE,
+ (errmsg("schema\"%s\" does not hava any table",
+ schema->relname)));
+
+ return heapOid;
+ }
+
/*
* ReindexDatabase
* Recreate indexes of a database.
*** a/src/backend/parser/gram.y
--- b/src/backend/parser/gram.y
***************
*** 7211,7216 **** ReindexStmt:
--- 7211,7217 ----
reindex_type:
INDEX { $$ = OBJECT_INDEX; }
| TABLE { $$ = OBJECT_TABLE; }
+ | SCHEMA { $$ = OBJECT_SCHEMA; }
;
opt_force: FORCE { $$ = TRUE; }
*** a/src/backend/tcop/utility.c
--- b/src/backend/tcop/utility.c
***************
*** 755,760 **** standard_ProcessUtility(Node *parsetree,
--- 755,763 ----
case OBJECT_MATVIEW:
ReindexTable(stmt->relation);
break;
+ case OBJECT_SCHEMA:
+ ReindexSchema(stmt->relation);
+ break;
case OBJECT_DATABASE:
/*
*** a/src/include/catalog/index.h
--- b/src/include/catalog/index.h
***************
*** 110,115 **** extern void reindex_index(Oid indexId, bool skip_constraint_checks);
--- 110,116 ----
#define REINDEX_REL_CHECK_CONSTRAINTS 0x04
extern bool reindex_relation(Oid relid, int flags);
+ extern bool reindex_schema(Oid schemaOid);
extern bool ReindexIsProcessingHeap(Oid heapOid);
extern bool ReindexIsProcessingIndex(Oid indexOid);
*** a/src/include/commands/defrem.h
--- b/src/include/commands/defrem.h
***************
*** 30,35 **** extern Oid DefineIndex(Oid relationId,
--- 30,36 ----
bool quiet);
extern Oid ReindexIndex(RangeVar *indexRelation);
extern Oid ReindexTable(RangeVar *relation);
+ extern Oid ReindexSchema(RangeVar *schema);
extern Oid ReindexDatabase(const char *databaseName,
bool do_system, bool do_user);
extern char *makeObjectName(const char *name1, const char *name2,
Sawada Masahiko wrote:
Hi all,
Attached WIP patch adds new syntax REINEX SCHEMA which does reindexing
all table of specified schema.
There are syntax dose reindexing specified index, per table and per database,
but we can not do reindexing per schema for now.
It seems doubtful that there really is much use for this feature, but if
there is, I think a better syntax precedent is the new ALTER TABLE ALL
IN TABLESPACE thingy, rather than your proposed REINDEX SCHEMA.
Something like REINDEX TABLE ALL IN SCHEMA perhaps.
--
�lvaro Herrera 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
* Alvaro Herrera (alvherre@2ndquadrant.com) wrote:
Sawada Masahiko wrote:
Attached WIP patch adds new syntax REINEX SCHEMA which does reindexing
all table of specified schema.
There are syntax dose reindexing specified index, per table and per database,
but we can not do reindexing per schema for now.It seems doubtful that there really is much use for this feature, but if
there is, I think a better syntax precedent is the new ALTER TABLE ALL
IN TABLESPACE thingy, rather than your proposed REINDEX SCHEMA.
Something like REINDEX TABLE ALL IN SCHEMA perhaps.
Yeah, I tend to agree that we should be looking at the 'ALL IN
TABLESPACE' and 'ALL IN SCHEMA' type of commands to keep things
consistent. This might be an alternative for the vacuum / analyze /
reindex database commands also..
Thanks,
Stephen
On Sun, Oct 12, 2014 at 2:27 PM, Stephen Frost <sfrost@snowman.net> wrote:
* Alvaro Herrera (alvherre@2ndquadrant.com) wrote:
Sawada Masahiko wrote:
Attached WIP patch adds new syntax REINEX SCHEMA which does reindexing
all table of specified schema.
There are syntax dose reindexing specified index, per table and per
database,
but we can not do reindexing per schema for now.
It seems doubtful that there really is much use for this feature, but if
there is, I think a better syntax precedent is the new ALTER TABLE ALL
IN TABLESPACE thingy, rather than your proposed REINDEX SCHEMA.
Something like REINDEX TABLE ALL IN SCHEMA perhaps.Yeah, I tend to agree that we should be looking at the 'ALL IN
TABLESPACE' and 'ALL IN SCHEMA' type of commands to keep things
consistent. This might be an alternative for the vacuum / analyze /
reindex database commands also..
Some review:
1) +1 to "REINDEX ALL IN SCHEMA name"
2) IMHO the logic should be exactly the same as REINDEX DATABASE, including
the transaction control. Imagine a schema with a lot of tables, you can
lead to a deadlock using just one transaction block.
3) The patch was applied to master and compile without warnings
4) Typo (... does not have any table)
+ if (!reindex_schema(heapOid))
+ ereport(NOTICE,
+ (errmsg("schema\"%s\" does not hava any table",
+ schema->relname)));
5) Missing of regression tests, please add it to
src/test/regress/sql/create_index.sql
6) You need to add psql complete tabs
7) I think we can add "-S / --schema" option do reindexdb in this patch
too. What do you think?
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
On Mon, Oct 13, 2014 at 1:25 PM, Fabrízio de Royes Mello
<fabriziomello@gmail.com> wrote:
On Sun, Oct 12, 2014 at 2:27 PM, Stephen Frost <sfrost@snowman.net> wrote:
* Alvaro Herrera (alvherre@2ndquadrant.com) wrote:
Sawada Masahiko wrote:
Attached WIP patch adds new syntax REINEX SCHEMA which does reindexing
all table of specified schema.
There are syntax dose reindexing specified index, per table and per
database,
but we can not do reindexing per schema for now.It seems doubtful that there really is much use for this feature, but if
there is, I think a better syntax precedent is the new ALTER TABLE ALL
IN TABLESPACE thingy, rather than your proposed REINDEX SCHEMA.
Something like REINDEX TABLE ALL IN SCHEMA perhaps.Yeah, I tend to agree that we should be looking at the 'ALL IN
TABLESPACE' and 'ALL IN SCHEMA' type of commands to keep things
consistent. This might be an alternative for the vacuum / analyze /
reindex database commands also..Some review:
1) +1 to "REINDEX ALL IN SCHEMA name"
Thank you for comment and reviewing!
I agree with this.
I will change syntax to above like that.
2) IMHO the logic should be exactly the same as REINDEX DATABASE, including
the transaction control. Imagine a schema with a lot of tables, you can lead
to a deadlock using just one transaction block.
Yep, it should be same as REINDEX DATABASE.
IMO, we can put them into one function if they use exactly same logic.
Thought?
3) The patch was applied to master and compile without warnings
4) Typo (... does not have any table)
+ if (!reindex_schema(heapOid)) + ereport(NOTICE, + (errmsg("schema\"%s\" does not hava any table", + schema->relname)));
Thanks! I will correct typo.
5) Missing of regression tests, please add it to
src/test/regress/sql/create_index.sql6) You need to add psql complete tabs
Next version patch, that I will submit, will have 5), 6) things you pointed.
7) I think we can add "-S / --schema" option do reindexdb in this patch too.
What do you think?
+1 to add "-S / --schema" option
I was misunderstanding about that.
I will make the patch which adds this option as separate 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
On Mon, Oct 13, 2014 at 5:39 AM, Sawada Masahiko <sawada.mshk@gmail.com>
wrote:
On Mon, Oct 13, 2014 at 1:25 PM, Fabrízio de Royes Mello
<fabriziomello@gmail.com> wrote:On Sun, Oct 12, 2014 at 2:27 PM, Stephen Frost <sfrost@snowman.net>
wrote:
* Alvaro Herrera (alvherre@2ndquadrant.com) wrote:
Sawada Masahiko wrote:
Attached WIP patch adds new syntax REINEX SCHEMA which does
reindexing
all table of specified schema.
There are syntax dose reindexing specified index, per table and per
database,
but we can not do reindexing per schema for now.It seems doubtful that there really is much use for this feature,
but if
there is, I think a better syntax precedent is the new ALTER TABLE
ALL
IN TABLESPACE thingy, rather than your proposed REINDEX SCHEMA.
Something like REINDEX TABLE ALL IN SCHEMA perhaps.Yeah, I tend to agree that we should be looking at the 'ALL IN
TABLESPACE' and 'ALL IN SCHEMA' type of commands to keep things
consistent. This might be an alternative for the vacuum / analyze /
reindex database commands also..Some review:
1) +1 to "REINDEX ALL IN SCHEMA name"
Thank you for comment and reviewing!
I agree with this.
I will change syntax to above like that.2) IMHO the logic should be exactly the same as REINDEX DATABASE,
including
the transaction control. Imagine a schema with a lot of tables, you can
lead
to a deadlock using just one transaction block.
Yep, it should be same as REINDEX DATABASE.
IMO, we can put them into one function if they use exactly same logic.
Thought?3) The patch was applied to master and compile without warnings
4) Typo (... does not have any table)
+ if (!reindex_schema(heapOid)) + ereport(NOTICE, + (errmsg("schema\"%s\" does not hava any table", + schema->relname)));Thanks! I will correct typo.
5) Missing of regression tests, please add it to
src/test/regress/sql/create_index.sql6) You need to add psql complete tabs
Next version patch, that I will submit, will have 5), 6) things you
pointed.
7) I think we can add "-S / --schema" option do reindexdb in this patch
too.
What do you think?
+1 to add "-S / --schema" option
I was misunderstanding about that.
I will make the patch which adds this option as separate patch.
I registered to the next commitfest [1]https://commitfest.postgresql.org/action/patch_view?id=1598 and put myself as reviewer.
Regards,
[1]: https://commitfest.postgresql.org/action/patch_view?id=1598
--
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
On Sun, Oct 12, 2014 at 1:27 PM, Stephen Frost <sfrost@snowman.net> wrote:
* Alvaro Herrera (alvherre@2ndquadrant.com) wrote:
Sawada Masahiko wrote:
Attached WIP patch adds new syntax REINEX SCHEMA which does reindexing
all table of specified schema.
There are syntax dose reindexing specified index, per table and per database,
but we can not do reindexing per schema for now.It seems doubtful that there really is much use for this feature, but if
there is, I think a better syntax precedent is the new ALTER TABLE ALL
IN TABLESPACE thingy, rather than your proposed REINDEX SCHEMA.
Something like REINDEX TABLE ALL IN SCHEMA perhaps.Yeah, I tend to agree that we should be looking at the 'ALL IN
TABLESPACE' and 'ALL IN SCHEMA' type of commands to keep things
consistent. This might be an alternative for the vacuum / analyze /
reindex database commands also..
Urgh. I don't have a problem with that syntax in general, but it
clashes pretty awfully with what we're already doing for REINDEX
otherwise.
--
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
On Mon, Oct 13, 2014 at 11:16 PM, Robert Haas <robertmhaas@gmail.com> wrote:
On Sun, Oct 12, 2014 at 1:27 PM, Stephen Frost <sfrost@snowman.net> wrote:
* Alvaro Herrera (alvherre@2ndquadrant.com) wrote:
Sawada Masahiko wrote:
Attached WIP patch adds new syntax REINEX SCHEMA which does reindexing
all table of specified schema.
There are syntax dose reindexing specified index, per table and per database,
but we can not do reindexing per schema for now.It seems doubtful that there really is much use for this feature, but if
there is, I think a better syntax precedent is the new ALTER TABLE ALL
IN TABLESPACE thingy, rather than your proposed REINDEX SCHEMA.
Something like REINDEX TABLE ALL IN SCHEMA perhaps.Yeah, I tend to agree that we should be looking at the 'ALL IN
TABLESPACE' and 'ALL IN SCHEMA' type of commands to keep things
consistent. This might be an alternative for the vacuum / analyze /
reindex database commands also..Urgh. I don't have a problem with that syntax in general, but it
clashes pretty awfully with what we're already doing for REINDEX
otherwise.
Attached patches are latest version patch.
I changed syntax to REINDEX ALL IN SCHEMA, but I felt a sense of
discomfort a little
as Robert mentioned.
Anyway, you can apply these patches in numerical order,
can use REINDEX ALL IN SCHEMA feature and "-S/--schema" option in reindexdb.
000_reindex_all_in_schema_v2.patch : It contains REINDEX ALL IN SCHEMA feature
001_Add_schema_option_to_reindexdb_v1.patch : It contains reindexdb
"-S/--schema" supporting
Please review and comments.
Regards,
-------
Sawada Masahiko
Attachments:
000_reindex_all_in_schema_v2.patchapplication/octet-stream; name=000_reindex_all_in_schema_v2.patchDownload
diff --git a/doc/src/sgml/ref/reindex.sgml b/doc/src/sgml/ref/reindex.sgml
index cabae19..e47604c 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 | DATABASE | SYSTEM } <replaceable class="PARAMETER">name</replaceable> [ FORCE ]
+REINDEX { INDEX | TABLE | ALL IN SCHEMA | DATABASE | SYSTEM } <replaceable class="PARAMETER">name</replaceable> [ FORCE ]
</synopsis>
</refsynopsisdiv>
@@ -101,6 +101,19 @@ REINDEX { INDEX | TABLE | DATABASE | SYSTEM } <replaceable class="PARAMETER">nam
</varlistentry>
<varlistentry>
+ <term><literal>ALL IN SCHEMA</literal></term>
+ <listitem>
+ <para>
+ Recreate all indexes of the specified schema. If the table has a
+ secondary <quote>TOAST</> table, that is reindexed as well.
+ Indexes on shared system catalogs are also processed.
+ This form of <command>REINDEX</command> cannot be executed inside a
+ transaction block.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
<term><literal>DATABASE</literal></term>
<listitem>
<para>
diff --git a/src/backend/commands/indexcmds.c b/src/backend/commands/indexcmds.c
index 8a1cb4b..eb8451b 100644
--- a/src/backend/commands/indexcmds.c
+++ b/src/backend/commands/indexcmds.c
@@ -1770,34 +1770,48 @@ ReindexTable(RangeVar *relation)
}
/*
- * ReindexDatabase
- * Recreate indexes of a database.
+ * ReindexDatabaseOrSchema
+ * Recreate indexes of a database or schema.
*
+ * kind means the type of object, database or schema.
* To reduce the probability of deadlocks, each table is reindexed in a
* separate transaction, so we can release the lock on it right away.
* That means this must not be called within a user transaction block!
*/
Oid
-ReindexDatabase(const char *databaseName, bool do_system, bool do_user)
+ReindexDatabaseOrSchema(const char *objectName, bool do_system, bool do_user, ObjectType kind)
{
+ Oid objectOid;
Relation relationRelation;
HeapScanDesc scan;
+ ScanKeyData *key = NULL;
HeapTuple tuple;
MemoryContext private_context;
MemoryContext old;
List *relids = NIL;
ListCell *l;
+ bool do_database = (kind == OBJECT_DATABASE) ? true : false;
+ int nkeys;
- AssertArg(databaseName);
+ AssertArg(objectName);
- if (strcmp(databaseName, get_database_name(MyDatabaseId)) != 0)
+ /* Get OID of object for result */
+ objectOid = (do_database) ? MyDatabaseId : get_namespace_oid(objectName, false);
+
+ if (!do_database)
+ {
+ do_system = IsSystemNamespace(objectOid);
+ do_user = !do_system;
+ }
+
+ if (do_database && strcmp(objectName, get_database_name(MyDatabaseId)) != 0)
ereport(ERROR,
(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
errmsg("can only reindex the currently open database")));
- if (!pg_database_ownercheck(MyDatabaseId, GetUserId()))
+ if (do_database && !pg_database_ownercheck(MyDatabaseId, GetUserId()))
aclcheck_error(ACLCHECK_NOT_OWNER, ACL_KIND_DATABASE,
- databaseName);
+ objectName);
/*
* Create a memory context that will survive forced transaction commits we
@@ -1806,7 +1820,8 @@ ReindexDatabase(const char *databaseName, bool do_system, bool do_user)
* abort cleanup logic.
*/
private_context = AllocSetContextCreate(PortalContext,
- "ReindexDatabase",
+ (do_database) ?
+ "ReindexDatabase" : "ReindexSchema",
ALLOCSET_DEFAULT_MINSIZE,
ALLOCSET_DEFAULT_INITSIZE,
ALLOCSET_DEFAULT_MAXSIZE);
@@ -1824,6 +1839,23 @@ ReindexDatabase(const char *databaseName, bool do_system, bool do_user)
MemoryContextSwitchTo(old);
}
+ /* For schema, we search target relations by relnamespce and relkind */
+ if (!do_database)
+ {
+ key = palloc(sizeof(ScanKeyData) * 2);
+ ScanKeyInit(&key[0],
+ Anum_pg_class_relnamespace,
+ BTEqualStrategyNumber, F_OIDEQ,
+ ObjectIdGetDatum(objectOid));
+ ScanKeyInit(&key[1],
+ Anum_pg_class_relkind,
+ BTEqualStrategyNumber, F_CHAREQ,
+ 'r');
+ nkeys = 2;
+ }
+ else
+ nkeys = 0;
+
/*
* Scan pg_class to build a list of the relations we need to reindex.
*
@@ -1831,7 +1863,7 @@ ReindexDatabase(const char *databaseName, bool do_system, bool do_user)
* rels will be processed indirectly by reindex_relation).
*/
relationRelation = heap_open(RelationRelationId, AccessShareLock);
- scan = heap_beginscan_catalog(relationRelation, 0, NULL);
+ scan = heap_beginscan_catalog(relationRelation, nkeys, key);
while ((tuple = heap_getnext(scan, ForwardScanDirection)) != NULL)
{
Form_pg_class classtuple = (Form_pg_class) GETSTRUCT(tuple);
@@ -1892,5 +1924,5 @@ ReindexDatabase(const char *databaseName, bool do_system, bool do_user)
MemoryContextDelete(private_context);
- return MyDatabaseId;
+ return objectOid;
}
diff --git a/src/backend/parser/gram.y b/src/backend/parser/gram.y
index c98c27a..6dfd10e 100644
--- a/src/backend/parser/gram.y
+++ b/src/backend/parser/gram.y
@@ -7197,6 +7197,14 @@ ReindexStmt:
n->do_user = false;
$$ = (Node *)n;
}
+ | REINDEX ALL IN_P SCHEMA name opt_force
+ {
+ ReindexStmt *n = makeNode(ReindexStmt);
+ n->kind = OBJECT_SCHEMA;
+ n->name = $5;
+ n->relation = NULL;
+ $$ = (Node *)n;
+ }
| REINDEX DATABASE name opt_force
{
ReindexStmt *n = makeNode(ReindexStmt);
diff --git a/src/backend/tcop/utility.c b/src/backend/tcop/utility.c
index 4a2a339..b5bda55 100644
--- a/src/backend/tcop/utility.c
+++ b/src/backend/tcop/utility.c
@@ -755,6 +755,7 @@ standard_ProcessUtility(Node *parsetree,
case OBJECT_MATVIEW:
ReindexTable(stmt->relation);
break;
+ case OBJECT_SCHEMA:
case OBJECT_DATABASE:
/*
@@ -764,9 +765,10 @@ standard_ProcessUtility(Node *parsetree,
* intended effect!
*/
PreventTransactionChain(isTopLevel,
- "REINDEX DATABASE");
- ReindexDatabase(stmt->name,
- stmt->do_system, stmt->do_user);
+ (stmt->kind == OBJECT_SCHEMA) ?
+ "REINDEX ALL IN SCHEMA" : "REINDEX DATABASE");
+ ReindexDatabaseOrSchema(stmt->name,
+ stmt->do_system, stmt->do_user, stmt->kind);
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 886188c..71e82ee 100644
--- a/src/bin/psql/tab-complete.c
+++ b/src/bin/psql/tab-complete.c
@@ -3330,7 +3330,7 @@ psql_completion(const char *text, int start, int end)
else if (pg_strcasecmp(prev_wd, "REINDEX") == 0)
{
static const char *const list_REINDEX[] =
- {"TABLE", "INDEX", "SYSTEM", "DATABASE", NULL};
+ {"TABLE", "INDEX", "SYSTEM", "ALL IN SCHEMA", "DATABASE", NULL};
COMPLETE_WITH_LIST(list_REINDEX);
}
@@ -3340,6 +3340,8 @@ 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, "ALL IN SCHEMA") == 0 )
+ COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_schemas, NULL);
else if (pg_strcasecmp(prev_wd, "SYSTEM") == 0 ||
pg_strcasecmp(prev_wd, "DATABASE") == 0)
COMPLETE_WITH_QUERY(Query_for_list_of_databases);
diff --git a/src/include/commands/defrem.h b/src/include/commands/defrem.h
index 0ebdbc1..330d05c 100644
--- a/src/include/commands/defrem.h
+++ b/src/include/commands/defrem.h
@@ -30,8 +30,8 @@ extern Oid DefineIndex(Oid relationId,
bool quiet);
extern Oid ReindexIndex(RangeVar *indexRelation);
extern Oid ReindexTable(RangeVar *relation);
-extern Oid ReindexDatabase(const char *databaseName,
- bool do_system, bool do_user);
+extern Oid ReindexDatabaseOrSchema(const char *databaseName,
+ bool do_system, bool do_user, ObjectType kind);
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/test/regress/expected/create_index.out b/src/test/regress/expected/create_index.out
index a2bef7a..ba8be4c 100644
--- a/src/test/regress/expected/create_index.out
+++ b/src/test/regress/expected/create_index.out
@@ -2354,6 +2354,59 @@ Indexes:
"concur_index5" btree (f2) WHERE f1 = 'x'::text
"std_index" btree (f2)
+REINDEX ALL IN SCHEMA pg_catalog;
+NOTICE: table "pg_catalog.pg_class" was reindexed
+NOTICE: table "pg_catalog.pg_statistic" was reindexed
+NOTICE: table "pg_catalog.pg_type" was reindexed
+NOTICE: table "pg_catalog.pg_authid" was reindexed
+NOTICE: table "pg_catalog.pg_largeobject" was reindexed
+NOTICE: table "pg_catalog.pg_user_mapping" was reindexed
+NOTICE: table "pg_catalog.pg_attribute" was reindexed
+NOTICE: table "pg_catalog.pg_proc" was reindexed
+NOTICE: table "pg_catalog.pg_attrdef" was reindexed
+NOTICE: table "pg_catalog.pg_constraint" was reindexed
+NOTICE: table "pg_catalog.pg_inherits" was reindexed
+NOTICE: table "pg_catalog.pg_index" was reindexed
+NOTICE: table "pg_catalog.pg_opfamily" was reindexed
+NOTICE: table "pg_catalog.pg_opclass" was reindexed
+NOTICE: table "pg_catalog.pg_am" was reindexed
+NOTICE: table "pg_catalog.pg_amop" was reindexed
+NOTICE: table "pg_catalog.pg_amproc" was reindexed
+NOTICE: table "pg_catalog.pg_language" was reindexed
+NOTICE: table "pg_catalog.pg_largeobject_metadata" was reindexed
+NOTICE: table "pg_catalog.pg_aggregate" was reindexed
+NOTICE: table "pg_catalog.pg_rewrite" was reindexed
+NOTICE: table "pg_catalog.pg_trigger" was reindexed
+NOTICE: table "pg_catalog.pg_event_trigger" was reindexed
+NOTICE: table "pg_catalog.pg_description" was reindexed
+NOTICE: table "pg_catalog.pg_cast" was reindexed
+NOTICE: table "pg_catalog.pg_namespace" was reindexed
+NOTICE: table "pg_catalog.pg_conversion" was reindexed
+NOTICE: table "pg_catalog.pg_database" was reindexed
+NOTICE: table "pg_catalog.pg_db_role_setting" was reindexed
+NOTICE: table "pg_catalog.pg_tablespace" was reindexed
+NOTICE: table "pg_catalog.pg_pltemplate" was reindexed
+NOTICE: table "pg_catalog.pg_auth_members" was reindexed
+NOTICE: table "pg_catalog.pg_shdepend" was reindexed
+NOTICE: table "pg_catalog.pg_shdescription" was reindexed
+NOTICE: table "pg_catalog.pg_ts_config" was reindexed
+NOTICE: table "pg_catalog.pg_ts_config_map" was reindexed
+NOTICE: table "pg_catalog.pg_ts_dict" was reindexed
+NOTICE: table "pg_catalog.pg_ts_parser" was reindexed
+NOTICE: table "pg_catalog.pg_ts_template" was reindexed
+NOTICE: table "pg_catalog.pg_extension" was reindexed
+NOTICE: table "pg_catalog.pg_foreign_data_wrapper" was reindexed
+NOTICE: table "pg_catalog.pg_foreign_server" was reindexed
+NOTICE: table "pg_catalog.pg_foreign_table" was reindexed
+NOTICE: table "pg_catalog.pg_rowsecurity" was reindexed
+NOTICE: table "pg_catalog.pg_default_acl" was reindexed
+NOTICE: table "pg_catalog.pg_seclabel" was reindexed
+NOTICE: table "pg_catalog.pg_shseclabel" was reindexed
+NOTICE: table "pg_catalog.pg_collation" was reindexed
+NOTICE: table "pg_catalog.pg_range" was reindexed
+NOTICE: table "pg_catalog.pg_operator" was reindexed
+NOTICE: table "pg_catalog.pg_enum" was reindexed
+NOTICE: table "pg_catalog.pg_depend" was reindexed
--
-- Try some concurrent index drops
--
diff --git a/src/test/regress/sql/create_index.sql b/src/test/regress/sql/create_index.sql
index d4d24ef..b4ff9b9 100644
--- a/src/test/regress/sql/create_index.sql
+++ b/src/test/regress/sql/create_index.sql
@@ -743,6 +743,7 @@ VACUUM FULL concur_heap;
\d concur_heap
REINDEX TABLE concur_heap;
\d concur_heap
+REINDEX ALL IN SCHEMA pg_catalog;
--
-- Try some concurrent index drops
001_Add_schema_option_to_reindexdb_v1.patchapplication/octet-stream; name=001_Add_schema_option_to_reindexdb_v1.patchDownload
diff --git a/src/bin/scripts/reindexdb.c b/src/bin/scripts/reindexdb.c
index 561bbce..dbea347 100644
--- a/src/bin/scripts/reindexdb.c
+++ b/src/bin/scripts/reindexdb.c
@@ -41,6 +41,7 @@ main(int argc, char *argv[])
{"password", no_argument, NULL, 'W'},
{"echo", no_argument, NULL, 'e'},
{"quiet", no_argument, NULL, 'q'},
+ {"schema", required_argument, NULL, 'S'},
{"dbname", required_argument, NULL, 'd'},
{"all", no_argument, NULL, 'a'},
{"system", no_argument, NULL, 's'},
@@ -66,6 +67,7 @@ main(int argc, char *argv[])
bool quiet = false;
SimpleStringList indexes = {NULL, NULL};
SimpleStringList tables = {NULL, NULL};
+ SimpleStringList schemas = {NULL, NULL};
progname = get_progname(argv[0]);
set_pglocale_pgservice(argv[0], PG_TEXTDOMAIN("pgscripts"));
@@ -73,7 +75,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:wWeqd:ast:i:", long_options, &optindex)) != -1)
+ while ((c = getopt_long(argc, argv, "h:p:U:wWeqS:d:ast:i:", long_options, &optindex)) != -1)
{
switch (c)
{
@@ -98,6 +100,9 @@ main(int argc, char *argv[])
case 'q':
quiet = true;
break;
+ case 'S':
+ simple_string_list_append(&schemas, optarg);
+ break;
case 'd':
dbname = pg_strdup(optarg);
break;
@@ -154,6 +159,11 @@ main(int argc, char *argv[])
fprintf(stderr, _("%s: cannot reindex all databases and system catalogs at the same time\n"), progname);
exit(1);
}
+ if (schemas.head != NULL)
+ {
+ fprintf(stderr, _("%s: cannot reindex specific schema(s) in all databases\n"), progname);
+ exit(1);
+ }
if (tables.head != NULL)
{
fprintf(stderr, _("%s: cannot reindex specific table(s) in all databases\n"), progname);
@@ -170,6 +180,11 @@ main(int argc, char *argv[])
}
else if (syscatalog)
{
+ if (schemas.head != NULL)
+ {
+ fprintf(stderr, _("%s: cannot reindex specific schema(s) and system catalogs at the same time\n"), progname);
+ exit(1);
+ }
if (tables.head != NULL)
{
fprintf(stderr, _("%s: cannot reindex specific table(s) and system catalogs at the same time\n"), progname);
@@ -206,6 +221,17 @@ main(int argc, char *argv[])
dbname = get_user_name_or_exit(progname);
}
+ if (schemas.head != NULL)
+ {
+ SimpleStringListCell *cell;
+
+ for (cell = schemas.head; cell; cell = cell->next)
+ {
+ reindex_one_database(cell->val, dbname, "SCHEMA", host, port,
+ username, prompt_password, progname, echo);
+ }
+ }
+
if (indexes.head != NULL)
{
SimpleStringListCell *cell;
@@ -226,8 +252,8 @@ main(int argc, char *argv[])
username, prompt_password, progname, echo);
}
}
- /* reindex database only if neither index nor table is specified */
- if (indexes.head == NULL && tables.head == NULL)
+ /* 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);
}
@@ -251,6 +277,8 @@ reindex_one_database(const char *name, const char *dbname, const char *type,
appendPQExpBuffer(&sql, " TABLE %s", name);
else if (strcmp(type, "INDEX") == 0)
appendPQExpBuffer(&sql, " INDEX %s", name);
+ else if (strcmp(type, "SCHEMA") == 0)
+ appendPQExpBuffer(&sql, " ALL IN SCHEMA %s", name);
else if (strcmp(type, "DATABASE") == 0)
appendPQExpBuffer(&sql, " DATABASE %s", fmtId(name));
appendPQExpBufferStr(&sql, ";");
@@ -266,6 +294,9 @@ reindex_one_database(const char *name, const char *dbname, const char *type,
if (strcmp(type, "INDEX") == 0)
fprintf(stderr, _("%s: reindexing of index \"%s\" in database \"%s\" failed: %s"),
progname, name, dbname, PQerrorMessage(conn));
+ if (strcmp(type, "SCHEMA") == 0)
+ fprintf(stderr, _("%s: reindexing of schema \"%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));
@@ -348,6 +379,7 @@ help(const char *progname)
printf(_(" -i, --index=INDEX recreate specific index(es) only\n"));
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(_(" -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"));
On Wed, Oct 15, 2014 at 11:41 AM, Sawada Masahiko <sawada.mshk@gmail.com>
wrote:
On Mon, Oct 13, 2014 at 11:16 PM, Robert Haas <robertmhaas@gmail.com>
wrote:
On Sun, Oct 12, 2014 at 1:27 PM, Stephen Frost <sfrost@snowman.net>
wrote:
* Alvaro Herrera (alvherre@2ndquadrant.com) wrote:
Sawada Masahiko wrote:
Attached WIP patch adds new syntax REINEX SCHEMA which does
reindexing
all table of specified schema.
There are syntax dose reindexing specified index, per table and per
database,
but we can not do reindexing per schema for now.
It seems doubtful that there really is much use for this feature, but
if
there is, I think a better syntax precedent is the new ALTER TABLE ALL
IN TABLESPACE thingy, rather than your proposed REINDEX SCHEMA.
Something like REINDEX TABLE ALL IN SCHEMA perhaps.Yeah, I tend to agree that we should be looking at the 'ALL IN
TABLESPACE' and 'ALL IN SCHEMA' type of commands to keep things
consistent. This might be an alternative for the vacuum / analyze /
reindex database commands also..Urgh. I don't have a problem with that syntax in general, but it
clashes pretty awfully with what we're already doing for REINDEX
otherwise.Attached patches are latest version patch.
Ok.
I changed syntax to REINDEX ALL IN SCHEMA, but I felt a sense of
discomfort a little
as Robert mentioned.
I understood, but the real problem will in a near future when the features
will be pushed... :-)
They are separated features, but maybe we can join this features to a one
future commit... it's just an idea.
Anyway, you can apply these patches in numerical order,
can use REINDEX ALL IN SCHEMA feature and "-S/--schema" option in
reindexdb.
000_reindex_all_in_schema_v2.patch : It contains REINDEX ALL IN SCHEMA
feature
1) Compile without warnings
2) IMHO you can add more test cases to better code coverage:
* reindex a schema that doesn't exists
* try to run "reindex all in schema" inside a transaction block
3) Isn't enough just?
bool do_database = (kind == OBJECT_DATABASE);
... instead of...
+ bool do_database = (kind == OBJECT_DATABASE) ? true : false;
4) IMHO you can add other Assert to check valid relkinds, like:
Assert(kind == OBJECT_DATABASE || kind == OBJECT_SCHEMA);
5) I think is more legible:
/* Get OID of object for result */
if (do_database)
objectOid = MyDatabaseId
else
objectOid = get_namespace_oid(objectName, false);
... insead of ...
+ /* Get OID of object for result */
+ objectOid = (do_database) ? MyDatabaseId :
get_namespace_oid(objectName, false);
001_Add_schema_option_to_reindexdb_v1.patch : It contains reindexdb
"-S/--schema" supporting
The code itself is good for me, but IMHO you can add test cases
to src/bin/scripts/t/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
On Fri, Oct 17, 2014 at 4:32 AM, Fabrízio de Royes Mello
<fabriziomello@gmail.com> wrote:
On Wed, Oct 15, 2014 at 11:41 AM, Sawada Masahiko <sawada.mshk@gmail.com>
wrote:On Mon, Oct 13, 2014 at 11:16 PM, Robert Haas <robertmhaas@gmail.com>
wrote:On Sun, Oct 12, 2014 at 1:27 PM, Stephen Frost <sfrost@snowman.net>
wrote:* Alvaro Herrera (alvherre@2ndquadrant.com) wrote:
Sawada Masahiko wrote:
Attached WIP patch adds new syntax REINEX SCHEMA which does
reindexing
all table of specified schema.
There are syntax dose reindexing specified index, per table and per
database,
but we can not do reindexing per schema for now.It seems doubtful that there really is much use for this feature, but
if
there is, I think a better syntax precedent is the new ALTER TABLE ALL
IN TABLESPACE thingy, rather than your proposed REINDEX SCHEMA.
Something like REINDEX TABLE ALL IN SCHEMA perhaps.Yeah, I tend to agree that we should be looking at the 'ALL IN
TABLESPACE' and 'ALL IN SCHEMA' type of commands to keep things
consistent. This might be an alternative for the vacuum / analyze /
reindex database commands also..Urgh. I don't have a problem with that syntax in general, but it
clashes pretty awfully with what we're already doing for REINDEX
otherwise.Attached patches are latest version patch.
Ok.
I changed syntax to REINDEX ALL IN SCHEMA, but I felt a sense of
discomfort a little
as Robert mentioned.I understood, but the real problem will in a near future when the features
will be pushed... :-)They are separated features, but maybe we can join this features to a one
future commit... it's just an idea.Anyway, you can apply these patches in numerical order,
can use REINDEX ALL IN SCHEMA feature and "-S/--schema" option in
reindexdb.000_reindex_all_in_schema_v2.patch : It contains REINDEX ALL IN SCHEMA
feature1) Compile without warnings
2) IMHO you can add more test cases to better code coverage:
* reindex a schema that doesn't exists
* try to run "reindex all in schema" inside a transaction block3) Isn't enough just?
bool do_database = (kind == OBJECT_DATABASE);
... instead of...
+ bool do_database = (kind == OBJECT_DATABASE) ? true : false;
4) IMHO you can add other Assert to check valid relkinds, like:
Assert(kind == OBJECT_DATABASE || kind == OBJECT_SCHEMA);
5) I think is more legible:
/* Get OID of object for result */
if (do_database)
objectOid = MyDatabaseId
else
objectOid = get_namespace_oid(objectName, false);... insead of ...
+ /* Get OID of object for result */ + objectOid = (do_database) ? MyDatabaseId : get_namespace_oid(objectName, false);001_Add_schema_option_to_reindexdb_v1.patch : It contains reindexdb
"-S/--schema" supportingThe code itself is good for me, but IMHO you can add test cases to
src/bin/scripts/t/090_reindexdb.pl
Thank you for reviewing.
I agree 2) - 5).
Attached patch is latest version patch I modified above.
Also, I noticed I had forgotten to add the patch regarding document of
reindexdb.
Please review and comments.
Regards,
-------
Sawada Masahiko
Attachments:
000_reindex_all_in_schema_v3.patchapplication/octet-stream; name=000_reindex_all_in_schema_v3.patchDownload
diff --git a/doc/src/sgml/ref/reindex.sgml b/doc/src/sgml/ref/reindex.sgml
index cabae19..e47604c 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 | DATABASE | SYSTEM } <replaceable class="PARAMETER">name</replaceable> [ FORCE ]
+REINDEX { INDEX | TABLE | ALL IN SCHEMA | DATABASE | SYSTEM } <replaceable class="PARAMETER">name</replaceable> [ FORCE ]
</synopsis>
</refsynopsisdiv>
@@ -101,6 +101,19 @@ REINDEX { INDEX | TABLE | DATABASE | SYSTEM } <replaceable class="PARAMETER">nam
</varlistentry>
<varlistentry>
+ <term><literal>ALL IN SCHEMA</literal></term>
+ <listitem>
+ <para>
+ Recreate all indexes of the specified schema. If the table has a
+ secondary <quote>TOAST</> table, that is reindexed as well.
+ Indexes on shared system catalogs are also processed.
+ This form of <command>REINDEX</command> cannot be executed inside a
+ transaction block.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
<term><literal>DATABASE</literal></term>
<listitem>
<para>
diff --git a/src/backend/commands/indexcmds.c b/src/backend/commands/indexcmds.c
index 8a1cb4b..bd7e183 100644
--- a/src/backend/commands/indexcmds.c
+++ b/src/backend/commands/indexcmds.c
@@ -1770,34 +1770,52 @@ ReindexTable(RangeVar *relation)
}
/*
- * ReindexDatabase
- * Recreate indexes of a database.
+ * ReindexDatabaseOrSchema
+ * Recreate indexes of a database or schema.
*
+ * kind means the type of object, database or schema.
* To reduce the probability of deadlocks, each table is reindexed in a
* separate transaction, so we can release the lock on it right away.
* That means this must not be called within a user transaction block!
*/
Oid
-ReindexDatabase(const char *databaseName, bool do_system, bool do_user)
+ReindexDatabaseOrSchema(const char *objectName, bool do_system, bool do_user, ObjectType kind)
{
+ Oid objectOid;
Relation relationRelation;
HeapScanDesc scan;
+ ScanKeyData *key = NULL;
HeapTuple tuple;
MemoryContext private_context;
MemoryContext old;
List *relids = NIL;
ListCell *l;
+ bool do_database = (kind == OBJECT_DATABASE);
+ int nkeys;
- AssertArg(databaseName);
+ AssertArg(objectName);
+ Assert(kind == OBJECT_DATABASE || kind == OBJECT_SCHEMA);
- if (strcmp(databaseName, get_database_name(MyDatabaseId)) != 0)
+ /* Get OID of object for result */
+ if (do_database)
+ objectOid = MyDatabaseId;
+ else
+ objectOid = get_namespace_oid(objectName, false);
+
+ if (!do_database)
+ {
+ do_system = IsSystemNamespace(objectOid);
+ do_user = !do_system;
+ }
+
+ if (do_database && strcmp(objectName, get_database_name(MyDatabaseId)) != 0)
ereport(ERROR,
(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
errmsg("can only reindex the currently open database")));
- if (!pg_database_ownercheck(MyDatabaseId, GetUserId()))
+ if (do_database && !pg_database_ownercheck(MyDatabaseId, GetUserId()))
aclcheck_error(ACLCHECK_NOT_OWNER, ACL_KIND_DATABASE,
- databaseName);
+ objectName);
/*
* Create a memory context that will survive forced transaction commits we
@@ -1806,7 +1824,8 @@ ReindexDatabase(const char *databaseName, bool do_system, bool do_user)
* abort cleanup logic.
*/
private_context = AllocSetContextCreate(PortalContext,
- "ReindexDatabase",
+ (do_database) ?
+ "ReindexDatabase" : "ReindexSchema",
ALLOCSET_DEFAULT_MINSIZE,
ALLOCSET_DEFAULT_INITSIZE,
ALLOCSET_DEFAULT_MAXSIZE);
@@ -1824,6 +1843,23 @@ ReindexDatabase(const char *databaseName, bool do_system, bool do_user)
MemoryContextSwitchTo(old);
}
+ /* For schema, we search target relations by relnamespce and relkind */
+ if (!do_database)
+ {
+ key = palloc(sizeof(ScanKeyData) * 2);
+ ScanKeyInit(&key[0],
+ Anum_pg_class_relnamespace,
+ BTEqualStrategyNumber, F_OIDEQ,
+ ObjectIdGetDatum(objectOid));
+ ScanKeyInit(&key[1],
+ Anum_pg_class_relkind,
+ BTEqualStrategyNumber, F_CHAREQ,
+ 'r');
+ nkeys = 2;
+ }
+ else
+ nkeys = 0;
+
/*
* Scan pg_class to build a list of the relations we need to reindex.
*
@@ -1831,7 +1867,7 @@ ReindexDatabase(const char *databaseName, bool do_system, bool do_user)
* rels will be processed indirectly by reindex_relation).
*/
relationRelation = heap_open(RelationRelationId, AccessShareLock);
- scan = heap_beginscan_catalog(relationRelation, 0, NULL);
+ scan = heap_beginscan_catalog(relationRelation, nkeys, key);
while ((tuple = heap_getnext(scan, ForwardScanDirection)) != NULL)
{
Form_pg_class classtuple = (Form_pg_class) GETSTRUCT(tuple);
@@ -1892,5 +1928,5 @@ ReindexDatabase(const char *databaseName, bool do_system, bool do_user)
MemoryContextDelete(private_context);
- return MyDatabaseId;
+ return objectOid;
}
diff --git a/src/backend/parser/gram.y b/src/backend/parser/gram.y
index c98c27a..6dfd10e 100644
--- a/src/backend/parser/gram.y
+++ b/src/backend/parser/gram.y
@@ -7197,6 +7197,14 @@ ReindexStmt:
n->do_user = false;
$$ = (Node *)n;
}
+ | REINDEX ALL IN_P SCHEMA name opt_force
+ {
+ ReindexStmt *n = makeNode(ReindexStmt);
+ n->kind = OBJECT_SCHEMA;
+ n->name = $5;
+ n->relation = NULL;
+ $$ = (Node *)n;
+ }
| REINDEX DATABASE name opt_force
{
ReindexStmt *n = makeNode(ReindexStmt);
diff --git a/src/backend/tcop/utility.c b/src/backend/tcop/utility.c
index 4a2a339..b5bda55 100644
--- a/src/backend/tcop/utility.c
+++ b/src/backend/tcop/utility.c
@@ -755,6 +755,7 @@ standard_ProcessUtility(Node *parsetree,
case OBJECT_MATVIEW:
ReindexTable(stmt->relation);
break;
+ case OBJECT_SCHEMA:
case OBJECT_DATABASE:
/*
@@ -764,9 +765,10 @@ standard_ProcessUtility(Node *parsetree,
* intended effect!
*/
PreventTransactionChain(isTopLevel,
- "REINDEX DATABASE");
- ReindexDatabase(stmt->name,
- stmt->do_system, stmt->do_user);
+ (stmt->kind == OBJECT_SCHEMA) ?
+ "REINDEX ALL IN SCHEMA" : "REINDEX DATABASE");
+ ReindexDatabaseOrSchema(stmt->name,
+ stmt->do_system, stmt->do_user, stmt->kind);
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 886188c..106ec8a 100644
--- a/src/bin/psql/tab-complete.c
+++ b/src/bin/psql/tab-complete.c
@@ -3330,7 +3330,7 @@ psql_completion(const char *text, int start, int end)
else if (pg_strcasecmp(prev_wd, "REINDEX") == 0)
{
static const char *const list_REINDEX[] =
- {"TABLE", "INDEX", "SYSTEM", "DATABASE", NULL};
+ {"TABLE", "INDEX", "SYSTEM", "ALL IN SCHEMA", "DATABASE", NULL};
COMPLETE_WITH_LIST(list_REINDEX);
}
@@ -3340,6 +3340,8 @@ 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, "ALL IN 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);
diff --git a/src/include/commands/defrem.h b/src/include/commands/defrem.h
index 0ebdbc1..330d05c 100644
--- a/src/include/commands/defrem.h
+++ b/src/include/commands/defrem.h
@@ -30,8 +30,8 @@ extern Oid DefineIndex(Oid relationId,
bool quiet);
extern Oid ReindexIndex(RangeVar *indexRelation);
extern Oid ReindexTable(RangeVar *relation);
-extern Oid ReindexDatabase(const char *databaseName,
- bool do_system, bool do_user);
+extern Oid ReindexDatabaseOrSchema(const char *databaseName,
+ bool do_system, bool do_user, ObjectType kind);
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/test/regress/expected/create_index.out b/src/test/regress/expected/create_index.out
index a2bef7a..f2763fd 100644
--- a/src/test/regress/expected/create_index.out
+++ b/src/test/regress/expected/create_index.out
@@ -2354,6 +2354,63 @@ Indexes:
"concur_index5" btree (f2) WHERE f1 = 'x'::text
"std_index" btree (f2)
+REINDEX ALL IN SCHEMA pg_catalog;
+NOTICE: table "pg_catalog.pg_class" was reindexed
+NOTICE: table "pg_catalog.pg_statistic" was reindexed
+NOTICE: table "pg_catalog.pg_type" was reindexed
+NOTICE: table "pg_catalog.pg_authid" was reindexed
+NOTICE: table "pg_catalog.pg_largeobject" was reindexed
+NOTICE: table "pg_catalog.pg_user_mapping" was reindexed
+NOTICE: table "pg_catalog.pg_attribute" was reindexed
+NOTICE: table "pg_catalog.pg_proc" was reindexed
+NOTICE: table "pg_catalog.pg_attrdef" was reindexed
+NOTICE: table "pg_catalog.pg_constraint" was reindexed
+NOTICE: table "pg_catalog.pg_inherits" was reindexed
+NOTICE: table "pg_catalog.pg_index" was reindexed
+NOTICE: table "pg_catalog.pg_opfamily" was reindexed
+NOTICE: table "pg_catalog.pg_opclass" was reindexed
+NOTICE: table "pg_catalog.pg_am" was reindexed
+NOTICE: table "pg_catalog.pg_amop" was reindexed
+NOTICE: table "pg_catalog.pg_amproc" was reindexed
+NOTICE: table "pg_catalog.pg_language" was reindexed
+NOTICE: table "pg_catalog.pg_largeobject_metadata" was reindexed
+NOTICE: table "pg_catalog.pg_aggregate" was reindexed
+NOTICE: table "pg_catalog.pg_rewrite" was reindexed
+NOTICE: table "pg_catalog.pg_trigger" was reindexed
+NOTICE: table "pg_catalog.pg_event_trigger" was reindexed
+NOTICE: table "pg_catalog.pg_description" was reindexed
+NOTICE: table "pg_catalog.pg_cast" was reindexed
+NOTICE: table "pg_catalog.pg_namespace" was reindexed
+NOTICE: table "pg_catalog.pg_conversion" was reindexed
+NOTICE: table "pg_catalog.pg_database" was reindexed
+NOTICE: table "pg_catalog.pg_db_role_setting" was reindexed
+NOTICE: table "pg_catalog.pg_tablespace" was reindexed
+NOTICE: table "pg_catalog.pg_pltemplate" was reindexed
+NOTICE: table "pg_catalog.pg_auth_members" was reindexed
+NOTICE: table "pg_catalog.pg_shdepend" was reindexed
+NOTICE: table "pg_catalog.pg_shdescription" was reindexed
+NOTICE: table "pg_catalog.pg_ts_config" was reindexed
+NOTICE: table "pg_catalog.pg_ts_config_map" was reindexed
+NOTICE: table "pg_catalog.pg_ts_dict" was reindexed
+NOTICE: table "pg_catalog.pg_ts_parser" was reindexed
+NOTICE: table "pg_catalog.pg_ts_template" was reindexed
+NOTICE: table "pg_catalog.pg_extension" was reindexed
+NOTICE: table "pg_catalog.pg_foreign_data_wrapper" was reindexed
+NOTICE: table "pg_catalog.pg_foreign_server" was reindexed
+NOTICE: table "pg_catalog.pg_foreign_table" was reindexed
+NOTICE: table "pg_catalog.pg_rowsecurity" was reindexed
+NOTICE: table "pg_catalog.pg_default_acl" was reindexed
+NOTICE: table "pg_catalog.pg_seclabel" was reindexed
+NOTICE: table "pg_catalog.pg_shseclabel" was reindexed
+NOTICE: table "pg_catalog.pg_collation" was reindexed
+NOTICE: table "pg_catalog.pg_range" was reindexed
+NOTICE: table "pg_catalog.pg_operator" was reindexed
+NOTICE: table "pg_catalog.pg_enum" was reindexed
+NOTICE: table "pg_catalog.pg_depend" was reindexed
+BEGIN;
+REINDEX ALL IN SCHEMA pg_catalog;
+ERROR: REINDEX ALL IN SCHEMA cannot run inside a transaction block
+END;
--
-- Try some concurrent index drops
--
diff --git a/src/test/regress/sql/create_index.sql b/src/test/regress/sql/create_index.sql
index d4d24ef..a3aa914 100644
--- a/src/test/regress/sql/create_index.sql
+++ b/src/test/regress/sql/create_index.sql
@@ -743,6 +743,10 @@ VACUUM FULL concur_heap;
\d concur_heap
REINDEX TABLE concur_heap;
\d concur_heap
+REINDEX ALL IN SCHEMA pg_catalog;
+BEGIN;
+REINDEX ALL IN SCHEMA pg_catalog;
+END;
--
-- Try some concurrent index drops
001_Add_schema_option_to_reindexdb_v2.patchapplication/octet-stream; name=001_Add_schema_option_to_reindexdb_v2.patchDownload
diff --git a/doc/src/sgml/ref/reindexdb.sgml b/doc/src/sgml/ref/reindexdb.sgml
index 486f5c9..b5b449c 100644
--- a/doc/src/sgml/ref/reindexdb.sgml
+++ b/doc/src/sgml/ref/reindexdb.sgml
@@ -27,6 +27,16 @@ PostgreSQL documentation
<arg choice="plain" rep="repeat">
<arg choice="opt">
<group choice="plain">
+ <arg choice="plain"><option>--schema</option></arg>
+ <arg choice="plain"><option>-S</option></arg>
+ </group>
+ <replaceable>table</replaceable>
+ </arg>
+ </arg>
+
+ <arg choice="plain" rep="repeat">
+ <arg choice="opt">
+ <group choice="plain">
<arg choice="plain"><option>--table</option></arg>
<arg choice="plain"><option>-t</option></arg>
</group>
@@ -162,6 +172,18 @@ PostgreSQL documentation
</varlistentry>
<varlistentry>
+ <term><option>-S <replaceable class="parameter">schema</replaceable></></term>
+ <term><option>--schema=<replaceable class="parameter">schema</replaceable></></term>
+ <listitem>
+ <para>
+ Reindex <replaceable class="parameter">schema</replaceable> only.
+ Multiple schemas can be reindexed by writing multiple
+ <option>-S</> switches.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
<term><option>-t <replaceable class="parameter">table</replaceable></></term>
<term><option>--table=<replaceable class="parameter">table</replaceable></></term>
<listitem>
diff --git a/src/bin/scripts/reindexdb.c b/src/bin/scripts/reindexdb.c
index 561bbce..dbea347 100644
--- a/src/bin/scripts/reindexdb.c
+++ b/src/bin/scripts/reindexdb.c
@@ -41,6 +41,7 @@ main(int argc, char *argv[])
{"password", no_argument, NULL, 'W'},
{"echo", no_argument, NULL, 'e'},
{"quiet", no_argument, NULL, 'q'},
+ {"schema", required_argument, NULL, 'S'},
{"dbname", required_argument, NULL, 'd'},
{"all", no_argument, NULL, 'a'},
{"system", no_argument, NULL, 's'},
@@ -66,6 +67,7 @@ main(int argc, char *argv[])
bool quiet = false;
SimpleStringList indexes = {NULL, NULL};
SimpleStringList tables = {NULL, NULL};
+ SimpleStringList schemas = {NULL, NULL};
progname = get_progname(argv[0]);
set_pglocale_pgservice(argv[0], PG_TEXTDOMAIN("pgscripts"));
@@ -73,7 +75,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:wWeqd:ast:i:", long_options, &optindex)) != -1)
+ while ((c = getopt_long(argc, argv, "h:p:U:wWeqS:d:ast:i:", long_options, &optindex)) != -1)
{
switch (c)
{
@@ -98,6 +100,9 @@ main(int argc, char *argv[])
case 'q':
quiet = true;
break;
+ case 'S':
+ simple_string_list_append(&schemas, optarg);
+ break;
case 'd':
dbname = pg_strdup(optarg);
break;
@@ -154,6 +159,11 @@ main(int argc, char *argv[])
fprintf(stderr, _("%s: cannot reindex all databases and system catalogs at the same time\n"), progname);
exit(1);
}
+ if (schemas.head != NULL)
+ {
+ fprintf(stderr, _("%s: cannot reindex specific schema(s) in all databases\n"), progname);
+ exit(1);
+ }
if (tables.head != NULL)
{
fprintf(stderr, _("%s: cannot reindex specific table(s) in all databases\n"), progname);
@@ -170,6 +180,11 @@ main(int argc, char *argv[])
}
else if (syscatalog)
{
+ if (schemas.head != NULL)
+ {
+ fprintf(stderr, _("%s: cannot reindex specific schema(s) and system catalogs at the same time\n"), progname);
+ exit(1);
+ }
if (tables.head != NULL)
{
fprintf(stderr, _("%s: cannot reindex specific table(s) and system catalogs at the same time\n"), progname);
@@ -206,6 +221,17 @@ main(int argc, char *argv[])
dbname = get_user_name_or_exit(progname);
}
+ if (schemas.head != NULL)
+ {
+ SimpleStringListCell *cell;
+
+ for (cell = schemas.head; cell; cell = cell->next)
+ {
+ reindex_one_database(cell->val, dbname, "SCHEMA", host, port,
+ username, prompt_password, progname, echo);
+ }
+ }
+
if (indexes.head != NULL)
{
SimpleStringListCell *cell;
@@ -226,8 +252,8 @@ main(int argc, char *argv[])
username, prompt_password, progname, echo);
}
}
- /* reindex database only if neither index nor table is specified */
- if (indexes.head == NULL && tables.head == NULL)
+ /* 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);
}
@@ -251,6 +277,8 @@ reindex_one_database(const char *name, const char *dbname, const char *type,
appendPQExpBuffer(&sql, " TABLE %s", name);
else if (strcmp(type, "INDEX") == 0)
appendPQExpBuffer(&sql, " INDEX %s", name);
+ else if (strcmp(type, "SCHEMA") == 0)
+ appendPQExpBuffer(&sql, " ALL IN SCHEMA %s", name);
else if (strcmp(type, "DATABASE") == 0)
appendPQExpBuffer(&sql, " DATABASE %s", fmtId(name));
appendPQExpBufferStr(&sql, ";");
@@ -266,6 +294,9 @@ reindex_one_database(const char *name, const char *dbname, const char *type,
if (strcmp(type, "INDEX") == 0)
fprintf(stderr, _("%s: reindexing of index \"%s\" in database \"%s\" failed: %s"),
progname, name, dbname, PQerrorMessage(conn));
+ if (strcmp(type, "SCHEMA") == 0)
+ fprintf(stderr, _("%s: reindexing of schema \"%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));
@@ -348,6 +379,7 @@ help(const char *progname)
printf(_(" -i, --index=INDEX recreate specific index(es) only\n"));
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(_(" -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 24b927c..d04d837 100644
--- a/src/bin/scripts/t/090_reindexdb.pl
+++ b/src/bin/scripts/t/090_reindexdb.pl
@@ -29,6 +29,10 @@ issues_sql_like(
'reindex specific index');
issues_sql_like(
+ [ 'reindexdb', 'postgres', '-S', 'pg_catalog' ],
+ qr/statement: REINDEX ALL IN SCHEMA pg_catalog;/,
+ 'reindex specific schema');
+issues_sql_like(
[ 'reindexdb', 'postgres', '-s' ],
qr/statement: REINDEX SYSTEM postgres;/,
'reindex system tables');
On Sun, Oct 19, 2014 at 1:02 PM, Sawada Masahiko <sawada.mshk@gmail.com>
wrote:
On Fri, Oct 17, 2014 at 4:32 AM, Fabrízio de Royes Mello
<fabriziomello@gmail.com> wrote:On Wed, Oct 15, 2014 at 11:41 AM, Sawada Masahiko <sawada.mshk@gmail.com
wrote:
On Mon, Oct 13, 2014 at 11:16 PM, Robert Haas <robertmhaas@gmail.com>
wrote:On Sun, Oct 12, 2014 at 1:27 PM, Stephen Frost <sfrost@snowman.net>
wrote:* Alvaro Herrera (alvherre@2ndquadrant.com) wrote:
Sawada Masahiko wrote:
Attached WIP patch adds new syntax REINEX SCHEMA which does
reindexing
all table of specified schema.
There are syntax dose reindexing specified index, per table and
per
database,
but we can not do reindexing per schema for now.It seems doubtful that there really is much use for this feature,
but
if
there is, I think a better syntax precedent is the new ALTER TABLE
ALL
IN TABLESPACE thingy, rather than your proposed REINDEX SCHEMA.
Something like REINDEX TABLE ALL IN SCHEMA perhaps.Yeah, I tend to agree that we should be looking at the 'ALL IN
TABLESPACE' and 'ALL IN SCHEMA' type of commands to keep things
consistent. This might be an alternative for the vacuum / analyze /
reindex database commands also..Urgh. I don't have a problem with that syntax in general, but it
clashes pretty awfully with what we're already doing for REINDEX
otherwise.Attached patches are latest version patch.
Ok.
I changed syntax to REINDEX ALL IN SCHEMA, but I felt a sense of
discomfort a little
as Robert mentioned.I understood, but the real problem will in a near future when the
features
will be pushed... :-)
They are separated features, but maybe we can join this features to a
one
future commit... it's just an idea.
Anyway, you can apply these patches in numerical order,
can use REINDEX ALL IN SCHEMA feature and "-S/--schema" option in
reindexdb.000_reindex_all_in_schema_v2.patch : It contains REINDEX ALL IN SCHEMA
feature1) Compile without warnings
2) IMHO you can add more test cases to better code coverage:
* reindex a schema that doesn't exists
* try to run "reindex all in schema" inside a transaction block3) Isn't enough just?
bool do_database = (kind == OBJECT_DATABASE);
... instead of...
+ bool do_database = (kind == OBJECT_DATABASE) ? true : false;
4) IMHO you can add other Assert to check valid relkinds, like:
Assert(kind == OBJECT_DATABASE || kind == OBJECT_SCHEMA);
5) I think is more legible:
/* Get OID of object for result */
if (do_database)
objectOid = MyDatabaseId
else
objectOid = get_namespace_oid(objectName, false);... insead of ...
+ /* Get OID of object for result */ + objectOid = (do_database) ? MyDatabaseId :
get_namespace_oid(objectName,
false);
001_Add_schema_option_to_reindexdb_v1.patch : It contains reindexdb
"-S/--schema" supportingThe code itself is good for me, but IMHO you can add test cases to
src/bin/scripts/t/090_reindexdb.plThank you for reviewing.
You're welcome!
I agree 2) - 5).
:-)
Attached patch is latest version patch I modified above.
All is fine to me now... all work as expected and no compiler warnings.
There are just a little fix to do in src/bin/scripts/t/090_reindexdb.pl
-use Test::More tests => 7;
+use Test::More tests => 8;
Because you added a new testcase to suittest, so you need to increase the
test count at beginning of the file.
Also, I noticed I had forgotten to add the patch regarding document of
reindexdb.
Yeah... I forgot it too... :-) I'm not a native speaker but IMHO the docs
is fine.
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
On Sun, Oct 19, 2014 at 10:37 PM, Fabrízio de Royes Mello <
fabriziomello@gmail.com> wrote:
On Sun, Oct 19, 2014 at 1:02 PM, Sawada Masahiko <sawada.mshk@gmail.com>
wrote:
On Fri, Oct 17, 2014 at 4:32 AM, Fabrízio de Royes Mello
<fabriziomello@gmail.com> wrote:On Wed, Oct 15, 2014 at 11:41 AM, Sawada Masahiko <
sawada.mshk@gmail.com>
wrote:
On Mon, Oct 13, 2014 at 11:16 PM, Robert Haas <robertmhaas@gmail.com>
wrote:On Sun, Oct 12, 2014 at 1:27 PM, Stephen Frost <sfrost@snowman.net>
wrote:* Alvaro Herrera (alvherre@2ndquadrant.com) wrote:
Sawada Masahiko wrote:
Attached WIP patch adds new syntax REINEX SCHEMA which does
reindexing
all table of specified schema.
There are syntax dose reindexing specified index, per table
and per
database,
but we can not do reindexing per schema for now.It seems doubtful that there really is much use for this
feature, but
if
there is, I think a better syntax precedent is the new ALTER
TABLE ALL
IN TABLESPACE thingy, rather than your proposed REINDEX SCHEMA.
Something like REINDEX TABLE ALL IN SCHEMA perhaps.Yeah, I tend to agree that we should be looking at the 'ALL IN
TABLESPACE' and 'ALL IN SCHEMA' type of commands to keep things
consistent. This might be an alternative for the vacuum /
analyze /
reindex database commands also..
Urgh. I don't have a problem with that syntax in general, but it
clashes pretty awfully with what we're already doing for REINDEX
otherwise.Attached patches are latest version patch.
Ok.
I changed syntax to REINDEX ALL IN SCHEMA, but I felt a sense of
discomfort a little
as Robert mentioned.I understood, but the real problem will in a near future when the
features
will be pushed... :-)
They are separated features, but maybe we can join this features to a
one
future commit... it's just an idea.
Anyway, you can apply these patches in numerical order,
can use REINDEX ALL IN SCHEMA feature and "-S/--schema" option in
reindexdb.000_reindex_all_in_schema_v2.patch : It contains REINDEX ALL IN
SCHEMA
feature
1) Compile without warnings
2) IMHO you can add more test cases to better code coverage:
* reindex a schema that doesn't exists
* try to run "reindex all in schema" inside a transaction block3) Isn't enough just?
bool do_database = (kind == OBJECT_DATABASE);
... instead of...
+ bool do_database = (kind == OBJECT_DATABASE) ? true : false;
4) IMHO you can add other Assert to check valid relkinds, like:
Assert(kind == OBJECT_DATABASE || kind == OBJECT_SCHEMA);
5) I think is more legible:
/* Get OID of object for result */
if (do_database)
objectOid = MyDatabaseId
else
objectOid = get_namespace_oid(objectName, false);... insead of ...
+ /* Get OID of object for result */ + objectOid = (do_database) ? MyDatabaseId :
get_namespace_oid(objectName,
false);
001_Add_schema_option_to_reindexdb_v1.patch : It contains reindexdb
"-S/--schema" supportingThe code itself is good for me, but IMHO you can add test cases to
src/bin/scripts/t/090_reindexdb.plThank you for reviewing.
You're welcome!
I agree 2) - 5).
:-)
Attached patch is latest version patch I modified above.
All is fine to me now... all work as expected and no compiler warnings.
There are just a little fix to do in src/bin/scripts/t/090_reindexdb.pl
-use Test::More tests => 7; +use Test::More tests => 8;Because you added a new testcase to suittest, so you need to increase the
test count at beginning of the file.
Patch attached. Now the regress run without errors.
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:
001_Add_schema_option_to_reindexdb_v3.patchtext/x-patch; charset=US-ASCII; name=001_Add_schema_option_to_reindexdb_v3.patchDownload
diff --git a/doc/src/sgml/ref/reindexdb.sgml b/doc/src/sgml/ref/reindexdb.sgml
index 486f5c9..b5b449c 100644
--- a/doc/src/sgml/ref/reindexdb.sgml
+++ b/doc/src/sgml/ref/reindexdb.sgml
@@ -27,6 +27,16 @@ PostgreSQL documentation
<arg choice="plain" rep="repeat">
<arg choice="opt">
<group choice="plain">
+ <arg choice="plain"><option>--schema</option></arg>
+ <arg choice="plain"><option>-S</option></arg>
+ </group>
+ <replaceable>table</replaceable>
+ </arg>
+ </arg>
+
+ <arg choice="plain" rep="repeat">
+ <arg choice="opt">
+ <group choice="plain">
<arg choice="plain"><option>--table</option></arg>
<arg choice="plain"><option>-t</option></arg>
</group>
@@ -162,6 +172,18 @@ PostgreSQL documentation
</varlistentry>
<varlistentry>
+ <term><option>-S <replaceable class="parameter">schema</replaceable></></term>
+ <term><option>--schema=<replaceable class="parameter">schema</replaceable></></term>
+ <listitem>
+ <para>
+ Reindex <replaceable class="parameter">schema</replaceable> only.
+ Multiple schemas can be reindexed by writing multiple
+ <option>-S</> switches.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
<term><option>-t <replaceable class="parameter">table</replaceable></></term>
<term><option>--table=<replaceable class="parameter">table</replaceable></></term>
<listitem>
diff --git a/src/bin/scripts/reindexdb.c b/src/bin/scripts/reindexdb.c
index 561bbce..dbea347 100644
--- a/src/bin/scripts/reindexdb.c
+++ b/src/bin/scripts/reindexdb.c
@@ -41,6 +41,7 @@ main(int argc, char *argv[])
{"password", no_argument, NULL, 'W'},
{"echo", no_argument, NULL, 'e'},
{"quiet", no_argument, NULL, 'q'},
+ {"schema", required_argument, NULL, 'S'},
{"dbname", required_argument, NULL, 'd'},
{"all", no_argument, NULL, 'a'},
{"system", no_argument, NULL, 's'},
@@ -66,6 +67,7 @@ main(int argc, char *argv[])
bool quiet = false;
SimpleStringList indexes = {NULL, NULL};
SimpleStringList tables = {NULL, NULL};
+ SimpleStringList schemas = {NULL, NULL};
progname = get_progname(argv[0]);
set_pglocale_pgservice(argv[0], PG_TEXTDOMAIN("pgscripts"));
@@ -73,7 +75,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:wWeqd:ast:i:", long_options, &optindex)) != -1)
+ while ((c = getopt_long(argc, argv, "h:p:U:wWeqS:d:ast:i:", long_options, &optindex)) != -1)
{
switch (c)
{
@@ -98,6 +100,9 @@ main(int argc, char *argv[])
case 'q':
quiet = true;
break;
+ case 'S':
+ simple_string_list_append(&schemas, optarg);
+ break;
case 'd':
dbname = pg_strdup(optarg);
break;
@@ -154,6 +159,11 @@ main(int argc, char *argv[])
fprintf(stderr, _("%s: cannot reindex all databases and system catalogs at the same time\n"), progname);
exit(1);
}
+ if (schemas.head != NULL)
+ {
+ fprintf(stderr, _("%s: cannot reindex specific schema(s) in all databases\n"), progname);
+ exit(1);
+ }
if (tables.head != NULL)
{
fprintf(stderr, _("%s: cannot reindex specific table(s) in all databases\n"), progname);
@@ -170,6 +180,11 @@ main(int argc, char *argv[])
}
else if (syscatalog)
{
+ if (schemas.head != NULL)
+ {
+ fprintf(stderr, _("%s: cannot reindex specific schema(s) and system catalogs at the same time\n"), progname);
+ exit(1);
+ }
if (tables.head != NULL)
{
fprintf(stderr, _("%s: cannot reindex specific table(s) and system catalogs at the same time\n"), progname);
@@ -206,6 +221,17 @@ main(int argc, char *argv[])
dbname = get_user_name_or_exit(progname);
}
+ if (schemas.head != NULL)
+ {
+ SimpleStringListCell *cell;
+
+ for (cell = schemas.head; cell; cell = cell->next)
+ {
+ reindex_one_database(cell->val, dbname, "SCHEMA", host, port,
+ username, prompt_password, progname, echo);
+ }
+ }
+
if (indexes.head != NULL)
{
SimpleStringListCell *cell;
@@ -226,8 +252,8 @@ main(int argc, char *argv[])
username, prompt_password, progname, echo);
}
}
- /* reindex database only if neither index nor table is specified */
- if (indexes.head == NULL && tables.head == NULL)
+ /* 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);
}
@@ -251,6 +277,8 @@ reindex_one_database(const char *name, const char *dbname, const char *type,
appendPQExpBuffer(&sql, " TABLE %s", name);
else if (strcmp(type, "INDEX") == 0)
appendPQExpBuffer(&sql, " INDEX %s", name);
+ else if (strcmp(type, "SCHEMA") == 0)
+ appendPQExpBuffer(&sql, " ALL IN SCHEMA %s", name);
else if (strcmp(type, "DATABASE") == 0)
appendPQExpBuffer(&sql, " DATABASE %s", fmtId(name));
appendPQExpBufferStr(&sql, ";");
@@ -266,6 +294,9 @@ reindex_one_database(const char *name, const char *dbname, const char *type,
if (strcmp(type, "INDEX") == 0)
fprintf(stderr, _("%s: reindexing of index \"%s\" in database \"%s\" failed: %s"),
progname, name, dbname, PQerrorMessage(conn));
+ if (strcmp(type, "SCHEMA") == 0)
+ fprintf(stderr, _("%s: reindexing of schema \"%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));
@@ -348,6 +379,7 @@ help(const char *progname)
printf(_(" -i, --index=INDEX recreate specific index(es) only\n"));
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(_(" -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 24b927c..934fe7d 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 => 7;
+use Test::More tests => 8;
program_help_ok('reindexdb');
program_version_ok('reindexdb');
@@ -29,6 +29,10 @@ issues_sql_like(
'reindex specific index');
issues_sql_like(
+ [ 'reindexdb', 'postgres', '-S', 'pg_catalog' ],
+ qr/statement: REINDEX ALL IN SCHEMA pg_catalog;/,
+ 'reindex specific schema');
+issues_sql_like(
[ 'reindexdb', 'postgres', '-s' ],
qr/statement: REINDEX SYSTEM postgres;/,
'reindex system tables');
On Mon, Oct 20, 2014 at 9:41 AM, Fabrízio de Royes Mello
<fabriziomello@gmail.com> wrote:
On Sun, Oct 19, 2014 at 10:37 PM, Fabrízio de Royes Mello
<fabriziomello@gmail.com> wrote:On Sun, Oct 19, 2014 at 1:02 PM, Sawada Masahiko <sawada.mshk@gmail.com>
wrote:On Fri, Oct 17, 2014 at 4:32 AM, Fabrízio de Royes Mello
<fabriziomello@gmail.com> wrote:On Wed, Oct 15, 2014 at 11:41 AM, Sawada Masahiko
<sawada.mshk@gmail.com>
wrote:On Mon, Oct 13, 2014 at 11:16 PM, Robert Haas <robertmhaas@gmail.com>
wrote:On Sun, Oct 12, 2014 at 1:27 PM, Stephen Frost <sfrost@snowman.net>
wrote:* Alvaro Herrera (alvherre@2ndquadrant.com) wrote:
Sawada Masahiko wrote:
Attached WIP patch adds new syntax REINEX SCHEMA which does
reindexing
all table of specified schema.
There are syntax dose reindexing specified index, per table and
per
database,
but we can not do reindexing per schema for now.It seems doubtful that there really is much use for this feature,
but
if
there is, I think a better syntax precedent is the new ALTER
TABLE ALL
IN TABLESPACE thingy, rather than your proposed REINDEX SCHEMA.
Something like REINDEX TABLE ALL IN SCHEMA perhaps.Yeah, I tend to agree that we should be looking at the 'ALL IN
TABLESPACE' and 'ALL IN SCHEMA' type of commands to keep things
consistent. This might be an alternative for the vacuum / analyze
/
reindex database commands also..Urgh. I don't have a problem with that syntax in general, but it
clashes pretty awfully with what we're already doing for REINDEX
otherwise.Attached patches are latest version patch.
Ok.
I changed syntax to REINDEX ALL IN SCHEMA, but I felt a sense of
discomfort a little
as Robert mentioned.I understood, but the real problem will in a near future when the
features
will be pushed... :-)They are separated features, but maybe we can join this features to a
one
future commit... it's just an idea.Anyway, you can apply these patches in numerical order,
can use REINDEX ALL IN SCHEMA feature and "-S/--schema" option in
reindexdb.000_reindex_all_in_schema_v2.patch : It contains REINDEX ALL IN
SCHEMA
feature1) Compile without warnings
2) IMHO you can add more test cases to better code coverage:
* reindex a schema that doesn't exists
* try to run "reindex all in schema" inside a transaction block3) Isn't enough just?
bool do_database = (kind == OBJECT_DATABASE);
... instead of...
+ bool do_database = (kind == OBJECT_DATABASE) ? true : false;
4) IMHO you can add other Assert to check valid relkinds, like:
Assert(kind == OBJECT_DATABASE || kind == OBJECT_SCHEMA);
5) I think is more legible:
/* Get OID of object for result */
if (do_database)
objectOid = MyDatabaseId
else
objectOid = get_namespace_oid(objectName, false);... insead of ...
+ /* Get OID of object for result */ + objectOid = (do_database) ? MyDatabaseId : get_namespace_oid(objectName, false);001_Add_schema_option_to_reindexdb_v1.patch : It contains reindexdb
"-S/--schema" supportingThe code itself is good for me, but IMHO you can add test cases to
src/bin/scripts/t/090_reindexdb.plThank you for reviewing.
You're welcome!
I agree 2) - 5).
:-)
Attached patch is latest version patch I modified above.
All is fine to me now... all work as expected and no compiler warnings.
There are just a little fix to do in src/bin/scripts/t/090_reindexdb.pl
-use Test::More tests => 7; +use Test::More tests => 8;Because you added a new testcase to suittest, so you need to increase the
test count at beginning of the file.Patch attached. Now the regress run without errors.
Thank you for reviewing and revising!
I also did successfully.
It looks good to me :)
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
On Mon, Oct 20, 2014 at 11:24 AM, Sawada Masahiko <sawada.mshk@gmail.com>
wrote:
On Mon, Oct 20, 2014 at 9:41 AM, Fabrízio de Royes Mello
<fabriziomello@gmail.com> wrote:On Sun, Oct 19, 2014 at 10:37 PM, Fabrízio de Royes Mello
<fabriziomello@gmail.com> wrote:On Sun, Oct 19, 2014 at 1:02 PM, Sawada Masahiko <sawada.mshk@gmail.com
wrote:
On Fri, Oct 17, 2014 at 4:32 AM, Fabrízio de Royes Mello
<fabriziomello@gmail.com> wrote:On Wed, Oct 15, 2014 at 11:41 AM, Sawada Masahiko
<sawada.mshk@gmail.com>
wrote:On Mon, Oct 13, 2014 at 11:16 PM, Robert Haas <
robertmhaas@gmail.com>
wrote:
On Sun, Oct 12, 2014 at 1:27 PM, Stephen Frost <
sfrost@snowman.net>
wrote:
* Alvaro Herrera (alvherre@2ndquadrant.com) wrote:
Sawada Masahiko wrote:
Attached WIP patch adds new syntax REINEX SCHEMA which does
reindexing
all table of specified schema.
There are syntax dose reindexing specified index, per table
and
per
database,
but we can not do reindexing per schema for now.It seems doubtful that there really is much use for this
feature,
but
if
there is, I think a better syntax precedent is the new ALTER
TABLE ALL
IN TABLESPACE thingy, rather than your proposed REINDEX
SCHEMA.
Something like REINDEX TABLE ALL IN SCHEMA perhaps.
Yeah, I tend to agree that we should be looking at the 'ALL IN
TABLESPACE' and 'ALL IN SCHEMA' type of commands to keep things
consistent. This might be an alternative for the vacuum /
analyze
/
reindex database commands also..Urgh. I don't have a problem with that syntax in general, but
it
clashes pretty awfully with what we're already doing for REINDEX
otherwise.Attached patches are latest version patch.
Ok.
I changed syntax to REINDEX ALL IN SCHEMA, but I felt a sense of
discomfort a little
as Robert mentioned.I understood, but the real problem will in a near future when the
features
will be pushed... :-)They are separated features, but maybe we can join this features
to a
one
future commit... it's just an idea.Anyway, you can apply these patches in numerical order,
can use REINDEX ALL IN SCHEMA feature and "-S/--schema" option in
reindexdb.000_reindex_all_in_schema_v2.patch : It contains REINDEX ALL IN
SCHEMA
feature1) Compile without warnings
2) IMHO you can add more test cases to better code coverage:
* reindex a schema that doesn't exists
* try to run "reindex all in schema" inside a transaction block3) Isn't enough just?
bool do_database = (kind == OBJECT_DATABASE);
... instead of...
+ bool do_database = (kind == OBJECT_DATABASE) ? true : false;
4) IMHO you can add other Assert to check valid relkinds, like:
Assert(kind == OBJECT_DATABASE || kind == OBJECT_SCHEMA);
5) I think is more legible:
/* Get OID of object for result */
if (do_database)
objectOid = MyDatabaseId
else
objectOid = get_namespace_oid(objectName, false);... insead of ...
+ /* Get OID of object for result */ + objectOid = (do_database) ? MyDatabaseId : get_namespace_oid(objectName, false);001_Add_schema_option_to_reindexdb_v1.patch : It contains
reindexdb
"-S/--schema" supporting
The code itself is good for me, but IMHO you can add test cases to
src/bin/scripts/t/090_reindexdb.plThank you for reviewing.
You're welcome!
I agree 2) - 5).
:-)
Attached patch is latest version patch I modified above.
All is fine to me now... all work as expected and no compiler warnings.
There are just a little fix to do in src/bin/scripts/t/090_reindexdb.pl
-use Test::More tests => 7; +use Test::More tests => 8;Because you added a new testcase to suittest, so you need to increase
the
test count at beginning of the file.
Patch attached. Now the regress run without errors.
Thank you for reviewing and revising!
You're welcome!
I also did successfully.
It looks good to me :)
Changed status to "Ready for commiter".
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
Sawada Masahiko wrote:
Thank you for reviewing.
I agree 2) - 5).
Attached patch is latest version patch I modified above.
Also, I noticed I had forgotten to add the patch regarding document of
reindexdb.
Please don't use pg_catalog in the regression test. That way we will
need to update the expected file whenever a new catalog is added, which
seems pointless. Maybe create a schema with a couple of tables
specifically for this, instead.
--
�lvaro Herrera 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
On Wed, Oct 22, 2014 at 9:21 PM, Alvaro Herrera <alvherre@2ndquadrant.com>
wrote:
Sawada Masahiko wrote:
Thank you for reviewing.
I agree 2) - 5).
Attached patch is latest version patch I modified above.
Also, I noticed I had forgotten to add the patch regarding document of
reindexdb.Please don't use pg_catalog in the regression test. That way we will
need to update the expected file whenever a new catalog is added, which
seems pointless. Maybe create a schema with a couple of tables
specifically for this, instead.
Attached new regression test.
Isn't better join the two patches in just one?
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_all_in_schema_v4.patchtext/x-patch; charset=US-ASCII; name=000_reindex_all_in_schema_v4.patchDownload
diff --git a/doc/src/sgml/ref/reindex.sgml b/doc/src/sgml/ref/reindex.sgml
index cabae19..e47604c 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 | DATABASE | SYSTEM } <replaceable class="PARAMETER">name</replaceable> [ FORCE ]
+REINDEX { INDEX | TABLE | ALL IN SCHEMA | DATABASE | SYSTEM } <replaceable class="PARAMETER">name</replaceable> [ FORCE ]
</synopsis>
</refsynopsisdiv>
@@ -101,6 +101,19 @@ REINDEX { INDEX | TABLE | DATABASE | SYSTEM } <replaceable class="PARAMETER">nam
</varlistentry>
<varlistentry>
+ <term><literal>ALL IN SCHEMA</literal></term>
+ <listitem>
+ <para>
+ Recreate all indexes of the specified schema. If the table has a
+ secondary <quote>TOAST</> table, that is reindexed as well.
+ Indexes on shared system catalogs are also processed.
+ This form of <command>REINDEX</command> cannot be executed inside a
+ transaction block.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
<term><literal>DATABASE</literal></term>
<listitem>
<para>
diff --git a/src/backend/commands/indexcmds.c b/src/backend/commands/indexcmds.c
index 3c1e90e..7c25e02 100644
--- a/src/backend/commands/indexcmds.c
+++ b/src/backend/commands/indexcmds.c
@@ -1770,34 +1770,52 @@ ReindexTable(RangeVar *relation)
}
/*
- * ReindexDatabase
- * Recreate indexes of a database.
+ * ReindexDatabaseOrSchema
+ * Recreate indexes of a database or schema.
*
+ * kind means the type of object, database or schema.
* To reduce the probability of deadlocks, each table is reindexed in a
* separate transaction, so we can release the lock on it right away.
* That means this must not be called within a user transaction block!
*/
Oid
-ReindexDatabase(const char *databaseName, bool do_system, bool do_user)
+ReindexDatabaseOrSchema(const char *objectName, bool do_system, bool do_user, ObjectType kind)
{
+ Oid objectOid;
Relation relationRelation;
HeapScanDesc scan;
+ ScanKeyData *key = NULL;
HeapTuple tuple;
MemoryContext private_context;
MemoryContext old;
List *relids = NIL;
ListCell *l;
+ bool do_database = (kind == OBJECT_DATABASE);
+ int nkeys;
- AssertArg(databaseName);
+ AssertArg(objectName);
+ Assert(kind == OBJECT_DATABASE || kind == OBJECT_SCHEMA);
- if (strcmp(databaseName, get_database_name(MyDatabaseId)) != 0)
+ /* Get OID of object for result */
+ if (do_database)
+ objectOid = MyDatabaseId;
+ else
+ objectOid = get_namespace_oid(objectName, false);
+
+ if (!do_database)
+ {
+ do_system = IsSystemNamespace(objectOid);
+ do_user = !do_system;
+ }
+
+ if (do_database && strcmp(objectName, get_database_name(MyDatabaseId)) != 0)
ereport(ERROR,
(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
errmsg("can only reindex the currently open database")));
- if (!pg_database_ownercheck(MyDatabaseId, GetUserId()))
+ if (do_database && !pg_database_ownercheck(MyDatabaseId, GetUserId()))
aclcheck_error(ACLCHECK_NOT_OWNER, ACL_KIND_DATABASE,
- databaseName);
+ objectName);
/*
* Create a memory context that will survive forced transaction commits we
@@ -1806,7 +1824,8 @@ ReindexDatabase(const char *databaseName, bool do_system, bool do_user)
* abort cleanup logic.
*/
private_context = AllocSetContextCreate(PortalContext,
- "ReindexDatabase",
+ (do_database) ?
+ "ReindexDatabase" : "ReindexSchema",
ALLOCSET_DEFAULT_MINSIZE,
ALLOCSET_DEFAULT_INITSIZE,
ALLOCSET_DEFAULT_MAXSIZE);
@@ -1824,6 +1843,23 @@ ReindexDatabase(const char *databaseName, bool do_system, bool do_user)
MemoryContextSwitchTo(old);
}
+ /* For schema, we search target relations by relnamespce and relkind */
+ if (!do_database)
+ {
+ key = palloc(sizeof(ScanKeyData) * 2);
+ ScanKeyInit(&key[0],
+ Anum_pg_class_relnamespace,
+ BTEqualStrategyNumber, F_OIDEQ,
+ ObjectIdGetDatum(objectOid));
+ ScanKeyInit(&key[1],
+ Anum_pg_class_relkind,
+ BTEqualStrategyNumber, F_CHAREQ,
+ 'r');
+ nkeys = 2;
+ }
+ else
+ nkeys = 0;
+
/*
* Scan pg_class to build a list of the relations we need to reindex.
*
@@ -1831,7 +1867,7 @@ ReindexDatabase(const char *databaseName, bool do_system, bool do_user)
* rels will be processed indirectly by reindex_relation).
*/
relationRelation = heap_open(RelationRelationId, AccessShareLock);
- scan = heap_beginscan_catalog(relationRelation, 0, NULL);
+ scan = heap_beginscan_catalog(relationRelation, nkeys, key);
while ((tuple = heap_getnext(scan, ForwardScanDirection)) != NULL)
{
Form_pg_class classtuple = (Form_pg_class) GETSTRUCT(tuple);
@@ -1892,5 +1928,5 @@ ReindexDatabase(const char *databaseName, bool do_system, bool do_user)
MemoryContextDelete(private_context);
- return MyDatabaseId;
+ return objectOid;
}
diff --git a/src/backend/parser/gram.y b/src/backend/parser/gram.y
index 0de9584..f59f880 100644
--- a/src/backend/parser/gram.y
+++ b/src/backend/parser/gram.y
@@ -7181,6 +7181,14 @@ ReindexStmt:
n->do_user = false;
$$ = (Node *)n;
}
+ | REINDEX ALL IN_P SCHEMA name opt_force
+ {
+ ReindexStmt *n = makeNode(ReindexStmt);
+ n->kind = OBJECT_SCHEMA;
+ n->name = $5;
+ n->relation = NULL;
+ $$ = (Node *)n;
+ }
| REINDEX DATABASE name opt_force
{
ReindexStmt *n = makeNode(ReindexStmt);
diff --git a/src/backend/tcop/utility.c b/src/backend/tcop/utility.c
index 4a2a339..b5bda55 100644
--- a/src/backend/tcop/utility.c
+++ b/src/backend/tcop/utility.c
@@ -755,6 +755,7 @@ standard_ProcessUtility(Node *parsetree,
case OBJECT_MATVIEW:
ReindexTable(stmt->relation);
break;
+ case OBJECT_SCHEMA:
case OBJECT_DATABASE:
/*
@@ -764,9 +765,10 @@ standard_ProcessUtility(Node *parsetree,
* intended effect!
*/
PreventTransactionChain(isTopLevel,
- "REINDEX DATABASE");
- ReindexDatabase(stmt->name,
- stmt->do_system, stmt->do_user);
+ (stmt->kind == OBJECT_SCHEMA) ?
+ "REINDEX ALL IN SCHEMA" : "REINDEX DATABASE");
+ ReindexDatabaseOrSchema(stmt->name,
+ stmt->do_system, stmt->do_user, stmt->kind);
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 886188c..106ec8a 100644
--- a/src/bin/psql/tab-complete.c
+++ b/src/bin/psql/tab-complete.c
@@ -3330,7 +3330,7 @@ psql_completion(const char *text, int start, int end)
else if (pg_strcasecmp(prev_wd, "REINDEX") == 0)
{
static const char *const list_REINDEX[] =
- {"TABLE", "INDEX", "SYSTEM", "DATABASE", NULL};
+ {"TABLE", "INDEX", "SYSTEM", "ALL IN SCHEMA", "DATABASE", NULL};
COMPLETE_WITH_LIST(list_REINDEX);
}
@@ -3340,6 +3340,8 @@ 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, "ALL IN 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);
diff --git a/src/include/commands/defrem.h b/src/include/commands/defrem.h
index 0ebdbc1..330d05c 100644
--- a/src/include/commands/defrem.h
+++ b/src/include/commands/defrem.h
@@ -30,8 +30,8 @@ extern Oid DefineIndex(Oid relationId,
bool quiet);
extern Oid ReindexIndex(RangeVar *indexRelation);
extern Oid ReindexTable(RangeVar *relation);
-extern Oid ReindexDatabase(const char *databaseName,
- bool do_system, bool do_user);
+extern Oid ReindexDatabaseOrSchema(const char *databaseName,
+ bool do_system, bool do_user, ObjectType kind);
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/test/regress/expected/create_index.out b/src/test/regress/expected/create_index.out
index 8326e94..07bd854 100644
--- a/src/test/regress/expected/create_index.out
+++ b/src/test/regress/expected/create_index.out
@@ -2786,3 +2786,22 @@ explain (costs off)
Index Cond: ((thousand = 1) AND (tenthous = 1001))
(2 rows)
+--
+-- Reindex All In Schema
+--
+REINDEX ALL IN SCHEMA tobereindexed; -- fail because schema doesn't exists
+ERROR: schema "tobereindexed" does not exist
+CREATE SCHEMA tobereindexed;
+CREATE TABLE tobereindexed.table1(col1 SERIAL PRIMARY KEY);
+CREATE TABLE tobereindexed.table2(col1 SERIAL PRIMARY KEY, col2 VARCHAR(100) NOT NULL);
+CREATE INDEX ON tobereindexed.table2(col2);
+REINDEX ALL IN SCHEMA tobereindexed;
+NOTICE: table "tobereindexed.table1" was reindexed
+NOTICE: table "tobereindexed.table2" was reindexed
+BEGIN;
+REINDEX ALL IN SCHEMA tobereindexed;
+ERROR: REINDEX ALL IN SCHEMA cannot run inside a transaction block
+END;
+DROP TABLE tobereindexed.table2;
+DROP TABLE tobereindexed.table1;
+DROP SCHEMA tobereindexed;
diff --git a/src/test/regress/sql/create_index.sql b/src/test/regress/sql/create_index.sql
index d4d24ef..5d6bcc0 100644
--- a/src/test/regress/sql/create_index.sql
+++ b/src/test/regress/sql/create_index.sql
@@ -938,3 +938,19 @@ ORDER BY thousand;
explain (costs off)
select * from tenk1 where (thousand, tenthous) in ((1,1001), (null,null));
+
+--
+-- Reindex All In Schema
+--
+REINDEX ALL IN SCHEMA tobereindexed; -- fail because schema doesn't exists
+CREATE SCHEMA tobereindexed;
+CREATE TABLE tobereindexed.table1(col1 SERIAL PRIMARY KEY);
+CREATE TABLE tobereindexed.table2(col1 SERIAL PRIMARY KEY, col2 VARCHAR(100) NOT NULL);
+CREATE INDEX ON tobereindexed.table2(col2);
+REINDEX ALL IN SCHEMA tobereindexed;
+BEGIN;
+REINDEX ALL IN SCHEMA tobereindexed;
+END;
+DROP TABLE tobereindexed.table2;
+DROP TABLE tobereindexed.table1;
+DROP SCHEMA tobereindexed;
On Fri, Oct 24, 2014 at 3:41 AM, Fabrízio de Royes Mello
<fabriziomello@gmail.com> wrote:
On Wed, Oct 22, 2014 at 9:21 PM, Alvaro Herrera <alvherre@2ndquadrant.com>
wrote:Sawada Masahiko wrote:
Thank you for reviewing.
I agree 2) - 5).
Attached patch is latest version patch I modified above.
Also, I noticed I had forgotten to add the patch regarding document of
reindexdb.Please don't use pg_catalog in the regression test. That way we will
need to update the expected file whenever a new catalog is added, which
seems pointless. Maybe create a schema with a couple of tables
specifically for this, instead.Attached new regression test.
Hunk #1 FAILED at 1.
1 out of 2 hunks FAILED -- saving rejects to file
src/bin/scripts/t/090_reindexdb.pl.rej
I tried to apply the 001 patch after applying the 000, but it was not
applied cleanly.
At least to me, it's more intuitive to use "SCHEMA" instead of "ALL IN SCHEMA"
here because we already use "DATABASE" instead of "ALL IN DATABASE".
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
On Thu, Nov 6, 2014 at 8:00 PM, Fujii Masao <masao.fujii@gmail.com> wrote:
On Fri, Oct 24, 2014 at 3:41 AM, Fabrízio de Royes Mello
<fabriziomello@gmail.com> wrote:On Wed, Oct 22, 2014 at 9:21 PM, Alvaro Herrera <alvherre@2ndquadrant.com>
wrote:Sawada Masahiko wrote:
Thank you for reviewing.
I agree 2) - 5).
Attached patch is latest version patch I modified above.
Also, I noticed I had forgotten to add the patch regarding document of
reindexdb.Please don't use pg_catalog in the regression test. That way we will
need to update the expected file whenever a new catalog is added, which
seems pointless. Maybe create a schema with a couple of tables
specifically for this, instead.Attached new regression test.
Hunk #1 FAILED at 1.
1 out of 2 hunks FAILED -- saving rejects to file
src/bin/scripts/t/090_reindexdb.pl.rejI tried to apply the 001 patch after applying the 000, but it was not
applied cleanly.At least to me, it's more intuitive to use "SCHEMA" instead of "ALL IN SCHEMA"
here because we already use "DATABASE" instead of "ALL IN DATABASE".
Thank you for reporting.
Um, that's one way of looking at it
I think It's not quite new syntax, and we have not used "ALL IN"
clause in REINDEX command by now.
If we add SQL command to reindex table of all in table space as newly syntax,
we might be able to name it "REINDEX TABLE ALL IN TABLESPACE".
Anyway, I created patch of "REINDEX SCHEMA" version, and attached.
Also inapplicable problem has been solved.
Regards,
-------
Sawada Masahiko
Attachments:
001_Add_schema_option_to_reindexdb_v4.patchapplication/octet-stream; name=001_Add_schema_option_to_reindexdb_v4.patchDownload
diff --git a/doc/src/sgml/ref/reindexdb.sgml b/doc/src/sgml/ref/reindexdb.sgml
index 486f5c9..b5b449c 100644
--- a/doc/src/sgml/ref/reindexdb.sgml
+++ b/doc/src/sgml/ref/reindexdb.sgml
@@ -27,6 +27,16 @@ PostgreSQL documentation
<arg choice="plain" rep="repeat">
<arg choice="opt">
<group choice="plain">
+ <arg choice="plain"><option>--schema</option></arg>
+ <arg choice="plain"><option>-S</option></arg>
+ </group>
+ <replaceable>table</replaceable>
+ </arg>
+ </arg>
+
+ <arg choice="plain" rep="repeat">
+ <arg choice="opt">
+ <group choice="plain">
<arg choice="plain"><option>--table</option></arg>
<arg choice="plain"><option>-t</option></arg>
</group>
@@ -162,6 +172,18 @@ PostgreSQL documentation
</varlistentry>
<varlistentry>
+ <term><option>-S <replaceable class="parameter">schema</replaceable></></term>
+ <term><option>--schema=<replaceable class="parameter">schema</replaceable></></term>
+ <listitem>
+ <para>
+ Reindex <replaceable class="parameter">schema</replaceable> only.
+ Multiple schemas can be reindexed by writing multiple
+ <option>-S</> switches.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
<term><option>-t <replaceable class="parameter">table</replaceable></></term>
<term><option>--table=<replaceable class="parameter">table</replaceable></></term>
<listitem>
diff --git a/src/bin/scripts/reindexdb.c b/src/bin/scripts/reindexdb.c
index 561bbce..5c4a64e 100644
--- a/src/bin/scripts/reindexdb.c
+++ b/src/bin/scripts/reindexdb.c
@@ -41,6 +41,7 @@ main(int argc, char *argv[])
{"password", no_argument, NULL, 'W'},
{"echo", no_argument, NULL, 'e'},
{"quiet", no_argument, NULL, 'q'},
+ {"schema", required_argument, NULL, 'S'},
{"dbname", required_argument, NULL, 'd'},
{"all", no_argument, NULL, 'a'},
{"system", no_argument, NULL, 's'},
@@ -66,6 +67,7 @@ main(int argc, char *argv[])
bool quiet = false;
SimpleStringList indexes = {NULL, NULL};
SimpleStringList tables = {NULL, NULL};
+ SimpleStringList schemas = {NULL, NULL};
progname = get_progname(argv[0]);
set_pglocale_pgservice(argv[0], PG_TEXTDOMAIN("pgscripts"));
@@ -73,7 +75,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:wWeqd:ast:i:", long_options, &optindex)) != -1)
+ while ((c = getopt_long(argc, argv, "h:p:U:wWeqS:d:ast:i:", long_options, &optindex)) != -1)
{
switch (c)
{
@@ -98,6 +100,9 @@ main(int argc, char *argv[])
case 'q':
quiet = true;
break;
+ case 'S':
+ simple_string_list_append(&schemas, optarg);
+ break;
case 'd':
dbname = pg_strdup(optarg);
break;
@@ -154,6 +159,11 @@ main(int argc, char *argv[])
fprintf(stderr, _("%s: cannot reindex all databases and system catalogs at the same time\n"), progname);
exit(1);
}
+ if (schemas.head != NULL)
+ {
+ fprintf(stderr, _("%s: cannot reindex specific schema(s) in all databases\n"), progname);
+ exit(1);
+ }
if (tables.head != NULL)
{
fprintf(stderr, _("%s: cannot reindex specific table(s) in all databases\n"), progname);
@@ -170,6 +180,11 @@ main(int argc, char *argv[])
}
else if (syscatalog)
{
+ if (schemas.head != NULL)
+ {
+ fprintf(stderr, _("%s: cannot reindex specific schema(s) and system catalogs at the same time\n"), progname);
+ exit(1);
+ }
if (tables.head != NULL)
{
fprintf(stderr, _("%s: cannot reindex specific table(s) and system catalogs at the same time\n"), progname);
@@ -206,6 +221,17 @@ main(int argc, char *argv[])
dbname = get_user_name_or_exit(progname);
}
+ if (schemas.head != NULL)
+ {
+ SimpleStringListCell *cell;
+
+ for (cell = schemas.head; cell; cell = cell->next)
+ {
+ reindex_one_database(cell->val, dbname, "SCHEMA", host, port,
+ username, prompt_password, progname, echo);
+ }
+ }
+
if (indexes.head != NULL)
{
SimpleStringListCell *cell;
@@ -226,8 +252,8 @@ main(int argc, char *argv[])
username, prompt_password, progname, echo);
}
}
- /* reindex database only if neither index nor table is specified */
- if (indexes.head == NULL && tables.head == NULL)
+ /* 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);
}
@@ -251,6 +277,8 @@ reindex_one_database(const char *name, const char *dbname, const char *type,
appendPQExpBuffer(&sql, " TABLE %s", name);
else if (strcmp(type, "INDEX") == 0)
appendPQExpBuffer(&sql, " INDEX %s", name);
+ else if (strcmp(type, "SCHEMA") == 0)
+ appendPQExpBuffer(&sql, " SCHEMA %s", name);
else if (strcmp(type, "DATABASE") == 0)
appendPQExpBuffer(&sql, " DATABASE %s", fmtId(name));
appendPQExpBufferStr(&sql, ";");
@@ -266,6 +294,9 @@ reindex_one_database(const char *name, const char *dbname, const char *type,
if (strcmp(type, "INDEX") == 0)
fprintf(stderr, _("%s: reindexing of index \"%s\" in database \"%s\" failed: %s"),
progname, name, dbname, PQerrorMessage(conn));
+ if (strcmp(type, "SCHEMA") == 0)
+ fprintf(stderr, _("%s: reindexing of schema \"%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));
@@ -348,6 +379,7 @@ help(const char *progname)
printf(_(" -i, --index=INDEX recreate specific index(es) only\n"));
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(_(" -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 d5b42de..1199bdc 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 => 16;
+use Test::More tests => 17;
program_help_ok('reindexdb');
program_version_ok('reindexdb');
@@ -29,6 +29,10 @@ issues_sql_like(
'reindex specific index');
issues_sql_like(
+ [ 'reindexdb', 'postgres', '-S', 'pg_catalog' ],
+ qr/statement: REINDEX ALL IN SCHEMA pg_catalog;/,
+ 'reindex specific schema');
+issues_sql_like(
[ 'reindexdb', 'postgres', '-s' ],
qr/statement: REINDEX SYSTEM postgres;/,
'reindex system tables');
000_reindex_schema_v5.patchapplication/octet-stream; name=000_reindex_schema_v5.patchDownload
diff --git a/doc/src/sgml/ref/reindex.sgml b/doc/src/sgml/ref/reindex.sgml
index cabae19..096960d 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 | DATABASE | SYSTEM } <replaceable class="PARAMETER">name</replaceable> [ FORCE ]
+REINDEX { INDEX | TABLE | SCHEMA | DATABASE | SYSTEM } <replaceable class="PARAMETER">name</replaceable> [ FORCE ]
</synopsis>
</refsynopsisdiv>
@@ -101,6 +101,19 @@ REINDEX { INDEX | TABLE | DATABASE | SYSTEM } <replaceable class="PARAMETER">nam
</varlistentry>
<varlistentry>
+ <term><literal>SCHEMA</literal></term>
+ <listitem>
+ <para>
+ Recreate all indexes of the specified schema. If the table has a
+ secondary <quote>TOAST</> table, that is reindexed as well.
+ Indexes on shared system catalogs are also processed.
+ This form of <command>REINDEX</command> cannot be executed inside a
+ transaction block.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
<term><literal>DATABASE</literal></term>
<listitem>
<para>
diff --git a/src/backend/commands/indexcmds.c b/src/backend/commands/indexcmds.c
index 12b4ac7..9cf09a8 100644
--- a/src/backend/commands/indexcmds.c
+++ b/src/backend/commands/indexcmds.c
@@ -1777,34 +1777,52 @@ ReindexTable(RangeVar *relation)
}
/*
- * ReindexDatabase
- * Recreate indexes of a database.
+ * ReindexDatabaseOrSchema
+ * Recreate indexes of a database or schema.
*
+ * kind means the type of object, database or schema.
* To reduce the probability of deadlocks, each table is reindexed in a
* separate transaction, so we can release the lock on it right away.
* That means this must not be called within a user transaction block!
*/
Oid
-ReindexDatabase(const char *databaseName, bool do_system, bool do_user)
+ReindexDatabaseOrSchema(const char *objectName, bool do_system, bool do_user, ObjectType kind)
{
+ Oid objectOid;
Relation relationRelation;
HeapScanDesc scan;
+ ScanKeyData *key = NULL;
HeapTuple tuple;
MemoryContext private_context;
MemoryContext old;
List *relids = NIL;
ListCell *l;
+ bool do_database = (kind == OBJECT_DATABASE);
+ int nkeys;
- AssertArg(databaseName);
+ AssertArg(objectName);
+ Assert(kind == OBJECT_DATABASE || kind == OBJECT_SCHEMA);
- if (strcmp(databaseName, get_database_name(MyDatabaseId)) != 0)
+ /* Get OID of object for result */
+ if (do_database)
+ objectOid = MyDatabaseId;
+ else
+ objectOid = get_namespace_oid(objectName, false);
+
+ if (!do_database)
+ {
+ do_system = IsSystemNamespace(objectOid);
+ do_user = !do_system;
+ }
+
+ if (do_database && strcmp(objectName, get_database_name(MyDatabaseId)) != 0)
ereport(ERROR,
(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
errmsg("can only reindex the currently open database")));
- if (!pg_database_ownercheck(MyDatabaseId, GetUserId()))
+ if (do_database && !pg_database_ownercheck(MyDatabaseId, GetUserId()))
aclcheck_error(ACLCHECK_NOT_OWNER, ACL_KIND_DATABASE,
- databaseName);
+ objectName);
/*
* Create a memory context that will survive forced transaction commits we
@@ -1813,7 +1831,8 @@ ReindexDatabase(const char *databaseName, bool do_system, bool do_user)
* abort cleanup logic.
*/
private_context = AllocSetContextCreate(PortalContext,
- "ReindexDatabase",
+ (do_database) ?
+ "ReindexDatabase" : "ReindexSchema",
ALLOCSET_DEFAULT_MINSIZE,
ALLOCSET_DEFAULT_INITSIZE,
ALLOCSET_DEFAULT_MAXSIZE);
@@ -1831,6 +1850,23 @@ ReindexDatabase(const char *databaseName, bool do_system, bool do_user)
MemoryContextSwitchTo(old);
}
+ /* For schema, we search target relations by relnamespce and relkind */
+ if (!do_database)
+ {
+ key = palloc(sizeof(ScanKeyData) * 2);
+ ScanKeyInit(&key[0],
+ Anum_pg_class_relnamespace,
+ BTEqualStrategyNumber, F_OIDEQ,
+ ObjectIdGetDatum(objectOid));
+ ScanKeyInit(&key[1],
+ Anum_pg_class_relkind,
+ BTEqualStrategyNumber, F_CHAREQ,
+ 'r');
+ nkeys = 2;
+ }
+ else
+ nkeys = 0;
+
/*
* Scan pg_class to build a list of the relations we need to reindex.
*
@@ -1838,7 +1874,7 @@ ReindexDatabase(const char *databaseName, bool do_system, bool do_user)
* rels will be processed indirectly by reindex_relation).
*/
relationRelation = heap_open(RelationRelationId, AccessShareLock);
- scan = heap_beginscan_catalog(relationRelation, 0, NULL);
+ scan = heap_beginscan_catalog(relationRelation, nkeys, key);
while ((tuple = heap_getnext(scan, ForwardScanDirection)) != NULL)
{
Form_pg_class classtuple = (Form_pg_class) GETSTRUCT(tuple);
@@ -1899,5 +1935,5 @@ ReindexDatabase(const char *databaseName, bool do_system, bool do_user)
MemoryContextDelete(private_context);
- return MyDatabaseId;
+ return objectOid;
}
diff --git a/src/backend/parser/gram.y b/src/backend/parser/gram.y
index bd180e7..7f35b34 100644
--- a/src/backend/parser/gram.y
+++ b/src/backend/parser/gram.y
@@ -7207,6 +7207,14 @@ ReindexStmt:
n->do_user = false;
$$ = (Node *)n;
}
+ | REINDEX SCHEMA name opt_force
+ {
+ ReindexStmt *n = makeNode(ReindexStmt);
+ n->kind = OBJECT_SCHEMA;
+ n->name = $3;
+ n->relation = NULL;
+ $$ = (Node *)n;
+ }
| REINDEX DATABASE name opt_force
{
ReindexStmt *n = makeNode(ReindexStmt);
diff --git a/src/backend/tcop/utility.c b/src/backend/tcop/utility.c
index 58f78ce..153b312 100644
--- a/src/backend/tcop/utility.c
+++ b/src/backend/tcop/utility.c
@@ -756,6 +756,7 @@ standard_ProcessUtility(Node *parsetree,
case OBJECT_MATVIEW:
ReindexTable(stmt->relation);
break;
+ case OBJECT_SCHEMA:
case OBJECT_DATABASE:
/*
@@ -765,9 +766,10 @@ standard_ProcessUtility(Node *parsetree,
* intended effect!
*/
PreventTransactionChain(isTopLevel,
- "REINDEX DATABASE");
- ReindexDatabase(stmt->name,
- stmt->do_system, stmt->do_user);
+ (stmt->kind == OBJECT_SCHEMA) ?
+ "REINDEX SCHEMA" : "REINDEX DATABASE");
+ ReindexDatabaseOrSchema(stmt->name,
+ stmt->do_system, stmt->do_user, stmt->kind);
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 8c85425..380c579 100644
--- a/src/bin/psql/tab-complete.c
+++ b/src/bin/psql/tab-complete.c
@@ -3330,7 +3330,7 @@ psql_completion(const char *text, int start, int end)
else if (pg_strcasecmp(prev_wd, "REINDEX") == 0)
{
static const char *const list_REINDEX[] =
- {"TABLE", "INDEX", "SYSTEM", "DATABASE", NULL};
+ {"TABLE", "INDEX", "SYSTEM", "SCHEMA", "DATABASE", NULL};
COMPLETE_WITH_LIST(list_REINDEX);
}
@@ -3340,6 +3340,8 @@ 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 )
+ 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);
diff --git a/src/include/commands/defrem.h b/src/include/commands/defrem.h
index 0ebdbc1..330d05c 100644
--- a/src/include/commands/defrem.h
+++ b/src/include/commands/defrem.h
@@ -30,8 +30,8 @@ extern Oid DefineIndex(Oid relationId,
bool quiet);
extern Oid ReindexIndex(RangeVar *indexRelation);
extern Oid ReindexTable(RangeVar *relation);
-extern Oid ReindexDatabase(const char *databaseName,
- bool do_system, bool do_user);
+extern Oid ReindexDatabaseOrSchema(const char *databaseName,
+ bool do_system, bool do_user, ObjectType kind);
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/test/regress/expected/create_index.out b/src/test/regress/expected/create_index.out
index 3ecb238..560a77b 100644
--- a/src/test/regress/expected/create_index.out
+++ b/src/test/regress/expected/create_index.out
@@ -2831,3 +2831,22 @@ explain (costs off)
Index Cond: ((thousand = 1) AND (tenthous = 1001))
(2 rows)
+--
+-- Reindex All In Schema
+--
+REINDEX SCHEMA tobereindexed; -- fail because schema doesn't exists
+ERROR: schema "tobereindexed" does not exist
+CREATE SCHEMA tobereindexed;
+CREATE TABLE tobereindexed.table1(col1 SERIAL PRIMARY KEY);
+CREATE TABLE tobereindexed.table2(col1 SERIAL PRIMARY KEY, col2 VARCHAR(100) NOT NULL);
+CREATE INDEX ON tobereindexed.table2(col2);
+REINDEX SCHEMA tobereindexed;
+NOTICE: table "tobereindexed.table1" was reindexed
+NOTICE: table "tobereindexed.table2" was reindexed
+BEGIN;
+REINDEX SCHEMA tobereindexed;
+ERROR: REINDEX SCHEMA cannot run inside a transaction block
+END;
+DROP TABLE tobereindexed.table2;
+DROP TABLE tobereindexed.table1;
+DROP SCHEMA tobereindexed;
diff --git a/src/test/regress/sql/create_index.sql b/src/test/regress/sql/create_index.sql
index e837676..299fd81 100644
--- a/src/test/regress/sql/create_index.sql
+++ b/src/test/regress/sql/create_index.sql
@@ -964,3 +964,19 @@ RESET enable_indexscan;
explain (costs off)
select * from tenk1 where (thousand, tenthous) in ((1,1001), (null,null));
+
+--
+-- Reindex All In Schema
+--
+REINDEX SCHEMA tobereindexed; -- fail because schema doesn't exists
+CREATE SCHEMA tobereindexed;
+CREATE TABLE tobereindexed.table1(col1 SERIAL PRIMARY KEY);
+CREATE TABLE tobereindexed.table2(col1 SERIAL PRIMARY KEY, col2 VARCHAR(100) NOT NULL);
+CREATE INDEX ON tobereindexed.table2(col2);
+REINDEX SCHEMA tobereindexed;
+BEGIN;
+REINDEX SCHEMA tobereindexed;
+END;
+DROP TABLE tobereindexed.table2;
+DROP TABLE tobereindexed.table1;
+DROP SCHEMA tobereindexed;
On 23 October 2014 00:21, Alvaro Herrera <alvherre@2ndquadrant.com> wrote:
Attached patch is latest version patch I modified above.
Also, I noticed I had forgotten to add the patch regarding document of
reindexdb.Please don't use pg_catalog in the regression test. That way we will
need to update the expected file whenever a new catalog is added, which
seems pointless. Maybe create a schema with a couple of tables
specifically for this, instead.
These patches look fine to me. Don't see anybody objecting either.
Are you looking to commit them, or shall I?
--
Simon Riggs 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
On Wed, Nov 19, 2014 at 1:37 AM, Simon Riggs <simon@2ndquadrant.com> wrote:
On 23 October 2014 00:21, Alvaro Herrera <alvherre@2ndquadrant.com> wrote:
Attached patch is latest version patch I modified above.
Also, I noticed I had forgotten to add the patch regarding document of
reindexdb.Please don't use pg_catalog in the regression test. That way we will
need to update the expected file whenever a new catalog is added, which
seems pointless. Maybe create a schema with a couple of tables
specifically for this, instead.These patches look fine to me. Don't see anybody objecting either.
Are you looking to commit them, or shall I?
IMO, SCHEMA is just but fine, that's more consistent with the existing
syntax we have for database and tables.
Btw, there is an error in this patch, there are no ACL checks on the
schema for the user doing the REINDEX, so any user is able to perform
a REINDEX on any schema. Here is an example for a given user, let's
say "poo'":
=> create table foo.g (a int);
ERROR: 42501: permission denied for schema foo
LOCATION: aclcheck_error, aclchk.c:3371
=> reindex schema foo ;
NOTICE: 00000: table "foo.c" was reindexed
LOCATION: ReindexDatabaseOrSchema, indexcmds.c:1930
REINDEX
A regression test to check that would be good as well.
Also, ISTM that it is awkward to modify the values of do_user and
do_system like that in ReindexDatabase for two reasons:
1) They should be set in gram.y
2) This patch passes as a new argument of ReindexDatabase the object
type, something that is overlapping with what do_user and do_system
are aimed for. Why not simply defining a new object type
OBJECT_SYSTEM? As this patch introduces a new object category for
REINDEX, this patch seems to be a good occasion to remove the boolean
dance in REINDEX at the cost of having a new object type for the
concept of a system, which would be a way to define the system
catalogs as a whole.
Another thing, ReindexDatabaseOrSchema should be renamed to ReindexObject.
So, I think that we need to think a bit more here. We are not far from
smth that could be committed, so marking as "Waiting on Author" for
now. Thoughts?
--
Michael
--
Sent via pgsql-hackers mailing list (pgsql-hackers@postgresql.org)
To make changes to your subscription:
http://www.postgresql.org/mailpref/pgsql-hackers
On Wed, Nov 26, 2014 at 3:48 PM, Michael Paquier
<michael.paquier@gmail.com> wrote:
On Wed, Nov 19, 2014 at 1:37 AM, Simon Riggs <simon@2ndquadrant.com> wrote:
On 23 October 2014 00:21, Alvaro Herrera <alvherre@2ndquadrant.com> wrote:
Attached patch is latest version patch I modified above.
Also, I noticed I had forgotten to add the patch regarding document of
reindexdb.Please don't use pg_catalog in the regression test. That way we will
need to update the expected file whenever a new catalog is added, which
seems pointless. Maybe create a schema with a couple of tables
specifically for this, instead.These patches look fine to me. Don't see anybody objecting either.
Are you looking to commit them, or shall I?
IMO, SCHEMA is just but fine, that's more consistent with the existing
syntax we have for database and tables.Btw, there is an error in this patch, there are no ACL checks on the
schema for the user doing the REINDEX, so any user is able to perform
a REINDEX on any schema. Here is an example for a given user, let's
say "poo'":
=> create table foo.g (a int);
ERROR: 42501: permission denied for schema foo
LOCATION: aclcheck_error, aclchk.c:3371
=> reindex schema foo ;
NOTICE: 00000: table "foo.c" was reindexed
LOCATION: ReindexDatabaseOrSchema, indexcmds.c:1930
REINDEX
A regression test to check that would be good as well.
Thank you for testing this patch.
It's a bug.
I will fix it and add test case to regression test.
Also, ISTM that it is awkward to modify the values of do_user and
do_system like that in ReindexDatabase for two reasons:
1) They should be set in gram.y
2) This patch passes as a new argument of ReindexDatabase the object
type, something that is overlapping with what do_user and do_system
are aimed for. Why not simply defining a new object type
OBJECT_SYSTEM? As this patch introduces a new object category for
REINDEX, this patch seems to be a good occasion to remove the boolean
dance in REINDEX at the cost of having a new object type for the
concept of a system, which would be a way to define the system
catalogs as a whole.
+1 to define new something object type and remove do_user and do_system.
But if we add OBJECT_SYSTEM to ObjectType data type,
system catalogs are OBJECT_SYSTEM as well as OBJECT_TABLE.
It's a bit redundant?
Another thing, ReindexDatabaseOrSchema should be renamed to ReindexObject.
So, I think that we need to think a bit more here. We are not far from
smth that could be committed, so marking as "Waiting on Author" for
now. Thoughts?
Is the table also kind of "object"?
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
On Thu, Nov 27, 2014 at 12:55 AM, Sawada Masahiko <sawada.mshk@gmail.com> wrote:
+1 to define new something object type and remove do_user and do_system.
But if we add OBJECT_SYSTEM to ObjectType data type,
system catalogs are OBJECT_SYSTEM as well as OBJECT_TABLE.
It's a bit redundant?
Yes, kind of. That's a superset of a type of relations, aka a set of
catalog tables. If you find something cleaner to propose, feel free.
Another thing, ReindexDatabaseOrSchema should be renamed to ReindexObject.
So, I think that we need to think a bit more here. We are not far from
smth that could be committed, so marking as "Waiting on Author" for
now. Thoughts?Is the table also kind of "object"?
Sorry, I am not sure I follow you here. Indexes and tables have
already their relkind set in ReindexStmt, and I think that we're fine
to continue letting them go in their own reindex code path for now.
--
Michael
--
Sent via pgsql-hackers mailing list (pgsql-hackers@postgresql.org)
To make changes to your subscription:
http://www.postgresql.org/mailpref/pgsql-hackers
On Thu, Nov 27, 2014 at 1:07 PM, Michael Paquier
<michael.paquier@gmail.com> wrote:
On Thu, Nov 27, 2014 at 12:55 AM, Sawada Masahiko <sawada.mshk@gmail.com> wrote:
+1 to define new something object type and remove do_user and do_system.
But if we add OBJECT_SYSTEM to ObjectType data type,
system catalogs are OBJECT_SYSTEM as well as OBJECT_TABLE.
It's a bit redundant?Yes, kind of. That's a superset of a type of relations, aka a set of
catalog tables. If you find something cleaner to propose, feel free.
I thought we can add new struct like ReindexObjectType which has
REINDEX_OBJECT_TABLE,
REINDEX_OBJECT_SYSTEM and so on. It's similar to GRANT syntax.
Another thing, ReindexDatabaseOrSchema should be renamed to ReindexObject.
So, I think that we need to think a bit more here. We are not far from
smth that could be committed, so marking as "Waiting on Author" for
now. Thoughts?Is the table also kind of "object"?
Sorry, I am not sure I follow you here. Indexes and tables have
already their relkind set in ReindexStmt, and I think that we're fine
to continue letting them go in their own reindex code path for now.
It was not enough, sorry.
I mean that there is already ReindexTable() function.
if we renamed ReindexObject, I would feel uncomfortable feeling.
Because table is also kind of "object".
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
On Thu, Nov 27, 2014 at 8:18 PM, Sawada Masahiko <sawada.mshk@gmail.com> wrote:
On Thu, Nov 27, 2014 at 1:07 PM, Michael Paquier
<michael.paquier@gmail.com> wrote:On Thu, Nov 27, 2014 at 12:55 AM, Sawada Masahiko <sawada.mshk@gmail.com> wrote:
+1 to define new something object type and remove do_user and do_system.
But if we add OBJECT_SYSTEM to ObjectType data type,
system catalogs are OBJECT_SYSTEM as well as OBJECT_TABLE.
It's a bit redundant?Yes, kind of. That's a superset of a type of relations, aka a set of
catalog tables. If you find something cleaner to propose, feel free.I thought we can add new struct like ReindexObjectType which has
REINDEX_OBJECT_TABLE,
REINDEX_OBJECT_SYSTEM and so on. It's similar to GRANT syntax.
Check.
Another thing, ReindexDatabaseOrSchema should be renamed to ReindexObject.
So, I think that we need to think a bit more here. We are not far from
smth that could be committed, so marking as "Waiting on Author" for
now. Thoughts?Is the table also kind of "object"?
Sorry, I am not sure I follow you here. Indexes and tables have
already their relkind set in ReindexStmt, and I think that we're fine
to continue letting them go in their own reindex code path for now.It was not enough, sorry.
I mean that there is already ReindexTable() function.
if we renamed ReindexObject, I would feel uncomfortable feeling.
Because table is also kind of "object".
Check.
If you get that done, I'll have an extra look at it and then let's
have a committer look at it.
Regards,
--
Michael
--
Sent via pgsql-hackers mailing list (pgsql-hackers@postgresql.org)
To make changes to your subscription:
http://www.postgresql.org/mailpref/pgsql-hackers
On Thu, Nov 27, 2014 at 11:43 PM, Michael Paquier
<michael.paquier@gmail.com> wrote:
On Thu, Nov 27, 2014 at 8:18 PM, Sawada Masahiko <sawada.mshk@gmail.com> wrote:
On Thu, Nov 27, 2014 at 1:07 PM, Michael Paquier
<michael.paquier@gmail.com> wrote:On Thu, Nov 27, 2014 at 12:55 AM, Sawada Masahiko <sawada.mshk@gmail.com> wrote:
+1 to define new something object type and remove do_user and do_system.
But if we add OBJECT_SYSTEM to ObjectType data type,
system catalogs are OBJECT_SYSTEM as well as OBJECT_TABLE.
It's a bit redundant?Yes, kind of. That's a superset of a type of relations, aka a set of
catalog tables. If you find something cleaner to propose, feel free.I thought we can add new struct like ReindexObjectType which has
REINDEX_OBJECT_TABLE,
REINDEX_OBJECT_SYSTEM and so on. It's similar to GRANT syntax.Check.
Another thing, ReindexDatabaseOrSchema should be renamed to ReindexObject.
So, I think that we need to think a bit more here. We are not far from
smth that could be committed, so marking as "Waiting on Author" for
now. Thoughts?Is the table also kind of "object"?
Sorry, I am not sure I follow you here. Indexes and tables have
already their relkind set in ReindexStmt, and I think that we're fine
to continue letting them go in their own reindex code path for now.It was not enough, sorry.
I mean that there is already ReindexTable() function.
if we renamed ReindexObject, I would feel uncomfortable feeling.
Because table is also kind of "object".Check.
If you get that done, I'll have an extra look at it and then let's
have a committer look at it.
Attached patch is latest version.
I added new enum values like REINDEX_OBJECT_XXX,
and changed ReindexObject() function.
Also ACL problem is fixed for this version.
Regards,
-------
Sawada Masahiko
Attachments:
000_reindex_schema_v6.patchapplication/octet-stream; name=000_reindex_schema_v6.patchDownload
diff --git a/doc/src/sgml/ref/reindex.sgml b/doc/src/sgml/ref/reindex.sgml
index cabae19..096960d 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 | DATABASE | SYSTEM } <replaceable class="PARAMETER">name</replaceable> [ FORCE ]
+REINDEX { INDEX | TABLE | SCHEMA | DATABASE | SYSTEM } <replaceable class="PARAMETER">name</replaceable> [ FORCE ]
</synopsis>
</refsynopsisdiv>
@@ -101,6 +101,19 @@ REINDEX { INDEX | TABLE | DATABASE | SYSTEM } <replaceable class="PARAMETER">nam
</varlistentry>
<varlistentry>
+ <term><literal>SCHEMA</literal></term>
+ <listitem>
+ <para>
+ Recreate all indexes of the specified schema. If the table has a
+ secondary <quote>TOAST</> table, that is reindexed as well.
+ Indexes on shared system catalogs are also processed.
+ This form of <command>REINDEX</command> cannot be executed inside a
+ transaction block.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
<term><literal>DATABASE</literal></term>
<listitem>
<para>
diff --git a/src/backend/commands/indexcmds.c b/src/backend/commands/indexcmds.c
index 12b4ac7..d00f663 100644
--- a/src/backend/commands/indexcmds.c
+++ b/src/backend/commands/indexcmds.c
@@ -1777,34 +1777,58 @@ ReindexTable(RangeVar *relation)
}
/*
- * ReindexDatabase
- * Recreate indexes of a database.
+ * ReindexObject
+ * Recreate indexes of a database or schema.
*
+ * kind means the type of object, database or schema.
* To reduce the probability of deadlocks, each table is reindexed in a
* separate transaction, so we can release the lock on it right away.
* That means this must not be called within a user transaction block!
*/
Oid
-ReindexDatabase(const char *databaseName, bool do_system, bool do_user)
+ReindexObject(const char *objectName, ReindexObjectType kind)
{
+ Oid objectOid;
Relation relationRelation;
HeapScanDesc scan;
+ ScanKeyData *key = NULL;
HeapTuple tuple;
MemoryContext private_context;
MemoryContext old;
List *relids = NIL;
ListCell *l;
+ bool do_database = (kind >= REINDEX_OBJECT_SYSTEM);
+ bool do_system = false;
+ bool do_user = false;
+ int nkeys;
- AssertArg(databaseName);
+ AssertArg(objectName);
+ Assert(kind >= REINDEX_OBJECT_SCHEMA && kind <= REINDEX_OBJECT_DATABASE);
- if (strcmp(databaseName, get_database_name(MyDatabaseId)) != 0)
+ /* Get OID of object for result */
+ if (do_database)
+ objectOid = MyDatabaseId;
+ else
+ objectOid = get_namespace_oid(objectName, false);
+
+ if (!do_database)
+ {
+ do_system = IsSystemNamespace(objectOid);
+ do_user = !do_system;
+ }
+
+ if (do_database && strcmp(objectName, get_database_name(MyDatabaseId)) != 0)
ereport(ERROR,
(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
errmsg("can only reindex the currently open database")));
- if (!pg_database_ownercheck(MyDatabaseId, GetUserId()))
+ if (do_database && !pg_database_ownercheck(MyDatabaseId, GetUserId()))
aclcheck_error(ACLCHECK_NOT_OWNER, ACL_KIND_DATABASE,
- databaseName);
+ objectName);
+
+ if (!do_database && !pg_namespace_ownercheck(objectOid, GetUserId()))
+ aclcheck_error(ACLCHECK_NOT_OWNER, ACL_KIND_NAMESPACE,
+ objectName);
/*
* Create a memory context that will survive forced transaction commits we
@@ -1813,7 +1837,8 @@ ReindexDatabase(const char *databaseName, bool do_system, bool do_user)
* abort cleanup logic.
*/
private_context = AllocSetContextCreate(PortalContext,
- "ReindexDatabase",
+ (do_database) ?
+ "ReindexDatabase" : "ReindexSchema",
ALLOCSET_DEFAULT_MINSIZE,
ALLOCSET_DEFAULT_INITSIZE,
ALLOCSET_DEFAULT_MAXSIZE);
@@ -1831,6 +1856,23 @@ ReindexDatabase(const char *databaseName, bool do_system, bool do_user)
MemoryContextSwitchTo(old);
}
+ /* For schema, we search target relations by relnamespce and relkind */
+ if (!do_database)
+ {
+ key = palloc(sizeof(ScanKeyData) * 2);
+ ScanKeyInit(&key[0],
+ Anum_pg_class_relnamespace,
+ BTEqualStrategyNumber, F_OIDEQ,
+ ObjectIdGetDatum(objectOid));
+ ScanKeyInit(&key[1],
+ Anum_pg_class_relkind,
+ BTEqualStrategyNumber, F_CHAREQ,
+ 'r');
+ nkeys = 2;
+ }
+ else
+ nkeys = 0;
+
/*
* Scan pg_class to build a list of the relations we need to reindex.
*
@@ -1838,7 +1880,7 @@ ReindexDatabase(const char *databaseName, bool do_system, bool do_user)
* rels will be processed indirectly by reindex_relation).
*/
relationRelation = heap_open(RelationRelationId, AccessShareLock);
- scan = heap_beginscan_catalog(relationRelation, 0, NULL);
+ scan = heap_beginscan_catalog(relationRelation, nkeys, key);
while ((tuple = heap_getnext(scan, ForwardScanDirection)) != NULL)
{
Form_pg_class classtuple = (Form_pg_class) GETSTRUCT(tuple);
@@ -1899,5 +1941,5 @@ ReindexDatabase(const char *databaseName, bool do_system, bool do_user)
MemoryContextDelete(private_context);
- return MyDatabaseId;
+ return objectOid;
}
diff --git a/src/backend/parser/gram.y b/src/backend/parser/gram.y
index bd180e7..da3dc31 100644
--- a/src/backend/parser/gram.y
+++ b/src/backend/parser/gram.y
@@ -404,7 +404,7 @@ static Node *makeRecursiveViewSelect(char *relname, List *aliases, Node *query);
%type <boolean> copy_from opt_program
%type <ival> opt_column event cursor_options opt_hold opt_set_data
-%type <objtype> reindex_type drop_type comment_type security_label_type
+%type <objtype> reindex_type reindex_object drop_type comment_type security_label_type
%type <node> fetch_args limit_clause select_limit_value
offset_clause select_offset_value
@@ -7197,31 +7197,25 @@ ReindexStmt:
n->name = NULL;
$$ = (Node *)n;
}
- | REINDEX SYSTEM_P name opt_force
+ | REINDEX reindex_object name opt_force
{
ReindexStmt *n = makeNode(ReindexStmt);
- n->kind = OBJECT_DATABASE;
- n->name = $3;
- n->relation = NULL;
- n->do_system = true;
- n->do_user = false;
- $$ = (Node *)n;
- }
- | REINDEX DATABASE name opt_force
- {
- ReindexStmt *n = makeNode(ReindexStmt);
- n->kind = OBJECT_DATABASE;
+ n->kind = $2;
n->name = $3;
n->relation = NULL;
- n->do_system = true;
- n->do_user = true;
$$ = (Node *)n;
}
;
reindex_type:
- INDEX { $$ = OBJECT_INDEX; }
- | TABLE { $$ = OBJECT_TABLE; }
+ INDEX { $$ = REINDEX_OBJECT_INDEX; }
+ | TABLE { $$ = REINDEX_OBJECT_TABLE; }
+ ;
+
+reindex_object:
+ SYSTEM_P { $$ = REINDEX_OBJECT_SYSTEM; }
+ | SCHEMA { $$ = REINDEX_OBJECT_SCHEMA; }
+ | DATABASE { $$ = REINDEX_OBJECT_DATABASE; }
;
opt_force: FORCE { $$ = TRUE; }
diff --git a/src/backend/tcop/utility.c b/src/backend/tcop/utility.c
index 58f78ce..f89d6cc 100644
--- a/src/backend/tcop/utility.c
+++ b/src/backend/tcop/utility.c
@@ -749,14 +749,16 @@ standard_ProcessUtility(Node *parsetree,
PreventCommandDuringRecovery("REINDEX");
switch (stmt->kind)
{
- case OBJECT_INDEX:
+ case REINDEX_OBJECT_INDEX:
ReindexIndex(stmt->relation);
break;
- case OBJECT_TABLE:
- case OBJECT_MATVIEW:
+ case REINDEX_OBJECT_TABLE:
+ case REINDEX_OBJECT_MATVIEW:
ReindexTable(stmt->relation);
break;
- case OBJECT_DATABASE:
+ case REINDEX_OBJECT_SCHEMA:
+ case REINDEX_OBJECT_SYSTEM:
+ case REINDEX_OBJECT_DATABASE:
/*
* This cannot run inside a user transaction block; if
@@ -765,9 +767,10 @@ standard_ProcessUtility(Node *parsetree,
* intended effect!
*/
PreventTransactionChain(isTopLevel,
- "REINDEX DATABASE");
- ReindexDatabase(stmt->name,
- stmt->do_system, stmt->do_user);
+ (stmt->kind == REINDEX_OBJECT_DATABASE) ?
+ "REINDEX DATABASE" : ((stmt->kind == REINDEX_OBJECT_SCHEMA) ?
+ "REINDEX SCHEMA" : "REINDEX SYSTEM"));
+ ReindexObject(stmt->name, stmt->kind);
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 8c85425..380c579 100644
--- a/src/bin/psql/tab-complete.c
+++ b/src/bin/psql/tab-complete.c
@@ -3330,7 +3330,7 @@ psql_completion(const char *text, int start, int end)
else if (pg_strcasecmp(prev_wd, "REINDEX") == 0)
{
static const char *const list_REINDEX[] =
- {"TABLE", "INDEX", "SYSTEM", "DATABASE", NULL};
+ {"TABLE", "INDEX", "SYSTEM", "SCHEMA", "DATABASE", NULL};
COMPLETE_WITH_LIST(list_REINDEX);
}
@@ -3340,6 +3340,8 @@ 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 )
+ 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);
diff --git a/src/include/commands/defrem.h b/src/include/commands/defrem.h
index 0ebdbc1..f6210d3 100644
--- a/src/include/commands/defrem.h
+++ b/src/include/commands/defrem.h
@@ -30,8 +30,7 @@ extern Oid DefineIndex(Oid relationId,
bool quiet);
extern Oid ReindexIndex(RangeVar *indexRelation);
extern Oid ReindexTable(RangeVar *relation);
-extern Oid ReindexDatabase(const char *databaseName,
- bool do_system, bool do_user);
+extern Oid ReindexObject(const char *databaseName, ReindexObjectType kind);
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 3e4f815..4984a55 100644
--- a/src/include/nodes/parsenodes.h
+++ b/src/include/nodes/parsenodes.h
@@ -2721,10 +2721,20 @@ typedef struct ConstraintsSetStmt
* REINDEX Statement
* ----------------------
*/
+typedef enum ReindexObjectType
+{
+ REINDEX_OBJECT_INDEX, /* index */
+ REINDEX_OBJECT_TABLE, /* table */
+ REINDEX_OBJECT_MATVIEW, /* materialized view */
+ REINDEX_OBJECT_SCHEMA, /* schema */
+ REINDEX_OBJECT_SYSTEM, /* system catalog */
+ REINDEX_OBJECT_DATABASE /* database */
+} ReindexObjectType;
+
typedef struct ReindexStmt
{
NodeTag type;
- ObjectType kind; /* OBJECT_INDEX, OBJECT_TABLE, etc. */
+ 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 do_system; /* include system tables in database case */
diff --git a/src/test/regress/expected/create_index.out b/src/test/regress/expected/create_index.out
index 3ecb238..895ce93 100644
--- a/src/test/regress/expected/create_index.out
+++ b/src/test/regress/expected/create_index.out
@@ -2831,3 +2831,30 @@ explain (costs off)
Index Cond: ((thousand = 1) AND (tenthous = 1001))
(2 rows)
+--
+-- Reindex All In Schema
+--
+REINDEX SCHEMA tobereindexed; -- fail because schema doesn't exists
+ERROR: schema "tobereindexed" does not exist
+CREATE SCHEMA tobereindexed;
+CREATE TABLE tobereindexed.table1(col1 SERIAL PRIMARY KEY);
+CREATE TABLE tobereindexed.table2(col1 SERIAL PRIMARY KEY, col2 VARCHAR(100) NOT NULL);
+CREATE INDEX ON tobereindexed.table2(col2);
+REINDEX SCHEMA tobereindexed;
+NOTICE: table "tobereindexed.table1" was reindexed
+NOTICE: table "tobereindexed.table2" was reindexed
+BEGIN;
+REINDEX SCHEMA tobereindexed;
+ERROR: REINDEX SCHEMA cannot run inside a transaction block
+END;
+-- Try to reindex by unprivileged user
+CREATE ROLE reindexuser login;
+SET SESSION ROLE reindexuser;
+REINDEX SCHEMA tobereindexed;
+ERROR: must be owner of schema tobereindexed
+-- clean up
+\c -
+DROP ROLE reindexuser;
+DROP TABLE tobereindexed.table2;
+DROP TABLE tobereindexed.table1;
+DROP SCHEMA tobereindexed;
diff --git a/src/test/regress/sql/create_index.sql b/src/test/regress/sql/create_index.sql
index e837676..544c31e 100644
--- a/src/test/regress/sql/create_index.sql
+++ b/src/test/regress/sql/create_index.sql
@@ -964,3 +964,28 @@ RESET enable_indexscan;
explain (costs off)
select * from tenk1 where (thousand, tenthous) in ((1,1001), (null,null));
+
+--
+-- Reindex All In Schema
+--
+REINDEX SCHEMA tobereindexed; -- fail because schema doesn't exists
+CREATE SCHEMA tobereindexed;
+CREATE TABLE tobereindexed.table1(col1 SERIAL PRIMARY KEY);
+CREATE TABLE tobereindexed.table2(col1 SERIAL PRIMARY KEY, col2 VARCHAR(100) NOT NULL);
+CREATE INDEX ON tobereindexed.table2(col2);
+REINDEX SCHEMA tobereindexed;
+BEGIN;
+REINDEX SCHEMA tobereindexed;
+END;
+
+-- Try to reindex by unprivileged user
+CREATE ROLE reindexuser login;
+SET SESSION ROLE reindexuser;
+REINDEX SCHEMA tobereindexed;
+
+-- clean up
+\c -
+DROP ROLE reindexuser;
+DROP TABLE tobereindexed.table2;
+DROP TABLE tobereindexed.table1;
+DROP SCHEMA tobereindexed;
On Mon, Dec 1, 2014 at 11:29 PM, Sawada Masahiko <sawada.mshk@gmail.com> wrote:
On Thu, Nov 27, 2014 at 11:43 PM, Michael Paquier
<michael.paquier@gmail.com> wrote:If you get that done, I'll have an extra look at it and then let's
have a committer look at it.Attached patch is latest version.
I added new enum values like REINDEX_OBJECT_XXX,
and changed ReindexObject() function.
Also ACL problem is fixed for this version.
Thanks for the updated version.
I have been looking at this patch more deeply, and I noticed a couple
of things that were missing or mishandled:
- The patch completely ignored that a catalog schema could be reindexed
- When reindexing pg_catalog as a schema, it is critical to reindex
pg_class first as reindex_relation updates pg_class.
- gram.y generated some warnings because ReindexObjectType stuff was
casted as ObjectType.
- There was a memory leak, the scan keys palloc'd in ReindexObject
were not pfree'd
- Using do_user, do_system and now do_database was really confusing
and reduced code lisibility. I reworked it using the object kind
- The patch to support SCHEMA in reindexdb has been forgotten.
Reattaching it here.
Adding on top of that a couple of things cleaned up, like docs and
typos, and I got the patch attached. Let's have a committer have a
look a it now, I am marking that as "Ready for Committer".
Regards,
--
Michael
Attachments:
0001-Support-for-REINDEX-SCHEMA.patchtext/x-diff; charset=US-ASCII; name=0001-Support-for-REINDEX-SCHEMA.patchDownload
From 1e384f579ffa865c364616573bd8767a24306c44 Mon Sep 17 00:00:00 2001
From: Michael Paquier <michael@otacoo.com>
Date: Tue, 2 Dec 2014 15:29:36 +0900
Subject: [PATCH 1/2] Support for REINDEX SCHEMA
When pg_catalog is reindexed, note that pg_class is reindexed first
for a behavior consistent with the cases of DATABASE and SYSTEM.
---
doc/src/sgml/ref/reindex.sgml | 15 +++-
src/backend/commands/indexcmds.c | 110 +++++++++++++++++++++--------
src/backend/parser/gram.y | 35 +++++----
src/backend/tcop/utility.c | 15 ++--
src/bin/psql/tab-complete.c | 4 +-
src/include/commands/defrem.h | 3 +-
src/include/nodes/parsenodes.h | 11 ++-
src/test/regress/expected/create_index.out | 31 ++++++++
src/test/regress/sql/create_index.sql | 23 ++++++
9 files changed, 191 insertions(+), 56 deletions(-)
diff --git a/doc/src/sgml/ref/reindex.sgml b/doc/src/sgml/ref/reindex.sgml
index cabae19..0a4c7d4 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 | DATABASE | SYSTEM } <replaceable class="PARAMETER">name</replaceable> [ FORCE ]
+REINDEX { INDEX | TABLE | SCHEMA | DATABASE | SYSTEM } <replaceable class="PARAMETER">name</replaceable> [ FORCE ]
</synopsis>
</refsynopsisdiv>
@@ -101,6 +101,19 @@ REINDEX { INDEX | TABLE | DATABASE | SYSTEM } <replaceable class="PARAMETER">nam
</varlistentry>
<varlistentry>
+ <term><literal>SCHEMA</literal></term>
+ <listitem>
+ <para>
+ Recreate all indexes of the specified schema. If a table of this
+ schema has a secondary <quote>TOAST</> table, that is reindexed as
+ well. Indexes on shared system catalogs are also processed.
+ This form of <command>REINDEX</command> cannot be executed inside a
+ transaction block.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
<term><literal>DATABASE</literal></term>
<listitem>
<para>
diff --git a/src/backend/commands/indexcmds.c b/src/backend/commands/indexcmds.c
index 12b4ac7..a3e8a15 100644
--- a/src/backend/commands/indexcmds.c
+++ b/src/backend/commands/indexcmds.c
@@ -1777,34 +1777,58 @@ ReindexTable(RangeVar *relation)
}
/*
- * ReindexDatabase
- * Recreate indexes of a database.
+ * ReindexObject
+ * Recreate indexes of object whose type is defined by objectKind.
*
* To reduce the probability of deadlocks, each table is reindexed in a
* separate transaction, so we can release the lock on it right away.
* That means this must not be called within a user transaction block!
*/
Oid
-ReindexDatabase(const char *databaseName, bool do_system, bool do_user)
+ReindexObject(const char *objectName, ReindexObjectType objectKind)
{
+ Oid objectOid;
Relation relationRelation;
HeapScanDesc scan;
+ ScanKeyData *scan_keys = NULL;
HeapTuple tuple;
MemoryContext private_context;
MemoryContext old;
List *relids = NIL;
ListCell *l;
+ int num_keys;
- AssertArg(databaseName);
+ AssertArg(objectName);
+ Assert(objectKind == REINDEX_OBJECT_SCHEMA ||
+ objectKind == REINDEX_OBJECT_SYSTEM ||
+ objectKind == REINDEX_OBJECT_DATABASE);
- if (strcmp(databaseName, get_database_name(MyDatabaseId)) != 0)
- ereport(ERROR,
- (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
- errmsg("can only reindex the currently open database")));
+ /*
+ * 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 by caller. At the same time do permission checks that need
+ * different processing depending on the object type.
+ */
+ if (objectKind == REINDEX_OBJECT_SCHEMA)
+ {
+ objectOid = get_namespace_oid(objectName, false);
- if (!pg_database_ownercheck(MyDatabaseId, GetUserId()))
- aclcheck_error(ACLCHECK_NOT_OWNER, ACL_KIND_DATABASE,
- databaseName);
+ if (!pg_namespace_ownercheck(objectOid, GetUserId()))
+ aclcheck_error(ACLCHECK_NOT_OWNER, ACL_KIND_NAMESPACE,
+ objectName);
+ }
+ else
+ {
+ objectOid = MyDatabaseId;
+
+ if (strcmp(objectName, get_database_name(MyDatabaseId)) != 0)
+ ereport(ERROR,
+ (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
+ errmsg("can only reindex the currently open database")));
+ if (!pg_database_ownercheck(MyDatabaseId, GetUserId()))
+ aclcheck_error(ACLCHECK_NOT_OWNER, ACL_KIND_DATABASE,
+ objectName);
+ }
/*
* Create a memory context that will survive forced transaction commits we
@@ -1813,18 +1837,23 @@ ReindexDatabase(const char *databaseName, bool do_system, bool do_user)
* abort cleanup logic.
*/
private_context = AllocSetContextCreate(PortalContext,
- "ReindexDatabase",
+ (objectKind == REINDEX_OBJECT_SCHEMA) ?
+ "ReindexSchema" : "ReindexDatabase",
ALLOCSET_DEFAULT_MINSIZE,
ALLOCSET_DEFAULT_INITSIZE,
ALLOCSET_DEFAULT_MAXSIZE);
/*
- * We always want to reindex pg_class first. This ensures that if there
- * is any corruption in pg_class' indexes, they will be fixed before we
- * process any other tables. This is critical because reindexing itself
- * will try to update pg_class.
+ * We always want to reindex pg_class first when reindexing system
+ * catalogs or a database. This ensures that if there is any corruption
+ * in pg_class' indexes, they will be fixed before we process any other
+ * tables. This is critical because reindexing itself will try to
+ * update pg_class.
*/
- if (do_system)
+ if (objectKind == REINDEX_OBJECT_DATABASE ||
+ objectKind == REINDEX_OBJECT_SYSTEM ||
+ (objectKind == REINDEX_OBJECT_SCHEMA &&
+ IsSystemNamespace(objectOid)))
{
old = MemoryContextSwitchTo(private_context);
relids = lappend_oid(relids, RelationRelationId);
@@ -1832,13 +1861,34 @@ ReindexDatabase(const char *databaseName, bool do_system, bool do_user)
}
/*
+ * Define the search keys to find the objects to reindex. For a schema,
+ * we search target relations using relnamespace and relkind, something
+ * not necessary for a database-wide operation.
+ */
+ if (objectKind == REINDEX_OBJECT_SCHEMA)
+ {
+ scan_keys = palloc(sizeof(ScanKeyData) * 2);
+ ScanKeyInit(&scan_keys[0],
+ Anum_pg_class_relnamespace,
+ BTEqualStrategyNumber, F_OIDEQ,
+ ObjectIdGetDatum(objectOid));
+ ScanKeyInit(&scan_keys[1],
+ Anum_pg_class_relkind,
+ BTEqualStrategyNumber, F_CHAREQ,
+ 'r');
+ num_keys = 2;
+ }
+ else
+ num_keys = 0;
+
+ /*
* Scan pg_class to build a list of the relations we need to reindex.
*
* We only consider plain relations and materialized views here (toast
* rels will be processed indirectly by reindex_relation).
*/
relationRelation = heap_open(RelationRelationId, AccessShareLock);
- scan = heap_beginscan_catalog(relationRelation, 0, NULL);
+ scan = heap_beginscan_catalog(relationRelation, num_keys, scan_keys);
while ((tuple = heap_getnext(scan, ForwardScanDirection)) != NULL)
{
Form_pg_class classtuple = (Form_pg_class) GETSTRUCT(tuple);
@@ -1854,19 +1904,17 @@ ReindexDatabase(const char *databaseName, bool do_system, bool do_user)
continue;
/* Check user/system classification, and optionally skip */
- if (IsSystemClass(relid, classtuple))
- {
- if (!do_system)
- continue;
- }
- else
- {
- if (!do_user)
- continue;
- }
+ if (!IsSystemClass(relid, classtuple) &&
+ objectKind == REINDEX_OBJECT_SYSTEM)
+ continue;
+ /*
+ * Already have it in the case of system catalogs being all
+ * reindexed, of a database or of a system catalog being reindexed
+ * as a schema.
+ */
if (HeapTupleGetOid(tuple) == RelationRelationId)
- continue; /* got it already */
+ continue;
old = MemoryContextSwitchTo(private_context);
relids = lappend_oid(relids, relid);
@@ -1898,6 +1946,8 @@ ReindexDatabase(const char *databaseName, bool do_system, bool do_user)
StartTransactionCommand();
MemoryContextDelete(private_context);
+ if (scan_keys)
+ pfree(scan_keys);
- return MyDatabaseId;
+ return objectOid;
}
diff --git a/src/backend/parser/gram.y b/src/backend/parser/gram.y
index 7e48958..4b5009b 100644
--- a/src/backend/parser/gram.y
+++ b/src/backend/parser/gram.y
@@ -404,7 +404,7 @@ static Node *makeRecursiveViewSelect(char *relname, List *aliases, Node *query);
%type <boolean> copy_from opt_program
%type <ival> opt_column event cursor_options opt_hold opt_set_data
-%type <objtype> reindex_type drop_type comment_type security_label_type
+%type <objtype> drop_type comment_type security_label_type
%type <node> fetch_args limit_clause select_limit_value
offset_clause select_offset_value
@@ -7198,41 +7198,48 @@ opt_if_exists: IF_P EXISTS { $$ = TRUE; }
*****************************************************************************/
ReindexStmt:
- REINDEX reindex_type qualified_name opt_force
+ REINDEX INDEX qualified_name opt_force
{
ReindexStmt *n = makeNode(ReindexStmt);
- n->kind = $2;
+ n->kind = REINDEX_OBJECT_INDEX;
n->relation = $3;
n->name = NULL;
$$ = (Node *)n;
}
+ | REINDEX TABLE qualified_name opt_force
+ {
+ ReindexStmt *n = makeNode(ReindexStmt);
+ n->kind = REINDEX_OBJECT_TABLE;
+ n->relation = $3;
+ n->name = NULL;
+ $$ = (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
{
ReindexStmt *n = makeNode(ReindexStmt);
- n->kind = OBJECT_DATABASE;
+ n->kind = REINDEX_OBJECT_SYSTEM;
n->name = $3;
n->relation = NULL;
- n->do_system = true;
- n->do_user = false;
$$ = (Node *)n;
}
| REINDEX DATABASE name opt_force
{
ReindexStmt *n = makeNode(ReindexStmt);
- n->kind = OBJECT_DATABASE;
+ n->kind = REINDEX_OBJECT_DATABASE;
n->name = $3;
n->relation = NULL;
- n->do_system = true;
- n->do_user = true;
$$ = (Node *)n;
}
;
-reindex_type:
- INDEX { $$ = OBJECT_INDEX; }
- | TABLE { $$ = OBJECT_TABLE; }
- ;
-
opt_force: FORCE { $$ = TRUE; }
| /* EMPTY */ { $$ = FALSE; }
;
diff --git a/src/backend/tcop/utility.c b/src/backend/tcop/utility.c
index 58f78ce..aa8fe88 100644
--- a/src/backend/tcop/utility.c
+++ b/src/backend/tcop/utility.c
@@ -749,14 +749,15 @@ standard_ProcessUtility(Node *parsetree,
PreventCommandDuringRecovery("REINDEX");
switch (stmt->kind)
{
- case OBJECT_INDEX:
+ case REINDEX_OBJECT_INDEX:
ReindexIndex(stmt->relation);
break;
- case OBJECT_TABLE:
- case OBJECT_MATVIEW:
+ case REINDEX_OBJECT_TABLE:
ReindexTable(stmt->relation);
break;
- case OBJECT_DATABASE:
+ case REINDEX_OBJECT_SCHEMA:
+ case REINDEX_OBJECT_SYSTEM:
+ case REINDEX_OBJECT_DATABASE:
/*
* This cannot run inside a user transaction block; if
@@ -765,9 +766,9 @@ standard_ProcessUtility(Node *parsetree,
* intended effect!
*/
PreventTransactionChain(isTopLevel,
- "REINDEX DATABASE");
- ReindexDatabase(stmt->name,
- stmt->do_system, stmt->do_user);
+ (stmt->kind == REINDEX_OBJECT_SCHEMA) ?
+ "REINDEX SCHEMA" : "REINDEX DATABASE");
+ ReindexObject(stmt->name, stmt->kind);
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 7a509c1..82c926d 100644
--- a/src/bin/psql/tab-complete.c
+++ b/src/bin/psql/tab-complete.c
@@ -3331,7 +3331,7 @@ psql_completion(const char *text, int start, int end)
else if (pg_strcasecmp(prev_wd, "REINDEX") == 0)
{
static const char *const list_REINDEX[] =
- {"TABLE", "INDEX", "SYSTEM", "DATABASE", NULL};
+ {"TABLE", "INDEX", "SYSTEM", "SCHEMA", "DATABASE", NULL};
COMPLETE_WITH_LIST(list_REINDEX);
}
@@ -3341,6 +3341,8 @@ 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 )
+ 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);
diff --git a/src/include/commands/defrem.h b/src/include/commands/defrem.h
index 0ebdbc1..f6210d3 100644
--- a/src/include/commands/defrem.h
+++ b/src/include/commands/defrem.h
@@ -30,8 +30,7 @@ extern Oid DefineIndex(Oid relationId,
bool quiet);
extern Oid ReindexIndex(RangeVar *indexRelation);
extern Oid ReindexTable(RangeVar *relation);
-extern Oid ReindexDatabase(const char *databaseName,
- bool do_system, bool do_user);
+extern Oid ReindexObject(const char *databaseName, ReindexObjectType kind);
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 255415d..5eaa435 100644
--- a/src/include/nodes/parsenodes.h
+++ b/src/include/nodes/parsenodes.h
@@ -2721,10 +2721,19 @@ typedef struct ConstraintsSetStmt
* REINDEX Statement
* ----------------------
*/
+typedef enum ReindexObjectType
+{
+ REINDEX_OBJECT_INDEX, /* index */
+ REINDEX_OBJECT_TABLE, /* table or materialized view */
+ REINDEX_OBJECT_SCHEMA, /* schema */
+ REINDEX_OBJECT_SYSTEM, /* system catalogs */
+ REINDEX_OBJECT_DATABASE /* database */
+} ReindexObjectType;
+
typedef struct ReindexStmt
{
NodeTag type;
- ObjectType kind; /* OBJECT_INDEX, OBJECT_TABLE, etc. */
+ 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 do_system; /* include system tables in database case */
diff --git a/src/test/regress/expected/create_index.out b/src/test/regress/expected/create_index.out
index 3ecb238..ebac939 100644
--- a/src/test/regress/expected/create_index.out
+++ b/src/test/regress/expected/create_index.out
@@ -2831,3 +2831,34 @@ explain (costs off)
Index Cond: ((thousand = 1) AND (tenthous = 1001))
(2 rows)
+--
+-- REINDEX SCHEMA
+--
+REINDEX SCHEMA schema_to_reindex; -- failure, schema does not exist
+ERROR: schema "schema_to_reindex" does not exist
+CREATE SCHEMA schema_to_reindex;
+CREATE TABLE schema_to_reindex.table1(col1 SERIAL PRIMARY KEY);
+CREATE TABLE schema_to_reindex.table2(col1 SERIAL PRIMARY KEY, col2 VARCHAR(100) NOT NULL);
+CREATE INDEX ON schema_to_reindex.table2(col2);
+REINDEX SCHEMA schema_to_reindex;
+NOTICE: table "schema_to_reindex.table1" was reindexed
+NOTICE: table "schema_to_reindex.table2" was reindexed
+BEGIN;
+REINDEX SCHEMA schema_to_reindex; -- failure, cannot run in a transaction
+ERROR: REINDEX SCHEMA cannot run inside a transaction block
+END;
+-- Failure for unauthorized user
+CREATE ROLE reindexuser login;
+SET SESSION ROLE user_reindex;
+ERROR: role "user_reindex" does not exist
+REINDEX SCHEMA schema_to_reindex;
+NOTICE: table "schema_to_reindex.table1" was reindexed
+NOTICE: table "schema_to_reindex.table2" was reindexed
+-- Clean up
+RESET ROLE;
+DROP ROLE user_reindex;
+ERROR: role "user_reindex" does not exist
+DROP SCHEMA schema_to_reindex CASCADE;
+NOTICE: drop cascades to 2 other objects
+DETAIL: drop cascades to table schema_to_reindex.table1
+drop cascades to table schema_to_reindex.table2
diff --git a/src/test/regress/sql/create_index.sql b/src/test/regress/sql/create_index.sql
index e837676..1cd57da 100644
--- a/src/test/regress/sql/create_index.sql
+++ b/src/test/regress/sql/create_index.sql
@@ -964,3 +964,26 @@ RESET enable_indexscan;
explain (costs off)
select * from tenk1 where (thousand, tenthous) in ((1,1001), (null,null));
+
+--
+-- REINDEX SCHEMA
+--
+REINDEX SCHEMA schema_to_reindex; -- failure, schema does not exist
+CREATE SCHEMA schema_to_reindex;
+CREATE TABLE schema_to_reindex.table1(col1 SERIAL PRIMARY KEY);
+CREATE TABLE schema_to_reindex.table2(col1 SERIAL PRIMARY KEY, col2 VARCHAR(100) NOT NULL);
+CREATE INDEX ON schema_to_reindex.table2(col2);
+REINDEX SCHEMA schema_to_reindex;
+BEGIN;
+REINDEX SCHEMA schema_to_reindex; -- failure, cannot run in a transaction
+END;
+
+-- Failure for unauthorized user
+CREATE ROLE reindexuser login;
+SET SESSION ROLE user_reindex;
+REINDEX SCHEMA schema_to_reindex;
+
+-- Clean up
+RESET ROLE;
+DROP ROLE user_reindex;
+DROP SCHEMA schema_to_reindex CASCADE;
--
2.2.0
0002-Add-support-for-REINDEX-SCHEMA-in-reindexdb.patchtext/x-diff; charset=US-ASCII; name=0002-Add-support-for-REINDEX-SCHEMA-in-reindexdb.patchDownload
From d7ab9e1d7ac78bf78f4c989fa812c0c47403f622 Mon Sep 17 00:00:00 2001
From: Michael Paquier <michael@otacoo.com>
Date: Tue, 2 Dec 2014 15:37:44 +0900
Subject: [PATCH 2/2] Add support for REINDEX SCHEMA in reindexdb
---
doc/src/sgml/ref/reindexdb.sgml | 22 ++++++++++++++++++++++
src/bin/scripts/reindexdb.c | 38 +++++++++++++++++++++++++++++++++++---
src/bin/scripts/t/090_reindexdb.pl | 7 +++++--
3 files changed, 62 insertions(+), 5 deletions(-)
diff --git a/doc/src/sgml/ref/reindexdb.sgml b/doc/src/sgml/ref/reindexdb.sgml
index 486f5c9..b5b449c 100644
--- a/doc/src/sgml/ref/reindexdb.sgml
+++ b/doc/src/sgml/ref/reindexdb.sgml
@@ -27,6 +27,16 @@ PostgreSQL documentation
<arg choice="plain" rep="repeat">
<arg choice="opt">
<group choice="plain">
+ <arg choice="plain"><option>--schema</option></arg>
+ <arg choice="plain"><option>-S</option></arg>
+ </group>
+ <replaceable>table</replaceable>
+ </arg>
+ </arg>
+
+ <arg choice="plain" rep="repeat">
+ <arg choice="opt">
+ <group choice="plain">
<arg choice="plain"><option>--table</option></arg>
<arg choice="plain"><option>-t</option></arg>
</group>
@@ -162,6 +172,18 @@ PostgreSQL documentation
</varlistentry>
<varlistentry>
+ <term><option>-S <replaceable class="parameter">schema</replaceable></></term>
+ <term><option>--schema=<replaceable class="parameter">schema</replaceable></></term>
+ <listitem>
+ <para>
+ Reindex <replaceable class="parameter">schema</replaceable> only.
+ Multiple schemas can be reindexed by writing multiple
+ <option>-S</> switches.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
<term><option>-t <replaceable class="parameter">table</replaceable></></term>
<term><option>--table=<replaceable class="parameter">table</replaceable></></term>
<listitem>
diff --git a/src/bin/scripts/reindexdb.c b/src/bin/scripts/reindexdb.c
index 561bbce..5c4a64e 100644
--- a/src/bin/scripts/reindexdb.c
+++ b/src/bin/scripts/reindexdb.c
@@ -41,6 +41,7 @@ main(int argc, char *argv[])
{"password", no_argument, NULL, 'W'},
{"echo", no_argument, NULL, 'e'},
{"quiet", no_argument, NULL, 'q'},
+ {"schema", required_argument, NULL, 'S'},
{"dbname", required_argument, NULL, 'd'},
{"all", no_argument, NULL, 'a'},
{"system", no_argument, NULL, 's'},
@@ -66,6 +67,7 @@ main(int argc, char *argv[])
bool quiet = false;
SimpleStringList indexes = {NULL, NULL};
SimpleStringList tables = {NULL, NULL};
+ SimpleStringList schemas = {NULL, NULL};
progname = get_progname(argv[0]);
set_pglocale_pgservice(argv[0], PG_TEXTDOMAIN("pgscripts"));
@@ -73,7 +75,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:wWeqd:ast:i:", long_options, &optindex)) != -1)
+ while ((c = getopt_long(argc, argv, "h:p:U:wWeqS:d:ast:i:", long_options, &optindex)) != -1)
{
switch (c)
{
@@ -98,6 +100,9 @@ main(int argc, char *argv[])
case 'q':
quiet = true;
break;
+ case 'S':
+ simple_string_list_append(&schemas, optarg);
+ break;
case 'd':
dbname = pg_strdup(optarg);
break;
@@ -154,6 +159,11 @@ main(int argc, char *argv[])
fprintf(stderr, _("%s: cannot reindex all databases and system catalogs at the same time\n"), progname);
exit(1);
}
+ if (schemas.head != NULL)
+ {
+ fprintf(stderr, _("%s: cannot reindex specific schema(s) in all databases\n"), progname);
+ exit(1);
+ }
if (tables.head != NULL)
{
fprintf(stderr, _("%s: cannot reindex specific table(s) in all databases\n"), progname);
@@ -170,6 +180,11 @@ main(int argc, char *argv[])
}
else if (syscatalog)
{
+ if (schemas.head != NULL)
+ {
+ fprintf(stderr, _("%s: cannot reindex specific schema(s) and system catalogs at the same time\n"), progname);
+ exit(1);
+ }
if (tables.head != NULL)
{
fprintf(stderr, _("%s: cannot reindex specific table(s) and system catalogs at the same time\n"), progname);
@@ -206,6 +221,17 @@ main(int argc, char *argv[])
dbname = get_user_name_or_exit(progname);
}
+ if (schemas.head != NULL)
+ {
+ SimpleStringListCell *cell;
+
+ for (cell = schemas.head; cell; cell = cell->next)
+ {
+ reindex_one_database(cell->val, dbname, "SCHEMA", host, port,
+ username, prompt_password, progname, echo);
+ }
+ }
+
if (indexes.head != NULL)
{
SimpleStringListCell *cell;
@@ -226,8 +252,8 @@ main(int argc, char *argv[])
username, prompt_password, progname, echo);
}
}
- /* reindex database only if neither index nor table is specified */
- if (indexes.head == NULL && tables.head == NULL)
+ /* 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);
}
@@ -251,6 +277,8 @@ reindex_one_database(const char *name, const char *dbname, const char *type,
appendPQExpBuffer(&sql, " TABLE %s", name);
else if (strcmp(type, "INDEX") == 0)
appendPQExpBuffer(&sql, " INDEX %s", name);
+ else if (strcmp(type, "SCHEMA") == 0)
+ appendPQExpBuffer(&sql, " SCHEMA %s", name);
else if (strcmp(type, "DATABASE") == 0)
appendPQExpBuffer(&sql, " DATABASE %s", fmtId(name));
appendPQExpBufferStr(&sql, ";");
@@ -266,6 +294,9 @@ reindex_one_database(const char *name, const char *dbname, const char *type,
if (strcmp(type, "INDEX") == 0)
fprintf(stderr, _("%s: reindexing of index \"%s\" in database \"%s\" failed: %s"),
progname, name, dbname, PQerrorMessage(conn));
+ if (strcmp(type, "SCHEMA") == 0)
+ fprintf(stderr, _("%s: reindexing of schema \"%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));
@@ -348,6 +379,7 @@ help(const char *progname)
printf(_(" -i, --index=INDEX recreate specific index(es) only\n"));
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(_(" -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 d5b42de..0cdf7be 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 => 16;
+use Test::More tests => 17;
program_help_ok('reindexdb');
program_version_ok('reindexdb');
@@ -27,7 +27,10 @@ issues_sql_like(
[ 'reindexdb', 'postgres', '-i', 'test1x' ],
qr/statement: REINDEX INDEX test1x;/,
'reindex specific index');
-
+issues_sql_like(
+ [ 'reindexdb', 'postgres', '-S', 'pg_catalog' ],
+ qr/statement: REINDEX SCHEMA pg_catalog;/,
+ 'reindex specific schema');
issues_sql_like(
[ 'reindexdb', 'postgres', '-s' ],
qr/statement: REINDEX SYSTEM postgres;/,
--
2.2.0
On Tue, Dec 2, 2014 at 3:42 PM, Michael Paquier
<michael.paquier@gmail.com> wrote:
Adding on top of that a couple of things cleaned up, like docs and
typos, and I got the patch attached. Let's have a committer have a
look a it now, I am marking that as "Ready for Committer".
For the archives, this has been committed as fe263d1. Thanks Simon for
looking and the final push. And sorry that I didn't spot the issue
with tap tests when reviewing, check-world passed but my dev VM missed
necessary perl packages.
Regards,
--
Michael
--
Sent via pgsql-hackers mailing list (pgsql-hackers@postgresql.org)
To make changes to your subscription:
http://www.postgresql.org/mailpref/pgsql-hackers
On Tue, Dec 9, 2014 at 10:10 AM, Michael Paquier
<michael.paquier@gmail.com> wrote:
On Tue, Dec 2, 2014 at 3:42 PM, Michael Paquier
<michael.paquier@gmail.com> wrote:Adding on top of that a couple of things cleaned up, like docs and
typos, and I got the patch attached. Let's have a committer have a
look a it now, I am marking that as "Ready for Committer".For the archives, this has been committed as fe263d1. Thanks Simon for
looking and the final push. And sorry that I didn't spot the issue
with tap tests when reviewing, check-world passed but my dev VM missed
necessary perl packages.
While re-looking at that. I just found that when selecting the
relations that are reindexed for a schema we ignore materialized view
as the key scan is only done using 'r' as relkind. The patch attached
fixes that.
Thanks,
--
Michael
Attachments:
20141209_reindex_schema_matview.patchapplication/x-patch; name=20141209_reindex_schema_matview.patchDownload
From ae2b1b8c426698bb7142f9f02e4cf08295e9dd73 Mon Sep 17 00:00:00 2001
From: Michael Paquier <michael@otacoo.com>
Date: Tue, 9 Dec 2014 16:40:39 +0900
Subject: [PATCH] Fix REINDEX SCHEMA ignoring matviews
The key scan used was using a filter on relation relkind, but that's not
actually necessary as a filter is applied when building the list of OIDs
reindexed.
---
src/backend/commands/indexcmds.c | 8 ++------
src/test/regress/expected/create_index.out | 18 +++++++++---------
src/test/regress/sql/create_index.sql | 6 +++---
3 files changed, 14 insertions(+), 18 deletions(-)
diff --git a/src/backend/commands/indexcmds.c b/src/backend/commands/indexcmds.c
index a3e8a15..9b07216 100644
--- a/src/backend/commands/indexcmds.c
+++ b/src/backend/commands/indexcmds.c
@@ -1867,16 +1867,12 @@ ReindexObject(const char *objectName, ReindexObjectType objectKind)
*/
if (objectKind == REINDEX_OBJECT_SCHEMA)
{
- scan_keys = palloc(sizeof(ScanKeyData) * 2);
+ scan_keys = palloc(sizeof(ScanKeyData));
ScanKeyInit(&scan_keys[0],
Anum_pg_class_relnamespace,
BTEqualStrategyNumber, F_OIDEQ,
ObjectIdGetDatum(objectOid));
- ScanKeyInit(&scan_keys[1],
- Anum_pg_class_relkind,
- BTEqualStrategyNumber, F_CHAREQ,
- 'r');
- num_keys = 2;
+ num_keys = 1;
}
else
num_keys = 0;
diff --git a/src/test/regress/expected/create_index.out b/src/test/regress/expected/create_index.out
index ebac939..abffe65 100644
--- a/src/test/regress/expected/create_index.out
+++ b/src/test/regress/expected/create_index.out
@@ -2837,12 +2837,12 @@ explain (costs off)
REINDEX SCHEMA schema_to_reindex; -- failure, schema does not exist
ERROR: schema "schema_to_reindex" does not exist
CREATE SCHEMA schema_to_reindex;
-CREATE TABLE schema_to_reindex.table1(col1 SERIAL PRIMARY KEY);
-CREATE TABLE schema_to_reindex.table2(col1 SERIAL PRIMARY KEY, col2 VARCHAR(100) NOT NULL);
-CREATE INDEX ON schema_to_reindex.table2(col2);
+CREATE TABLE schema_to_reindex.table(col1 SERIAL PRIMARY KEY);
+CREATE MATERIALIZED VIEW schema_to_reindex.matview AS SELECT col1 FROM schema_to_reindex.table;
+CREATE INDEX ON schema_to_reindex.matview(col1);
REINDEX SCHEMA schema_to_reindex;
-NOTICE: table "schema_to_reindex.table1" was reindexed
-NOTICE: table "schema_to_reindex.table2" was reindexed
+NOTICE: table "schema_to_reindex.table" was reindexed
+NOTICE: table "schema_to_reindex.matview" was reindexed
BEGIN;
REINDEX SCHEMA schema_to_reindex; -- failure, cannot run in a transaction
ERROR: REINDEX SCHEMA cannot run inside a transaction block
@@ -2852,13 +2852,13 @@ CREATE ROLE reindexuser login;
SET SESSION ROLE user_reindex;
ERROR: role "user_reindex" does not exist
REINDEX SCHEMA schema_to_reindex;
-NOTICE: table "schema_to_reindex.table1" was reindexed
-NOTICE: table "schema_to_reindex.table2" was reindexed
+NOTICE: table "schema_to_reindex.table" was reindexed
+NOTICE: table "schema_to_reindex.matview" was reindexed
-- Clean up
RESET ROLE;
DROP ROLE user_reindex;
ERROR: role "user_reindex" does not exist
DROP SCHEMA schema_to_reindex CASCADE;
NOTICE: drop cascades to 2 other objects
-DETAIL: drop cascades to table schema_to_reindex.table1
-drop cascades to table schema_to_reindex.table2
+DETAIL: drop cascades to table schema_to_reindex."table"
+drop cascades to materialized view schema_to_reindex.matview
diff --git a/src/test/regress/sql/create_index.sql b/src/test/regress/sql/create_index.sql
index 1cd57da..a5b3403 100644
--- a/src/test/regress/sql/create_index.sql
+++ b/src/test/regress/sql/create_index.sql
@@ -970,9 +970,9 @@ explain (costs off)
--
REINDEX SCHEMA schema_to_reindex; -- failure, schema does not exist
CREATE SCHEMA schema_to_reindex;
-CREATE TABLE schema_to_reindex.table1(col1 SERIAL PRIMARY KEY);
-CREATE TABLE schema_to_reindex.table2(col1 SERIAL PRIMARY KEY, col2 VARCHAR(100) NOT NULL);
-CREATE INDEX ON schema_to_reindex.table2(col2);
+CREATE TABLE schema_to_reindex.table(col1 SERIAL PRIMARY KEY);
+CREATE MATERIALIZED VIEW schema_to_reindex.matview AS SELECT col1 FROM schema_to_reindex.table;
+CREATE INDEX ON schema_to_reindex.matview(col1);
REINDEX SCHEMA schema_to_reindex;
BEGIN;
REINDEX SCHEMA schema_to_reindex; -- failure, cannot run in a transaction
--
2.2.0
On Tue, Dec 9, 2014 at 4:44 PM, Michael Paquier
<michael.paquier@gmail.com> wrote:
On Tue, Dec 9, 2014 at 10:10 AM, Michael Paquier
<michael.paquier@gmail.com> wrote:On Tue, Dec 2, 2014 at 3:42 PM, Michael Paquier
<michael.paquier@gmail.com> wrote:Adding on top of that a couple of things cleaned up, like docs and
typos, and I got the patch attached. Let's have a committer have a
look a it now, I am marking that as "Ready for Committer".For the archives, this has been committed as fe263d1. Thanks Simon for
looking and the final push. And sorry that I didn't spot the issue
with tap tests when reviewing, check-world passed but my dev VM missed
necessary perl packages.While re-looking at that. I just found that when selecting the
relations that are reindexed for a schema we ignore materialized view
as the key scan is only done using 'r' as relkind. The patch attached
fixes that.
Here is an updated patch doing as well that:
- Regression test checking if user has permissions on schema was broken
- Silent NOTICE messages of REINDEX by having client_min_messages set
to WARINING (thoughts about having a plpgsql function doing
consistency checks of relfilenode before and after reindex?)
--
Michael
Attachments:
20141209_reindex_schema_fixes.patchapplication/x-patch; name=20141209_reindex_schema_fixes.patchDownload
From 402afad6c124d2b74a5a82e36e017d2dedb0186d Mon Sep 17 00:00:00 2001
From: Michael Paquier <michael@otacoo.com>
Date: Tue, 9 Dec 2014 16:40:39 +0900
Subject: [PATCH] Fix a couple of bugs in REINDEX SCHEMA
The following issues are fixed:
- The key scan used was using a filter on relation relkind, but that's not
actually necessary as a filter is applied when building the list of OIDs
reindexed.
- Regression test checking permission of reindexed schema was broken
- Upgrade client_min_messages to 'warning' per complaints from jaragundi
and leech as the table reindex ordering is not entirely guaranteed (we
may as well here use a plpgsql function that does check if relfilenode
has been changed for the reindexed relations.
---
src/backend/commands/indexcmds.c | 8 ++------
src/test/regress/expected/create_index.out | 21 +++++++++------------
src/test/regress/sql/create_index.sql | 10 ++++++----
3 files changed, 17 insertions(+), 22 deletions(-)
diff --git a/src/backend/commands/indexcmds.c b/src/backend/commands/indexcmds.c
index a3e8a15..9b07216 100644
--- a/src/backend/commands/indexcmds.c
+++ b/src/backend/commands/indexcmds.c
@@ -1867,16 +1867,12 @@ ReindexObject(const char *objectName, ReindexObjectType objectKind)
*/
if (objectKind == REINDEX_OBJECT_SCHEMA)
{
- scan_keys = palloc(sizeof(ScanKeyData) * 2);
+ scan_keys = palloc(sizeof(ScanKeyData));
ScanKeyInit(&scan_keys[0],
Anum_pg_class_relnamespace,
BTEqualStrategyNumber, F_OIDEQ,
ObjectIdGetDatum(objectOid));
- ScanKeyInit(&scan_keys[1],
- Anum_pg_class_relkind,
- BTEqualStrategyNumber, F_CHAREQ,
- 'r');
- num_keys = 2;
+ num_keys = 1;
}
else
num_keys = 0;
diff --git a/src/test/regress/expected/create_index.out b/src/test/regress/expected/create_index.out
index ebac939..418b0ec 100644
--- a/src/test/regress/expected/create_index.out
+++ b/src/test/regress/expected/create_index.out
@@ -2834,31 +2834,28 @@ explain (costs off)
--
-- REINDEX SCHEMA
--
+SET client_min_messages TO 'warning';
REINDEX SCHEMA schema_to_reindex; -- failure, schema does not exist
ERROR: schema "schema_to_reindex" does not exist
CREATE SCHEMA schema_to_reindex;
-CREATE TABLE schema_to_reindex.table1(col1 SERIAL PRIMARY KEY);
-CREATE TABLE schema_to_reindex.table2(col1 SERIAL PRIMARY KEY, col2 VARCHAR(100) NOT NULL);
-CREATE INDEX ON schema_to_reindex.table2(col2);
+CREATE TABLE schema_to_reindex.table(col1 SERIAL PRIMARY KEY);
+CREATE MATERIALIZED VIEW schema_to_reindex.matview AS SELECT col1 FROM schema_to_reindex.table;
+CREATE INDEX ON schema_to_reindex.matview(col1);
REINDEX SCHEMA schema_to_reindex;
-NOTICE: table "schema_to_reindex.table1" was reindexed
-NOTICE: table "schema_to_reindex.table2" was reindexed
BEGIN;
REINDEX SCHEMA schema_to_reindex; -- failure, cannot run in a transaction
ERROR: REINDEX SCHEMA cannot run inside a transaction block
END;
+RESET client_min_messages;
-- Failure for unauthorized user
-CREATE ROLE reindexuser login;
+CREATE ROLE user_reindex login;
SET SESSION ROLE user_reindex;
-ERROR: role "user_reindex" does not exist
REINDEX SCHEMA schema_to_reindex;
-NOTICE: table "schema_to_reindex.table1" was reindexed
-NOTICE: table "schema_to_reindex.table2" was reindexed
+ERROR: must be owner of schema schema_to_reindex
-- Clean up
RESET ROLE;
DROP ROLE user_reindex;
-ERROR: role "user_reindex" does not exist
DROP SCHEMA schema_to_reindex CASCADE;
NOTICE: drop cascades to 2 other objects
-DETAIL: drop cascades to table schema_to_reindex.table1
-drop cascades to table schema_to_reindex.table2
+DETAIL: drop cascades to table schema_to_reindex."table"
+drop cascades to materialized view schema_to_reindex.matview
diff --git a/src/test/regress/sql/create_index.sql b/src/test/regress/sql/create_index.sql
index 1cd57da..dd348b5 100644
--- a/src/test/regress/sql/create_index.sql
+++ b/src/test/regress/sql/create_index.sql
@@ -968,18 +968,20 @@ explain (costs off)
--
-- REINDEX SCHEMA
--
+SET client_min_messages TO 'warning';
REINDEX SCHEMA schema_to_reindex; -- failure, schema does not exist
CREATE SCHEMA schema_to_reindex;
-CREATE TABLE schema_to_reindex.table1(col1 SERIAL PRIMARY KEY);
-CREATE TABLE schema_to_reindex.table2(col1 SERIAL PRIMARY KEY, col2 VARCHAR(100) NOT NULL);
-CREATE INDEX ON schema_to_reindex.table2(col2);
+CREATE TABLE schema_to_reindex.table(col1 SERIAL PRIMARY KEY);
+CREATE MATERIALIZED VIEW schema_to_reindex.matview AS SELECT col1 FROM schema_to_reindex.table;
+CREATE INDEX ON schema_to_reindex.matview(col1);
REINDEX SCHEMA schema_to_reindex;
BEGIN;
REINDEX SCHEMA schema_to_reindex; -- failure, cannot run in a transaction
END;
+RESET client_min_messages;
-- Failure for unauthorized user
-CREATE ROLE reindexuser login;
+CREATE ROLE user_reindex login;
SET SESSION ROLE user_reindex;
REINDEX SCHEMA schema_to_reindex;
--
2.2.0
On 9 December 2014 at 17:17, Michael Paquier <michael.paquier@gmail.com> wrote:
While re-looking at that. I just found that when selecting the
relations that are reindexed for a schema we ignore materialized view
as the key scan is only done using 'r' as relkind. The patch attached
fixes that.Here is an updated patch doing as well that:
- Regression test checking if user has permissions on schema was broken
- Silent NOTICE messages of REINDEX by having client_min_messages set
to WARINING (thoughts about having a plpgsql function doing
consistency checks of relfilenode before and after reindex?)
ISTM that REINDEX is not consistent with VACUUM, ANALYZE or CLUSTER in
the way it issues NOTICE messages.
I'm inclined to simply remove the NOTICE messages, except when a
REINDEX ... VERBOSE is requested.
--
Simon Riggs 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
On Tuesday, December 9, 2014, Simon Riggs <simon@2ndquadrant.com> wrote:
On 9 December 2014 at 17:17, Michael Paquier <michael.paquier@gmail.com
<javascript:;>> wrote:While re-looking at that. I just found that when selecting the
relations that are reindexed for a schema we ignore materialized view
as the key scan is only done using 'r' as relkind. The patch attached
fixes that.Here is an updated patch doing as well that:
- Regression test checking if user has permissions on schema was broken
- Silent NOTICE messages of REINDEX by having client_min_messages set
to WARINING (thoughts about having a plpgsql function doing
consistency checks of relfilenode before and after reindex?)ISTM that REINDEX is not consistent with VACUUM, ANALYZE or CLUSTER in
the way it issues NOTICE messages.I'm inclined to simply remove the NOTICE messages, except when a
REINDEX ... VERBOSE is requested.
+1 to remove the NOTICE messages except when specifying VERBOSE.
It would output a lot of messages if there are many table in schema.
If nobody objects to it, I will work on this.
Regards,
--
Sawada Masahiko
--
Regards,
-------
Sawada Masahiko
Import Notes
Reply to msg id not found: CAD21AoCaUNQcNA+apiDTtfx7cjLi_51h5_sM7_fawwkzeWkS8w@mail.gmail.com
On Tue, Dec 9, 2014 at 6:00 PM, Simon Riggs <simon@2ndquadrant.com> wrote:
On 9 December 2014 at 17:17, Michael Paquier <michael.paquier@gmail.com> wrote:
While re-looking at that. I just found that when selecting the
relations that are reindexed for a schema we ignore materialized view
as the key scan is only done using 'r' as relkind. The patch attached
fixes that.Here is an updated patch doing as well that:
- Regression test checking if user has permissions on schema was broken
- Silent NOTICE messages of REINDEX by having client_min_messages set
to WARINING (thoughts about having a plpgsql function doing
consistency checks of relfilenode before and after reindex?)ISTM that REINDEX is not consistent with VACUUM, ANALYZE or CLUSTER in
the way it issues NOTICE messages.I'm inclined to simply remove the NOTICE messages, except when a
REINDEX ... VERBOSE is requested.
OK. Perhaps that's not worth mentioning in the release notes, but some
users may be used to the old behavior. What about the other issues
(regression test for permissions incorrect and matviews)?
--
Michael
--
Sent via pgsql-hackers mailing list (pgsql-hackers@postgresql.org)
To make changes to your subscription:
http://www.postgresql.org/mailpref/pgsql-hackers
On Tue, Dec 9, 2014 at 6:43 PM, Michael Paquier
<michael.paquier@gmail.com> wrote:
OK. Perhaps that's not worth mentioning in the release notes, but some
users may be used to the old behavior. What about the other issues
(regression test for permissions incorrect and matviews)?
Here is in any case an updated patch to fix all those things rebased
on latest HEAD (ae4e688).
Thanks,
--
Michael
Attachments:
20141209_reindex_schema_fixes_v2.patchapplication/x-patch; name=20141209_reindex_schema_fixes_v2.patchDownload
From 4cc862ed78b3537438e257aa24a5d0ee1479eb24 Mon Sep 17 00:00:00 2001
From: Michael Paquier <michael@otacoo.com>
Date: Tue, 9 Dec 2014 16:40:39 +0900
Subject: [PATCH] Fix two bugs in REINDEX SCHEMA: regression and matviews
The following issues are fixed:
- The key scan used was using a filter on relation relkind, but that's not
actually necessary as a filter is applied when building the list of OIDs
reindexed.
- Regression test checking permission of reindexed schema was broken
---
src/backend/commands/indexcmds.c | 8 ++------
src/test/regress/expected/create_index.out | 15 +++++++--------
src/test/regress/sql/create_index.sql | 8 ++++----
3 files changed, 13 insertions(+), 18 deletions(-)
diff --git a/src/backend/commands/indexcmds.c b/src/backend/commands/indexcmds.c
index cf4de72..6711a66 100644
--- a/src/backend/commands/indexcmds.c
+++ b/src/backend/commands/indexcmds.c
@@ -1867,16 +1867,12 @@ ReindexObject(const char *objectName, ReindexObjectType objectKind)
*/
if (objectKind == REINDEX_OBJECT_SCHEMA)
{
- scan_keys = palloc(sizeof(ScanKeyData) * 2);
+ scan_keys = palloc(sizeof(ScanKeyData));
ScanKeyInit(&scan_keys[0],
Anum_pg_class_relnamespace,
BTEqualStrategyNumber, F_OIDEQ,
ObjectIdGetDatum(objectOid));
- ScanKeyInit(&scan_keys[1],
- Anum_pg_class_relkind,
- BTEqualStrategyNumber, F_CHAREQ,
- 'r');
- num_keys = 2;
+ num_keys = 1;
}
else
num_keys = 0;
diff --git a/src/test/regress/expected/create_index.out b/src/test/regress/expected/create_index.out
index eba14e2..0d0a5ca 100644
--- a/src/test/regress/expected/create_index.out
+++ b/src/test/regress/expected/create_index.out
@@ -2837,24 +2837,23 @@ explain (costs off)
REINDEX SCHEMA schema_to_reindex; -- failure, schema does not exist
ERROR: schema "schema_to_reindex" does not exist
CREATE SCHEMA schema_to_reindex;
-CREATE TABLE schema_to_reindex.table1(col1 SERIAL PRIMARY KEY);
-CREATE TABLE schema_to_reindex.table2(col1 SERIAL PRIMARY KEY, col2 VARCHAR(100) NOT NULL);
-CREATE INDEX ON schema_to_reindex.table2(col2);
+CREATE TABLE schema_to_reindex.table(col1 SERIAL PRIMARY KEY);
+CREATE MATERIALIZED VIEW schema_to_reindex.matview AS SELECT col1 FROM schema_to_reindex.table;
+CREATE INDEX ON schema_to_reindex.matview(col1);
REINDEX SCHEMA schema_to_reindex;
BEGIN;
REINDEX SCHEMA schema_to_reindex; -- failure, cannot run in a transaction
ERROR: REINDEX SCHEMA cannot run inside a transaction block
END;
-- Failure for unauthorized user
-CREATE ROLE reindexuser login;
+CREATE ROLE user_reindex login;
SET SESSION ROLE user_reindex;
-ERROR: role "user_reindex" does not exist
REINDEX SCHEMA schema_to_reindex;
+ERROR: must be owner of schema schema_to_reindex
-- Clean up
RESET ROLE;
DROP ROLE user_reindex;
-ERROR: role "user_reindex" does not exist
DROP SCHEMA schema_to_reindex CASCADE;
NOTICE: drop cascades to 2 other objects
-DETAIL: drop cascades to table schema_to_reindex.table1
-drop cascades to table schema_to_reindex.table2
+DETAIL: drop cascades to table schema_to_reindex."table"
+drop cascades to materialized view schema_to_reindex.matview
diff --git a/src/test/regress/sql/create_index.sql b/src/test/regress/sql/create_index.sql
index 1cd57da..5b6c9e6 100644
--- a/src/test/regress/sql/create_index.sql
+++ b/src/test/regress/sql/create_index.sql
@@ -970,16 +970,16 @@ explain (costs off)
--
REINDEX SCHEMA schema_to_reindex; -- failure, schema does not exist
CREATE SCHEMA schema_to_reindex;
-CREATE TABLE schema_to_reindex.table1(col1 SERIAL PRIMARY KEY);
-CREATE TABLE schema_to_reindex.table2(col1 SERIAL PRIMARY KEY, col2 VARCHAR(100) NOT NULL);
-CREATE INDEX ON schema_to_reindex.table2(col2);
+CREATE TABLE schema_to_reindex.table(col1 SERIAL PRIMARY KEY);
+CREATE MATERIALIZED VIEW schema_to_reindex.matview AS SELECT col1 FROM schema_to_reindex.table;
+CREATE INDEX ON schema_to_reindex.matview(col1);
REINDEX SCHEMA schema_to_reindex;
BEGIN;
REINDEX SCHEMA schema_to_reindex; -- failure, cannot run in a transaction
END;
-- Failure for unauthorized user
-CREATE ROLE reindexuser login;
+CREATE ROLE user_reindex login;
SET SESSION ROLE user_reindex;
REINDEX SCHEMA schema_to_reindex;
--
2.2.0
Simon Riggs <simon@2ndQuadrant.com> writes:
ISTM that REINDEX is not consistent with VACUUM, ANALYZE or CLUSTER in
the way it issues NOTICE messages.
I'm inclined to simply remove the NOTICE messages, except when a
REINDEX ... VERBOSE is requested.
My recollection is that those other commands do issue messages always,
but at some DEBUGn log level when not VERBOSE. Ideally REINDEX would
adopt that same behavior.
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
On Tue, Dec 9, 2014 at 11:59 PM, Tom Lane <tgl@sss.pgh.pa.us> wrote:
Simon Riggs <simon@2ndQuadrant.com> writes:
ISTM that REINDEX is not consistent with VACUUM, ANALYZE or CLUSTER in
the way it issues NOTICE messages.I'm inclined to simply remove the NOTICE messages, except when a
REINDEX ... VERBOSE is requested.My recollection is that those other commands do issue messages always,
but at some DEBUGn log level when not VERBOSE. Ideally REINDEX would
adopt that same behavior.
So it seems to that REINDEX command issues messages as INFO level when
that is specified VERBOSE option.
If not specified, it issue message as DEBUG2.
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
On Tue, Dec 9, 2014 at 10:21 AM, Michael Paquier <michael.paquier@gmail.com>
wrote:
On Tue, Dec 9, 2014 at 6:43 PM, Michael Paquier
<michael.paquier@gmail.com> wrote:OK. Perhaps that's not worth mentioning in the release notes, but some
users may be used to the old behavior. What about the other issues
(regression test for permissions incorrect and matviews)?Here is in any case an updated patch to fix all those things rebased
on latest HEAD (ae4e688).
The patch is fine:
- No compiler warnings
- Added properly regressions tests and run ok
There are no changes in the docs. Maybe we can mention matviews on REINDEX
SCHEMA docs, what do you think?
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
On Wed, Dec 10, 2014 at 1:37 AM, Fabrízio de Royes Mello
<fabriziomello@gmail.com> wrote:
On Tue, Dec 9, 2014 at 10:21 AM, Michael Paquier <michael.paquier@gmail.com>
wrote:On Tue, Dec 9, 2014 at 6:43 PM, Michael Paquier
<michael.paquier@gmail.com> wrote:OK. Perhaps that's not worth mentioning in the release notes, but some
users may be used to the old behavior. What about the other issues
(regression test for permissions incorrect and matviews)?Here is in any case an updated patch to fix all those things rebased
on latest HEAD (ae4e688).The patch is fine:
- No compiler warnings
- Added properly regressions tests and run okThere are no changes in the docs. Maybe we can mention matviews on REINDEX
SCHEMA docs, what do you think?
Current documentation tells that all the indexes in schema are
reindexed, only matviews and relations can have one, so that's
implicitly specified IMO. If in the future we add support for another
relkind and that it can have indexes, we won't need to update the docs
as well.
--
Michael
--
Sent via pgsql-hackers mailing list (pgsql-hackers@postgresql.org)
To make changes to your subscription:
http://www.postgresql.org/mailpref/pgsql-hackers
On 9 December 2014 at 12:21, Michael Paquier <michael.paquier@gmail.com> wrote:
On Tue, Dec 9, 2014 at 6:43 PM, Michael Paquier
<michael.paquier@gmail.com> wrote:OK. Perhaps that's not worth mentioning in the release notes, but some
users may be used to the old behavior. What about the other issues
(regression test for permissions incorrect and matviews)?Here is in any case an updated patch to fix all those things rebased
on latest HEAD (ae4e688).
Thanks,
I rewrote and applied this patch to ensure we didn't introduce further bugs.
Tests for the reindex part were rewritten from scratch also.
Rather unluckily that seems to have coincided with Tom's changes, so
I've only added the bits that have nothing to do with Tom's changes -
all of which stand.
(I just got going again after my flight back from Tokyo).
--
Simon Riggs 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
On Fri, Dec 12, 2014 at 8:00 AM, Simon Riggs <simon@2ndquadrant.com> wrote:
On 9 December 2014 at 12:21, Michael Paquier <michael.paquier@gmail.com>
wrote:On Tue, Dec 9, 2014 at 6:43 PM, Michael Paquier
<michael.paquier@gmail.com> wrote:OK. Perhaps that's not worth mentioning in the release notes, but some
users may be used to the old behavior. What about the other issues
(regression test for permissions incorrect and matviews)?Here is in any case an updated patch to fix all those things rebased
on latest HEAD (ae4e688).
Thanks,I rewrote and applied this patch to ensure we didn't introduce further
bugs.Tests for the reindex part were rewritten from scratch also.
Rather unluckily that seems to have coincided with Tom's changes, so
I've only added the bits that have nothing to do with Tom's changes -
all of which stand.
Glad that things are in order now. I have nothing else left to complain
about with this feature. Thanks.
(I just got going again after my flight back from Tokyo).
I understand going east makes one day longer :)
--
Michael
On Fri, Dec 12, 2014 at 8:41 AM, Michael Paquier <michael.paquier@gmail.com>
wrote:
On Fri, Dec 12, 2014 at 8:00 AM, Simon Riggs <simon@2ndquadrant.com>
wrote:Rather unluckily that seems to have coincided with Tom's changes, so
I've only added the bits that have nothing to do with Tom's changes -
all of which stand.Glad that things are in order now. I have nothing else left to complain
about with this feature. Thanks.
Actually there is one thing left: this patch from Sawada-san to finish the
cleanup of ReindexStmt for the boolean flags.
/messages/by-id/CAD21AoCXFE1J+hSkbeJ80rqqnhR8m_YUxdGKwZ4dL8zPqT8gjg@mail.gmail.com
Regards,
--
Michael
On 11 December 2014 at 23:41, Michael Paquier <michael.paquier@gmail.com> wrote:
Glad that things are in order now. I have nothing else left to complain
about with this feature. Thanks.
I think you've discovered a new meaning of Ready for Committer
--
Simon Riggs 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
On Fri, Dec 12, 2014 at 10:19 AM, Simon Riggs <simon@2ndquadrant.com> wrote:
On 11 December 2014 at 23:41, Michael Paquier <michael.paquier@gmail.com>
wrote:Glad that things are in order now. I have nothing else left to complain
about with this feature. Thanks.I think you've discovered a new meaning of Ready for Committer
Yep. Sorry for missing so many things.
--
Michael