Skip to content

Commit 9d952e8

Browse files
committed
Fix chunk skipping range check bug
Chunk skipping based on column stats had a convoluted way of detecting if query clauses were hitting a chunk in certain cases. This change makes things more straight forward and adds missing test cases for range checking.
1 parent ae030ef commit 9d952e8

File tree

7 files changed

+826
-207
lines changed

7 files changed

+826
-207
lines changed

src/hypertable_restrict_info.c

Lines changed: 4 additions & 79 deletions
Original file line numberDiff line numberDiff line change
@@ -175,81 +175,6 @@ dimension_restrict_info_open_add(DimensionRestrictInfoOpen *dri, StrategyNumber
175175
return restriction_added;
176176
}
177177

178-
/*
179-
* for DIMENSION_TYPE_STATS entries, we need to use regular bounded strategies.
180-
* We can have multiple entries satisfying the inputs. It basically becomes a
181-
* problem of:
182-
*
183-
* "given an input value, find all ranges which encompass that value"
184-
*
185-
* For "column >= constant" (e.g id >= 9), the check has to be:
186-
*
187-
* start_range >= 9 OR end_range >= 9 (second check covers +INF)
188-
*
189-
* For "column <= constant" (e.g id <= 90), the check has to be:
190-
*
191-
* start_range <= 90 OR end_range <= 90 (first check covers -INF)
192-
*
193-
* For "column == constant" (e.g id = 9)
194-
*
195-
* start_range <= 9 OR end_range >= 9 (covers +INF to -INF)
196-
*/
197-
static bool
198-
dimension_restrict_info_range_add(DimensionRestrictInfoOpen *dri, StrategyNumber strategy,
199-
Oid collation, DimensionValues *dimvalues)
200-
{
201-
ListCell *item;
202-
bool restriction_added = false;
203-
204-
/* can't handle IN/ANY with multiple values */
205-
if (dimvalues->use_or && list_length(dimvalues->values) > 1)
206-
return false;
207-
208-
foreach (item, dimvalues->values)
209-
{
210-
Oid restype;
211-
Datum datum = ts_dimension_transform_value(dri->base.dimension,
212-
collation,
213-
PointerGetDatum(lfirst(item)),
214-
dimvalues->type,
215-
&restype);
216-
int64 value = ts_time_value_to_internal_or_infinite(datum, restype);
217-
218-
switch (strategy)
219-
{
220-
case BTLessEqualStrategyNumber:
221-
case BTLessStrategyNumber: /* e.g: id <= 90 */
222-
if (dri->upper_strategy == InvalidStrategy || value < dri->upper_bound)
223-
{
224-
dri->upper_strategy = strategy;
225-
dri->upper_bound = value;
226-
restriction_added = true;
227-
}
228-
break;
229-
case BTGreaterEqualStrategyNumber:
230-
case BTGreaterStrategyNumber: /* e.g: id >= 9 */
231-
if (dri->lower_strategy == InvalidStrategy || value > dri->lower_bound)
232-
{
233-
dri->lower_strategy = strategy;
234-
dri->lower_bound = value;
235-
restriction_added = true;
236-
}
237-
break;
238-
case BTEqualStrategyNumber: /* e.g: id = 9 */
239-
dri->lower_bound = value;
240-
dri->upper_bound = value;
241-
dri->lower_strategy = BTEqualStrategyNumber;
242-
dri->upper_strategy = BTEqualStrategyNumber;
243-
restriction_added = true;
244-
break;
245-
default:
246-
/* unsupported strategy */
247-
break;
248-
}
249-
}
250-
return restriction_added;
251-
}
252-
253178
static List *
254179
dimension_restrict_info_get_partitions(DimensionRestrictInfoClosed *dri, Oid collation,
255180
List *values)
@@ -330,10 +255,10 @@ dimension_restrict_info_add(DimensionRestrictInfo *dri, int strategy, Oid collat
330255
values);
331256
case DIMENSION_TYPE_STATS:
332257
/* we reuse the DimensionRestrictInfoOpen structure for these */
333-
return dimension_restrict_info_range_add((DimensionRestrictInfoOpen *) dri,
334-
strategy,
335-
collation,
336-
values);
258+
return dimension_restrict_info_open_add((DimensionRestrictInfoOpen *) dri,
259+
strategy,
260+
collation,
261+
values);
337262
case DIMENSION_TYPE_CLOSED:
338263
return dimension_restrict_info_closed_add((DimensionRestrictInfoClosed *) dri,
339264
strategy,

src/ts_catalog/chunk_column_stats.c

Lines changed: 8 additions & 81 deletions
Original file line numberDiff line numberDiff line change
@@ -1071,7 +1071,6 @@ ts_chunk_column_stats_get_chunk_ids_by_scan(DimensionRestrictInfo *dri)
10711071
ScanIterator it;
10721072
List *chunkids = NIL;
10731073
DimensionRestrictInfoOpen *open;
1074-
bool check_both = false;
10751074

10761075
Assert(dri && dri->dimension->type == DIMENSION_TYPE_STATS);
10771076

@@ -1082,25 +1081,6 @@ ts_chunk_column_stats_get_chunk_ids_by_scan(DimensionRestrictInfo *dri)
10821081

10831082
open = (DimensionRestrictInfoOpen *) dri;
10841083

1085-
/*
1086-
* Since we need to find chunks with overlapping ranges. We use checks on both the
1087-
* lower_bound and the upper_bound.
1088-
*/
1089-
if (open->upper_strategy != InvalidStrategy && open->lower_strategy != InvalidStrategy)
1090-
check_both = true;
1091-
1092-
if (open->upper_strategy == InvalidStrategy)
1093-
{
1094-
open->upper_strategy = open->lower_strategy;
1095-
open->upper_bound = open->lower_bound;
1096-
}
1097-
1098-
if (open->lower_strategy == InvalidStrategy)
1099-
{
1100-
open->lower_strategy = open->upper_strategy;
1101-
open->lower_bound = open->upper_bound;
1102-
}
1103-
11041084
/*
11051085
* We need to get all chunks matching the hypertable ID and the column name.
11061086
*/
@@ -1143,18 +1123,6 @@ ts_chunk_column_stats_get_chunk_ids_by_scan(DimensionRestrictInfo *dri)
11431123
goto done;
11441124
}
11451125

