Skip to content

Commit

Permalink
Fix chunk index column name mapping
Browse files Browse the repository at this point in the history
When mapping index column references from the hypertable index
to the chunk index the name of the index column was used instead
of the column name of the hypertables. While those names are
identical most of time unless modified this is not true for indexes
with INCLUDE on a column that is also a key column. Additionally
this fixes a bug where expression indexes would never get their
column references adjusted.

Fixes #3056
  • Loading branch information
svenklemm committed Apr 8, 2021
1 parent 639aef7 commit b01b60e
Show file tree
Hide file tree
Showing 6 changed files with 47 additions and 25 deletions.
2 changes: 2 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,9 +10,11 @@ accidentally triggering the load of a previous DB version.**
* #2989 Refactor and harden size and stats functions
* #3058 Reduce memory usage for distributed inserts
* #3067 Fix extremely slow multi-node order by queries
* #3082 Fix chunk index column name mapping
* #3083 Keep Append pathkeys in ChunkAppend

**Thanks**
* @BowenGG for reporting an issue with indexes with INCLUDE
* @fvannee for reporting an issue with ChunkAppend pathkeys
* @pedrokost and @RobAtticus for reporting an issue with size
functions on empty hypertables
Expand Down
36 changes: 21 additions & 15 deletions src/chunk_index.c
Original file line number Diff line number Diff line change
Expand Up @@ -123,24 +123,30 @@ adjust_expr_attnos(Oid ht_relid, IndexInfo *ii, Relation chunkrel)
* Adjust column reference attribute numbers for regular indexes.
*/
static void
chunk_adjust_colref_attnos(IndexInfo *ii, Relation idxrel, Relation chunkrel)
chunk_adjust_colref_attnos(IndexInfo *ii, Oid ht_relid, Relation chunkrel)
{
int i;

for (i = 0; i < idxrel->rd_att->natts; i++)
for (i = 0; i < ii->ii_NumIndexAttrs; i++)
{
FormData_pg_attribute *idxattr = TupleDescAttr(idxrel->rd_att, i);
AttrNumber attno = get_attnum(chunkrel->rd_id, NameStr(idxattr->attname));
/* zeroes indicate expressions */
if (ii->ii_IndexAttrNumbers[i] == 0)
continue;
/* we must not use get_attname on the index here as the index column names
* are independent of parent relation column names. Instead we need to look
* up the attno of the referenced hypertable column and do the matching
* with the hypertable column name */
char *colname = get_attname(ht_relid, ii->ii_IndexAttrNumbers[i], false);
AttrNumber attno = get_attnum(chunkrel->rd_id, colname);

if (attno == InvalidAttrNumber)
elog(ERROR, "index attribute %s not found in chunk", NameStr(idxattr->attname));
elog(ERROR, "index attribute %s not found in chunk", colname);
ii->ii_IndexAttrNumbers[i] = attno;
}
}

void
ts_adjust_indexinfo_attnos(IndexInfo *indexinfo, Oid ht_relid, Relation template_indexrel,
Relation chunkrel)
ts_adjust_indexinfo_attnos(IndexInfo *indexinfo, Oid ht_relid, Relation chunkrel)
{
/*
* Adjust a hypertable's index attribute numbers to match a chunk.
Expand All @@ -151,15 +157,15 @@ ts_adjust_indexinfo_attnos(IndexInfo *indexinfo, Oid ht_relid, Relation template
* IndexInfo from a hypertable's index to create a corresponding index on a
* chunk, we need to adjust the attribute numbers to match the chunk.
*
* We need to handle two cases: (1) regular indexes that reference columns
* directly, and (2) expression indexes that reference columns in expressions.
*
* Additionally we need to adjust column references in predicates.
* We need to handle 3 places:
* - direct column references in ii_IndexAttrNumbers
* - references in expressions in ii_Expressions
* - references in expressions in ii_Predicate
*/
if (list_length(indexinfo->ii_Expressions) == 0)
chunk_adjust_colref_attnos(indexinfo, template_indexrel, chunkrel);
chunk_adjust_colref_attnos(indexinfo, ht_relid, chunkrel);

adjust_expr_attnos(ht_relid, indexinfo, chunkrel);
if (indexinfo->ii_Expressions || indexinfo->ii_Predicate)
adjust_expr_attnos(ht_relid, indexinfo, chunkrel);
}

