diff --git a/src/hypertable.h b/src/hypertable.h index d3937518e..8213a0538 100644 --- a/src/hypertable.h +++ b/src/hypertable.h @@ -52,7 +52,6 @@ typedef struct Hypertable Oid chunk_sizing_func; Hyperspace *space; SubspaceStore *chunk_cache; - bool push_gapfill; /* * Allows restricting the data nodes to use for the hypertable. Default is to * use all available data nodes. diff --git a/tsl/src/fdw/data_node_scan_plan.c b/tsl/src/fdw/data_node_scan_plan.c index ec0b6e27f..1c0ac86e8 100644 --- a/tsl/src/fdw/data_node_scan_plan.c +++ b/tsl/src/fdw/data_node_scan_plan.c @@ -40,8 +40,6 @@ #include "data_node_scan_exec.h" #include "fdw_utils.h" -#include "nodes/gapfill/planner.h" - /* * DataNodeScan is a custom scan implementation for scanning hypertables on * remote data nodes instead of scanning individual remote chunks. @@ -375,7 +373,7 @@ force_group_by_push_down(PlannerInfo *root, RelOptInfo *hyper_rel) */ static void push_down_group_bys(PlannerInfo *root, RelOptInfo *hyper_rel, Hyperspace *hs, - DataNodeChunkAssignments *scas, bool gapfill_safe) + DataNodeChunkAssignments *scas) { const Dimension *dim; bool overlaps; @@ -416,9 +414,6 @@ push_down_group_bys(PlannerInfo *root, RelOptInfo *hyper_rel, Hyperspace *hs, Assert(NULL != dim); hyper_rel->partexprs[0] = ts_dimension_get_partexprs(dim, hyper_rel->relid); hyper_rel->part_scheme->partnatts = 1; - - if (gapfill_safe) - force_group_by_push_down(root, hyper_rel); } } @@ -445,7 +440,6 @@ data_node_scan_add_node_paths(PlannerInfo *root, RelOptInfo *hyper_rel) int ndata_node_rels; DataNodeChunkAssignments scas; int i; - bool gapfill_safe = false; Assert(NULL != ht); @@ -465,11 +459,8 @@ data_node_scan_add_node_paths(PlannerInfo *root, RelOptInfo *hyper_rel) /* Assign chunks to data nodes */ data_node_chunk_assignment_assign_chunks(&scas, chunk_rels, nchunk_rels); - /* Check if we can push down gapfill to data nodes */ - gapfill_safe = pushdown_gapfill(root, hyper_rel, ht->space, &scas); - /* Try to push down GROUP BY expressions and bucketing, if possible */ - push_down_group_bys(root, hyper_rel, ht->space, &scas, gapfill_safe); + push_down_group_bys(root, hyper_rel, ht->space, &scas); /* * Create estimates and paths for each data node rel based on data node chunk @@ -496,18 +487,10 @@ data_node_scan_add_node_paths(PlannerInfo *root, RelOptInfo *hyper_rel) data_node_rel, data_node_rel->serverid, hyper_rte->relid, - TS_FDW_RELINFO_HYPERTABLE_DATA_NODE, - gapfill_safe); + TS_FDW_RELINFO_HYPERTABLE_DATA_NODE); fpinfo->sca = sca; - /* - * Since we can not always call pushdown_gapfill where scas are not available, - * remember if gapfill is safe to be pushed down for this relation for later - * uses e.g. in add_foreign_grouping_paths. - */ - ht->push_gapfill = gapfill_safe; - if (!bms_is_empty(sca->chunk_relids)) { add_data_node_scan_paths(root, data_node_rel); diff --git a/tsl/src/fdw/deparse.c b/tsl/src/fdw/deparse.c index cfe4c55fc..e035d99b0 100644 --- a/tsl/src/fdw/deparse.c +++ b/tsl/src/fdw/deparse.c @@ -69,7 +69,6 @@ #include #include -#include #include #include "relinfo.h" @@ -106,7 +105,6 @@ typedef struct deparse_expr_cxt StringInfo buf; /* output buffer to append to */ List **params_list; /* exprs that will become remote Params */ DataNodeChunkAssignment *sca; - bool has_gapfill; } deparse_expr_cxt; #define REL_ALIAS_PREFIX "r" @@ -418,8 +416,10 @@ is_foreign_expr(PlannerInfo *root, RelOptInfo *baserel, Expr *expr) if (!foreign_expr_walker((Node *) expr, &glob_cxt)) return false; - /* It is safe to pushdown gapfill in limited cases */ - if (gapfill_in_expression(expr) && !fpinfo->pushdown_gapfill) + /* + * It is not supported to execute time_bucket_gapfill on data node. + */ + if (gapfill_in_expression(expr)) return false; /* @@ -817,7 +817,6 @@ deparseSelectStmtForRel(StringInfo buf, PlannerInfo *root, RelOptInfo *rel, List context.scanrel = IS_UPPER_REL(rel) ? fpinfo->outerrel : rel; context.params_list = params_list; context.sca = sca; - context.has_gapfill = false; /* Construct SELECT clause */ deparseSelectSql(tlist, is_subquery, retrieved_attrs, &context, pathkeys); @@ -2101,8 +2100,6 @@ deparseExpr(Expr *node, deparse_expr_cxt *context) deparseSubscriptingRef(castNode(SubscriptingRef, node), context); break; case T_FuncExpr: - if (gapfill_in_expression(node)) - context->has_gapfill = true; deparseFuncExpr(castNode(FuncExpr, node), context); break; case T_OpExpr: @@ -2719,7 +2716,7 @@ deparseAggref(Aggref *node, deparse_expr_cxt *context) use_variadic = node->aggvariadic; /* Find aggregate name from aggfnoid which is a pg_proc entry */ - if (!context->has_gapfill && partial_agg) + if (partial_agg) appendStringInfoString(buf, INTERNAL_SCHEMA_NAME "." PARTIALIZE_FUNC_NAME "("); appendFunctionName(node->aggfnoid, context); @@ -2795,7 +2792,7 @@ deparseAggref(Aggref *node, deparse_expr_cxt *context) deparseExpr((Expr *) node->aggfilter, context); } - appendStringInfoString(buf, !context->has_gapfill && partial_agg ? "))" : ")"); + appendStringInfoString(buf, partial_agg ? "))" : ")"); } /* diff --git a/tsl/src/fdw/fdw.c b/tsl/src/fdw/fdw.c index 0dc7e2842..5cf8c4a9c 100644 --- a/tsl/src/fdw/fdw.c +++ b/tsl/src/fdw/fdw.c @@ -65,12 +65,7 @@ get_foreign_rel_size(PlannerInfo *root, RelOptInfo *baserel, Oid foreigntableid) * kind of regular table that will ever have this callback called on it. */ if (RELKIND_RELATION == rte->relkind) { - fdw_relinfo_create(root, - baserel, - InvalidOid, - foreigntableid, - TS_FDW_RELINFO_HYPERTABLE, - false); + fdw_relinfo_create(root, baserel, InvalidOid, foreigntableid, TS_FDW_RELINFO_HYPERTABLE); } else { @@ -80,8 +75,7 @@ get_foreign_rel_size(PlannerInfo *root, RelOptInfo *baserel, Oid foreigntableid) baserel, table->serverid, foreigntableid, - TS_FDW_RELINFO_FOREIGN_TABLE, - false); + TS_FDW_RELINFO_FOREIGN_TABLE); apply_table_options(table, fdw_relinfo_get(baserel)); } diff --git a/tsl/src/fdw/relinfo.c b/tsl/src/fdw/relinfo.c index c5c52bff1..bcaacafce 100644 --- a/tsl/src/fdw/relinfo.c +++ b/tsl/src/fdw/relinfo.c @@ -373,7 +373,7 @@ estimate_chunk_size(PlannerInfo *root, RelOptInfo *chunk_rel) TsFdwRelInfo * fdw_relinfo_create(PlannerInfo *root, RelOptInfo *rel, Oid server_oid, Oid local_table_id, - TsFdwRelInfoType type, bool gapfill_safe) + TsFdwRelInfoType type) { TsFdwRelInfo *fpinfo; ListCell *lc; @@ -406,8 +406,6 @@ fdw_relinfo_create(PlannerInfo *root, RelOptInfo *rel, Oid server_oid, Oid local if (*refname && strcmp(refname, get_rel_name(rte->relid)) != 0) appendStringInfo(fpinfo->relation_name, " %s", quote_identifier(rte->eref->aliasname)); - fpinfo->pushdown_gapfill = gapfill_safe; - if (type == TS_FDW_RELINFO_HYPERTABLE) { /* nothing more to do for hypertables */ diff --git a/tsl/src/fdw/relinfo.h b/tsl/src/fdw/relinfo.h index bd848e3d8..2d8544e8a 100644 --- a/tsl/src/fdw/relinfo.h +++ b/tsl/src/fdw/relinfo.h @@ -49,7 +49,6 @@ typedef struct TsFdwRelInfo * foreign scan. */ bool pushdown_safe; - bool pushdown_gapfill; /* * Restriction clauses, divided into safe and unsafe to pushdown subsets. @@ -147,8 +146,7 @@ typedef struct TsFdwRelInfo } TsFdwRelInfo; extern TsFdwRelInfo *fdw_relinfo_create(PlannerInfo *root, RelOptInfo *rel, Oid server_oid, - Oid local_table_id, TsFdwRelInfoType type, - bool gapfill_safe); + Oid local_table_id, TsFdwRelInfoType type); extern TsFdwRelInfo *fdw_relinfo_alloc_or_get(RelOptInfo *rel); extern TsFdwRelInfo *fdw_relinfo_get(RelOptInfo *rel); diff --git a/tsl/src/fdw/scan_plan.c b/tsl/src/fdw/scan_plan.c index a2a690c7c..2fb073229 100644 --- a/tsl/src/fdw/scan_plan.c +++ b/tsl/src/fdw/scan_plan.c @@ -905,9 +905,6 @@ add_foreign_grouping_paths(PlannerInfo *root, RelOptInfo *input_rel, RelOptInfo fpinfo->sca = ifpinfo->sca; merge_fdw_options(fpinfo, ifpinfo, NULL); - if (ifpinfo->pushdown_gapfill) - fpinfo->pushdown_gapfill = true; - /* * Assess if it is safe to push down aggregation and grouping. * @@ -926,23 +923,6 @@ add_foreign_grouping_paths(PlannerInfo *root, RelOptInfo *input_rel, RelOptInfo fpinfo->startup_cost = startup_cost; fpinfo->total_cost = total_cost; - if (ifpinfo->pushdown_gapfill) - { - /* - * If pushdown of gapfill is possible then also check if it would - * be beneficial to actually push it down. Since, it can create - * more tuples and they need to be transferred to the data node. - * However, still pushing of gapfill to the data nodes could make - * sense because aggregating over it could be then done at the data - * nodes itself, hence ignore pushing down gapfill to data nodes - * when it produces a "really" larger amount of tuples. - */ - if (10 * ifpinfo->rows > fpinfo->rows) - { - fpinfo->pushdown_gapfill = false; - ifpinfo->pushdown_gapfill = false; - } - } /* Create and add path to the grouping relation. */ grouppath = (Path *) create_path(root, grouped_rel, diff --git a/tsl/src/nodes/gapfill/planner.c b/tsl/src/nodes/gapfill/planner.c index cc866aebe..1d4345a15 100644 --- a/tsl/src/nodes/gapfill/planner.c +++ b/tsl/src/nodes/gapfill/planner.c @@ -21,8 +21,6 @@ #include "nodes/gapfill/gapfill.h" #include "nodes/gapfill/planner.h" #include "nodes/gapfill/exec.h" -#include "func_cache.h" -#include "estimate.h" static CustomScanMethods gapfill_plan_methods = { .CustomName = "GapFill", @@ -575,96 +573,3 @@ gapfill_adjust_window_targetlist(PlannerInfo *root, RelOptInfo *input_rel, RelOp } } } - -/* - * Check if it is safe to push down gapfill to data nodes. - * Currently, we allow only in the following cases, - * - * 1. when only one data node has all the chunks - * 2. when relation has at least one closed dimension and chunks - * do not overlap across data nodes. - * 3. when group by matches space dimension - * and is not an expression of space dimension. - */ -bool -pushdown_gapfill(PlannerInfo *root, RelOptInfo *hyper_rel, Hyperspace *hs, - DataNodeChunkAssignments *scas) -{ - const Dimension *dim; - ListCell *lc; - TargetEntry *tle; - bool space_dim_in_group_by = false; - - Query *parse = root->parse; - gapfill_walker_context context = { .call.node = NULL, .count = 0 }; - - if (CMD_SELECT != parse->commandType || parse->groupClause == NIL) - return false; - - if (!enable_partitionwise_aggregate) - return false; - /* - * Only check for queries with gapfill call. - */ - gapfill_function_walker((Node *) parse->targetList, &context); - - if (context.count == 0) - return false; - - if (context.count > 1) - ereport(ERROR, - (errcode(ERRCODE_FEATURE_NOT_SUPPORTED), - errmsg("multiple time_bucket_gapfill calls not allowed"))); - - Assert(hs->num_dimensions >= 1); - - /* Avoid push down of gapfill when window funcs are present */ - if (parse->hasWindowFuncs) - return false; - - /* - * Check for special case when there is only one data node with chunks. This - * can always be safely pushed down irrespective of partitioning - */ - if (scas->num_nodes_with_chunks == 1) - return true; - - /* - * Get first closed dimension that we use for assigning chunks to - * data nodes. If there is no closed dimension, then pushing gapfill - * to data nodes is not possible. - */ - dim = hyperspace_get_closed_dimension(hs, 0); - - if (dim == NULL) - return false; - else - { - if (parse->groupClause) - { - foreach (lc, parse->groupClause) - { - /* - * Check if the group by matches dimension and - * group by clause has exact dimension and not - * an expression of that attribute. - */ - SortGroupClause *sort = (SortGroupClause *) lfirst(lc); - tle = get_sortgroupref_tle(sort->tleSortGroupRef, parse->targetList); - - if (tle->resno == dim->column_attno) - { - space_dim_in_group_by = true; - - if (IsA(tle->expr, Var)) - break; - else - return false; - } - } - } - if (!space_dim_in_group_by) - return false; - } - return !data_node_chunk_assignments_are_overlapping(scas, dim->fd.id); -} diff --git a/tsl/src/nodes/gapfill/planner.h b/tsl/src/nodes/gapfill/planner.h index 03226250f..22176e604 100644 --- a/tsl/src/nodes/gapfill/planner.h +++ b/tsl/src/nodes/gapfill/planner.h @@ -8,28 +8,10 @@ #include -#include "fdw/data_node_scan_plan.h" -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "fdw/data_node_chunk_assignment.h" -#include "fdw/scan_plan.h" -#include "fdw/data_node_scan_plan.h" -#include "fdw/data_node_scan_exec.h" - bool gapfill_in_expression(Expr *node); void plan_add_gapfill(PlannerInfo *root, RelOptInfo *group_rel); void gapfill_adjust_window_targetlist(PlannerInfo *root, RelOptInfo *input_rel, RelOptInfo *output_rel); -bool pushdown_gapfill(PlannerInfo *root, RelOptInfo *hyper_rel, Hyperspace *hs, - DataNodeChunkAssignments *scas); typedef struct GapFillPath { diff --git a/tsl/src/planner.c b/tsl/src/planner.c index e53095059..fbf2285ec 100644 --- a/tsl/src/planner.c +++ b/tsl/src/planner.c @@ -71,11 +71,7 @@ tsl_create_upper_paths_hook(PlannerInfo *root, UpperRelationKind stage, RelOptIn { case UPPERREL_GROUP_AGG: if (input_reltype != TS_REL_HYPERTABLE_CHILD) - { - /* Avoid adding gapfill node to the access node if it is pushed to data node */ - if (!dist_ht || !ht->push_gapfill) - plan_add_gapfill(root, output_rel); - } + plan_add_gapfill(root, output_rel); break; case UPPERREL_WINDOW: if (IsA(linitial(input_rel->pathlist), CustomPath)) diff --git a/tsl/test/shared/expected/dist_fetcher_type.out b/tsl/test/shared/expected/dist_fetcher_type.out index 363999069..1476ebce8 100644 --- a/tsl/test/shared/expected/dist_fetcher_type.out +++ b/tsl/test/shared/expected/dist_fetcher_type.out @@ -132,9 +132,9 @@ select * from disttable_with_ct; ----------------------------------------------------------------------------------------------------------------------------------------------------------- Custom Scan (DataNodeScan) on public.disttable_with_ct (actual rows=2 loops=1) Output: disttable_with_ct."time", disttable_with_ct.txn_id, disttable_with_ct.val, disttable_with_ct.info - Data node: data_node_1 + Data node: data_node_2 Fetcher Type: Cursor Chunks: _dist_hyper_X_X_chunk - Remote SQL: SELECT "time", txn_id, val, info FROM public.disttable_with_ct WHERE _timescaledb_internal.chunks_in(public.disttable_with_ct.*, ARRAY[33]) + Remote SQL: SELECT "time", txn_id, val, info FROM public.disttable_with_ct WHERE _timescaledb_internal.chunks_in(public.disttable_with_ct.*, ARRAY[20]) (6 rows) diff --git a/tsl/test/shared/expected/dist_gapfill.out b/tsl/test/shared/expected/dist_gapfill.out index a75946729..b0447c6b4 100644 --- a/tsl/test/shared/expected/dist_gapfill.out +++ b/tsl/test/shared/expected/dist_gapfill.out @@ -36,8 +36,7 @@ SELECT time_bucket_gapfill('3 hours', time, '2017-01-01 06:00', '2017-01-01 18:0 first(value, time), avg(value) FROM :CONDITIONS -GROUP BY 1,2 -ORDER BY 2,1; +GROUP BY 1,2; time_bucket_gapfill | device | first | avg ------------------------------+--------+----------+---------- Sun Jan 01 04:00:00 2017 PST | 1 | 1.2 | 1.2 @@ -87,8 +86,7 @@ SELECT time_bucket_gapfill('3 hours', time, '2017-01-01 06:00', '2017-01-01 18:0 first(value, time), avg(value) FROM :CONDITIONS -GROUP BY 2,1 -ORDER BY 2,1; +GROUP BY 2,1; time_bucket_gapfill | device | first | avg ------------------------------+--------+----------+---------- Sun Jan 01 04:00:00 2017 PST | 1 | 1.2 | 1.2 diff --git a/tsl/test/shared/expected/dist_gapfill_pushdown-12.out b/tsl/test/shared/expected/dist_gapfill_pushdown-12.out deleted file mode 100644 index 442a62bc6..000000000 --- a/tsl/test/shared/expected/dist_gapfill_pushdown-12.out +++ /dev/null @@ -1,316 +0,0 @@ --- This file and its contents are licensed under the Timescale License. --- Please see the included NOTICE for copyright information and --- LICENSE-TIMESCALE for a copy of the license. -\set ON_ERROR_STOP 0 -SET enable_partitionwise_aggregate = 'on'; -SET timescaledb.enable_remote_explain = true; --- Cases where gapfill is pushed down to data-nodes -EXPLAIN (VERBOSE, COSTS OFF) SELECT time_bucket_gapfill('3 hours', time, '2017-01-01 06:00', '2017-01-01 18:00'), - name, - first(value, time), - avg(value) -FROM test_gapfill -GROUP BY 1,2; - QUERY PLAN ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- - Custom Scan (AsyncAppend) - Output: (time_bucket_gapfill('@ 3 hours'::interval, "time", 'Sun Jan 01 06:00:00 2017'::timestamp without time zone, 'Sun Jan 01 18:00:00 2017'::timestamp without time zone)), name, (first(value, "time")), (avg(value)) - -> Append - -> Custom Scan (DataNodeScan) - Output: (time_bucket_gapfill('@ 3 hours'::interval, test_gapfill."time", 'Sun Jan 01 06:00:00 2017'::timestamp without time zone, 'Sun Jan 01 18:00:00 2017'::timestamp without time zone)), test_gapfill.name, (first(test_gapfill.value, test_gapfill."time")), (avg(test_gapfill.value)) - Relations: Aggregate on (public.test_gapfill) - Data node: data_node_1 - Chunks: _dist_hyper_X_X_chunk - Remote SQL: SELECT public.time_bucket_gapfill('@ 3 hours'::interval, "time", 'Sun Jan 01 06:00:00 2017'::timestamp without time zone, 'Sun Jan 01 18:00:00 2017'::timestamp without time zone), name, public.first(value, "time"), avg(value) FROM public.test_gapfill WHERE _timescaledb_internal.chunks_in(public.test_gapfill.*, ARRAY[28]) GROUP BY 1, 2 - Remote EXPLAIN: - Custom Scan (GapFill) - Output: (public.time_bucket_gapfill('03:00:00'::interval, "time", '2017-01-01 06:00:00'::timestamp without time zone, '2017-01-01 18:00:00'::timestamp without time zone)), name, (public.first(value, "time")), (avg(value)) - -> Sort - Output: (public.time_bucket_gapfill('03:00:00'::interval, _dist_hyper_X_X_chunk."time", '2017-01-01 06:00:00'::timestamp without time zone, '2017-01-01 18:00:00'::timestamp without time zone)), _dist_hyper_X_X_chunk.name, (public.first(_dist_hyper_X_X_chunk.value, _dist_hyper_X_X_chunk."time")), (avg(_dist_hyper_X_X_chunk.value)) - Sort Key: _dist_hyper_X_X_chunk.name, (public.time_bucket_gapfill('03:00:00'::interval, _dist_hyper_X_X_chunk."time", '2017-01-01 06:00:00'::timestamp without time zone, '2017-01-01 18:00:00'::timestamp without time zone)) - -> HashAggregate - Output: (public.time_bucket_gapfill('03:00:00'::interval, _dist_hyper_X_X_chunk."time", '2017-01-01 06:00:00'::timestamp without time zone, '2017-01-01 18:00:00'::timestamp without time zone)), _dist_hyper_X_X_chunk.name, public.first(_dist_hyper_X_X_chunk.value, _dist_hyper_X_X_chunk."time"), avg(_dist_hyper_X_X_chunk.value) - Group Key: public.time_bucket_gapfill('03:00:00'::interval, _dist_hyper_X_X_chunk."time", '2017-01-01 06:00:00'::timestamp without time zone, '2017-01-01 18:00:00'::timestamp without time zone), _dist_hyper_X_X_chunk.name - -> Result - Output: public.time_bucket_gapfill('03:00:00'::interval, _dist_hyper_X_X_chunk."time", '2017-01-01 06:00:00'::timestamp without time zone, '2017-01-01 18:00:00'::timestamp without time zone), _dist_hyper_X_X_chunk.name, _dist_hyper_X_X_chunk.value, _dist_hyper_X_X_chunk."time" - -> Seq Scan on _timescaledb_internal._dist_hyper_X_X_chunk - Output: _dist_hyper_X_X_chunk."time", _dist_hyper_X_X_chunk.name, _dist_hyper_X_X_chunk.value - - -> Custom Scan (DataNodeScan) - Output: (time_bucket_gapfill('@ 3 hours'::interval, test_gapfill_1."time", 'Sun Jan 01 06:00:00 2017'::timestamp without time zone, 'Sun Jan 01 18:00:00 2017'::timestamp without time zone)), test_gapfill_1.name, (first(test_gapfill_1.value, test_gapfill_1."time")), (avg(test_gapfill_1.value)) - Relations: Aggregate on (public.test_gapfill) - Data node: data_node_3 - Chunks: _dist_hyper_X_X_chunk, _dist_hyper_X_X_chunk, _dist_hyper_X_X_chunk - Remote SQL: SELECT public.time_bucket_gapfill('@ 3 hours'::interval, "time", 'Sun Jan 01 06:00:00 2017'::timestamp without time zone, 'Sun Jan 01 18:00:00 2017'::timestamp without time zone), name, public.first(value, "time"), avg(value) FROM public.test_gapfill WHERE _timescaledb_internal.chunks_in(public.test_gapfill.*, ARRAY[23, 24, 25]) GROUP BY 1, 2 - Remote EXPLAIN: - Custom Scan (GapFill) - Output: (public.time_bucket_gapfill('03:00:00'::interval, "time", '2017-01-01 06:00:00'::timestamp without time zone, '2017-01-01 18:00:00'::timestamp without time zone)), name, (public.first(value, "time")), (avg(value)) - -> Sort - Output: (public.time_bucket_gapfill('03:00:00'::interval, _dist_hyper_X_X_chunk."time", '2017-01-01 06:00:00'::timestamp without time zone, '2017-01-01 18:00:00'::timestamp without time zone)), _dist_hyper_X_X_chunk.name, (public.first(_dist_hyper_X_X_chunk.value, _dist_hyper_X_X_chunk."time")), (avg(_dist_hyper_X_X_chunk.value)) - Sort Key: _dist_hyper_X_X_chunk.name, (public.time_bucket_gapfill('03:00:00'::interval, _dist_hyper_X_X_chunk."time", '2017-01-01 06:00:00'::timestamp without time zone, '2017-01-01 18:00:00'::timestamp without time zone)) - -> HashAggregate - Output: (public.time_bucket_gapfill('03:00:00'::interval, _dist_hyper_X_X_chunk."time", '2017-01-01 06:00:00'::timestamp without time zone, '2017-01-01 18:00:00'::timestamp without time zone)), _dist_hyper_X_X_chunk.name, public.first(_dist_hyper_X_X_chunk.value, _dist_hyper_X_X_chunk."time"), avg(_dist_hyper_X_X_chunk.value) - Group Key: public.time_bucket_gapfill('03:00:00'::interval, _dist_hyper_X_X_chunk."time", '2017-01-01 06:00:00'::timestamp without time zone, '2017-01-01 18:00:00'::timestamp without time zone), _dist_hyper_X_X_chunk.name - -> Result - Output: public.time_bucket_gapfill('03:00:00'::interval, _dist_hyper_X_X_chunk."time", '2017-01-01 06:00:00'::timestamp without time zone, '2017-01-01 18:00:00'::timestamp without time zone), _dist_hyper_X_X_chunk.name, _dist_hyper_X_X_chunk.value, _dist_hyper_X_X_chunk."time" - -> Append - -> Seq Scan on _timescaledb_internal._dist_hyper_X_X_chunk - Output: _dist_hyper_X_X_chunk."time", _dist_hyper_X_X_chunk.name, _dist_hyper_X_X_chunk.value - -> Seq Scan on _timescaledb_internal._dist_hyper_X_X_chunk - Output: _dist_hyper_X_X_chunk."time", _dist_hyper_X_X_chunk.name, _dist_hyper_X_X_chunk.value - -> Seq Scan on _timescaledb_internal._dist_hyper_X_X_chunk - Output: _dist_hyper_X_X_chunk."time", _dist_hyper_X_X_chunk.name, _dist_hyper_X_X_chunk.value - -(48 rows) - -EXPLAIN (VERBOSE, COSTS OFF) SELECT time_bucket_gapfill('3 hours', time, '2017-01-01 06:00', '2017-01-01 18:00'), - name, - first(value, time), - avg(value) -FROM test_gapfill -GROUP BY 2,1; - QUERY PLAN ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- - Custom Scan (AsyncAppend) - Output: (time_bucket_gapfill('@ 3 hours'::interval, "time", 'Sun Jan 01 06:00:00 2017'::timestamp without time zone, 'Sun Jan 01 18:00:00 2017'::timestamp without time zone)), name, (first(value, "time")), (avg(value)) - -> Append - -> Custom Scan (DataNodeScan) - Output: (time_bucket_gapfill('@ 3 hours'::interval, test_gapfill."time", 'Sun Jan 01 06:00:00 2017'::timestamp without time zone, 'Sun Jan 01 18:00:00 2017'::timestamp without time zone)), test_gapfill.name, (first(test_gapfill.value, test_gapfill."time")), (avg(test_gapfill.value)) - Relations: Aggregate on (public.test_gapfill) - Data node: data_node_1 - Chunks: _dist_hyper_X_X_chunk - Remote SQL: SELECT public.time_bucket_gapfill('@ 3 hours'::interval, "time", 'Sun Jan 01 06:00:00 2017'::timestamp without time zone, 'Sun Jan 01 18:00:00 2017'::timestamp without time zone), name, public.first(value, "time"), avg(value) FROM public.test_gapfill WHERE _timescaledb_internal.chunks_in(public.test_gapfill.*, ARRAY[28]) GROUP BY 2, 1 - Remote EXPLAIN: - Custom Scan (GapFill) - Output: (public.time_bucket_gapfill('03:00:00'::interval, "time", '2017-01-01 06:00:00'::timestamp without time zone, '2017-01-01 18:00:00'::timestamp without time zone)), name, (public.first(value, "time")), (avg(value)) - -> Sort - Output: (public.time_bucket_gapfill('03:00:00'::interval, _dist_hyper_X_X_chunk."time", '2017-01-01 06:00:00'::timestamp without time zone, '2017-01-01 18:00:00'::timestamp without time zone)), _dist_hyper_X_X_chunk.name, (public.first(_dist_hyper_X_X_chunk.value, _dist_hyper_X_X_chunk."time")), (avg(_dist_hyper_X_X_chunk.value)) - Sort Key: _dist_hyper_X_X_chunk.name, (public.time_bucket_gapfill('03:00:00'::interval, _dist_hyper_X_X_chunk."time", '2017-01-01 06:00:00'::timestamp without time zone, '2017-01-01 18:00:00'::timestamp without time zone)) - -> HashAggregate - Output: (public.time_bucket_gapfill('03:00:00'::interval, _dist_hyper_X_X_chunk."time", '2017-01-01 06:00:00'::timestamp without time zone, '2017-01-01 18:00:00'::timestamp without time zone)), _dist_hyper_X_X_chunk.name, public.first(_dist_hyper_X_X_chunk.value, _dist_hyper_X_X_chunk."time"), avg(_dist_hyper_X_X_chunk.value) - Group Key: _dist_hyper_X_X_chunk.name, public.time_bucket_gapfill('03:00:00'::interval, _dist_hyper_X_X_chunk."time", '2017-01-01 06:00:00'::timestamp without time zone, '2017-01-01 18:00:00'::timestamp without time zone) - -> Result - Output: public.time_bucket_gapfill('03:00:00'::interval, _dist_hyper_X_X_chunk."time", '2017-01-01 06:00:00'::timestamp without time zone, '2017-01-01 18:00:00'::timestamp without time zone), _dist_hyper_X_X_chunk.name, _dist_hyper_X_X_chunk.value, _dist_hyper_X_X_chunk."time" - -> Seq Scan on _timescaledb_internal._dist_hyper_X_X_chunk - Output: _dist_hyper_X_X_chunk."time", _dist_hyper_X_X_chunk.name, _dist_hyper_X_X_chunk.value - - -> Custom Scan (DataNodeScan) - Output: (time_bucket_gapfill('@ 3 hours'::interval, test_gapfill_1."time", 'Sun Jan 01 06:00:00 2017'::timestamp without time zone, 'Sun Jan 01 18:00:00 2017'::timestamp without time zone)), test_gapfill_1.name, (first(test_gapfill_1.value, test_gapfill_1."time")), (avg(test_gapfill_1.value)) - Relations: Aggregate on (public.test_gapfill) - Data node: data_node_3 - Chunks: _dist_hyper_X_X_chunk, _dist_hyper_X_X_chunk, _dist_hyper_X_X_chunk - Remote SQL: SELECT public.time_bucket_gapfill('@ 3 hours'::interval, "time", 'Sun Jan 01 06:00:00 2017'::timestamp without time zone, 'Sun Jan 01 18:00:00 2017'::timestamp without time zone), name, public.first(value, "time"), avg(value) FROM public.test_gapfill WHERE _timescaledb_internal.chunks_in(public.test_gapfill.*, ARRAY[23, 24, 25]) GROUP BY 2, 1 - Remote EXPLAIN: - Custom Scan (GapFill) - Output: (public.time_bucket_gapfill('03:00:00'::interval, "time", '2017-01-01 06:00:00'::timestamp without time zone, '2017-01-01 18:00:00'::timestamp without time zone)), name, (public.first(value, "time")), (avg(value)) - -> Sort - Output: (public.time_bucket_gapfill('03:00:00'::interval, _dist_hyper_X_X_chunk."time", '2017-01-01 06:00:00'::timestamp without time zone, '2017-01-01 18:00:00'::timestamp without time zone)), _dist_hyper_X_X_chunk.name, (public.first(_dist_hyper_X_X_chunk.value, _dist_hyper_X_X_chunk."time")), (avg(_dist_hyper_X_X_chunk.value)) - Sort Key: _dist_hyper_X_X_chunk.name, (public.time_bucket_gapfill('03:00:00'::interval, _dist_hyper_X_X_chunk."time", '2017-01-01 06:00:00'::timestamp without time zone, '2017-01-01 18:00:00'::timestamp without time zone)) - -> HashAggregate - Output: (public.time_bucket_gapfill('03:00:00'::interval, _dist_hyper_X_X_chunk."time", '2017-01-01 06:00:00'::timestamp without time zone, '2017-01-01 18:00:00'::timestamp without time zone)), _dist_hyper_X_X_chunk.name, public.first(_dist_hyper_X_X_chunk.value, _dist_hyper_X_X_chunk."time"), avg(_dist_hyper_X_X_chunk.value) - Group Key: _dist_hyper_X_X_chunk.name, public.time_bucket_gapfill('03:00:00'::interval, _dist_hyper_X_X_chunk."time", '2017-01-01 06:00:00'::timestamp without time zone, '2017-01-01 18:00:00'::timestamp without time zone) - -> Result - Output: public.time_bucket_gapfill('03:00:00'::interval, _dist_hyper_X_X_chunk."time", '2017-01-01 06:00:00'::timestamp without time zone, '2017-01-01 18:00:00'::timestamp without time zone), _dist_hyper_X_X_chunk.name, _dist_hyper_X_X_chunk.value, _dist_hyper_X_X_chunk."time" - -> Append - -> Seq Scan on _timescaledb_internal._dist_hyper_X_X_chunk - Output: _dist_hyper_X_X_chunk."time", _dist_hyper_X_X_chunk.name, _dist_hyper_X_X_chunk.value - -> Seq Scan on _timescaledb_internal._dist_hyper_X_X_chunk - Output: _dist_hyper_X_X_chunk."time", _dist_hyper_X_X_chunk.name, _dist_hyper_X_X_chunk.value - -> Seq Scan on _timescaledb_internal._dist_hyper_X_X_chunk - Output: _dist_hyper_X_X_chunk."time", _dist_hyper_X_X_chunk.name, _dist_hyper_X_X_chunk.value - -(48 rows) - --- Check for multiple gapfill calls -SELECT time_bucket_gapfill('3 hours', time, '2017-01-01 06:00', '2017-01-01 18:00'), - time_bucket_gapfill('6 hours', time, '2017-01-01 08:00', '2017-01-01 18:00'), - name, - first(value, time), - avg(value) -FROM test_gapfill -GROUP BY 2,1,3; -ERROR: multiple time_bucket_gapfill calls not allowed --- Cases where gapfill is not pushed down to data-nodes --- Space dimension is not in group by clause -EXPLAIN (VERBOSE, COSTS OFF) SELECT time_bucket_gapfill('3 hours', time, '2017-01-01 06:00', '2017-01-02 18:00'), - first(value, time), - avg(value) -FROM test_gapfill -GROUP BY 1; - QUERY PLAN ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- - Custom Scan (GapFill) - Output: (time_bucket_gapfill('@ 3 hours'::interval, "time", 'Sun Jan 01 06:00:00 2017'::timestamp without time zone, 'Mon Jan 02 18:00:00 2017'::timestamp without time zone)), (first(value, "time")), (avg(value)) - -> Finalize GroupAggregate - Output: (time_bucket_gapfill('@ 3 hours'::interval, test_gapfill."time", 'Sun Jan 01 06:00:00 2017'::timestamp without time zone, 'Mon Jan 02 18:00:00 2017'::timestamp without time zone)), first(test_gapfill.value, test_gapfill."time"), avg(test_gapfill.value) - Group Key: (time_bucket_gapfill('@ 3 hours'::interval, test_gapfill."time", 'Sun Jan 01 06:00:00 2017'::timestamp without time zone, 'Mon Jan 02 18:00:00 2017'::timestamp without time zone)) - -> Sort - Output: (time_bucket_gapfill('@ 3 hours'::interval, test_gapfill."time", 'Sun Jan 01 06:00:00 2017'::timestamp without time zone, 'Mon Jan 02 18:00:00 2017'::timestamp without time zone)), (PARTIAL first(test_gapfill.value, test_gapfill."time")), (PARTIAL avg(test_gapfill.value)) - Sort Key: (time_bucket_gapfill('@ 3 hours'::interval, test_gapfill."time", 'Sun Jan 01 06:00:00 2017'::timestamp without time zone, 'Mon Jan 02 18:00:00 2017'::timestamp without time zone)) - -> Append - -> Partial HashAggregate - Output: (time_bucket_gapfill('@ 3 hours'::interval, test_gapfill."time", 'Sun Jan 01 06:00:00 2017'::timestamp without time zone, 'Mon Jan 02 18:00:00 2017'::timestamp without time zone)), PARTIAL first(test_gapfill.value, test_gapfill."time"), PARTIAL avg(test_gapfill.value) - Group Key: time_bucket_gapfill('@ 3 hours'::interval, test_gapfill."time", 'Sun Jan 01 06:00:00 2017'::timestamp without time zone, 'Mon Jan 02 18:00:00 2017'::timestamp without time zone) - -> Custom Scan (DataNodeScan) on public.test_gapfill - Output: time_bucket_gapfill('@ 3 hours'::interval, test_gapfill."time", 'Sun Jan 01 06:00:00 2017'::timestamp without time zone, 'Mon Jan 02 18:00:00 2017'::timestamp without time zone), test_gapfill.value, test_gapfill."time" - Data node: data_node_1 - Chunks: _dist_hyper_X_X_chunk - Remote SQL: SELECT "time", value FROM public.test_gapfill WHERE _timescaledb_internal.chunks_in(public.test_gapfill.*, ARRAY[28]) - Remote EXPLAIN: - Seq Scan on _timescaledb_internal._dist_hyper_X_X_chunk - Output: _dist_hyper_X_X_chunk."time", _dist_hyper_X_X_chunk.value - - -> Partial HashAggregate - Output: (time_bucket_gapfill('@ 3 hours'::interval, test_gapfill_1."time", 'Sun Jan 01 06:00:00 2017'::timestamp without time zone, 'Mon Jan 02 18:00:00 2017'::timestamp without time zone)), PARTIAL first(test_gapfill_1.value, test_gapfill_1."time"), PARTIAL avg(test_gapfill_1.value) - Group Key: time_bucket_gapfill('@ 3 hours'::interval, test_gapfill_1."time", 'Sun Jan 01 06:00:00 2017'::timestamp without time zone, 'Mon Jan 02 18:00:00 2017'::timestamp without time zone) - -> Custom Scan (DataNodeScan) on public.test_gapfill test_gapfill_1 - Output: time_bucket_gapfill('@ 3 hours'::interval, test_gapfill_1."time", 'Sun Jan 01 06:00:00 2017'::timestamp without time zone, 'Mon Jan 02 18:00:00 2017'::timestamp without time zone), test_gapfill_1.value, test_gapfill_1."time" - Data node: data_node_3 - Chunks: _dist_hyper_X_X_chunk, _dist_hyper_X_X_chunk, _dist_hyper_X_X_chunk - Remote SQL: SELECT "time", value FROM public.test_gapfill WHERE _timescaledb_internal.chunks_in(public.test_gapfill.*, ARRAY[23, 24, 25]) - Remote EXPLAIN: - Append - -> Seq Scan on _timescaledb_internal._dist_hyper_X_X_chunk - Output: _dist_hyper_X_X_chunk."time", _dist_hyper_X_X_chunk.value - -> Seq Scan on _timescaledb_internal._dist_hyper_X_X_chunk - Output: _dist_hyper_X_X_chunk."time", _dist_hyper_X_X_chunk.value - -> Seq Scan on _timescaledb_internal._dist_hyper_X_X_chunk - Output: _dist_hyper_X_X_chunk."time", _dist_hyper_X_X_chunk.value - -(38 rows) - --- Window functions -EXPLAIN (VERBOSE, COSTS OFF) SELECT - time_bucket_gapfill('3 hours', time, '2017-01-01 06:00', '2017-01-01 18:00'), - lag(min(time)) OVER () -FROM test_gapfill -GROUP BY 1; - QUERY PLAN -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- - WindowAgg - Output: (time_bucket_gapfill('@ 3 hours'::interval, "time", 'Sun Jan 01 06:00:00 2017'::timestamp without time zone, 'Sun Jan 01 18:00:00 2017'::timestamp without time zone)), lag((min("time"))) OVER (?) - -> Custom Scan (GapFill) - Output: (time_bucket_gapfill('@ 3 hours'::interval, "time", 'Sun Jan 01 06:00:00 2017'::timestamp without time zone, 'Sun Jan 01 18:00:00 2017'::timestamp without time zone)), (min("time")) - -> Finalize GroupAggregate - Output: (time_bucket_gapfill('@ 3 hours'::interval, test_gapfill."time", 'Sun Jan 01 06:00:00 2017'::timestamp without time zone, 'Sun Jan 01 18:00:00 2017'::timestamp without time zone)), min(test_gapfill."time") - Group Key: (time_bucket_gapfill('@ 3 hours'::interval, test_gapfill."time", 'Sun Jan 01 06:00:00 2017'::timestamp without time zone, 'Sun Jan 01 18:00:00 2017'::timestamp without time zone)) - -> Sort - Output: (time_bucket_gapfill('@ 3 hours'::interval, test_gapfill."time", 'Sun Jan 01 06:00:00 2017'::timestamp without time zone, 'Sun Jan 01 18:00:00 2017'::timestamp without time zone)), (PARTIAL min(test_gapfill."time")) - Sort Key: (time_bucket_gapfill('@ 3 hours'::interval, test_gapfill."time", 'Sun Jan 01 06:00:00 2017'::timestamp without time zone, 'Sun Jan 01 18:00:00 2017'::timestamp without time zone)) - -> Append - -> Partial HashAggregate - Output: (time_bucket_gapfill('@ 3 hours'::interval, test_gapfill."time", 'Sun Jan 01 06:00:00 2017'::timestamp without time zone, 'Sun Jan 01 18:00:00 2017'::timestamp without time zone)), PARTIAL min(test_gapfill."time") - Group Key: time_bucket_gapfill('@ 3 hours'::interval, test_gapfill."time", 'Sun Jan 01 06:00:00 2017'::timestamp without time zone, 'Sun Jan 01 18:00:00 2017'::timestamp without time zone) - -> Custom Scan (DataNodeScan) on public.test_gapfill - Output: time_bucket_gapfill('@ 3 hours'::interval, test_gapfill."time", 'Sun Jan 01 06:00:00 2017'::timestamp without time zone, 'Sun Jan 01 18:00:00 2017'::timestamp without time zone), test_gapfill."time" - Data node: data_node_1 - Chunks: _dist_hyper_X_X_chunk - Remote SQL: SELECT "time" FROM public.test_gapfill WHERE _timescaledb_internal.chunks_in(public.test_gapfill.*, ARRAY[28]) - Remote EXPLAIN: - Seq Scan on _timescaledb_internal._dist_hyper_X_X_chunk - Output: _dist_hyper_X_X_chunk."time" - - -> Partial HashAggregate - Output: (time_bucket_gapfill('@ 3 hours'::interval, test_gapfill_1."time", 'Sun Jan 01 06:00:00 2017'::timestamp without time zone, 'Sun Jan 01 18:00:00 2017'::timestamp without time zone)), PARTIAL min(test_gapfill_1."time") - Group Key: time_bucket_gapfill('@ 3 hours'::interval, test_gapfill_1."time", 'Sun Jan 01 06:00:00 2017'::timestamp without time zone, 'Sun Jan 01 18:00:00 2017'::timestamp without time zone) - -> Custom Scan (DataNodeScan) on public.test_gapfill test_gapfill_1 - Output: time_bucket_gapfill('@ 3 hours'::interval, test_gapfill_1."time", 'Sun Jan 01 06:00:00 2017'::timestamp without time zone, 'Sun Jan 01 18:00:00 2017'::timestamp without time zone), test_gapfill_1."time" - Data node: data_node_3 - Chunks: _dist_hyper_X_X_chunk, _dist_hyper_X_X_chunk, _dist_hyper_X_X_chunk - Remote SQL: SELECT "time" FROM public.test_gapfill WHERE _timescaledb_internal.chunks_in(public.test_gapfill.*, ARRAY[23, 24, 25]) - Remote EXPLAIN: - Append - -> Seq Scan on _timescaledb_internal._dist_hyper_X_X_chunk - Output: _dist_hyper_X_X_chunk."time" - -> Seq Scan on _timescaledb_internal._dist_hyper_X_X_chunk - Output: _dist_hyper_X_X_chunk."time" - -> Seq Scan on _timescaledb_internal._dist_hyper_X_X_chunk - Output: _dist_hyper_X_X_chunk."time" - -(40 rows) - --- Data nodes are overlapping -EXPLAIN (VERBOSE, COSTS OFF) SELECT time_bucket_gapfill('3 hours', time, '2018-01-01 06:00', '2018-01-01 18:00'), - name, - first(value, time), - avg(value) -FROM test_gapfill_overlap -GROUP BY 1,2; - QUERY PLAN -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- - Custom Scan (GapFill) - Output: (time_bucket_gapfill('@ 3 hours'::interval, "time", 'Mon Jan 01 06:00:00 2018'::timestamp without time zone, 'Mon Jan 01 18:00:00 2018'::timestamp without time zone)), name, (first(value, "time")), (avg(value)) - -> Sort - Output: (time_bucket_gapfill('@ 3 hours'::interval, test_gapfill_overlap."time", 'Mon Jan 01 06:00:00 2018'::timestamp without time zone, 'Mon Jan 01 18:00:00 2018'::timestamp without time zone)), test_gapfill_overlap.name, (first(test_gapfill_overlap.value, test_gapfill_overlap."time")), (avg(test_gapfill_overlap.value)) - Sort Key: test_gapfill_overlap.name, (time_bucket_gapfill('@ 3 hours'::interval, test_gapfill_overlap."time", 'Mon Jan 01 06:00:00 2018'::timestamp without time zone, 'Mon Jan 01 18:00:00 2018'::timestamp without time zone)) - -> Finalize GroupAggregate - Output: (time_bucket_gapfill('@ 3 hours'::interval, test_gapfill_overlap."time", 'Mon Jan 01 06:00:00 2018'::timestamp without time zone, 'Mon Jan 01 18:00:00 2018'::timestamp without time zone)), test_gapfill_overlap.name, first(test_gapfill_overlap.value, test_gapfill_overlap."time"), avg(test_gapfill_overlap.value) - Group Key: (time_bucket_gapfill('@ 3 hours'::interval, test_gapfill_overlap."time", 'Mon Jan 01 06:00:00 2018'::timestamp without time zone, 'Mon Jan 01 18:00:00 2018'::timestamp without time zone)), test_gapfill_overlap.name - -> Merge Append - Sort Key: (time_bucket_gapfill('@ 3 hours'::interval, test_gapfill_overlap."time", 'Mon Jan 01 06:00:00 2018'::timestamp without time zone, 'Mon Jan 01 18:00:00 2018'::timestamp without time zone)), test_gapfill_overlap.name - -> Partial GroupAggregate - Output: (time_bucket_gapfill('@ 3 hours'::interval, test_gapfill_overlap."time", 'Mon Jan 01 06:00:00 2018'::timestamp without time zone, 'Mon Jan 01 18:00:00 2018'::timestamp without time zone)), test_gapfill_overlap.name, PARTIAL first(test_gapfill_overlap.value, test_gapfill_overlap."time"), PARTIAL avg(test_gapfill_overlap.value) - Group Key: (time_bucket_gapfill('@ 3 hours'::interval, test_gapfill_overlap."time", 'Mon Jan 01 06:00:00 2018'::timestamp without time zone, 'Mon Jan 01 18:00:00 2018'::timestamp without time zone)), test_gapfill_overlap.name - -> Sort - Output: (time_bucket_gapfill('@ 3 hours'::interval, test_gapfill_overlap."time", 'Mon Jan 01 06:00:00 2018'::timestamp without time zone, 'Mon Jan 01 18:00:00 2018'::timestamp without time zone)), test_gapfill_overlap.name, test_gapfill_overlap.value, test_gapfill_overlap."time" - Sort Key: (time_bucket_gapfill('@ 3 hours'::interval, test_gapfill_overlap."time", 'Mon Jan 01 06:00:00 2018'::timestamp without time zone, 'Mon Jan 01 18:00:00 2018'::timestamp without time zone)), test_gapfill_overlap.name - -> Custom Scan (DataNodeScan) on public.test_gapfill_overlap - Output: time_bucket_gapfill('@ 3 hours'::interval, test_gapfill_overlap."time", 'Mon Jan 01 06:00:00 2018'::timestamp without time zone, 'Mon Jan 01 18:00:00 2018'::timestamp without time zone), test_gapfill_overlap.name, test_gapfill_overlap.value, test_gapfill_overlap."time" - Data node: data_node_1 - Chunks: _dist_hyper_X_X_chunk, _dist_hyper_X_X_chunk, _dist_hyper_X_X_chunk, _dist_hyper_X_X_chunk - Remote SQL: SELECT "time", name, value FROM public.test_gapfill_overlap WHERE _timescaledb_internal.chunks_in(public.test_gapfill_overlap.*, ARRAY[29, 30, 31, 32]) - Remote EXPLAIN: - Append - -> Seq Scan on _timescaledb_internal._dist_hyper_X_X_chunk - Output: _dist_hyper_X_X_chunk."time", _dist_hyper_X_X_chunk.name, _dist_hyper_X_X_chunk.value - -> Seq Scan on _timescaledb_internal._dist_hyper_X_X_chunk - Output: _dist_hyper_X_X_chunk."time", _dist_hyper_X_X_chunk.name, _dist_hyper_X_X_chunk.value - -> Seq Scan on _timescaledb_internal._dist_hyper_X_X_chunk - Output: _dist_hyper_X_X_chunk."time", _dist_hyper_X_X_chunk.name, _dist_hyper_X_X_chunk.value - -> Seq Scan on _timescaledb_internal._dist_hyper_X_X_chunk - Output: _dist_hyper_X_X_chunk."time", _dist_hyper_X_X_chunk.name, _dist_hyper_X_X_chunk.value - - -> Partial GroupAggregate - Output: (time_bucket_gapfill('@ 3 hours'::interval, test_gapfill_overlap_1."time", 'Mon Jan 01 06:00:00 2018'::timestamp without time zone, 'Mon Jan 01 18:00:00 2018'::timestamp without time zone)), test_gapfill_overlap_1.name, PARTIAL first(test_gapfill_overlap_1.value, test_gapfill_overlap_1."time"), PARTIAL avg(test_gapfill_overlap_1.value) - Group Key: (time_bucket_gapfill('@ 3 hours'::interval, test_gapfill_overlap_1."time", 'Mon Jan 01 06:00:00 2018'::timestamp without time zone, 'Mon Jan 01 18:00:00 2018'::timestamp without time zone)), test_gapfill_overlap_1.name - -> Sort - Output: (time_bucket_gapfill('@ 3 hours'::interval, test_gapfill_overlap_1."time", 'Mon Jan 01 06:00:00 2018'::timestamp without time zone, 'Mon Jan 01 18:00:00 2018'::timestamp without time zone)), test_gapfill_overlap_1.name, test_gapfill_overlap_1.value, test_gapfill_overlap_1."time" - Sort Key: (time_bucket_gapfill('@ 3 hours'::interval, test_gapfill_overlap_1."time", 'Mon Jan 01 06:00:00 2018'::timestamp without time zone, 'Mon Jan 01 18:00:00 2018'::timestamp without time zone)), test_gapfill_overlap_1.name - -> Custom Scan (DataNodeScan) on public.test_gapfill_overlap test_gapfill_overlap_1 - Output: time_bucket_gapfill('@ 3 hours'::interval, test_gapfill_overlap_1."time", 'Mon Jan 01 06:00:00 2018'::timestamp without time zone, 'Mon Jan 01 18:00:00 2018'::timestamp without time zone), test_gapfill_overlap_1.name, test_gapfill_overlap_1.value, test_gapfill_overlap_1."time" - Data node: data_node_2 - Chunks: _dist_hyper_X_X_chunk - Remote SQL: SELECT "time", name, value FROM public.test_gapfill_overlap WHERE _timescaledb_internal.chunks_in(public.test_gapfill_overlap.*, ARRAY[20]) - Remote EXPLAIN: - Seq Scan on _timescaledb_internal._dist_hyper_X_X_chunk - Output: _dist_hyper_X_X_chunk."time", _dist_hyper_X_X_chunk.name, _dist_hyper_X_X_chunk.value - - -> Partial GroupAggregate - Output: (time_bucket_gapfill('@ 3 hours'::interval, test_gapfill_overlap_2."time", 'Mon Jan 01 06:00:00 2018'::timestamp without time zone, 'Mon Jan 01 18:00:00 2018'::timestamp without time zone)), test_gapfill_overlap_2.name, PARTIAL first(test_gapfill_overlap_2.value, test_gapfill_overlap_2."time"), PARTIAL avg(test_gapfill_overlap_2.value) - Group Key: (time_bucket_gapfill('@ 3 hours'::interval, test_gapfill_overlap_2."time", 'Mon Jan 01 06:00:00 2018'::timestamp without time zone, 'Mon Jan 01 18:00:00 2018'::timestamp without time zone)), test_gapfill_overlap_2.name - -> Sort - Output: (time_bucket_gapfill('@ 3 hours'::interval, test_gapfill_overlap_2."time", 'Mon Jan 01 06:00:00 2018'::timestamp without time zone, 'Mon Jan 01 18:00:00 2018'::timestamp without time zone)), test_gapfill_overlap_2.name, test_gapfill_overlap_2.value, test_gapfill_overlap_2."time" - Sort Key: (time_bucket_gapfill('@ 3 hours'::interval, test_gapfill_overlap_2."time", 'Mon Jan 01 06:00:00 2018'::timestamp without time zone, 'Mon Jan 01 18:00:00 2018'::timestamp without time zone)), test_gapfill_overlap_2.name - -> Custom Scan (DataNodeScan) on public.test_gapfill_overlap test_gapfill_overlap_2 - Output: time_bucket_gapfill('@ 3 hours'::interval, test_gapfill_overlap_2."time", 'Mon Jan 01 06:00:00 2018'::timestamp without time zone, 'Mon Jan 01 18:00:00 2018'::timestamp without time zone), test_gapfill_overlap_2.name, test_gapfill_overlap_2.value, test_gapfill_overlap_2."time" - Data node: data_node_3 - Chunks: _dist_hyper_X_X_chunk, _dist_hyper_X_X_chunk, _dist_hyper_X_X_chunk, _dist_hyper_X_X_chunk, _dist_hyper_X_X_chunk - Remote SQL: SELECT "time", name, value FROM public.test_gapfill_overlap WHERE _timescaledb_internal.chunks_in(public.test_gapfill_overlap.*, ARRAY[26, 27, 28, 29, 30]) - Remote EXPLAIN: - Append - -> Seq Scan on _timescaledb_internal._dist_hyper_X_X_chunk - Output: _dist_hyper_X_X_chunk."time", _dist_hyper_X_X_chunk.name, _dist_hyper_X_X_chunk.value - -> Seq Scan on _timescaledb_internal._dist_hyper_X_X_chunk - Output: _dist_hyper_X_X_chunk."time", _dist_hyper_X_X_chunk.name, _dist_hyper_X_X_chunk.value - -> Seq Scan on _timescaledb_internal._dist_hyper_X_X_chunk - Output: _dist_hyper_X_X_chunk."time", _dist_hyper_X_X_chunk.name, _dist_hyper_X_X_chunk.value - -> Seq Scan on _timescaledb_internal._dist_hyper_X_X_chunk - Output: _dist_hyper_X_X_chunk."time", _dist_hyper_X_X_chunk.name, _dist_hyper_X_X_chunk.value - -> Seq Scan on _timescaledb_internal._dist_hyper_X_X_chunk - Output: _dist_hyper_X_X_chunk."time", _dist_hyper_X_X_chunk.name, _dist_hyper_X_X_chunk.value - -(71 rows) - -SET timescaledb.enable_remote_explain = false; -DROP TABLE test_gapfill; -DROP TABLE test_gapfill_overlap; diff --git a/tsl/test/shared/expected/dist_gapfill_pushdown-13.out b/tsl/test/shared/expected/dist_gapfill_pushdown-13.out deleted file mode 100644 index ff3f29930..000000000 --- a/tsl/test/shared/expected/dist_gapfill_pushdown-13.out +++ /dev/null @@ -1,297 +0,0 @@ --- This file and its contents are licensed under the Timescale License. --- Please see the included NOTICE for copyright information and --- LICENSE-TIMESCALE for a copy of the license. -\set ON_ERROR_STOP 0 -SET enable_partitionwise_aggregate = 'on'; -SET timescaledb.enable_remote_explain = true; --- Cases where gapfill is pushed down to data-nodes -EXPLAIN (VERBOSE, COSTS OFF) SELECT time_bucket_gapfill('3 hours', time, '2017-01-01 06:00', '2017-01-01 18:00'), - name, - first(value, time), - avg(value) -FROM test_gapfill -GROUP BY 1,2; - QUERY PLAN ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- - Custom Scan (AsyncAppend) - Output: (time_bucket_gapfill('@ 3 hours'::interval, "time", 'Sun Jan 01 06:00:00 2017'::timestamp without time zone, 'Sun Jan 01 18:00:00 2017'::timestamp without time zone)), name, (first(value, "time")), (avg(value)) - -> Append - -> Custom Scan (DataNodeScan) - Output: (time_bucket_gapfill('@ 3 hours'::interval, test_gapfill."time", 'Sun Jan 01 06:00:00 2017'::timestamp without time zone, 'Sun Jan 01 18:00:00 2017'::timestamp without time zone)), test_gapfill.name, (first(test_gapfill.value, test_gapfill."time")), (avg(test_gapfill.value)) - Relations: Aggregate on (public.test_gapfill) - Data node: data_node_1 - Chunks: _dist_hyper_X_X_chunk - Remote SQL: SELECT public.time_bucket_gapfill('@ 3 hours'::interval, "time", 'Sun Jan 01 06:00:00 2017'::timestamp without time zone, 'Sun Jan 01 18:00:00 2017'::timestamp without time zone), name, public.first(value, "time"), avg(value) FROM public.test_gapfill WHERE _timescaledb_internal.chunks_in(public.test_gapfill.*, ARRAY[28]) GROUP BY 1, 2 - Remote EXPLAIN: - Custom Scan (GapFill) - Output: (public.time_bucket_gapfill('03:00:00'::interval, "time", '2017-01-01 06:00:00'::timestamp without time zone, '2017-01-01 18:00:00'::timestamp without time zone)), name, (public.first(value, "time")), (avg(value)) - -> Sort - Output: (public.time_bucket_gapfill('03:00:00'::interval, _dist_hyper_X_X_chunk."time", '2017-01-01 06:00:00'::timestamp without time zone, '2017-01-01 18:00:00'::timestamp without time zone)), _dist_hyper_X_X_chunk.name, (public.first(_dist_hyper_X_X_chunk.value, _dist_hyper_X_X_chunk."time")), (avg(_dist_hyper_X_X_chunk.value)) - Sort Key: _dist_hyper_X_X_chunk.name, (public.time_bucket_gapfill('03:00:00'::interval, _dist_hyper_X_X_chunk."time", '2017-01-01 06:00:00'::timestamp without time zone, '2017-01-01 18:00:00'::timestamp without time zone)) - -> HashAggregate - Output: (public.time_bucket_gapfill('03:00:00'::interval, _dist_hyper_X_X_chunk."time", '2017-01-01 06:00:00'::timestamp without time zone, '2017-01-01 18:00:00'::timestamp without time zone)), _dist_hyper_X_X_chunk.name, public.first(_dist_hyper_X_X_chunk.value, _dist_hyper_X_X_chunk."time"), avg(_dist_hyper_X_X_chunk.value) - Group Key: public.time_bucket_gapfill('03:00:00'::interval, _dist_hyper_X_X_chunk."time", '2017-01-01 06:00:00'::timestamp without time zone, '2017-01-01 18:00:00'::timestamp without time zone), _dist_hyper_X_X_chunk.name - -> Result - Output: public.time_bucket_gapfill('03:00:00'::interval, _dist_hyper_X_X_chunk."time", '2017-01-01 06:00:00'::timestamp without time zone, '2017-01-01 18:00:00'::timestamp without time zone), _dist_hyper_X_X_chunk.name, _dist_hyper_X_X_chunk.value, _dist_hyper_X_X_chunk."time" - -> Seq Scan on _timescaledb_internal._dist_hyper_X_X_chunk - Output: _dist_hyper_X_X_chunk."time", _dist_hyper_X_X_chunk.name, _dist_hyper_X_X_chunk.value - - -> Custom Scan (DataNodeScan) - Output: (time_bucket_gapfill('@ 3 hours'::interval, test_gapfill_1."time", 'Sun Jan 01 06:00:00 2017'::timestamp without time zone, 'Sun Jan 01 18:00:00 2017'::timestamp without time zone)), test_gapfill_1.name, (first(test_gapfill_1.value, test_gapfill_1."time")), (avg(test_gapfill_1.value)) - Relations: Aggregate on (public.test_gapfill) - Data node: data_node_3 - Chunks: _dist_hyper_X_X_chunk, _dist_hyper_X_X_chunk, _dist_hyper_X_X_chunk - Remote SQL: SELECT public.time_bucket_gapfill('@ 3 hours'::interval, "time", 'Sun Jan 01 06:00:00 2017'::timestamp without time zone, 'Sun Jan 01 18:00:00 2017'::timestamp without time zone), name, public.first(value, "time"), avg(value) FROM public.test_gapfill WHERE _timescaledb_internal.chunks_in(public.test_gapfill.*, ARRAY[23, 24, 25]) GROUP BY 1, 2 - Remote EXPLAIN: - Custom Scan (GapFill) - Output: (public.time_bucket_gapfill('03:00:00'::interval, test_gapfill."time", '2017-01-01 06:00:00'::timestamp without time zone, '2017-01-01 18:00:00'::timestamp without time zone)), test_gapfill.name, (public.first(test_gapfill.value, test_gapfill."time")), (avg(test_gapfill.value)) - -> Sort - Output: (public.time_bucket_gapfill('03:00:00'::interval, _dist_hyper_X_X_chunk."time", '2017-01-01 06:00:00'::timestamp without time zone, '2017-01-01 18:00:00'::timestamp without time zone)), _dist_hyper_X_X_chunk.name, (public.first(_dist_hyper_X_X_chunk.value, _dist_hyper_X_X_chunk."time")), (avg(_dist_hyper_X_X_chunk.value)) - Sort Key: _dist_hyper_X_X_chunk.name, (public.time_bucket_gapfill('03:00:00'::interval, _dist_hyper_X_X_chunk."time", '2017-01-01 06:00:00'::timestamp without time zone, '2017-01-01 18:00:00'::timestamp without time zone)) - -> HashAggregate - Output: (public.time_bucket_gapfill('03:00:00'::interval, _dist_hyper_X_X_chunk."time", '2017-01-01 06:00:00'::timestamp without time zone, '2017-01-01 18:00:00'::timestamp without time zone)), _dist_hyper_X_X_chunk.name, public.first(_dist_hyper_X_X_chunk.value, _dist_hyper_X_X_chunk."time"), avg(_dist_hyper_X_X_chunk.value) - Group Key: public.time_bucket_gapfill('03:00:00'::interval, _dist_hyper_X_X_chunk."time", '2017-01-01 06:00:00'::timestamp without time zone, '2017-01-01 18:00:00'::timestamp without time zone), _dist_hyper_X_X_chunk.name - -> Result - Output: public.time_bucket_gapfill('03:00:00'::interval, _dist_hyper_X_X_chunk."time", '2017-01-01 06:00:00'::timestamp without time zone, '2017-01-01 18:00:00'::timestamp without time zone), _dist_hyper_X_X_chunk.name, _dist_hyper_X_X_chunk.value, _dist_hyper_X_X_chunk."time" - -> Append - -> Seq Scan on _timescaledb_internal._dist_hyper_X_X_chunk - Output: _dist_hyper_X_X_chunk."time", _dist_hyper_X_X_chunk.name, _dist_hyper_X_X_chunk.value - -> Seq Scan on _timescaledb_internal._dist_hyper_X_X_chunk - Output: _dist_hyper_X_X_chunk."time", _dist_hyper_X_X_chunk.name, _dist_hyper_X_X_chunk.value - -> Seq Scan on _timescaledb_internal._dist_hyper_X_X_chunk - Output: _dist_hyper_X_X_chunk."time", _dist_hyper_X_X_chunk.name, _dist_hyper_X_X_chunk.value - -(48 rows) - -EXPLAIN (VERBOSE, COSTS OFF) SELECT time_bucket_gapfill('3 hours', time, '2017-01-01 06:00', '2017-01-01 18:00'), - name, - first(value, time), - avg(value) -FROM test_gapfill -GROUP BY 2,1; - QUERY PLAN ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- - Custom Scan (AsyncAppend) - Output: (time_bucket_gapfill('@ 3 hours'::interval, "time", 'Sun Jan 01 06:00:00 2017'::timestamp without time zone, 'Sun Jan 01 18:00:00 2017'::timestamp without time zone)), name, (first(value, "time")), (avg(value)) - -> Append - -> Custom Scan (DataNodeScan) - Output: (time_bucket_gapfill('@ 3 hours'::interval, test_gapfill."time", 'Sun Jan 01 06:00:00 2017'::timestamp without time zone, 'Sun Jan 01 18:00:00 2017'::timestamp without time zone)), test_gapfill.name, (first(test_gapfill.value, test_gapfill."time")), (avg(test_gapfill.value)) - Relations: Aggregate on (public.test_gapfill) - Data node: data_node_1 - Chunks: _dist_hyper_X_X_chunk - Remote SQL: SELECT public.time_bucket_gapfill('@ 3 hours'::interval, "time", 'Sun Jan 01 06:00:00 2017'::timestamp without time zone, 'Sun Jan 01 18:00:00 2017'::timestamp without time zone), name, public.first(value, "time"), avg(value) FROM public.test_gapfill WHERE _timescaledb_internal.chunks_in(public.test_gapfill.*, ARRAY[28]) GROUP BY 2, 1 - Remote EXPLAIN: - Custom Scan (GapFill) - Output: (public.time_bucket_gapfill('03:00:00'::interval, "time", '2017-01-01 06:00:00'::timestamp without time zone, '2017-01-01 18:00:00'::timestamp without time zone)), name, (public.first(value, "time")), (avg(value)) - -> Sort - Output: (public.time_bucket_gapfill('03:00:00'::interval, _dist_hyper_X_X_chunk."time", '2017-01-01 06:00:00'::timestamp without time zone, '2017-01-01 18:00:00'::timestamp without time zone)), _dist_hyper_X_X_chunk.name, (public.first(_dist_hyper_X_X_chunk.value, _dist_hyper_X_X_chunk."time")), (avg(_dist_hyper_X_X_chunk.value)) - Sort Key: _dist_hyper_X_X_chunk.name, (public.time_bucket_gapfill('03:00:00'::interval, _dist_hyper_X_X_chunk."time", '2017-01-01 06:00:00'::timestamp without time zone, '2017-01-01 18:00:00'::timestamp without time zone)) - -> HashAggregate - Output: (public.time_bucket_gapfill('03:00:00'::interval, _dist_hyper_X_X_chunk."time", '2017-01-01 06:00:00'::timestamp without time zone, '2017-01-01 18:00:00'::timestamp without time zone)), _dist_hyper_X_X_chunk.name, public.first(_dist_hyper_X_X_chunk.value, _dist_hyper_X_X_chunk."time"), avg(_dist_hyper_X_X_chunk.value) - Group Key: _dist_hyper_X_X_chunk.name, public.time_bucket_gapfill('03:00:00'::interval, _dist_hyper_X_X_chunk."time", '2017-01-01 06:00:00'::timestamp without time zone, '2017-01-01 18:00:00'::timestamp without time zone) - -> Result - Output: public.time_bucket_gapfill('03:00:00'::interval, _dist_hyper_X_X_chunk."time", '2017-01-01 06:00:00'::timestamp without time zone, '2017-01-01 18:00:00'::timestamp without time zone), _dist_hyper_X_X_chunk.name, _dist_hyper_X_X_chunk.value, _dist_hyper_X_X_chunk."time" - -> Seq Scan on _timescaledb_internal._dist_hyper_X_X_chunk - Output: _dist_hyper_X_X_chunk."time", _dist_hyper_X_X_chunk.name, _dist_hyper_X_X_chunk.value - - -> Custom Scan (DataNodeScan) - Output: (time_bucket_gapfill('@ 3 hours'::interval, test_gapfill_1."time", 'Sun Jan 01 06:00:00 2017'::timestamp without time zone, 'Sun Jan 01 18:00:00 2017'::timestamp without time zone)), test_gapfill_1.name, (first(test_gapfill_1.value, test_gapfill_1."time")), (avg(test_gapfill_1.value)) - Relations: Aggregate on (public.test_gapfill) - Data node: data_node_3 - Chunks: _dist_hyper_X_X_chunk, _dist_hyper_X_X_chunk, _dist_hyper_X_X_chunk - Remote SQL: SELECT public.time_bucket_gapfill('@ 3 hours'::interval, "time", 'Sun Jan 01 06:00:00 2017'::timestamp without time zone, 'Sun Jan 01 18:00:00 2017'::timestamp without time zone), name, public.first(value, "time"), avg(value) FROM public.test_gapfill WHERE _timescaledb_internal.chunks_in(public.test_gapfill.*, ARRAY[23, 24, 25]) GROUP BY 2, 1 - Remote EXPLAIN: - Custom Scan (GapFill) - Output: (public.time_bucket_gapfill('03:00:00'::interval, test_gapfill."time", '2017-01-01 06:00:00'::timestamp without time zone, '2017-01-01 18:00:00'::timestamp without time zone)), test_gapfill.name, (public.first(test_gapfill.value, test_gapfill."time")), (avg(test_gapfill.value)) - -> Sort - Output: (public.time_bucket_gapfill('03:00:00'::interval, _dist_hyper_X_X_chunk."time", '2017-01-01 06:00:00'::timestamp without time zone, '2017-01-01 18:00:00'::timestamp without time zone)), _dist_hyper_X_X_chunk.name, (public.first(_dist_hyper_X_X_chunk.value, _dist_hyper_X_X_chunk."time")), (avg(_dist_hyper_X_X_chunk.value)) - Sort Key: _dist_hyper_X_X_chunk.name, (public.time_bucket_gapfill('03:00:00'::interval, _dist_hyper_X_X_chunk."time", '2017-01-01 06:00:00'::timestamp without time zone, '2017-01-01 18:00:00'::timestamp without time zone)) - -> HashAggregate - Output: (public.time_bucket_gapfill('03:00:00'::interval, _dist_hyper_X_X_chunk."time", '2017-01-01 06:00:00'::timestamp without time zone, '2017-01-01 18:00:00'::timestamp without time zone)), _dist_hyper_X_X_chunk.name, public.first(_dist_hyper_X_X_chunk.value, _dist_hyper_X_X_chunk."time"), avg(_dist_hyper_X_X_chunk.value) - Group Key: _dist_hyper_X_X_chunk.name, public.time_bucket_gapfill('03:00:00'::interval, _dist_hyper_X_X_chunk."time", '2017-01-01 06:00:00'::timestamp without time zone, '2017-01-01 18:00:00'::timestamp without time zone) - -> Result - Output: public.time_bucket_gapfill('03:00:00'::interval, _dist_hyper_X_X_chunk."time", '2017-01-01 06:00:00'::timestamp without time zone, '2017-01-01 18:00:00'::timestamp without time zone), _dist_hyper_X_X_chunk.name, _dist_hyper_X_X_chunk.value, _dist_hyper_X_X_chunk."time" - -> Append - -> Seq Scan on _timescaledb_internal._dist_hyper_X_X_chunk - Output: _dist_hyper_X_X_chunk."time", _dist_hyper_X_X_chunk.name, _dist_hyper_X_X_chunk.value - -> Seq Scan on _timescaledb_internal._dist_hyper_X_X_chunk - Output: _dist_hyper_X_X_chunk."time", _dist_hyper_X_X_chunk.name, _dist_hyper_X_X_chunk.value - -> Seq Scan on _timescaledb_internal._dist_hyper_X_X_chunk - Output: _dist_hyper_X_X_chunk."time", _dist_hyper_X_X_chunk.name, _dist_hyper_X_X_chunk.value - -(48 rows) - --- Check for multiple gapfill calls -SELECT time_bucket_gapfill('3 hours', time, '2017-01-01 06:00', '2017-01-01 18:00'), - time_bucket_gapfill('6 hours', time, '2017-01-01 08:00', '2017-01-01 18:00'), - name, - first(value, time), - avg(value) -FROM test_gapfill -GROUP BY 2,1,3; -ERROR: multiple time_bucket_gapfill calls not allowed --- Cases where gapfill is not pushed down to data-nodes --- Space dimension is not in group by clause -EXPLAIN (VERBOSE, COSTS OFF) SELECT time_bucket_gapfill('3 hours', time, '2017-01-01 06:00', '2017-01-02 18:00'), - first(value, time), - avg(value) -FROM test_gapfill -GROUP BY 1; - QUERY PLAN ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- - Custom Scan (GapFill) - Output: (time_bucket_gapfill('@ 3 hours'::interval, "time", 'Sun Jan 01 06:00:00 2017'::timestamp without time zone, 'Mon Jan 02 18:00:00 2017'::timestamp without time zone)), (first(value, "time")), (avg(value)) - -> Finalize GroupAggregate - Output: (time_bucket_gapfill('@ 3 hours'::interval, test_gapfill."time", 'Sun Jan 01 06:00:00 2017'::timestamp without time zone, 'Mon Jan 02 18:00:00 2017'::timestamp without time zone)), first(test_gapfill.value, test_gapfill."time"), avg(test_gapfill.value) - Group Key: (time_bucket_gapfill('@ 3 hours'::interval, test_gapfill."time", 'Sun Jan 01 06:00:00 2017'::timestamp without time zone, 'Mon Jan 02 18:00:00 2017'::timestamp without time zone)) - -> Sort - Output: (time_bucket_gapfill('@ 3 hours'::interval, test_gapfill."time", 'Sun Jan 01 06:00:00 2017'::timestamp without time zone, 'Mon Jan 02 18:00:00 2017'::timestamp without time zone)), (PARTIAL first(test_gapfill.value, test_gapfill."time")), (PARTIAL avg(test_gapfill.value)) - Sort Key: (time_bucket_gapfill('@ 3 hours'::interval, test_gapfill."time", 'Sun Jan 01 06:00:00 2017'::timestamp without time zone, 'Mon Jan 02 18:00:00 2017'::timestamp without time zone)) - -> Append - -> Partial HashAggregate - Output: (time_bucket_gapfill('@ 3 hours'::interval, test_gapfill."time", 'Sun Jan 01 06:00:00 2017'::timestamp without time zone, 'Mon Jan 02 18:00:00 2017'::timestamp without time zone)), PARTIAL first(test_gapfill.value, test_gapfill."time"), PARTIAL avg(test_gapfill.value) - Group Key: time_bucket_gapfill('@ 3 hours'::interval, test_gapfill."time", 'Sun Jan 01 06:00:00 2017'::timestamp without time zone, 'Mon Jan 02 18:00:00 2017'::timestamp without time zone) - -> Custom Scan (DataNodeScan) on public.test_gapfill - Output: time_bucket_gapfill('@ 3 hours'::interval, test_gapfill."time", 'Sun Jan 01 06:00:00 2017'::timestamp without time zone, 'Mon Jan 02 18:00:00 2017'::timestamp without time zone), test_gapfill.value, test_gapfill."time" - Data node: data_node_1 - Chunks: _dist_hyper_X_X_chunk - Remote SQL: SELECT "time", value FROM public.test_gapfill WHERE _timescaledb_internal.chunks_in(public.test_gapfill.*, ARRAY[28]) - Remote EXPLAIN: - Seq Scan on _timescaledb_internal._dist_hyper_X_X_chunk - Output: _dist_hyper_X_X_chunk."time", _dist_hyper_X_X_chunk.value - - -> Partial HashAggregate - Output: (time_bucket_gapfill('@ 3 hours'::interval, test_gapfill_1."time", 'Sun Jan 01 06:00:00 2017'::timestamp without time zone, 'Mon Jan 02 18:00:00 2017'::timestamp without time zone)), PARTIAL first(test_gapfill_1.value, test_gapfill_1."time"), PARTIAL avg(test_gapfill_1.value) - Group Key: time_bucket_gapfill('@ 3 hours'::interval, test_gapfill_1."time", 'Sun Jan 01 06:00:00 2017'::timestamp without time zone, 'Mon Jan 02 18:00:00 2017'::timestamp without time zone) - -> Custom Scan (DataNodeScan) on public.test_gapfill test_gapfill_1 - Output: time_bucket_gapfill('@ 3 hours'::interval, test_gapfill_1."time", 'Sun Jan 01 06:00:00 2017'::timestamp without time zone, 'Mon Jan 02 18:00:00 2017'::timestamp without time zone), test_gapfill_1.value, test_gapfill_1."time" - Data node: data_node_3 - Chunks: _dist_hyper_X_X_chunk, _dist_hyper_X_X_chunk, _dist_hyper_X_X_chunk - Remote SQL: SELECT "time", value FROM public.test_gapfill WHERE _timescaledb_internal.chunks_in(public.test_gapfill.*, ARRAY[23, 24, 25]) - Remote EXPLAIN: - Append - -> Seq Scan on _timescaledb_internal._dist_hyper_X_X_chunk - Output: _dist_hyper_X_X_chunk."time", _dist_hyper_X_X_chunk.value - -> Seq Scan on _timescaledb_internal._dist_hyper_X_X_chunk - Output: _dist_hyper_X_X_chunk."time", _dist_hyper_X_X_chunk.value - -> Seq Scan on _timescaledb_internal._dist_hyper_X_X_chunk - Output: _dist_hyper_X_X_chunk."time", _dist_hyper_X_X_chunk.value - -(38 rows) - --- Window functions -EXPLAIN (VERBOSE, COSTS OFF) SELECT - time_bucket_gapfill('3 hours', time, '2017-01-01 06:00', '2017-01-01 18:00'), - lag(min(time)) OVER () -FROM test_gapfill -GROUP BY 1; - QUERY PLAN -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- - WindowAgg - Output: (time_bucket_gapfill('@ 3 hours'::interval, "time", 'Sun Jan 01 06:00:00 2017'::timestamp without time zone, 'Sun Jan 01 18:00:00 2017'::timestamp without time zone)), lag((min("time"))) OVER (?) - -> Custom Scan (GapFill) - Output: (time_bucket_gapfill('@ 3 hours'::interval, "time", 'Sun Jan 01 06:00:00 2017'::timestamp without time zone, 'Sun Jan 01 18:00:00 2017'::timestamp without time zone)), (min("time")) - -> Finalize GroupAggregate - Output: (time_bucket_gapfill('@ 3 hours'::interval, test_gapfill."time", 'Sun Jan 01 06:00:00 2017'::timestamp without time zone, 'Sun Jan 01 18:00:00 2017'::timestamp without time zone)), min(test_gapfill."time") - Group Key: (time_bucket_gapfill('@ 3 hours'::interval, test_gapfill."time", 'Sun Jan 01 06:00:00 2017'::timestamp without time zone, 'Sun Jan 01 18:00:00 2017'::timestamp without time zone)) - -> Sort - Output: (time_bucket_gapfill('@ 3 hours'::interval, test_gapfill."time", 'Sun Jan 01 06:00:00 2017'::timestamp without time zone, 'Sun Jan 01 18:00:00 2017'::timestamp without time zone)), (PARTIAL min(test_gapfill."time")) - Sort Key: (time_bucket_gapfill('@ 3 hours'::interval, test_gapfill."time", 'Sun Jan 01 06:00:00 2017'::timestamp without time zone, 'Sun Jan 01 18:00:00 2017'::timestamp without time zone)) - -> Append - -> Partial HashAggregate - Output: (time_bucket_gapfill('@ 3 hours'::interval, test_gapfill."time", 'Sun Jan 01 06:00:00 2017'::timestamp without time zone, 'Sun Jan 01 18:00:00 2017'::timestamp without time zone)), PARTIAL min(test_gapfill."time") - Group Key: time_bucket_gapfill('@ 3 hours'::interval, test_gapfill."time", 'Sun Jan 01 06:00:00 2017'::timestamp without time zone, 'Sun Jan 01 18:00:00 2017'::timestamp without time zone) - -> Custom Scan (DataNodeScan) on public.test_gapfill - Output: time_bucket_gapfill('@ 3 hours'::interval, test_gapfill."time", 'Sun Jan 01 06:00:00 2017'::timestamp without time zone, 'Sun Jan 01 18:00:00 2017'::timestamp without time zone), test_gapfill."time" - Data node: data_node_1 - Chunks: _dist_hyper_X_X_chunk - Remote SQL: SELECT "time" FROM public.test_gapfill WHERE _timescaledb_internal.chunks_in(public.test_gapfill.*, ARRAY[28]) - Remote EXPLAIN: - Seq Scan on _timescaledb_internal._dist_hyper_X_X_chunk - Output: _dist_hyper_X_X_chunk."time" - - -> Partial HashAggregate - Output: (time_bucket_gapfill('@ 3 hours'::interval, test_gapfill_1."time", 'Sun Jan 01 06:00:00 2017'::timestamp without time zone, 'Sun Jan 01 18:00:00 2017'::timestamp without time zone)), PARTIAL min(test_gapfill_1."time") - Group Key: time_bucket_gapfill('@ 3 hours'::interval, test_gapfill_1."time", 'Sun Jan 01 06:00:00 2017'::timestamp without time zone, 'Sun Jan 01 18:00:00 2017'::timestamp without time zone) - -> Custom Scan (DataNodeScan) on public.test_gapfill test_gapfill_1 - Output: time_bucket_gapfill('@ 3 hours'::interval, test_gapfill_1."time", 'Sun Jan 01 06:00:00 2017'::timestamp without time zone, 'Sun Jan 01 18:00:00 2017'::timestamp without time zone), test_gapfill_1."time" - Data node: data_node_3 - Chunks: _dist_hyper_X_X_chunk, _dist_hyper_X_X_chunk, _dist_hyper_X_X_chunk - Remote SQL: SELECT "time" FROM public.test_gapfill WHERE _timescaledb_internal.chunks_in(public.test_gapfill.*, ARRAY[23, 24, 25]) - Remote EXPLAIN: - Append - -> Seq Scan on _timescaledb_internal._dist_hyper_X_X_chunk - Output: _dist_hyper_X_X_chunk."time" - -> Seq Scan on _timescaledb_internal._dist_hyper_X_X_chunk - Output: _dist_hyper_X_X_chunk."time" - -> Seq Scan on _timescaledb_internal._dist_hyper_X_X_chunk - Output: _dist_hyper_X_X_chunk."time" - -(40 rows) - --- Data nodes are overlapping -EXPLAIN (VERBOSE, COSTS OFF) SELECT time_bucket_gapfill('3 hours', time, '2018-01-01 06:00', '2018-01-01 18:00'), - name, - first(value, time), - avg(value) -FROM test_gapfill_overlap -GROUP BY 1,2; - QUERY PLAN ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- - Custom Scan (GapFill) - Output: (time_bucket_gapfill('@ 3 hours'::interval, test_gapfill_overlap."time", 'Mon Jan 01 06:00:00 2018'::timestamp without time zone, 'Mon Jan 01 18:00:00 2018'::timestamp without time zone)), test_gapfill_overlap.name, (first(test_gapfill_overlap.value, test_gapfill_overlap."time")), (avg(test_gapfill_overlap.value)) - -> Sort - Output: (time_bucket_gapfill('@ 3 hours'::interval, test_gapfill_overlap_1."time", 'Mon Jan 01 06:00:00 2018'::timestamp without time zone, 'Mon Jan 01 18:00:00 2018'::timestamp without time zone)), test_gapfill_overlap_1.name, (first(test_gapfill_overlap_1.value, test_gapfill_overlap_1."time")), (avg(test_gapfill_overlap_1.value)) - Sort Key: test_gapfill_overlap_1.name, (time_bucket_gapfill('@ 3 hours'::interval, test_gapfill_overlap_1."time", 'Mon Jan 01 06:00:00 2018'::timestamp without time zone, 'Mon Jan 01 18:00:00 2018'::timestamp without time zone)) - -> HashAggregate - Output: (time_bucket_gapfill('@ 3 hours'::interval, test_gapfill_overlap_1."time", 'Mon Jan 01 06:00:00 2018'::timestamp without time zone, 'Mon Jan 01 18:00:00 2018'::timestamp without time zone)), test_gapfill_overlap_1.name, first(test_gapfill_overlap_1.value, test_gapfill_overlap_1."time"), avg(test_gapfill_overlap_1.value) - Group Key: (time_bucket_gapfill('@ 3 hours'::interval, test_gapfill_overlap_1."time", 'Mon Jan 01 06:00:00 2018'::timestamp without time zone, 'Mon Jan 01 18:00:00 2018'::timestamp without time zone)), test_gapfill_overlap_1.name - -> Append - -> Custom Scan (DataNodeScan) on public.test_gapfill_overlap test_gapfill_overlap_1 - Output: time_bucket_gapfill('@ 3 hours'::interval, test_gapfill_overlap_1."time", 'Mon Jan 01 06:00:00 2018'::timestamp without time zone, 'Mon Jan 01 18:00:00 2018'::timestamp without time zone), test_gapfill_overlap_1.name, test_gapfill_overlap_1.value, test_gapfill_overlap_1."time" - Data node: data_node_1 - Chunks: _dist_hyper_X_X_chunk, _dist_hyper_X_X_chunk, _dist_hyper_X_X_chunk, _dist_hyper_X_X_chunk - Remote SQL: SELECT "time", name, value FROM public.test_gapfill_overlap WHERE _timescaledb_internal.chunks_in(public.test_gapfill_overlap.*, ARRAY[29, 30, 31, 32]) - Remote EXPLAIN: - Append - -> Seq Scan on _timescaledb_internal._dist_hyper_X_X_chunk - Output: _dist_hyper_X_X_chunk."time", _dist_hyper_X_X_chunk.name, _dist_hyper_X_X_chunk.value - -> Seq Scan on _timescaledb_internal._dist_hyper_X_X_chunk - Output: _dist_hyper_X_X_chunk."time", _dist_hyper_X_X_chunk.name, _dist_hyper_X_X_chunk.value - -> Seq Scan on _timescaledb_internal._dist_hyper_X_X_chunk - Output: _dist_hyper_X_X_chunk."time", _dist_hyper_X_X_chunk.name, _dist_hyper_X_X_chunk.value - -> Seq Scan on _timescaledb_internal._dist_hyper_X_X_chunk - Output: _dist_hyper_X_X_chunk."time", _dist_hyper_X_X_chunk.name, _dist_hyper_X_X_chunk.value - - -> Custom Scan (DataNodeScan) on public.test_gapfill_overlap test_gapfill_overlap_2 - Output: time_bucket_gapfill('@ 3 hours'::interval, test_gapfill_overlap_2."time", 'Mon Jan 01 06:00:00 2018'::timestamp without time zone, 'Mon Jan 01 18:00:00 2018'::timestamp without time zone), test_gapfill_overlap_2.name, test_gapfill_overlap_2.value, test_gapfill_overlap_2."time" - Data node: data_node_2 - Chunks: _dist_hyper_X_X_chunk - Remote SQL: SELECT "time", name, value FROM public.test_gapfill_overlap WHERE _timescaledb_internal.chunks_in(public.test_gapfill_overlap.*, ARRAY[20]) - Remote EXPLAIN: - Seq Scan on _timescaledb_internal._dist_hyper_X_X_chunk - Output: _dist_hyper_X_X_chunk."time", _dist_hyper_X_X_chunk.name, _dist_hyper_X_X_chunk.value - - -> Custom Scan (DataNodeScan) on public.test_gapfill_overlap test_gapfill_overlap_3 - Output: time_bucket_gapfill('@ 3 hours'::interval, test_gapfill_overlap_3."time", 'Mon Jan 01 06:00:00 2018'::timestamp without time zone, 'Mon Jan 01 18:00:00 2018'::timestamp without time zone), test_gapfill_overlap_3.name, test_gapfill_overlap_3.value, test_gapfill_overlap_3."time" - Data node: data_node_3 - Chunks: _dist_hyper_X_X_chunk, _dist_hyper_X_X_chunk, _dist_hyper_X_X_chunk, _dist_hyper_X_X_chunk, _dist_hyper_X_X_chunk - Remote SQL: SELECT "time", name, value FROM public.test_gapfill_overlap WHERE _timescaledb_internal.chunks_in(public.test_gapfill_overlap.*, ARRAY[26, 27, 28, 29, 30]) - Remote EXPLAIN: - Append - -> Seq Scan on _timescaledb_internal._dist_hyper_X_X_chunk - Output: _dist_hyper_X_X_chunk."time", _dist_hyper_X_X_chunk.name, _dist_hyper_X_X_chunk.value - -> Seq Scan on _timescaledb_internal._dist_hyper_X_X_chunk - Output: _dist_hyper_X_X_chunk."time", _dist_hyper_X_X_chunk.name, _dist_hyper_X_X_chunk.value - -> Seq Scan on _timescaledb_internal._dist_hyper_X_X_chunk - Output: _dist_hyper_X_X_chunk."time", _dist_hyper_X_X_chunk.name, _dist_hyper_X_X_chunk.value - -> Seq Scan on _timescaledb_internal._dist_hyper_X_X_chunk - Output: _dist_hyper_X_X_chunk."time", _dist_hyper_X_X_chunk.name, _dist_hyper_X_X_chunk.value - -> Seq Scan on _timescaledb_internal._dist_hyper_X_X_chunk - Output: _dist_hyper_X_X_chunk."time", _dist_hyper_X_X_chunk.name, _dist_hyper_X_X_chunk.value - -(52 rows) - -SET timescaledb.enable_remote_explain = false; -DROP TABLE test_gapfill; -DROP TABLE test_gapfill_overlap; diff --git a/tsl/test/shared/expected/dist_gapfill_pushdown-14.out b/tsl/test/shared/expected/dist_gapfill_pushdown-14.out deleted file mode 100644 index ff3f29930..000000000 --- a/tsl/test/shared/expected/dist_gapfill_pushdown-14.out +++ /dev/null @@ -1,297 +0,0 @@ --- This file and its contents are licensed under the Timescale License. --- Please see the included NOTICE for copyright information and --- LICENSE-TIMESCALE for a copy of the license. -\set ON_ERROR_STOP 0 -SET enable_partitionwise_aggregate = 'on'; -SET timescaledb.enable_remote_explain = true; --- Cases where gapfill is pushed down to data-nodes -EXPLAIN (VERBOSE, COSTS OFF) SELECT time_bucket_gapfill('3 hours', time, '2017-01-01 06:00', '2017-01-01 18:00'), - name, - first(value, time), - avg(value) -FROM test_gapfill -GROUP BY 1,2; - QUERY PLAN ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- - Custom Scan (AsyncAppend) - Output: (time_bucket_gapfill('@ 3 hours'::interval, "time", 'Sun Jan 01 06:00:00 2017'::timestamp without time zone, 'Sun Jan 01 18:00:00 2017'::timestamp without time zone)), name, (first(value, "time")), (avg(value)) - -> Append - -> Custom Scan (DataNodeScan) - Output: (time_bucket_gapfill('@ 3 hours'::interval, test_gapfill."time", 'Sun Jan 01 06:00:00 2017'::timestamp without time zone, 'Sun Jan 01 18:00:00 2017'::timestamp without time zone)), test_gapfill.name, (first(test_gapfill.value, test_gapfill."time")), (avg(test_gapfill.value)) - Relations: Aggregate on (public.test_gapfill) - Data node: data_node_1 - Chunks: _dist_hyper_X_X_chunk - Remote SQL: SELECT public.time_bucket_gapfill('@ 3 hours'::interval, "time", 'Sun Jan 01 06:00:00 2017'::timestamp without time zone, 'Sun Jan 01 18:00:00 2017'::timestamp without time zone), name, public.first(value, "time"), avg(value) FROM public.test_gapfill WHERE _timescaledb_internal.chunks_in(public.test_gapfill.*, ARRAY[28]) GROUP BY 1, 2 - Remote EXPLAIN: - Custom Scan (GapFill) - Output: (public.time_bucket_gapfill('03:00:00'::interval, "time", '2017-01-01 06:00:00'::timestamp without time zone, '2017-01-01 18:00:00'::timestamp without time zone)), name, (public.first(value, "time")), (avg(value)) - -> Sort - Output: (public.time_bucket_gapfill('03:00:00'::interval, _dist_hyper_X_X_chunk."time", '2017-01-01 06:00:00'::timestamp without time zone, '2017-01-01 18:00:00'::timestamp without time zone)), _dist_hyper_X_X_chunk.name, (public.first(_dist_hyper_X_X_chunk.value, _dist_hyper_X_X_chunk."time")), (avg(_dist_hyper_X_X_chunk.value)) - Sort Key: _dist_hyper_X_X_chunk.name, (public.time_bucket_gapfill('03:00:00'::interval, _dist_hyper_X_X_chunk."time", '2017-01-01 06:00:00'::timestamp without time zone, '2017-01-01 18:00:00'::timestamp without time zone)) - -> HashAggregate - Output: (public.time_bucket_gapfill('03:00:00'::interval, _dist_hyper_X_X_chunk."time", '2017-01-01 06:00:00'::timestamp without time zone, '2017-01-01 18:00:00'::timestamp without time zone)), _dist_hyper_X_X_chunk.name, public.first(_dist_hyper_X_X_chunk.value, _dist_hyper_X_X_chunk."time"), avg(_dist_hyper_X_X_chunk.value) - Group Key: public.time_bucket_gapfill('03:00:00'::interval, _dist_hyper_X_X_chunk."time", '2017-01-01 06:00:00'::timestamp without time zone, '2017-01-01 18:00:00'::timestamp without time zone), _dist_hyper_X_X_chunk.name - -> Result - Output: public.time_bucket_gapfill('03:00:00'::interval, _dist_hyper_X_X_chunk."time", '2017-01-01 06:00:00'::timestamp without time zone, '2017-01-01 18:00:00'::timestamp without time zone), _dist_hyper_X_X_chunk.name, _dist_hyper_X_X_chunk.value, _dist_hyper_X_X_chunk."time" - -> Seq Scan on _timescaledb_internal._dist_hyper_X_X_chunk - Output: _dist_hyper_X_X_chunk."time", _dist_hyper_X_X_chunk.name, _dist_hyper_X_X_chunk.value - - -> Custom Scan (DataNodeScan) - Output: (time_bucket_gapfill('@ 3 hours'::interval, test_gapfill_1."time", 'Sun Jan 01 06:00:00 2017'::timestamp without time zone, 'Sun Jan 01 18:00:00 2017'::timestamp without time zone)), test_gapfill_1.name, (first(test_gapfill_1.value, test_gapfill_1."time")), (avg(test_gapfill_1.value)) - Relations: Aggregate on (public.test_gapfill) - Data node: data_node_3 - Chunks: _dist_hyper_X_X_chunk, _dist_hyper_X_X_chunk, _dist_hyper_X_X_chunk - Remote SQL: SELECT public.time_bucket_gapfill('@ 3 hours'::interval, "time", 'Sun Jan 01 06:00:00 2017'::timestamp without time zone, 'Sun Jan 01 18:00:00 2017'::timestamp without time zone), name, public.first(value, "time"), avg(value) FROM public.test_gapfill WHERE _timescaledb_internal.chunks_in(public.test_gapfill.*, ARRAY[23, 24, 25]) GROUP BY 1, 2 - Remote EXPLAIN: - Custom Scan (GapFill) - Output: (public.time_bucket_gapfill('03:00:00'::interval, test_gapfill."time", '2017-01-01 06:00:00'::timestamp without time zone, '2017-01-01 18:00:00'::timestamp without time zone)), test_gapfill.name, (public.first(test_gapfill.value, test_gapfill."time")), (avg(test_gapfill.value)) - -> Sort - Output: (public.time_bucket_gapfill('03:00:00'::interval, _dist_hyper_X_X_chunk."time", '2017-01-01 06:00:00'::timestamp without time zone, '2017-01-01 18:00:00'::timestamp without time zone)), _dist_hyper_X_X_chunk.name, (public.first(_dist_hyper_X_X_chunk.value, _dist_hyper_X_X_chunk."time")), (avg(_dist_hyper_X_X_chunk.value)) - Sort Key: _dist_hyper_X_X_chunk.name, (public.time_bucket_gapfill('03:00:00'::interval, _dist_hyper_X_X_chunk."time", '2017-01-01 06:00:00'::timestamp without time zone, '2017-01-01 18:00:00'::timestamp without time zone)) - -> HashAggregate - Output: (public.time_bucket_gapfill('03:00:00'::interval, _dist_hyper_X_X_chunk."time", '2017-01-01 06:00:00'::timestamp without time zone, '2017-01-01 18:00:00'::timestamp without time zone)), _dist_hyper_X_X_chunk.name, public.first(_dist_hyper_X_X_chunk.value, _dist_hyper_X_X_chunk."time"), avg(_dist_hyper_X_X_chunk.value) - Group Key: public.time_bucket_gapfill('03:00:00'::interval, _dist_hyper_X_X_chunk."time", '2017-01-01 06:00:00'::timestamp without time zone, '2017-01-01 18:00:00'::timestamp without time zone), _dist_hyper_X_X_chunk.name - -> Result - Output: public.time_bucket_gapfill('03:00:00'::interval, _dist_hyper_X_X_chunk."time", '2017-01-01 06:00:00'::timestamp without time zone, '2017-01-01 18:00:00'::timestamp without time zone), _dist_hyper_X_X_chunk.name, _dist_hyper_X_X_chunk.value, _dist_hyper_X_X_chunk."time" - -> Append - -> Seq Scan on _timescaledb_internal._dist_hyper_X_X_chunk - Output: _dist_hyper_X_X_chunk."time", _dist_hyper_X_X_chunk.name, _dist_hyper_X_X_chunk.value - -> Seq Scan on _timescaledb_internal._dist_hyper_X_X_chunk - Output: _dist_hyper_X_X_chunk."time", _dist_hyper_X_X_chunk.name, _dist_hyper_X_X_chunk.value - -> Seq Scan on _timescaledb_internal._dist_hyper_X_X_chunk - Output: _dist_hyper_X_X_chunk."time", _dist_hyper_X_X_chunk.name, _dist_hyper_X_X_chunk.value - -(48 rows) - -EXPLAIN (VERBOSE, COSTS OFF) SELECT time_bucket_gapfill('3 hours', time, '2017-01-01 06:00', '2017-01-01 18:00'), - name, - first(value, time), - avg(value) -FROM test_gapfill -GROUP BY 2,1; - QUERY PLAN ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- - Custom Scan (AsyncAppend) - Output: (time_bucket_gapfill('@ 3 hours'::interval, "time", 'Sun Jan 01 06:00:00 2017'::timestamp without time zone, 'Sun Jan 01 18:00:00 2017'::timestamp without time zone)), name, (first(value, "time")), (avg(value)) - -> Append - -> Custom Scan (DataNodeScan) - Output: (time_bucket_gapfill('@ 3 hours'::interval, test_gapfill."time", 'Sun Jan 01 06:00:00 2017'::timestamp without time zone, 'Sun Jan 01 18:00:00 2017'::timestamp without time zone)), test_gapfill.name, (first(test_gapfill.value, test_gapfill."time")), (avg(test_gapfill.value)) - Relations: Aggregate on (public.test_gapfill) - Data node: data_node_1 - Chunks: _dist_hyper_X_X_chunk - Remote SQL: SELECT public.time_bucket_gapfill('@ 3 hours'::interval, "time", 'Sun Jan 01 06:00:00 2017'::timestamp without time zone, 'Sun Jan 01 18:00:00 2017'::timestamp without time zone), name, public.first(value, "time"), avg(value) FROM public.test_gapfill WHERE _timescaledb_internal.chunks_in(public.test_gapfill.*, ARRAY[28]) GROUP BY 2, 1 - Remote EXPLAIN: - Custom Scan (GapFill) - Output: (public.time_bucket_gapfill('03:00:00'::interval, "time", '2017-01-01 06:00:00'::timestamp without time zone, '2017-01-01 18:00:00'::timestamp without time zone)), name, (public.first(value, "time")), (avg(value)) - -> Sort - Output: (public.time_bucket_gapfill('03:00:00'::interval, _dist_hyper_X_X_chunk."time", '2017-01-01 06:00:00'::timestamp without time zone, '2017-01-01 18:00:00'::timestamp without time zone)), _dist_hyper_X_X_chunk.name, (public.first(_dist_hyper_X_X_chunk.value, _dist_hyper_X_X_chunk."time")), (avg(_dist_hyper_X_X_chunk.value)) - Sort Key: _dist_hyper_X_X_chunk.name, (public.time_bucket_gapfill('03:00:00'::interval, _dist_hyper_X_X_chunk."time", '2017-01-01 06:00:00'::timestamp without time zone, '2017-01-01 18:00:00'::timestamp without time zone)) - -> HashAggregate - Output: (public.time_bucket_gapfill('03:00:00'::interval, _dist_hyper_X_X_chunk."time", '2017-01-01 06:00:00'::timestamp without time zone, '2017-01-01 18:00:00'::timestamp without time zone)), _dist_hyper_X_X_chunk.name, public.first(_dist_hyper_X_X_chunk.value, _dist_hyper_X_X_chunk."time"), avg(_dist_hyper_X_X_chunk.value) - Group Key: _dist_hyper_X_X_chunk.name, public.time_bucket_gapfill('03:00:00'::interval, _dist_hyper_X_X_chunk."time", '2017-01-01 06:00:00'::timestamp without time zone, '2017-01-01 18:00:00'::timestamp without time zone) - -> Result - Output: public.time_bucket_gapfill('03:00:00'::interval, _dist_hyper_X_X_chunk."time", '2017-01-01 06:00:00'::timestamp without time zone, '2017-01-01 18:00:00'::timestamp without time zone), _dist_hyper_X_X_chunk.name, _dist_hyper_X_X_chunk.value, _dist_hyper_X_X_chunk."time" - -> Seq Scan on _timescaledb_internal._dist_hyper_X_X_chunk - Output: _dist_hyper_X_X_chunk."time", _dist_hyper_X_X_chunk.name, _dist_hyper_X_X_chunk.value - - -> Custom Scan (DataNodeScan) - Output: (time_bucket_gapfill('@ 3 hours'::interval, test_gapfill_1."time", 'Sun Jan 01 06:00:00 2017'::timestamp without time zone, 'Sun Jan 01 18:00:00 2017'::timestamp without time zone)), test_gapfill_1.name, (first(test_gapfill_1.value, test_gapfill_1."time")), (avg(test_gapfill_1.value)) - Relations: Aggregate on (public.test_gapfill) - Data node: data_node_3 - Chunks: _dist_hyper_X_X_chunk, _dist_hyper_X_X_chunk, _dist_hyper_X_X_chunk - Remote SQL: SELECT public.time_bucket_gapfill('@ 3 hours'::interval, "time", 'Sun Jan 01 06:00:00 2017'::timestamp without time zone, 'Sun Jan 01 18:00:00 2017'::timestamp without time zone), name, public.first(value, "time"), avg(value) FROM public.test_gapfill WHERE _timescaledb_internal.chunks_in(public.test_gapfill.*, ARRAY[23, 24, 25]) GROUP BY 2, 1 - Remote EXPLAIN: - Custom Scan (GapFill) - Output: (public.time_bucket_gapfill('03:00:00'::interval, test_gapfill."time", '2017-01-01 06:00:00'::timestamp without time zone, '2017-01-01 18:00:00'::timestamp without time zone)), test_gapfill.name, (public.first(test_gapfill.value, test_gapfill."time")), (avg(test_gapfill.value)) - -> Sort - Output: (public.time_bucket_gapfill('03:00:00'::interval, _dist_hyper_X_X_chunk."time", '2017-01-01 06:00:00'::timestamp without time zone, '2017-01-01 18:00:00'::timestamp without time zone)), _dist_hyper_X_X_chunk.name, (public.first(_dist_hyper_X_X_chunk.value, _dist_hyper_X_X_chunk."time")), (avg(_dist_hyper_X_X_chunk.value)) - Sort Key: _dist_hyper_X_X_chunk.name, (public.time_bucket_gapfill('03:00:00'::interval, _dist_hyper_X_X_chunk."time", '2017-01-01 06:00:00'::timestamp without time zone, '2017-01-01 18:00:00'::timestamp without time zone)) - -> HashAggregate - Output: (public.time_bucket_gapfill('03:00:00'::interval, _dist_hyper_X_X_chunk."time", '2017-01-01 06:00:00'::timestamp without time zone, '2017-01-01 18:00:00'::timestamp without time zone)), _dist_hyper_X_X_chunk.name, public.first(_dist_hyper_X_X_chunk.value, _dist_hyper_X_X_chunk."time"), avg(_dist_hyper_X_X_chunk.value) - Group Key: _dist_hyper_X_X_chunk.name, public.time_bucket_gapfill('03:00:00'::interval, _dist_hyper_X_X_chunk."time", '2017-01-01 06:00:00'::timestamp without time zone, '2017-01-01 18:00:00'::timestamp without time zone) - -> Result - Output: public.time_bucket_gapfill('03:00:00'::interval, _dist_hyper_X_X_chunk."time", '2017-01-01 06:00:00'::timestamp without time zone, '2017-01-01 18:00:00'::timestamp without time zone), _dist_hyper_X_X_chunk.name, _dist_hyper_X_X_chunk.value, _dist_hyper_X_X_chunk."time" - -> Append - -> Seq Scan on _timescaledb_internal._dist_hyper_X_X_chunk - Output: _dist_hyper_X_X_chunk."time", _dist_hyper_X_X_chunk.name, _dist_hyper_X_X_chunk.value - -> Seq Scan on _timescaledb_internal._dist_hyper_X_X_chunk - Output: _dist_hyper_X_X_chunk."time", _dist_hyper_X_X_chunk.name, _dist_hyper_X_X_chunk.value - -> Seq Scan on _timescaledb_internal._dist_hyper_X_X_chunk - Output: _dist_hyper_X_X_chunk."time", _dist_hyper_X_X_chunk.name, _dist_hyper_X_X_chunk.value - -(48 rows) - --- Check for multiple gapfill calls -SELECT time_bucket_gapfill('3 hours', time, '2017-01-01 06:00', '2017-01-01 18:00'), - time_bucket_gapfill('6 hours', time, '2017-01-01 08:00', '2017-01-01 18:00'), - name, - first(value, time), - avg(value) -FROM test_gapfill -GROUP BY 2,1,3; -ERROR: multiple time_bucket_gapfill calls not allowed --- Cases where gapfill is not pushed down to data-nodes --- Space dimension is not in group by clause -EXPLAIN (VERBOSE, COSTS OFF) SELECT time_bucket_gapfill('3 hours', time, '2017-01-01 06:00', '2017-01-02 18:00'), - first(value, time), - avg(value) -FROM test_gapfill -GROUP BY 1; - QUERY PLAN ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- - Custom Scan (GapFill) - Output: (time_bucket_gapfill('@ 3 hours'::interval, "time", 'Sun Jan 01 06:00:00 2017'::timestamp without time zone, 'Mon Jan 02 18:00:00 2017'::timestamp without time zone)), (first(value, "time")), (avg(value)) - -> Finalize GroupAggregate - Output: (time_bucket_gapfill('@ 3 hours'::interval, test_gapfill."time", 'Sun Jan 01 06:00:00 2017'::timestamp without time zone, 'Mon Jan 02 18:00:00 2017'::timestamp without time zone)), first(test_gapfill.value, test_gapfill."time"), avg(test_gapfill.value) - Group Key: (time_bucket_gapfill('@ 3 hours'::interval, test_gapfill."time", 'Sun Jan 01 06:00:00 2017'::timestamp without time zone, 'Mon Jan 02 18:00:00 2017'::timestamp without time zone)) - -> Sort - Output: (time_bucket_gapfill('@ 3 hours'::interval, test_gapfill."time", 'Sun Jan 01 06:00:00 2017'::timestamp without time zone, 'Mon Jan 02 18:00:00 2017'::timestamp without time zone)), (PARTIAL first(test_gapfill.value, test_gapfill."time")), (PARTIAL avg(test_gapfill.value)) - Sort Key: (time_bucket_gapfill('@ 3 hours'::interval, test_gapfill."time", 'Sun Jan 01 06:00:00 2017'::timestamp without time zone, 'Mon Jan 02 18:00:00 2017'::timestamp without time zone)) - -> Append - -> Partial HashAggregate - Output: (time_bucket_gapfill('@ 3 hours'::interval, test_gapfill."time", 'Sun Jan 01 06:00:00 2017'::timestamp without time zone, 'Mon Jan 02 18:00:00 2017'::timestamp without time zone)), PARTIAL first(test_gapfill.value, test_gapfill."time"), PARTIAL avg(test_gapfill.value) - Group Key: time_bucket_gapfill('@ 3 hours'::interval, test_gapfill."time", 'Sun Jan 01 06:00:00 2017'::timestamp without time zone, 'Mon Jan 02 18:00:00 2017'::timestamp without time zone) - -> Custom Scan (DataNodeScan) on public.test_gapfill - Output: time_bucket_gapfill('@ 3 hours'::interval, test_gapfill."time", 'Sun Jan 01 06:00:00 2017'::timestamp without time zone, 'Mon Jan 02 18:00:00 2017'::timestamp without time zone), test_gapfill.value, test_gapfill."time" - Data node: data_node_1 - Chunks: _dist_hyper_X_X_chunk - Remote SQL: SELECT "time", value FROM public.test_gapfill WHERE _timescaledb_internal.chunks_in(public.test_gapfill.*, ARRAY[28]) - Remote EXPLAIN: - Seq Scan on _timescaledb_internal._dist_hyper_X_X_chunk - Output: _dist_hyper_X_X_chunk."time", _dist_hyper_X_X_chunk.value - - -> Partial HashAggregate - Output: (time_bucket_gapfill('@ 3 hours'::interval, test_gapfill_1."time", 'Sun Jan 01 06:00:00 2017'::timestamp without time zone, 'Mon Jan 02 18:00:00 2017'::timestamp without time zone)), PARTIAL first(test_gapfill_1.value, test_gapfill_1."time"), PARTIAL avg(test_gapfill_1.value) - Group Key: time_bucket_gapfill('@ 3 hours'::interval, test_gapfill_1."time", 'Sun Jan 01 06:00:00 2017'::timestamp without time zone, 'Mon Jan 02 18:00:00 2017'::timestamp without time zone) - -> Custom Scan (DataNodeScan) on public.test_gapfill test_gapfill_1 - Output: time_bucket_gapfill('@ 3 hours'::interval, test_gapfill_1."time", 'Sun Jan 01 06:00:00 2017'::timestamp without time zone, 'Mon Jan 02 18:00:00 2017'::timestamp without time zone), test_gapfill_1.value, test_gapfill_1."time" - Data node: data_node_3 - Chunks: _dist_hyper_X_X_chunk, _dist_hyper_X_X_chunk, _dist_hyper_X_X_chunk - Remote SQL: SELECT "time", value FROM public.test_gapfill WHERE _timescaledb_internal.chunks_in(public.test_gapfill.*, ARRAY[23, 24, 25]) - Remote EXPLAIN: - Append - -> Seq Scan on _timescaledb_internal._dist_hyper_X_X_chunk - Output: _dist_hyper_X_X_chunk."time", _dist_hyper_X_X_chunk.value - -> Seq Scan on _timescaledb_internal._dist_hyper_X_X_chunk - Output: _dist_hyper_X_X_chunk."time", _dist_hyper_X_X_chunk.value - -> Seq Scan on _timescaledb_internal._dist_hyper_X_X_chunk - Output: _dist_hyper_X_X_chunk."time", _dist_hyper_X_X_chunk.value - -(38 rows) - --- Window functions -EXPLAIN (VERBOSE, COSTS OFF) SELECT - time_bucket_gapfill('3 hours', time, '2017-01-01 06:00', '2017-01-01 18:00'), - lag(min(time)) OVER () -FROM test_gapfill -GROUP BY 1; - QUERY PLAN -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- - WindowAgg - Output: (time_bucket_gapfill('@ 3 hours'::interval, "time", 'Sun Jan 01 06:00:00 2017'::timestamp without time zone, 'Sun Jan 01 18:00:00 2017'::timestamp without time zone)), lag((min("time"))) OVER (?) - -> Custom Scan (GapFill) - Output: (time_bucket_gapfill('@ 3 hours'::interval, "time", 'Sun Jan 01 06:00:00 2017'::timestamp without time zone, 'Sun Jan 01 18:00:00 2017'::timestamp without time zone)), (min("time")) - -> Finalize GroupAggregate - Output: (time_bucket_gapfill('@ 3 hours'::interval, test_gapfill."time", 'Sun Jan 01 06:00:00 2017'::timestamp without time zone, 'Sun Jan 01 18:00:00 2017'::timestamp without time zone)), min(test_gapfill."time") - Group Key: (time_bucket_gapfill('@ 3 hours'::interval, test_gapfill."time", 'Sun Jan 01 06:00:00 2017'::timestamp without time zone, 'Sun Jan 01 18:00:00 2017'::timestamp without time zone)) - -> Sort - Output: (time_bucket_gapfill('@ 3 hours'::interval, test_gapfill."time", 'Sun Jan 01 06:00:00 2017'::timestamp without time zone, 'Sun Jan 01 18:00:00 2017'::timestamp without time zone)), (PARTIAL min(test_gapfill."time")) - Sort Key: (time_bucket_gapfill('@ 3 hours'::interval, test_gapfill."time", 'Sun Jan 01 06:00:00 2017'::timestamp without time zone, 'Sun Jan 01 18:00:00 2017'::timestamp without time zone)) - -> Append - -> Partial HashAggregate - Output: (time_bucket_gapfill('@ 3 hours'::interval, test_gapfill."time", 'Sun Jan 01 06:00:00 2017'::timestamp without time zone, 'Sun Jan 01 18:00:00 2017'::timestamp without time zone)), PARTIAL min(test_gapfill."time") - Group Key: time_bucket_gapfill('@ 3 hours'::interval, test_gapfill."time", 'Sun Jan 01 06:00:00 2017'::timestamp without time zone, 'Sun Jan 01 18:00:00 2017'::timestamp without time zone) - -> Custom Scan (DataNodeScan) on public.test_gapfill - Output: time_bucket_gapfill('@ 3 hours'::interval, test_gapfill."time", 'Sun Jan 01 06:00:00 2017'::timestamp without time zone, 'Sun Jan 01 18:00:00 2017'::timestamp without time zone), test_gapfill."time" - Data node: data_node_1 - Chunks: _dist_hyper_X_X_chunk - Remote SQL: SELECT "time" FROM public.test_gapfill WHERE _timescaledb_internal.chunks_in(public.test_gapfill.*, ARRAY[28]) - Remote EXPLAIN: - Seq Scan on _timescaledb_internal._dist_hyper_X_X_chunk - Output: _dist_hyper_X_X_chunk."time" - - -> Partial HashAggregate - Output: (time_bucket_gapfill('@ 3 hours'::interval, test_gapfill_1."time", 'Sun Jan 01 06:00:00 2017'::timestamp without time zone, 'Sun Jan 01 18:00:00 2017'::timestamp without time zone)), PARTIAL min(test_gapfill_1."time") - Group Key: time_bucket_gapfill('@ 3 hours'::interval, test_gapfill_1."time", 'Sun Jan 01 06:00:00 2017'::timestamp without time zone, 'Sun Jan 01 18:00:00 2017'::timestamp without time zone) - -> Custom Scan (DataNodeScan) on public.test_gapfill test_gapfill_1 - Output: time_bucket_gapfill('@ 3 hours'::interval, test_gapfill_1."time", 'Sun Jan 01 06:00:00 2017'::timestamp without time zone, 'Sun Jan 01 18:00:00 2017'::timestamp without time zone), test_gapfill_1."time" - Data node: data_node_3 - Chunks: _dist_hyper_X_X_chunk, _dist_hyper_X_X_chunk, _dist_hyper_X_X_chunk - Remote SQL: SELECT "time" FROM public.test_gapfill WHERE _timescaledb_internal.chunks_in(public.test_gapfill.*, ARRAY[23, 24, 25]) - Remote EXPLAIN: - Append - -> Seq Scan on _timescaledb_internal._dist_hyper_X_X_chunk - Output: _dist_hyper_X_X_chunk."time" - -> Seq Scan on _timescaledb_internal._dist_hyper_X_X_chunk - Output: _dist_hyper_X_X_chunk."time" - -> Seq Scan on _timescaledb_internal._dist_hyper_X_X_chunk - Output: _dist_hyper_X_X_chunk."time" - -(40 rows) - --- Data nodes are overlapping -EXPLAIN (VERBOSE, COSTS OFF) SELECT time_bucket_gapfill('3 hours', time, '2018-01-01 06:00', '2018-01-01 18:00'), - name, - first(value, time), - avg(value) -FROM test_gapfill_overlap -GROUP BY 1,2; - QUERY PLAN ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- - Custom Scan (GapFill) - Output: (time_bucket_gapfill('@ 3 hours'::interval, test_gapfill_overlap."time", 'Mon Jan 01 06:00:00 2018'::timestamp without time zone, 'Mon Jan 01 18:00:00 2018'::timestamp without time zone)), test_gapfill_overlap.name, (first(test_gapfill_overlap.value, test_gapfill_overlap."time")), (avg(test_gapfill_overlap.value)) - -> Sort - Output: (time_bucket_gapfill('@ 3 hours'::interval, test_gapfill_overlap_1."time", 'Mon Jan 01 06:00:00 2018'::timestamp without time zone, 'Mon Jan 01 18:00:00 2018'::timestamp without time zone)), test_gapfill_overlap_1.name, (first(test_gapfill_overlap_1.value, test_gapfill_overlap_1."time")), (avg(test_gapfill_overlap_1.value)) - Sort Key: test_gapfill_overlap_1.name, (time_bucket_gapfill('@ 3 hours'::interval, test_gapfill_overlap_1."time", 'Mon Jan 01 06:00:00 2018'::timestamp without time zone, 'Mon Jan 01 18:00:00 2018'::timestamp without time zone)) - -> HashAggregate - Output: (time_bucket_gapfill('@ 3 hours'::interval, test_gapfill_overlap_1."time", 'Mon Jan 01 06:00:00 2018'::timestamp without time zone, 'Mon Jan 01 18:00:00 2018'::timestamp without time zone)), test_gapfill_overlap_1.name, first(test_gapfill_overlap_1.value, test_gapfill_overlap_1."time"), avg(test_gapfill_overlap_1.value) - Group Key: (time_bucket_gapfill('@ 3 hours'::interval, test_gapfill_overlap_1."time", 'Mon Jan 01 06:00:00 2018'::timestamp without time zone, 'Mon Jan 01 18:00:00 2018'::timestamp without time zone)), test_gapfill_overlap_1.name - -> Append - -> Custom Scan (DataNodeScan) on public.test_gapfill_overlap test_gapfill_overlap_1 - Output: time_bucket_gapfill('@ 3 hours'::interval, test_gapfill_overlap_1."time", 'Mon Jan 01 06:00:00 2018'::timestamp without time zone, 'Mon Jan 01 18:00:00 2018'::timestamp without time zone), test_gapfill_overlap_1.name, test_gapfill_overlap_1.value, test_gapfill_overlap_1."time" - Data node: data_node_1 - Chunks: _dist_hyper_X_X_chunk, _dist_hyper_X_X_chunk, _dist_hyper_X_X_chunk, _dist_hyper_X_X_chunk - Remote SQL: SELECT "time", name, value FROM public.test_gapfill_overlap WHERE _timescaledb_internal.chunks_in(public.test_gapfill_overlap.*, ARRAY[29, 30, 31, 32]) - Remote EXPLAIN: - Append - -> Seq Scan on _timescaledb_internal._dist_hyper_X_X_chunk - Output: _dist_hyper_X_X_chunk."time", _dist_hyper_X_X_chunk.name, _dist_hyper_X_X_chunk.value - -> Seq Scan on _timescaledb_internal._dist_hyper_X_X_chunk - Output: _dist_hyper_X_X_chunk."time", _dist_hyper_X_X_chunk.name, _dist_hyper_X_X_chunk.value - -> Seq Scan on _timescaledb_internal._dist_hyper_X_X_chunk - Output: _dist_hyper_X_X_chunk."time", _dist_hyper_X_X_chunk.name, _dist_hyper_X_X_chunk.value - -> Seq Scan on _timescaledb_internal._dist_hyper_X_X_chunk - Output: _dist_hyper_X_X_chunk."time", _dist_hyper_X_X_chunk.name, _dist_hyper_X_X_chunk.value - - -> Custom Scan (DataNodeScan) on public.test_gapfill_overlap test_gapfill_overlap_2 - Output: time_bucket_gapfill('@ 3 hours'::interval, test_gapfill_overlap_2."time", 'Mon Jan 01 06:00:00 2018'::timestamp without time zone, 'Mon Jan 01 18:00:00 2018'::timestamp without time zone), test_gapfill_overlap_2.name, test_gapfill_overlap_2.value, test_gapfill_overlap_2."time" - Data node: data_node_2 - Chunks: _dist_hyper_X_X_chunk - Remote SQL: SELECT "time", name, value FROM public.test_gapfill_overlap WHERE _timescaledb_internal.chunks_in(public.test_gapfill_overlap.*, ARRAY[20]) - Remote EXPLAIN: - Seq Scan on _timescaledb_internal._dist_hyper_X_X_chunk - Output: _dist_hyper_X_X_chunk."time", _dist_hyper_X_X_chunk.name, _dist_hyper_X_X_chunk.value - - -> Custom Scan (DataNodeScan) on public.test_gapfill_overlap test_gapfill_overlap_3 - Output: time_bucket_gapfill('@ 3 hours'::interval, test_gapfill_overlap_3."time", 'Mon Jan 01 06:00:00 2018'::timestamp without time zone, 'Mon Jan 01 18:00:00 2018'::timestamp without time zone), test_gapfill_overlap_3.name, test_gapfill_overlap_3.value, test_gapfill_overlap_3."time" - Data node: data_node_3 - Chunks: _dist_hyper_X_X_chunk, _dist_hyper_X_X_chunk, _dist_hyper_X_X_chunk, _dist_hyper_X_X_chunk, _dist_hyper_X_X_chunk - Remote SQL: SELECT "time", name, value FROM public.test_gapfill_overlap WHERE _timescaledb_internal.chunks_in(public.test_gapfill_overlap.*, ARRAY[26, 27, 28, 29, 30]) - Remote EXPLAIN: - Append - -> Seq Scan on _timescaledb_internal._dist_hyper_X_X_chunk - Output: _dist_hyper_X_X_chunk."time", _dist_hyper_X_X_chunk.name, _dist_hyper_X_X_chunk.value - -> Seq Scan on _timescaledb_internal._dist_hyper_X_X_chunk - Output: _dist_hyper_X_X_chunk."time", _dist_hyper_X_X_chunk.name, _dist_hyper_X_X_chunk.value - -> Seq Scan on _timescaledb_internal._dist_hyper_X_X_chunk - Output: _dist_hyper_X_X_chunk."time", _dist_hyper_X_X_chunk.name, _dist_hyper_X_X_chunk.value - -> Seq Scan on _timescaledb_internal._dist_hyper_X_X_chunk - Output: _dist_hyper_X_X_chunk."time", _dist_hyper_X_X_chunk.name, _dist_hyper_X_X_chunk.value - -> Seq Scan on _timescaledb_internal._dist_hyper_X_X_chunk - Output: _dist_hyper_X_X_chunk."time", _dist_hyper_X_X_chunk.name, _dist_hyper_X_X_chunk.value - -(52 rows) - -SET timescaledb.enable_remote_explain = false; -DROP TABLE test_gapfill; -DROP TABLE test_gapfill_overlap; diff --git a/tsl/test/shared/expected/dist_remote_error.out b/tsl/test/shared/expected/dist_remote_error.out index 5cf40fd76..465f8943f 100644 --- a/tsl/test/shared/expected/dist_remote_error.out +++ b/tsl/test/shared/expected/dist_remote_error.out @@ -37,7 +37,7 @@ select 1 from metrics_dist1 where ts_debug_shippable_error_after_n_rows(10000000 Data node: data_node_1 Fetcher Type: Row by row Chunks: _dist_hyper_X_X_chunk, _dist_hyper_X_X_chunk, _dist_hyper_X_X_chunk - Remote SQL: SELECT NULL FROM public.metrics_dist1 WHERE _timescaledb_internal.chunks_in(public.metrics_dist1.*, ARRAY[34, 35, 36]) AND ((public.ts_debug_shippable_error_after_n_rows(10000000, device_id) <> 0)) + Remote SQL: SELECT NULL FROM public.metrics_dist1 WHERE _timescaledb_internal.chunks_in(public.metrics_dist1.*, ARRAY[28, 29, 30]) AND ((public.ts_debug_shippable_error_after_n_rows(10000000, device_id) <> 0)) (6 rows) explain (analyze, verbose, costs off, timing off, summary off) @@ -55,7 +55,7 @@ select 1 from metrics_dist1 where ts_debug_shippable_fatal_after_n_rows(10000000 Data node: data_node_1 Fetcher Type: Row by row Chunks: _dist_hyper_X_X_chunk, _dist_hyper_X_X_chunk, _dist_hyper_X_X_chunk - Remote SQL: SELECT NULL FROM public.metrics_dist1 WHERE _timescaledb_internal.chunks_in(public.metrics_dist1.*, ARRAY[34, 35, 36]) AND ((public.ts_debug_shippable_fatal_after_n_rows(10000000, device_id) <> 0)) + Remote SQL: SELECT NULL FROM public.metrics_dist1 WHERE _timescaledb_internal.chunks_in(public.metrics_dist1.*, ARRAY[28, 29, 30]) AND ((public.ts_debug_shippable_fatal_after_n_rows(10000000, device_id) <> 0)) (6 rows) set timescaledb.remote_data_fetcher = 'cursor'; @@ -74,7 +74,7 @@ select 1 from metrics_dist1 where ts_debug_shippable_error_after_n_rows(10000000 Data node: data_node_1 Fetcher Type: Cursor Chunks: _dist_hyper_X_X_chunk, _dist_hyper_X_X_chunk, _dist_hyper_X_X_chunk - Remote SQL: SELECT NULL FROM public.metrics_dist1 WHERE _timescaledb_internal.chunks_in(public.metrics_dist1.*, ARRAY[34, 35, 36]) AND ((public.ts_debug_shippable_error_after_n_rows(10000000, device_id) <> 0)) + Remote SQL: SELECT NULL FROM public.metrics_dist1 WHERE _timescaledb_internal.chunks_in(public.metrics_dist1.*, ARRAY[28, 29, 30]) AND ((public.ts_debug_shippable_error_after_n_rows(10000000, device_id) <> 0)) (6 rows) explain (analyze, verbose, costs off, timing off, summary off) @@ -92,6 +92,6 @@ select 1 from metrics_dist1 where ts_debug_shippable_fatal_after_n_rows(10000000 Data node: data_node_1 Fetcher Type: Cursor Chunks: _dist_hyper_X_X_chunk, _dist_hyper_X_X_chunk, _dist_hyper_X_X_chunk - Remote SQL: SELECT NULL FROM public.metrics_dist1 WHERE _timescaledb_internal.chunks_in(public.metrics_dist1.*, ARRAY[34, 35, 36]) AND ((public.ts_debug_shippable_fatal_after_n_rows(10000000, device_id) <> 0)) + Remote SQL: SELECT NULL FROM public.metrics_dist1 WHERE _timescaledb_internal.chunks_in(public.metrics_dist1.*, ARRAY[28, 29, 30]) AND ((public.ts_debug_shippable_fatal_after_n_rows(10000000, device_id) <> 0)) (6 rows) diff --git a/tsl/test/shared/sql/CMakeLists.txt b/tsl/test/shared/sql/CMakeLists.txt index f163c7104..1c8da084c 100644 --- a/tsl/test/shared/sql/CMakeLists.txt +++ b/tsl/test/shared/sql/CMakeLists.txt @@ -23,9 +23,8 @@ if(CMAKE_BUILD_TYPE MATCHES Debug) endif(CMAKE_BUILD_TYPE MATCHES Debug) set(TEST_TEMPLATES_SHARED - dist_gapfill_pushdown.sql.in gapfill.sql.in generated_columns.sql.in - ordered_append.sql.in ordered_append_join.sql.in - transparent_decompress_chunk.sql.in) + gapfill.sql.in generated_columns.sql.in ordered_append.sql.in + ordered_append_join.sql.in transparent_decompress_chunk.sql.in) # Regression tests that vary with PostgreSQL version. Generated test files are # put in the original source directory since all tests must be in the same diff --git a/tsl/test/shared/sql/dist_gapfill_pushdown.sql.in b/tsl/test/shared/sql/dist_gapfill_pushdown.sql.in deleted file mode 100644 index e48be8587..000000000 --- a/tsl/test/shared/sql/dist_gapfill_pushdown.sql.in +++ /dev/null @@ -1,62 +0,0 @@ --- This file and its contents are licensed under the Timescale License. --- Please see the included NOTICE for copyright information and --- LICENSE-TIMESCALE for a copy of the license. - -\set ON_ERROR_STOP 0 - -SET enable_partitionwise_aggregate = 'on'; -SET timescaledb.enable_remote_explain = true; - --- Cases where gapfill is pushed down to data-nodes -EXPLAIN (VERBOSE, COSTS OFF) SELECT time_bucket_gapfill('3 hours', time, '2017-01-01 06:00', '2017-01-01 18:00'), - name, - first(value, time), - avg(value) -FROM test_gapfill -GROUP BY 1,2; - -EXPLAIN (VERBOSE, COSTS OFF) SELECT time_bucket_gapfill('3 hours', time, '2017-01-01 06:00', '2017-01-01 18:00'), - name, - first(value, time), - avg(value) -FROM test_gapfill -GROUP BY 2,1; - --- Check for multiple gapfill calls -SELECT time_bucket_gapfill('3 hours', time, '2017-01-01 06:00', '2017-01-01 18:00'), - time_bucket_gapfill('6 hours', time, '2017-01-01 08:00', '2017-01-01 18:00'), - name, - first(value, time), - avg(value) -FROM test_gapfill -GROUP BY 2,1,3; - --- Cases where gapfill is not pushed down to data-nodes - --- Space dimension is not in group by clause -EXPLAIN (VERBOSE, COSTS OFF) SELECT time_bucket_gapfill('3 hours', time, '2017-01-01 06:00', '2017-01-02 18:00'), - first(value, time), - avg(value) -FROM test_gapfill -GROUP BY 1; - --- Window functions -EXPLAIN (VERBOSE, COSTS OFF) SELECT - time_bucket_gapfill('3 hours', time, '2017-01-01 06:00', '2017-01-01 18:00'), - lag(min(time)) OVER () -FROM test_gapfill -GROUP BY 1; - --- Data nodes are overlapping - -EXPLAIN (VERBOSE, COSTS OFF) SELECT time_bucket_gapfill('3 hours', time, '2018-01-01 06:00', '2018-01-01 18:00'), - name, - first(value, time), - avg(value) -FROM test_gapfill_overlap -GROUP BY 1,2; - -SET timescaledb.enable_remote_explain = false; - -DROP TABLE test_gapfill; -DROP TABLE test_gapfill_overlap; diff --git a/tsl/test/shared/sql/include/dist_gapfill_query.sql b/tsl/test/shared/sql/include/dist_gapfill_query.sql index f64d08f5a..099d735c5 100644 --- a/tsl/test/shared/sql/include/dist_gapfill_query.sql +++ b/tsl/test/shared/sql/include/dist_gapfill_query.sql @@ -13,16 +13,14 @@ SELECT time_bucket_gapfill('3 hours', time, '2017-01-01 06:00', '2017-01-01 18:0 first(value, time), avg(value) FROM :CONDITIONS -GROUP BY 1,2 -ORDER BY 2,1; +GROUP BY 1,2; SELECT time_bucket_gapfill('3 hours', time, '2017-01-01 06:00', '2017-01-01 18:00'), device, first(value, time), avg(value) FROM :CONDITIONS -GROUP BY 2,1 -ORDER BY 2,1; +GROUP BY 2,1; SELECT time_bucket_gapfill('3 hours', time, '2017-01-01 06:00', '2017-01-01 18:00'), diff --git a/tsl/test/shared/sql/include/shared_setup.sql b/tsl/test/shared/sql/include/shared_setup.sql index 8e42618c3..ecc36ceef 100644 --- a/tsl/test/shared/sql/include/shared_setup.sql +++ b/tsl/test/shared/sql/include/shared_setup.sql @@ -156,8 +156,8 @@ INSERT INTO metrics_tstz VALUES ; CREATE TABLE conditions( - time timestamptz NOT NULL, - device int, + time timestamptz NOT NULL, + device int, value float ); SELECT * FROM create_hypertable('conditions', 'time'); @@ -172,8 +172,8 @@ INSERT INTO conditions VALUES ('2018-07-01 08:01', 29, 64); CREATE TABLE conditions_dist( - time timestamptz NOT NULL, - device int, + time timestamptz NOT NULL, + device int, value float ); SELECT * FROM create_distributed_hypertable('conditions_dist', 'time', 'device', 3); @@ -202,8 +202,8 @@ INSERT INTO metrics_int_dist VALUES (100,1,2,-100.0); CREATE TABLE conditions_dist1( - time timestamptz NOT NULL, - device int, + time timestamptz NOT NULL, + device int, value float ); SELECT * FROM create_distributed_hypertable('conditions_dist1', 'time', 'device', 1, @@ -244,7 +244,7 @@ SELECT create_distributed_hypertable('dist_chunk_copy', 'time', 'device', replic ALTER TABLE dist_chunk_copy SET (timescaledb.compress); SELECT setseed(0); -INSERT INTO dist_chunk_copy +INSERT INTO dist_chunk_copy SELECT t, ceil(_timescaledb_internal.get_partition_hash(t)::int % 5), random() * 20 FROM generate_series('2020-01-01'::timestamp, '2020-01-25'::timestamp, '1d') t; @@ -274,44 +274,9 @@ create table distinct_on_distributed(ts timestamp, id int, val numeric); select create_distributed_hypertable('distinct_on_distributed', 'ts'); insert into distinct_on_distributed select * from distinct_on_hypertable; --- Table with non-overlapping data across data-nodes to test gapfill pushdown to data nodes -CREATE TABLE test_gapfill(time timestamp, name text, value numeric); - -SELECT table_name from create_distributed_hypertable('test_gapfill', 'time', partitioning_column => 'name'); - -INSERT INTO test_gapfill VALUES - ('2018-01-01 06:01', 'one', 1.2), - ('2018-01-02 09:11', 'two', 4.3), - ('2018-01-03 08:01', 'three', 7.3), - ('2018-01-04 08:01', 'one', 0.23), - ('2018-07-05 08:01', 'five', 0.0), - ('2018-07-06 06:01', 'forty', 3.1), - ('2018-07-07 09:11', 'eleven', 10303.12), - ('2018-07-08 08:01', 'ten', 64); - --- Make table with data nodes overlapping - -CREATE TABLE test_gapfill_overlap(time timestamp, name text, value numeric); - -SELECT table_name from create_distributed_hypertable('test_gapfill_overlap', 'time', partitioning_column => 'name'); - -INSERT INTO test_gapfill_overlap SELECT * FROM test_gapfill; - -SELECT set_number_partitions('test_gapfill_overlap', 4); - -INSERT INTO test_gapfill_overlap VALUES -('2020-01-01 06:01', 'eleven', 1.2), -('2020-01-02 09:11', 'twenty-two', 4.3), -('2020-01-03 08:01', 'three', 7.3), -('2020-01-04 08:01', 'one', 0.23), -('2020-07-05 08:01', 'five', 0.0), -('2020-07-06 06:01', 'forty-six', 3.1), -('2020-07-07 09:11', 'eleven', 10303.12), -('2020-07-08 08:01', 'ten', 64); - -- Distributed table with custom type that has no binary output CREATE TABLE disttable_with_ct(time timestamptz, txn_id rxid, val float, info text); -SELECT * FROM create_hypertable('disttable_with_ct', 'time', replication_factor => 2); +SELECT * FROM create_hypertable('disttable_with_ct', 'time', replication_factor => 1); -- Insert data with custom type INSERT INTO disttable_with_ct VALUES