1146-
/*
1147-
* If both upper and lower bounds have been specified then we need to check
1148-
* if that range overlaps (subset, superset, intersect) with the current fd entry
1149-
* values
1150-
*/
1151-
if (check_both)
1152-
{
1153-
/* range is before or after our fd range_start/range_end values */
1154-
if (open->upper_bound < fd->range_start || open->lower_bound > fd->range_end)
1155-
goto done;
1156-
}
1157-
11581126
/*
11591127
* All data is in int8 format so we do regular comparisons. Also, it's an OR
11601128
* check so prepare to short circuit if one evaluates to true.
@@ -1166,78 +1134,37 @@ ts_chunk_column_stats_get_chunk_ids_by_scan(DimensionRestrictInfo *dri)
11661134
{
11671135
case BTLessEqualStrategyNumber: /* e.g: id <= 90 */
11681136
{
1169-
/* range_end is exclusive, so check accordingly */
1170-
if ((fd->range_end - 1) <= open->upper_bound)
1171-
matched = check_both ? false : true;
1137+
matched = fd->range_start <= open->upper_bound;
11721138
}
11731139
break;
11741140
case BTLessStrategyNumber: /* e.g: id < 90 */
11751141
{
1176-
/* range_end is exclusive, so check accordingly */
1177-
if ((fd->range_end - 1) < open->upper_bound)
1178-
matched = check_both ? false : true;
1179-
}
1180-
break;
1181-
case BTGreaterEqualStrategyNumber: /* e.g: id >= 90 */
1182-
{
1183-
/* range_end is exclusive, so check accordingly */
1184-
if ((fd->range_end - 1) >= open->upper_bound)
1185-
matched = check_both ? false : true;
1186-
}
1187-
break;
1188-
case BTGreaterStrategyNumber: /* e.g: id > 9 */
1189-
{
1190-
/* range_end is exclusive, so check accordingly */
1191-
if ((fd->range_end - 1) > open->upper_bound)
1192-
matched = check_both ? false : true;
1193-
}
1194-
break;
1195-
case BTEqualStrategyNumber: /* e.g: id == 9 */
1196-
{
1197-
/* need to check for both range_start and range_end */
1198-
if (fd->range_start <= open->lower_bound &&
1199-
(fd->range_end - 1) >= open->upper_bound)
1200-
matched = true;
1142+
matched = fd->range_start < open->upper_bound;
12011143
}
12021144
break;
12031145
default:
1204-
/* unsupported strategy */
1146+
open->upper_strategy = InvalidStrategy;
12051147
break;
12061148
}
12071149

1208-
if (matched)
1150+
if (open->upper_strategy != InvalidStrategy && !matched)
12091151
goto done;
12101152

12111153
/* range_end checks didn't match, check for range_start now */
12121154
switch (open->lower_strategy)
12131155
{
1214-
case BTLessEqualStrategyNumber:
1215-
{
1216-
if (fd->range_start <= open->lower_bound)
1217-
matched = true;
1218-
}
1219-
break;
1220-
case BTLessStrategyNumber:
1221-
{
1222-
if (fd->range_start < open->lower_bound)
1223-
matched = true;
1224-
}
1225-
break;
12261156
case BTGreaterEqualStrategyNumber:
12271157
{
1228-
if (fd->range_start >= open->lower_bound)
1229-
matched = true;
1158+
/* range_end is exclusive */
1159+
matched = (fd->range_end - 1) >= open->lower_bound;
12301160
}
12311161
break;
12321162
case BTGreaterStrategyNumber:
12331163
{
1234-
/* range_start is inclusive */
1235-
if (fd->range_start >= open->lower_bound)
1236-
matched = true;
1164+
/* range_end is exclusive */
1165+
matched = (fd->range_end - 1) > open->lower_bound;
12371166
}
12381167
break;
1239-
case BTEqualStrategyNumber:
1240-
/* already handled above with upper_strategy */
12411168
default:
12421169
/* unsupported strategy */
12431170
break;

0 commit comments

Comments
 (0)