#define CHUNK_INDEX_TABLESPACE_OFFSET 1
Expand Down Expand Up @@ -213,7 +219,7 @@ chunk_relation_index_create(Relation htrel, Relation template_indexrel, Relation
* hypertable
*/
if (chunk_index_need_attnos_adjustment(RelationGetDescr(htrel), RelationGetDescr(chunkrel)))
ts_adjust_indexinfo_attnos(indexinfo, htrel->rd_id, template_indexrel, chunkrel);
ts_adjust_indexinfo_attnos(indexinfo, htrel->rd_id, chunkrel);

hypertable_id = ts_hypertable_relid_to_id(htrel->rd_id);

Expand Down
3 changes: 1 addition & 2 deletions src/chunk_index.h
Original file line number Diff line number Diff line change
Expand Up @@ -29,8 +29,7 @@ typedef struct ChunkIndexMapping
extern void ts_chunk_index_create(Relation hypertable_rel, int32 hypertable_id,
Relation hypertable_idxrel, int32 chunk_id, Relation chunkrel);

void ts_adjust_indexinfo_attnos(IndexInfo *indexinfo, Oid ht_relid, Relation template_indexrel,
Relation chunkrel);
void ts_adjust_indexinfo_attnos(IndexInfo *indexinfo, Oid ht_relid, Relation chunkrel);
extern void ts_chunk_index_create_from_adjusted_index_info(int32 hypertable_id,
Relation hypertable_idxrel,
int32 chunk_id, Relation chunkrel,
Expand Down
10 changes: 2 additions & 8 deletions src/process_utility.c
Original file line number Diff line number Diff line change
Expand Up @@ -2041,10 +2041,7 @@ process_index_chunk(Hypertable *ht, Oid chunk_relid, void *arg)
if (chunk_index_columns_changed(info->extended_options.n_ht_atts,
info->extended_options.ht_hasoid,
RelationGetDescr(chunk_rel)))
ts_adjust_indexinfo_attnos(indexinfo,
info->main_table_relid,
hypertable_index_rel,
chunk_rel);
ts_adjust_indexinfo_attnos(indexinfo, info->main_table_relid, chunk_rel);

ts_chunk_index_create_from_adjusted_index_info(ht->fd.id,
hypertable_index_rel,
Expand Down Expand Up @@ -2133,10 +2130,7 @@ process_index_chunk_multitransaction(int32 hypertable_id, Oid chunk_relid, void
if (chunk_index_columns_changed(info->extended_options.n_ht_atts,
info->extended_options.ht_hasoid,
RelationGetDescr(chunk_rel)))
ts_adjust_indexinfo_attnos(indexinfo,
info->main_table_relid,
hypertable_index_rel,
chunk_rel);
ts_adjust_indexinfo_attnos(indexinfo, info->main_table_relid, chunk_rel);

ts_chunk_index_create_from_adjusted_index_info(hypertable_id,
hypertable_index_rel,
Expand Down
12 changes: 12 additions & 0 deletions test/expected/index.out
Original file line number Diff line number Diff line change
Expand Up @@ -710,3 +710,15 @@ ORDER BY
_timescaledb_internal._hyper_13_19_chunk | _timescaledb_internal._hyper_13_19_chunk_ht_dropped_c0_c1_c2_idx1 | {c0,c1,c2} | | f | f | f |
(9 rows)

-- #3056 check chunk index column name mapping
CREATE TABLE i3056(c int, order_number int NOT NULL, date_created timestamptz NOT NULL);
CREATE INDEX ON i3056(order_number) INCLUDE(order_number);
CREATE INDEX ON i3056(date_created, (order_number % 5)) INCLUDE(order_number);
SELECT table_name FROM create_hypertable('i3056', 'date_created');
table_name
------------
i3056
(1 row)

ALTER TABLE i3056 DROP COLUMN c;
INSERT INTO i3056(order_number,date_created) VALUES (1, '2000-01-01');
9 changes: 9 additions & 0 deletions test/sql/index.sql
Original file line number Diff line number Diff line change
Expand Up @@ -330,3 +330,12 @@ FROM
ORDER BY
1, 2;

-- #3056 check chunk index column name mapping
CREATE TABLE i3056(c int, order_number int NOT NULL, date_created timestamptz NOT NULL);
CREATE INDEX ON i3056(order_number) INCLUDE(order_number);
CREATE INDEX ON i3056(date_created, (order_number % 5)) INCLUDE(order_number);
SELECT table_name FROM create_hypertable('i3056', 'date_created');
ALTER TABLE i3056 DROP COLUMN c;
INSERT INTO i3056(order_number,date_created) VALUES (1, '2000-01-01');


0 comments on commit b01b60e

Please sign in to comment.