Compare commits

...

1 commit

Author SHA1 Message Date
Yugo Nagata
d954439b17 Prevent automatic index creation with set-returning function
Previously, a unique index is automatically created even when
a set-returning function is contained in FROM clause, but this
results in an error due to key duplication. Now, an index is
not created automatically when a relation other than table,
sub-query, or join is contained in FROM clause.

Issue (#99)
2024-12-09 19:46:58 +09:00
3 changed files with 33 additions and 9 deletions

View file

@ -1597,13 +1597,13 @@ get_primary_key_attnos_from_query(Query *query, List **constraintList)
{
RangeTblEntry *r = (RangeTblEntry*) lfirst(lc);
Bitmapset *key_attnos;
bool has_pkey = true;
bool has_no_pkey = false;
/* for subqueries, scan recursively */
if (r->rtekind == RTE_SUBQUERY)
{
key_attnos = get_primary_key_attnos_from_query(r->subquery, constraintList);
has_pkey = (key_attnos != NULL);
has_no_pkey = (key_attnos == NULL);
}
/* for tables, call get_primary_key_attnos */
else if (r->rtekind == RTE_RELATION)
@ -1611,17 +1611,27 @@ get_primary_key_attnos_from_query(Query *query, List **constraintList)
Oid constraintOid;
key_attnos = get_primary_key_attnos(r->relid, false, &constraintOid);
*constraintList = lappend_oid(*constraintList, constraintOid);
has_pkey = (key_attnos != NULL);
has_no_pkey = (key_attnos == NULL);
}
/* for other RTEs, store NULL into key_attnos_list */
else
/*
* Ignore join rels, because they are flatten later by
* flatten_join_alias_vars(). Store NULL into key_attnos_list
* as a dummy.
*/
else if (r->rtekind == RTE_JOIN)
{
key_attnos = NULL;
}
/* for other RTEs, we assume they have no candidate key */
else
has_no_pkey = true;
/*
* If any table or subquery has no primary key or its pkey constraint is deferrable,
* If any table or subquery has no primary key or its pkey constraint
* is deferrable (i.e., get_primary_key_attnos returned NULL),
* we cannot get key attributes for this query, so return NULL.
*/
if (!has_pkey)
if (has_no_pkey)
return NULL;
key_attnos_list = lappend(key_attnos_list, key_attnos);

View file

@ -1663,7 +1663,7 @@ HINT: Create an index on the immv for efficient incremental maintenance.
0
(1 row)
--- subqueries
--- subqueries: create an index
SELECT create_immv('mv_idx6(i_a, i_b)', 'SELECT a.i, b.i FROM (SELECT * FROM base_a) a, (SELECT * FROM base_b) b');
NOTICE: created index "mv_idx6_index" on immv "mv_idx6"
create_immv
@ -1671,6 +1671,16 @@ NOTICE: created index "mv_idx6_index" on immv "mv_idx6"
0
(1 row)
--- with set-returning function: no index
SELECT create_immv('mv_idx7', 'SELECT i FROM base_a, generate_series(1,10)');
NOTICE: could not create an index on immv "mv_idx7" automatically
DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause.
HINT: Create an index on the immv for efficient incremental maintenance.
create_immv
-------------
0
(1 row)
ROLLBACK;
-- type that doesn't have default operator class for access method btree
BEGIN;

View file

@ -662,8 +662,12 @@ SELECT create_immv('mv_idx3(i_a, i_b)', 'SELECT a.i, b.i FROM base_a a, base_b b
SELECT create_immv('mv_idx4', 'SELECT j FROM base_a');
SELECT create_immv('mv_idx5', 'SELECT a.i, b.j FROM base_a a, base_b b');
--- subqueries
--- subqueries: create an index
SELECT create_immv('mv_idx6(i_a, i_b)', 'SELECT a.i, b.i FROM (SELECT * FROM base_a) a, (SELECT * FROM base_b) b');
--- with set-returning function: no index
SELECT create_immv('mv_idx7', 'SELECT i FROM base_a, generate_series(1,10)');
ROLLBACK;
-- type that doesn't have default operator class for access method btree