mirror of
https://github.com/timescale/timescaledb.git
synced 2025-05-18 03:23:37 +08:00
Handle drops on continuous agg views and tables
Previously we used postgres dependency tracking to ensure consistent deletes between various continuous agg postgres objects (views and tables). This does not work with dump/restore and thus this PR removes that dependency tracking in favor of handling these deps ourselves in various drop hooks. This PR also adds logic for deleting rows in the continuous_agg metadata table when the view is dropped. It does not yet handle deleting associated threshold metadata, that's left for a future PR. Most of this logic is in the apache-licensed code and not in the TSL since we want people who downgraded from TSL to apache to still be able to drop continuous views.
This commit is contained in:
parent
bf44985ac3
commit
7a4191bd84
@ -4,6 +4,7 @@ set(SOURCES
|
|||||||
cache.c
|
cache.c
|
||||||
cache_invalidate.c
|
cache_invalidate.c
|
||||||
catalog.c
|
catalog.c
|
||||||
|
continuous_agg.c
|
||||||
chunk.c
|
chunk.c
|
||||||
chunk_adaptive.c
|
chunk_adaptive.c
|
||||||
chunk_constraint.c
|
chunk_constraint.c
|
||||||
|
@ -189,6 +189,12 @@ static const TableIndexDef catalog_table_index_definitions[_MAX_CATALOG_TABLES]
|
|||||||
[BGW_POLICY_CHUNK_STATS_JOB_ID_CHUNK_ID_IDX] = "bgw_policy_chunk_stats_job_id_chunk_id_key",
|
[BGW_POLICY_CHUNK_STATS_JOB_ID_CHUNK_ID_IDX] = "bgw_policy_chunk_stats_job_id_chunk_id_key",
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
[CONTINUOUS_AGG] = {
|
||||||
|
.length = _MAX_CONTINUOUS_AGG_INDEX,
|
||||||
|
.names = (char *[]) {
|
||||||
|
[CONTINUOUS_AGG_PKEY] = "continuous_agg_pkey"
|
||||||
|
},
|
||||||
|
},
|
||||||
[CONTINUOUS_AGGS_COMPLETED_THRESHOLD] = {
|
[CONTINUOUS_AGGS_COMPLETED_THRESHOLD] = {
|
||||||
.length = _MAX_CONTINUOUS_AGGS_COMPLETED_THRESHOLD_INDEX,
|
.length = _MAX_CONTINUOUS_AGGS_COMPLETED_THRESHOLD_INDEX,
|
||||||
.names = (char *[]) {
|
.names = (char *[]) {
|
||||||
|
208
src/continuous_agg.c
Normal file
208
src/continuous_agg.c
Normal file
@ -0,0 +1,208 @@
|
|||||||
|
/*
|
||||||
|
* This file and its contents are licensed under the Timescale License.
|
||||||
|
* Please see the included NOTICE for copyright information and
|
||||||
|
* LICENSE-APACHE for a copy of the license.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* This file handles commands on continuous aggs that should be allowed in
|
||||||
|
* apache only mode. Right now this consists mostly of drop commands
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <postgres.h>
|
||||||
|
#include <fmgr.h>
|
||||||
|
#include <access/htup_details.h>
|
||||||
|
#include <utils/builtins.h>
|
||||||
|
#include <catalog/dependency.h>
|
||||||
|
#include <catalog/namespace.h>
|
||||||
|
#include <utils/lsyscache.h>
|
||||||
|
|
||||||
|
#include "scan_iterator.h"
|
||||||
|
#include "continuous_agg.h"
|
||||||
|
#include "hypertable.h"
|
||||||
|
#include "compat.h"
|
||||||
|
|
||||||
|
#if !PG96
|
||||||
|
#include <utils/fmgrprotos.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
static void
|
||||||
|
init_scan_by_mat_hypertable_id(ScanIterator *iterator, const int32 mat_hypertable_id)
|
||||||
|
{
|
||||||
|
iterator->ctx.index = catalog_get_index(ts_catalog_get(), CONTINUOUS_AGG, CONTINUOUS_AGG_PKEY);
|
||||||
|
|
||||||
|
ts_scan_iterator_scan_key_init(iterator,
|
||||||
|
Anum_continuous_agg_pkey_mat_hypertable_id,
|
||||||
|
BTEqualStrategyNumber,
|
||||||
|
F_INT4EQ,
|
||||||
|
Int32GetDatum(mat_hypertable_id));
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
continuous_agg_init(ContinuousAgg *cagg, FormData_continuous_agg *fd)
|
||||||
|
{
|
||||||
|
memcpy(&cagg->data, fd, sizeof(cagg->data));
|
||||||
|
}
|
||||||
|
|
||||||
|
ContinuousAgg *
|
||||||
|
ts_continuous_agg_find_by_view_name(const char *schema, const char *name)
|
||||||
|
{
|
||||||
|
ScanIterator iterator =
|
||||||
|
ts_scan_iterator_create(CONTINUOUS_AGG, AccessShareLock, CurrentMemoryContext);
|
||||||
|
ContinuousAgg *ca = NULL;
|
||||||
|
int count = 0;
|
||||||
|
|
||||||
|
ts_scanner_foreach(&iterator)
|
||||||
|
{
|
||||||
|
FormData_continuous_agg *data =
|
||||||
|
(FormData_continuous_agg *) GETSTRUCT(ts_scan_iterator_tuple(&iterator));
|
||||||
|
if (ts_continuous_agg_is_user_view(data, schema, name) ||
|
||||||
|
ts_continuous_agg_is_partial_view(data, schema, name))
|
||||||
|
{
|
||||||
|
ca = palloc0(sizeof(*ca));
|
||||||
|
continuous_agg_init(ca, data);
|
||||||
|
count++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Assert(count <= 1);
|
||||||
|
return ca;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Drops continuous aggs and all related objects.
|
||||||
|
*
|
||||||
|
* These objects are: the user view itself, the catalog entry, the partial view,
|
||||||
|
* the materialization hypertable.
|
||||||
|
*
|
||||||
|
* drop_user_view indicates whether to drop the user view.
|
||||||
|
* (should be false if called as part of the drop-user-view callback)
|
||||||
|
*/
|
||||||
|
static void
|
||||||
|
drop_continuous_agg(ContinuousAgg *agg, bool drop_user_view)
|
||||||
|
{
|
||||||
|
ScanIterator iterator =
|
||||||
|
ts_scan_iterator_create(CONTINUOUS_AGG, RowExclusiveLock, CurrentMemoryContext);
|
||||||
|
ObjectAddress user_view, partial_view;
|
||||||
|
Hypertable *mat_hypertable;
|
||||||
|
int count = 0;
|
||||||
|
|
||||||
|
/* Delete view itself */
|
||||||
|
if (drop_user_view)
|
||||||
|
{
|
||||||
|
user_view = (ObjectAddress){
|
||||||
|
.classId = RelationRelationId,
|
||||||
|
.objectId =
|
||||||
|
get_relname_relid(NameStr(agg->data.user_view_name),
|
||||||
|
get_namespace_oid(NameStr(agg->data.user_view_schema), false)),
|
||||||
|
};
|
||||||
|
performDeletion(&user_view, DROP_RESTRICT, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Delete catalog entry. */
|
||||||
|
init_scan_by_mat_hypertable_id(&iterator, agg->data.mat_hypertable_id);
|
||||||
|
ts_scanner_foreach(&iterator)
|
||||||
|
{
|
||||||
|
TupleInfo *ti = ts_scan_iterator_tuple_info(&iterator);
|
||||||
|
ts_catalog_delete(ti->scanrel, ti->tuple);
|
||||||
|
count++;
|
||||||
|
}
|
||||||
|
Assert(count == 1);
|
||||||
|
|
||||||
|
/* Drop partial view, materialized table */
|
||||||
|
partial_view = (ObjectAddress){
|
||||||
|
.classId = RelationRelationId,
|
||||||
|
.objectId =
|
||||||
|
get_relname_relid(NameStr(agg->data.partial_view_name),
|
||||||
|
get_namespace_oid(NameStr(agg->data.partial_view_schema), false)),
|
||||||
|
};
|
||||||
|
|
||||||
|
/* The partial view may already be dropped by PG's dependency system (e.g. the raw table was
|
||||||
|
* dropped) */
|
||||||
|
if (OidIsValid(partial_view.objectId))
|
||||||
|
performDeletion(&partial_view, DROP_RESTRICT, 0);
|
||||||
|
|
||||||
|
mat_hypertable = ts_hypertable_get_by_id(agg->data.mat_hypertable_id);
|
||||||
|
|
||||||
|
/* Drop materialized hypertable */
|
||||||
|
ts_hypertable_drop(mat_hypertable);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* This is a called when a hypertable gets dropped.
|
||||||
|
*
|
||||||
|
* If the hypertable is a raw hypertable for a continuous agg,
|
||||||
|
* drop the continuous agg.
|
||||||
|
*
|
||||||
|
* If the hypertable is a materialization hypertable, error out
|
||||||
|
* and force the user to drop the continuous agg instead.
|
||||||
|
*/
|
||||||
|
void
|
||||||
|
ts_continuous_agg_drop_hypertable_callback(int32 hypertable_id)
|
||||||
|
{
|
||||||
|
ScanIterator iterator =
|
||||||
|
ts_scan_iterator_create(CONTINUOUS_AGG, AccessShareLock, CurrentMemoryContext);
|
||||||
|
ContinuousAgg ca;
|
||||||
|
|
||||||
|
ts_scanner_foreach(&iterator)
|
||||||
|
{
|
||||||
|
FormData_continuous_agg *data =
|
||||||
|
(FormData_continuous_agg *) GETSTRUCT(ts_scan_iterator_tuple(&iterator));
|
||||||
|
if (data->raw_hypertable_id == hypertable_id)
|
||||||
|
{
|
||||||
|
continuous_agg_init(&ca, data);
|
||||||
|
drop_continuous_agg(&ca, true);
|
||||||
|
}
|
||||||
|
if (data->mat_hypertable_id == hypertable_id)
|
||||||
|
ereport(ERROR,
|
||||||
|
(errcode(ERRCODE_DEPENDENT_OBJECTS_STILL_EXIST),
|
||||||
|
errmsg("cannot drop the materialized table because it is required by a "
|
||||||
|
"continuous aggregate")));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Block dropping the partial view if the continuous aggregate still exists */
|
||||||
|
static void
|
||||||
|
drop_partial_view(ContinuousAgg *agg)
|
||||||
|
{
|
||||||
|
ScanIterator iterator =
|
||||||
|
ts_scan_iterator_create(CONTINUOUS_AGG, AccessShareLock, CurrentMemoryContext);
|
||||||
|
int count = 0;
|
||||||
|
init_scan_by_mat_hypertable_id(&iterator, agg->data.mat_hypertable_id);
|
||||||
|
ts_scanner_foreach(&iterator)
|
||||||
|
{
|
||||||
|
TupleInfo *ti = ts_scan_iterator_tuple_info(&iterator);
|
||||||
|
ts_catalog_delete(ti->scanrel, ti->tuple);
|
||||||
|
count++;
|
||||||
|
}
|
||||||
|
if (count > 0)
|
||||||
|
ereport(ERROR,
|
||||||
|
(errcode(ERRCODE_DEPENDENT_OBJECTS_STILL_EXIST),
|
||||||
|
errmsg("cannot drop the partial view because it is required by a continuous "
|
||||||
|
"aggregate")));
|
||||||
|
}
|
||||||
|
|
||||||
|
/* This gets called when a view gets dropped. */
|
||||||
|
void
|
||||||
|
ts_continuous_agg_drop_view_callback(ContinuousAgg *ca, const char *schema, const char *name)
|
||||||
|
{
|
||||||
|
if (ts_continuous_agg_is_user_view(&ca->data, schema, name))
|
||||||
|
drop_continuous_agg(ca, false /* The user view has already been dropped */);
|
||||||
|
else if (ts_continuous_agg_is_partial_view(&ca->data, schema, name))
|
||||||
|
drop_partial_view(ca);
|
||||||
|
else
|
||||||
|
elog(ERROR, "unknown continuous aggregate view type");
|
||||||
|
}
|
||||||
|
|
||||||
|
bool
|
||||||
|
ts_continuous_agg_is_user_view(FormData_continuous_agg *data, const char *schema, const char *name)
|
||||||
|
{
|
||||||
|
return (namestrcmp(&data->user_view_schema, schema) == 0) &&
|
||||||
|
(namestrcmp(&data->user_view_name, name) == 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool
|
||||||
|
ts_continuous_agg_is_partial_view(FormData_continuous_agg *data, const char *schema,
|
||||||
|
const char *name)
|
||||||
|
{
|
||||||
|
return (namestrcmp(&data->partial_view_schema, schema) == 0) &&
|
||||||
|
(namestrcmp(&data->partial_view_name, name) == 0);
|
||||||
|
}
|
28
src/continuous_agg.h
Normal file
28
src/continuous_agg.h
Normal file
@ -0,0 +1,28 @@
|
|||||||
|
/*
|
||||||
|
* This file and its contents are licensed under the Timescale License.
|
||||||
|
* Please see the included NOTICE for copyright information and
|
||||||
|
* LICENSE-APACHE for a copy of the license.
|
||||||
|
*/
|
||||||
|
#ifndef TIMESCALEDB_TSL_CONTINUOUS_AGGS_CONTIGUOUS_AGG_H
|
||||||
|
#define TIMESCALEDB_TSL_CONTINUOUS_AGGS_CONTIGUOUS_AGG_H
|
||||||
|
#include <postgres.h>
|
||||||
|
|
||||||
|
#include <catalog.h>
|
||||||
|
|
||||||
|
typedef struct ContinuousAgg
|
||||||
|
{
|
||||||
|
FormData_continuous_agg data;
|
||||||
|
} ContinuousAgg;
|
||||||
|
|
||||||
|
extern ContinuousAgg *ts_continuous_agg_find_by_view_name(const char *schema, const char *name);
|
||||||
|
extern void ts_continuous_agg_drop_view_callback(ContinuousAgg *ca, const char *schema,
|
||||||
|
const char *name);
|
||||||
|
|
||||||
|
extern void ts_continuous_agg_drop_hypertable_callback(int32 hypertable_id);
|
||||||
|
|
||||||
|
extern bool ts_continuous_agg_is_user_view(FormData_continuous_agg *data, const char *schema,
|
||||||
|
const char *name);
|
||||||
|
extern bool ts_continuous_agg_is_partial_view(FormData_continuous_agg *data, const char *schema,
|
||||||
|
const char *name);
|
||||||
|
|
||||||
|
#endif /* TIMESCALEDB_TSL_CONTINUOUS_AGGS_CONTIGUOUS_AGG_H */
|
@ -142,6 +142,19 @@ make_event_trigger_drop_table(char *table_name, char *schema)
|
|||||||
return obj;
|
return obj;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static EventTriggerDropView *
|
||||||
|
make_event_trigger_drop_view(char *view_name, char *schema)
|
||||||
|
{
|
||||||
|
EventTriggerDropView *obj = palloc(sizeof(*obj));
|
||||||
|
|
||||||
|
*obj = (EventTriggerDropView){
|
||||||
|
.obj = { .type = EVENT_TRIGGER_DROP_VIEW },
|
||||||
|
.view_name = view_name,
|
||||||
|
.schema = schema,
|
||||||
|
};
|
||||||
|
return obj;
|
||||||
|
}
|
||||||
|
|
||||||
static EventTriggerDropSchema *
|
static EventTriggerDropSchema *
|
||||||
make_event_trigger_drop_schema(char *schema)
|
make_event_trigger_drop_schema(char *schema)
|
||||||
{
|
{
|
||||||
@ -233,6 +246,14 @@ ts_event_trigger_dropped_objects(void)
|
|||||||
make_event_trigger_drop_table(lsecond(addrnames),
|
make_event_trigger_drop_table(lsecond(addrnames),
|
||||||
linitial(addrnames)));
|
linitial(addrnames)));
|
||||||
}
|
}
|
||||||
|
else if (strcmp(objtype, "view") == 0)
|
||||||
|
{
|
||||||
|
List *addrnames = extract_addrnames(DatumGetArrayTypeP(values[10]));
|
||||||
|
|
||||||
|
objects = lappend(objects,
|
||||||
|
make_event_trigger_drop_view(lsecond(addrnames),
|
||||||
|
linitial(addrnames)));
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
case NamespaceRelationId:
|
case NamespaceRelationId:
|
||||||
{
|
{
|
||||||
|
@ -14,6 +14,7 @@ typedef enum EventTriggerDropType
|
|||||||
EVENT_TRIGGER_DROP_TABLE_CONSTRAINT,
|
EVENT_TRIGGER_DROP_TABLE_CONSTRAINT,
|
||||||
EVENT_TRIGGER_DROP_INDEX,
|
EVENT_TRIGGER_DROP_INDEX,
|
||||||
EVENT_TRIGGER_DROP_TABLE,
|
EVENT_TRIGGER_DROP_TABLE,
|
||||||
|
EVENT_TRIGGER_DROP_VIEW,
|
||||||
EVENT_TRIGGER_DROP_SCHEMA,
|
EVENT_TRIGGER_DROP_SCHEMA,
|
||||||
EVENT_TRIGGER_DROP_TRIGGER
|
EVENT_TRIGGER_DROP_TRIGGER
|
||||||
} EventTriggerDropType;
|
} EventTriggerDropType;
|
||||||
@ -45,6 +46,13 @@ typedef struct EventTriggerDropTable
|
|||||||
char *schema;
|
char *schema;
|
||||||
} EventTriggerDropTable;
|
} EventTriggerDropTable;
|
||||||
|
|
||||||
|
typedef struct EventTriggerDropView
|
||||||
|
{
|
||||||
|
EventTriggerDropObject obj;
|
||||||
|
char *view_name;
|
||||||
|
char *schema;
|
||||||
|
} EventTriggerDropView;
|
||||||
|
|
||||||
typedef struct EventTriggerDropSchema
|
typedef struct EventTriggerDropSchema
|
||||||
{
|
{
|
||||||
EventTriggerDropObject obj;
|
EventTriggerDropObject obj;
|
||||||
|
@ -57,6 +57,7 @@
|
|||||||
#include "funcapi.h"
|
#include "funcapi.h"
|
||||||
#include "utils.h"
|
#include "utils.h"
|
||||||
#include "bgw_policy/policy.h"
|
#include "bgw_policy/policy.h"
|
||||||
|
#include "continuous_agg.h"
|
||||||
|
|
||||||
Oid
|
Oid
|
||||||
ts_rel_get_owner(Oid relid)
|
ts_rel_get_owner(Oid relid)
|
||||||
@ -411,6 +412,9 @@ hypertable_tuple_delete(TupleInfo *ti, void *data)
|
|||||||
/* Also remove any policy argument / job that uses this hypertable */
|
/* Also remove any policy argument / job that uses this hypertable */
|
||||||
ts_bgw_policy_delete_by_hypertable_id(hypertable_id);
|
ts_bgw_policy_delete_by_hypertable_id(hypertable_id);
|
||||||
|
|
||||||
|
/* Remove any dependent continuous aggs */
|
||||||
|
ts_continuous_agg_drop_hypertable_callback(hypertable_id);
|
||||||
|
|
||||||
ts_catalog_database_info_become_owner(ts_catalog_database_info_get(), &sec_ctx);
|
ts_catalog_database_info_become_owner(ts_catalog_database_info_get(), &sec_ctx);
|
||||||
ts_catalog_delete(ti->scanrel, ti->tuple);
|
ts_catalog_delete(ti->scanrel, ti->tuple);
|
||||||
ts_catalog_restore_user(&sec_ctx);
|
ts_catalog_restore_user(&sec_ctx);
|
||||||
@ -446,6 +450,20 @@ ts_hypertable_delete_by_name(const char *schema_name, const char *table_name)
|
|||||||
CurrentMemoryContext);
|
CurrentMemoryContext);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
ts_hypertable_drop(Hypertable *hypertable)
|
||||||
|
{
|
||||||
|
ObjectAddress hypertable_addr = (ObjectAddress){
|
||||||
|
.classId = RelationRelationId,
|
||||||
|
.objectId = hypertable->main_table_relid,
|
||||||
|
};
|
||||||
|
|
||||||
|
/* Drop the postgres table */
|
||||||
|
performDeletion(&hypertable_addr, DROP_CASCADE, 0);
|
||||||
|
/* Clean up catalog */
|
||||||
|
ts_hypertable_delete_by_name(hypertable->fd.schema_name.data, hypertable->fd.table_name.data);
|
||||||
|
}
|
||||||
|
|
||||||
static ScanTupleResult
|
static ScanTupleResult
|
||||||
reset_associated_tuple_found(TupleInfo *ti, void *data)
|
reset_associated_tuple_found(TupleInfo *ti, void *data)
|
||||||
{
|
{
|
||||||
|
@ -76,6 +76,7 @@ extern int ts_hypertable_set_name(Hypertable *ht, const char *newname);
|
|||||||
extern int ts_hypertable_set_schema(Hypertable *ht, const char *newname);
|
extern int ts_hypertable_set_schema(Hypertable *ht, const char *newname);
|
||||||
extern int ts_hypertable_set_num_dimensions(Hypertable *ht, int16 num_dimensions);
|
extern int ts_hypertable_set_num_dimensions(Hypertable *ht, int16 num_dimensions);
|
||||||
extern int ts_hypertable_delete_by_name(const char *schema_name, const char *table_name);
|
extern int ts_hypertable_delete_by_name(const char *schema_name, const char *table_name);
|
||||||
|
extern void ts_hypertable_drop(Hypertable *hypertable);
|
||||||
extern int ts_hypertable_reset_associated_schema_name(const char *associated_schema);
|
extern int ts_hypertable_reset_associated_schema_name(const char *associated_schema);
|
||||||
extern TSDLLEXPORT Oid ts_hypertable_id_to_relid(int32 hypertable_id);
|
extern TSDLLEXPORT Oid ts_hypertable_id_to_relid(int32 hypertable_id);
|
||||||
extern TSDLLEXPORT int32 ts_hypertable_relid_to_id(Oid relid);
|
extern TSDLLEXPORT int32 ts_hypertable_relid_to_id(Oid relid);
|
||||||
|
@ -61,6 +61,7 @@
|
|||||||
#include "utils.h"
|
#include "utils.h"
|
||||||
#include "with_clause_parser.h"
|
#include "with_clause_parser.h"
|
||||||
#include "cross_module_fn.h"
|
#include "cross_module_fn.h"
|
||||||
|
#include "continuous_agg.h"
|
||||||
|
|
||||||
#include "cross_module_fn.h"
|
#include "cross_module_fn.h"
|
||||||
|
|
||||||
@ -770,6 +771,45 @@ process_grant_and_revoke_role(ProcessUtilityArgs *args)
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Force the use of CASCADE to drop continuous aggregates */
|
||||||
|
static void
|
||||||
|
block_dropping_continuous_aggregates_without_cascade(ProcessUtilityArgs *args, DropStmt *stmt)
|
||||||
|
{
|
||||||
|
ListCell *lc;
|
||||||
|
|
||||||
|
if (stmt->behavior == DROP_CASCADE)
|
||||||
|
return;
|
||||||
|
|
||||||
|
foreach (lc, stmt->objects)
|
||||||
|
{
|
||||||
|
List *object = lfirst(lc);
|
||||||
|
RangeVar *relation = makeRangeVarFromNameList(object);
|
||||||
|
Oid relid;
|
||||||
|
char *schema;
|
||||||
|
char *name;
|
||||||
|
ContinuousAgg *cagg;
|
||||||
|
|
||||||
|
if (NULL == relation)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
relid = RangeVarGetRelid(relation, NoLock, true);
|
||||||
|
if (!OidIsValid(relid))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
schema = get_namespace_name(get_rel_namespace(relid));
|
||||||
|
name = get_rel_name(relid);
|
||||||
|
|
||||||
|
cagg = ts_continuous_agg_find_by_view_name(schema, name);
|
||||||
|
if (cagg == NULL)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
if (ts_continuous_agg_is_user_view(&cagg->data, schema, name))
|
||||||
|
ereport(ERROR,
|
||||||
|
(errcode(ERRCODE_DEPENDENT_OBJECTS_STILL_EXIST),
|
||||||
|
errmsg("dropping a continous aggregate requires using CASCADE")));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
process_drop(ProcessUtilityArgs *args)
|
process_drop(ProcessUtilityArgs *args)
|
||||||
{
|
{
|
||||||
@ -783,6 +823,9 @@ process_drop(ProcessUtilityArgs *args)
|
|||||||
case OBJECT_INDEX:
|
case OBJECT_INDEX:
|
||||||
process_drop_hypertable_index(args, stmt);
|
process_drop_hypertable_index(args, stmt);
|
||||||
break;
|
break;
|
||||||
|
case OBJECT_VIEW:
|
||||||
|
block_dropping_continuous_aggregates_without_cascade(args, stmt);
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@ -2769,6 +2812,16 @@ process_drop_trigger(EventTriggerDropObject *obj)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
process_drop_view(EventTriggerDropView *dropped_view)
|
||||||
|
{
|
||||||
|
ContinuousAgg *ca;
|
||||||
|
|
||||||
|
ca = ts_continuous_agg_find_by_view_name(dropped_view->schema, dropped_view->view_name);
|
||||||
|
if (ca != NULL)
|
||||||
|
ts_continuous_agg_drop_view_callback(ca, dropped_view->schema, dropped_view->view_name);
|
||||||
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
process_ddl_sql_drop(EventTriggerDropObject *obj)
|
process_ddl_sql_drop(EventTriggerDropObject *obj)
|
||||||
{
|
{
|
||||||
@ -2789,6 +2842,9 @@ process_ddl_sql_drop(EventTriggerDropObject *obj)
|
|||||||
case EVENT_TRIGGER_DROP_TRIGGER:
|
case EVENT_TRIGGER_DROP_TRIGGER:
|
||||||
process_drop_trigger(obj);
|
process_drop_trigger(obj);
|
||||||
break;
|
break;
|
||||||
|
case EVENT_TRIGGER_DROP_VIEW:
|
||||||
|
process_drop_view((EventTriggerDropView *) obj);
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -49,11 +49,11 @@ ts_scan_iterator_tupledesc(ScanIterator *iterator)
|
|||||||
return iterator->tinfo->desc;
|
return iterator->tinfo->desc;
|
||||||
}
|
}
|
||||||
|
|
||||||
void ts_scan_iterator_close(ScanIterator *iterator);
|
void TSDLLEXPORT ts_scan_iterator_close(ScanIterator *iterator);
|
||||||
|
|
||||||
void ts_scan_iterator_scan_key_init(ScanIterator *iterator, AttrNumber attributeNumber,
|
void TSDLLEXPORT ts_scan_iterator_scan_key_init(ScanIterator *iterator, AttrNumber attributeNumber,
|
||||||
StrategyNumber strategy, RegProcedure procedure,
|
StrategyNumber strategy, RegProcedure procedure,
|
||||||
Datum argument);
|
Datum argument);
|
||||||
|
|
||||||
/* You must use `ts_scan_iterator_close` if terminating this loop early */
|
/* You must use `ts_scan_iterator_close` if terminating this loop early */
|
||||||
#define ts_scanner_foreach(scan_iterator) \
|
#define ts_scanner_foreach(scan_iterator) \
|
||||||
|
@ -136,8 +136,9 @@ typedef struct InternalScannerCtx
|
|||||||
bool closed;
|
bool closed;
|
||||||
} InternalScannerCtx;
|
} InternalScannerCtx;
|
||||||
|
|
||||||
void ts_scanner_start_scan(ScannerCtx *ctx, InternalScannerCtx *ictx);
|
extern TSDLLEXPORT void ts_scanner_start_scan(ScannerCtx *ctx, InternalScannerCtx *ictx);
|
||||||
void ts_scanner_end_scan(ScannerCtx *ctx, InternalScannerCtx *ictx);
|
|
||||||
TupleInfo *ts_scanner_next(ScannerCtx *ctx, InternalScannerCtx *ictx);
|
extern TSDLLEXPORT void ts_scanner_end_scan(ScannerCtx *ctx, InternalScannerCtx *ictx);
|
||||||
|
extern TSDLLEXPORT TupleInfo *ts_scanner_next(ScannerCtx *ctx, InternalScannerCtx *ictx);
|
||||||
|
|
||||||
#endif /* TIMESCALEDB_SCANNER_H */
|
#endif /* TIMESCALEDB_SCANNER_H */
|
||||||
|
@ -1307,7 +1307,7 @@ finalizequery_get_select_query(FinalizeQueryInfo *inp, List *matcollist,
|
|||||||
static void
|
static void
|
||||||
cagg_create(ViewStmt *stmt, Query *panquery, CAggTimebucketInfo *origquery_ht)
|
cagg_create(ViewStmt *stmt, Query *panquery, CAggTimebucketInfo *origquery_ht)
|
||||||
{
|
{
|
||||||
ObjectAddress userview_address, mataddress, internal_viewaddress;
|
ObjectAddress mataddress;
|
||||||
char relnamebuf[NAMEDATALEN];
|
char relnamebuf[NAMEDATALEN];
|
||||||
MatTableColumnInfo mattblinfo;
|
MatTableColumnInfo mattblinfo;
|
||||||
FinalizeQueryInfo finalqinfo;
|
FinalizeQueryInfo finalqinfo;
|
||||||
@ -1345,7 +1345,7 @@ cagg_create(ViewStmt *stmt, Query *panquery, CAggTimebucketInfo *origquery_ht)
|
|||||||
*/
|
*/
|
||||||
final_selquery =
|
final_selquery =
|
||||||
finalizequery_get_select_query(&finalqinfo, mattblinfo.matcollist, &mataddress);
|
finalizequery_get_select_query(&finalqinfo, mattblinfo.matcollist, &mataddress);
|
||||||
userview_address = create_view_for_query(final_selquery, stmt->view);
|
create_view_for_query(final_selquery, stmt->view);
|
||||||
|
|
||||||
/* Step 3: create the internal view with select partialize(..)
|
/* Step 3: create the internal view with select partialize(..)
|
||||||
*/
|
*/
|
||||||
@ -1354,7 +1354,7 @@ cagg_create(ViewStmt *stmt, Query *panquery, CAggTimebucketInfo *origquery_ht)
|
|||||||
PRINT_MATINTERNAL_NAME(relnamebuf, "ts_internal_%sview", stmt->view->relname);
|
PRINT_MATINTERNAL_NAME(relnamebuf, "ts_internal_%sview", stmt->view->relname);
|
||||||
part_rel = makeRangeVar(pstrdup(INTERNAL_SCHEMA_NAME), pstrdup(relnamebuf), -1);
|
part_rel = makeRangeVar(pstrdup(INTERNAL_SCHEMA_NAME), pstrdup(relnamebuf), -1);
|
||||||
|
|
||||||
internal_viewaddress = create_view_for_query(partial_selquery, part_rel);
|
create_view_for_query(partial_selquery, part_rel);
|
||||||
|
|
||||||
Assert(mat_rel != NULL);
|
Assert(mat_rel != NULL);
|
||||||
/* Step 4 add catalog table entry for the objects we just created */
|
/* Step 4 add catalog table entry for the objects we just created */
|
||||||
@ -1366,9 +1366,6 @@ cagg_create(ViewStmt *stmt, Query *panquery, CAggTimebucketInfo *origquery_ht)
|
|||||||
part_rel->schemaname,
|
part_rel->schemaname,
|
||||||
part_rel->relname,
|
part_rel->relname,
|
||||||
origquery_ht->bucket_width);
|
origquery_ht->bucket_width);
|
||||||
/* record dependency: user view depends on materialization table and internal view */
|
|
||||||
recordDependencyOn(&mataddress, &userview_address, DEPENDENCY_INTERNAL);
|
|
||||||
recordDependencyOn(&internal_viewaddress, &userview_address, DEPENDENCY_INTERNAL);
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -3,8 +3,10 @@
|
|||||||
* Please see the included NOTICE for copyright information and
|
* Please see the included NOTICE for copyright information and
|
||||||
* LICENSE-TIMESCALE for a copy of the license.
|
* LICENSE-TIMESCALE for a copy of the license.
|
||||||
*/
|
*/
|
||||||
#ifndef CONT_CAGG_H
|
#ifndef TIMESCALEDB_TSL_CONTINUOUS_AGGS_CAGG_CREATE_H
|
||||||
#define CONT_CAGG_H
|
#define TIMESCALEDB_TSL_CONTINUOUS_AGGS_CAGG_CREATE_H
|
||||||
|
#include <postgres.h>
|
||||||
|
#include <nodes/parsenodes.h>
|
||||||
|
|
||||||
bool tsl_process_continuous_agg_viewstmt(ViewStmt *stmt, const char *query_string, void *pstmt);
|
bool tsl_process_continuous_agg_viewstmt(ViewStmt *stmt, const char *query_string, void *pstmt);
|
||||||
#endif
|
#endif /* TIMESCALEDB_TSL_CONTINUOUS_AGGS_CAGG_CREATE_H */
|
||||||
|
@ -105,7 +105,8 @@ order by 1;
|
|||||||
-- drop on table conditions should cascade to materialized mat_v1
|
-- drop on table conditions should cascade to materialized mat_v1
|
||||||
-- Oid used in timescaledb_catalog table from catalog table -- TODO
|
-- Oid used in timescaledb_catalog table from catalog table -- TODO
|
||||||
drop table conditions cascade;
|
drop table conditions cascade;
|
||||||
NOTICE: drop cascades to 3 other objects
|
NOTICE: drop cascades to view _timescaledb_internal.ts_internal_mat_m1view
|
||||||
|
NOTICE: drop cascades to 2 other objects
|
||||||
CREATE TABLE conditions (
|
CREATE TABLE conditions (
|
||||||
timec TIMESTAMPTZ NOT NULL,
|
timec TIMESTAMPTZ NOT NULL,
|
||||||
location TEXT NOT NULL,
|
location TEXT NOT NULL,
|
||||||
@ -263,7 +264,8 @@ order by sum(temperature)+sum(humidity);
|
|||||||
--group by with more than 1 group column
|
--group by with more than 1 group column
|
||||||
-- having clause with a mix of columns from select list + others
|
-- having clause with a mix of columns from select list + others
|
||||||
drop table conditions cascade;
|
drop table conditions cascade;
|
||||||
NOTICE: drop cascades to 3 other objects
|
NOTICE: drop cascades to view _timescaledb_internal.ts_internal_mat_m1view
|
||||||
|
NOTICE: drop cascades to 2 other objects
|
||||||
CREATE TABLE conditions (
|
CREATE TABLE conditions (
|
||||||
timec TIMESTAMPTZ NOT NULL,
|
timec TIMESTAMPTZ NOT NULL,
|
||||||
location TEXT NOT NULL,
|
location TEXT NOT NULL,
|
||||||
@ -345,17 +347,11 @@ order by time_bucket('1week', timec), min(location);
|
|||||||
|
|
||||||
--TEST6 -- catalog entries and select from internal view
|
--TEST6 -- catalog entries and select from internal view
|
||||||
--check the entry in the catalog tables --
|
--check the entry in the catalog tables --
|
||||||
--TODO wrong results
|
|
||||||
select partial_view_name from _timescaledb_catalog.continuous_agg where user_view_name like 'mat_m1';
|
select partial_view_name from _timescaledb_catalog.continuous_agg where user_view_name like 'mat_m1';
|
||||||
partial_view_name
|
partial_view_name
|
||||||
------------------------
|
------------------------
|
||||||
ts_internal_mat_m1view
|
ts_internal_mat_m1view
|
||||||
ts_internal_mat_m1view
|
(1 row)
|
||||||
ts_internal_mat_m1view
|
|
||||||
ts_internal_mat_m1view
|
|
||||||
ts_internal_mat_m1view
|
|
||||||
ts_internal_mat_m1view
|
|
||||||
(6 rows)
|
|
||||||
|
|
||||||
\c :TEST_DBNAME :ROLE_SUPERUSER
|
\c :TEST_DBNAME :ROLE_SUPERUSER
|
||||||
insert into _timescaledb_internal.ts_internal_mat_m1tab
|
insert into _timescaledb_internal.ts_internal_mat_m1tab
|
||||||
@ -421,3 +417,145 @@ psql:include/cont_agg_equal.sql:13: NOTICE: adding not-null constraint to colum
|
|||||||
Number of rows different between view and original (expect 0) | 0
|
Number of rows different between view and original (expect 0) | 0
|
||||||
(1 row)
|
(1 row)
|
||||||
|
|
||||||
|
--DROP tests
|
||||||
|
\set ON_ERROR_STOP 0
|
||||||
|
SELECT h.schema_name AS "MAT_SCHEMA_NAME",
|
||||||
|
h.table_name AS "MAT_TABLE_NAME",
|
||||||
|
partial_view_name as "PART_VIEW_NAME",
|
||||||
|
partial_view_schema as "PART_VIEW_SCHEMA"
|
||||||
|
FROM _timescaledb_catalog.continuous_agg ca
|
||||||
|
INNER JOIN _timescaledb_catalog.hypertable h ON(h.id = ca.mat_hypertable_id)
|
||||||
|
WHERE user_view_name = 'mat_test'
|
||||||
|
\gset
|
||||||
|
DROP TABLE :"MAT_SCHEMA_NAME".:"MAT_TABLE_NAME";
|
||||||
|
ERROR: cannot drop table _timescaledb_internal.ts_internal_mat_testtab because other objects depend on it
|
||||||
|
DROP VIEW :"PART_VIEW_SCHEMA".:"PART_VIEW_NAME";
|
||||||
|
ERROR: cannot drop the partial view because it is required by a continuous aggregate
|
||||||
|
DROP VIEW mat_test;
|
||||||
|
ERROR: dropping a continous aggregate requires using CASCADE
|
||||||
|
\set ON_ERROR_STOP 1
|
||||||
|
--catalog entry still there;
|
||||||
|
SELECT count(*)
|
||||||
|
FROM _timescaledb_catalog.continuous_agg ca
|
||||||
|
WHERE user_view_name = 'mat_test';
|
||||||
|
count
|
||||||
|
-------
|
||||||
|
1
|
||||||
|
(1 row)
|
||||||
|
|
||||||
|
--mat table, user_view, and partial view all there
|
||||||
|
select count(*) from pg_class where relname = :'PART_VIEW_NAME';
|
||||||
|
count
|
||||||
|
-------
|
||||||
|
1
|
||||||
|
(1 row)
|
||||||
|
|
||||||
|
select count(*) from pg_class where relname = :'MAT_TABLE_NAME';
|
||||||
|
count
|
||||||
|
-------
|
||||||
|
1
|
||||||
|
(1 row)
|
||||||
|
|
||||||
|
select count(*) from pg_class where relname = 'mat_test';
|
||||||
|
count
|
||||||
|
-------
|
||||||
|
1
|
||||||
|
(1 row)
|
||||||
|
|
||||||
|
DROP VIEW mat_test CASCADE;
|
||||||
|
NOTICE: drop cascades to 2 other objects
|
||||||
|
--catalog entry should be gone
|
||||||
|
SELECT count(*)
|
||||||
|
FROM _timescaledb_catalog.continuous_agg ca
|
||||||
|
WHERE user_view_name = 'mat_test';
|
||||||
|
count
|
||||||
|
-------
|
||||||
|
0
|
||||||
|
(1 row)
|
||||||
|
|
||||||
|
--mat table, user_view, and partial view all gone
|
||||||
|
select count(*) from pg_class where relname = :'PART_VIEW_NAME';
|
||||||
|
count
|
||||||
|
-------
|
||||||
|
0
|
||||||
|
(1 row)
|
||||||
|
|
||||||
|
select count(*) from pg_class where relname = :'MAT_TABLE_NAME';
|
||||||
|
count
|
||||||
|
-------
|
||||||
|
0
|
||||||
|
(1 row)
|
||||||
|
|
||||||
|
select count(*) from pg_class where relname = 'mat_test';
|
||||||
|
count
|
||||||
|
-------
|
||||||
|
0
|
||||||
|
(1 row)
|
||||||
|
|
||||||
|
--test dropping raw table
|
||||||
|
DROP TABLE conditions;
|
||||||
|
CREATE TABLE conditions (
|
||||||
|
timec TIMESTAMPTZ NOT NULL,
|
||||||
|
location TEXT NOT NULL,
|
||||||
|
temperature DOUBLE PRECISION NULL,
|
||||||
|
humidity DOUBLE PRECISION NULL,
|
||||||
|
lowp double precision NULL,
|
||||||
|
highp double precision null,
|
||||||
|
allnull double precision null
|
||||||
|
);
|
||||||
|
select table_name from create_hypertable( 'conditions', 'timec');
|
||||||
|
table_name
|
||||||
|
------------
|
||||||
|
conditions
|
||||||
|
(1 row)
|
||||||
|
|
||||||
|
--no data in hyper table on purpose so that CASCADE is not required because of chunks
|
||||||
|
create or replace view mat_drop_test( timec, minl, sumt , sumh)
|
||||||
|
WITH ( timescaledb.continuous_agg = 'start')
|
||||||
|
as
|
||||||
|
select time_bucket('1day', timec), min(location), sum(temperature),sum(humidity)
|
||||||
|
from conditions
|
||||||
|
group by time_bucket('1day', timec);
|
||||||
|
NOTICE: adding not-null constraint to column "time_partition_col"
|
||||||
|
\set ON_ERROR_STOP 0
|
||||||
|
DROP TABLE conditions;
|
||||||
|
ERROR: cannot drop table conditions because other objects depend on it
|
||||||
|
\set ON_ERROR_STOP 1
|
||||||
|
SELECT h.schema_name AS "MAT_SCHEMA_NAME",
|
||||||
|
h.table_name AS "MAT_TABLE_NAME",
|
||||||
|
partial_view_name as "PART_VIEW_NAME",
|
||||||
|
partial_view_schema as "PART_VIEW_SCHEMA"
|
||||||
|
FROM _timescaledb_catalog.continuous_agg ca
|
||||||
|
INNER JOIN _timescaledb_catalog.hypertable h ON(h.id = ca.mat_hypertable_id)
|
||||||
|
WHERE user_view_name = 'mat_drop_test'
|
||||||
|
\gset
|
||||||
|
DROP TABLE conditions CASCADE;
|
||||||
|
NOTICE: drop cascades to view _timescaledb_internal.ts_internal_mat_drop_testview
|
||||||
|
--catalog entry should be gone
|
||||||
|
SELECT count(*)
|
||||||
|
FROM _timescaledb_catalog.continuous_agg ca
|
||||||
|
WHERE user_view_name = 'mat_drop_test';
|
||||||
|
count
|
||||||
|
-------
|
||||||
|
0
|
||||||
|
(1 row)
|
||||||
|
|
||||||
|
--mat table, user_view, and partial view all gone
|
||||||
|
select count(*) from pg_class where relname = :'PART_VIEW_NAME';
|
||||||
|
count
|
||||||
|
-------
|
||||||
|
0
|
||||||
|
(1 row)
|
||||||
|
|
||||||
|
select count(*) from pg_class where relname = :'MAT_TABLE_NAME';
|
||||||
|
count
|
||||||
|
-------
|
||||||
|
0
|
||||||
|
(1 row)
|
||||||
|
|
||||||
|
select count(*) from pg_class where relname = 'mat_drop_test';
|
||||||
|
count
|
||||||
|
-------
|
||||||
|
0
|
||||||
|
(1 row)
|
||||||
|
|
||||||
|
@ -272,7 +272,6 @@ order by time_bucket('1week', timec), min(location);
|
|||||||
|
|
||||||
--TEST6 -- catalog entries and select from internal view
|
--TEST6 -- catalog entries and select from internal view
|
||||||
--check the entry in the catalog tables --
|
--check the entry in the catalog tables --
|
||||||
--TODO wrong results
|
|
||||||
select partial_view_name from _timescaledb_catalog.continuous_agg where user_view_name like 'mat_m1';
|
select partial_view_name from _timescaledb_catalog.continuous_agg where user_view_name like 'mat_m1';
|
||||||
|
|
||||||
\c :TEST_DBNAME :ROLE_SUPERUSER
|
\c :TEST_DBNAME :ROLE_SUPERUSER
|
||||||
@ -333,3 +332,90 @@ SELECT
|
|||||||
\set ECHO errors
|
\set ECHO errors
|
||||||
\ir include/cont_agg_equal.sql
|
\ir include/cont_agg_equal.sql
|
||||||
\set ECHO all
|
\set ECHO all
|
||||||
|
|
||||||
|
--DROP tests
|
||||||
|
\set ON_ERROR_STOP 0
|
||||||
|
SELECT h.schema_name AS "MAT_SCHEMA_NAME",
|
||||||
|
h.table_name AS "MAT_TABLE_NAME",
|
||||||
|
partial_view_name as "PART_VIEW_NAME",
|
||||||
|
partial_view_schema as "PART_VIEW_SCHEMA"
|
||||||
|
FROM _timescaledb_catalog.continuous_agg ca
|
||||||
|
INNER JOIN _timescaledb_catalog.hypertable h ON(h.id = ca.mat_hypertable_id)
|
||||||
|
WHERE user_view_name = 'mat_test'
|
||||||
|
\gset
|
||||||
|
|
||||||
|
DROP TABLE :"MAT_SCHEMA_NAME".:"MAT_TABLE_NAME";
|
||||||
|
DROP VIEW :"PART_VIEW_SCHEMA".:"PART_VIEW_NAME";
|
||||||
|
DROP VIEW mat_test;
|
||||||
|
\set ON_ERROR_STOP 1
|
||||||
|
|
||||||
|
--catalog entry still there;
|
||||||
|
SELECT count(*)
|
||||||
|
FROM _timescaledb_catalog.continuous_agg ca
|
||||||
|
WHERE user_view_name = 'mat_test';
|
||||||
|
|
||||||
|
--mat table, user_view, and partial view all there
|
||||||
|
select count(*) from pg_class where relname = :'PART_VIEW_NAME';
|
||||||
|
select count(*) from pg_class where relname = :'MAT_TABLE_NAME';
|
||||||
|
select count(*) from pg_class where relname = 'mat_test';
|
||||||
|
|
||||||
|
DROP VIEW mat_test CASCADE;
|
||||||
|
|
||||||
|
--catalog entry should be gone
|
||||||
|
SELECT count(*)
|
||||||
|
FROM _timescaledb_catalog.continuous_agg ca
|
||||||
|
WHERE user_view_name = 'mat_test';
|
||||||
|
|
||||||
|
--mat table, user_view, and partial view all gone
|
||||||
|
select count(*) from pg_class where relname = :'PART_VIEW_NAME';
|
||||||
|
select count(*) from pg_class where relname = :'MAT_TABLE_NAME';
|
||||||
|
select count(*) from pg_class where relname = 'mat_test';
|
||||||
|
|
||||||
|
|
||||||
|
--test dropping raw table
|
||||||
|
DROP TABLE conditions;
|
||||||
|
CREATE TABLE conditions (
|
||||||
|
timec TIMESTAMPTZ NOT NULL,
|
||||||
|
location TEXT NOT NULL,
|
||||||
|
temperature DOUBLE PRECISION NULL,
|
||||||
|
humidity DOUBLE PRECISION NULL,
|
||||||
|
lowp double precision NULL,
|
||||||
|
highp double precision null,
|
||||||
|
allnull double precision null
|
||||||
|
);
|
||||||
|
|
||||||
|
select table_name from create_hypertable( 'conditions', 'timec');
|
||||||
|
|
||||||
|
--no data in hyper table on purpose so that CASCADE is not required because of chunks
|
||||||
|
|
||||||
|
create or replace view mat_drop_test( timec, minl, sumt , sumh)
|
||||||
|
WITH ( timescaledb.continuous_agg = 'start')
|
||||||
|
as
|
||||||
|
select time_bucket('1day', timec), min(location), sum(temperature),sum(humidity)
|
||||||
|
from conditions
|
||||||
|
group by time_bucket('1day', timec);
|
||||||
|
|
||||||
|
\set ON_ERROR_STOP 0
|
||||||
|
DROP TABLE conditions;
|
||||||
|
\set ON_ERROR_STOP 1
|
||||||
|
|
||||||
|
SELECT h.schema_name AS "MAT_SCHEMA_NAME",
|
||||||
|
h.table_name AS "MAT_TABLE_NAME",
|
||||||
|
partial_view_name as "PART_VIEW_NAME",
|
||||||
|
partial_view_schema as "PART_VIEW_SCHEMA"
|
||||||
|
FROM _timescaledb_catalog.continuous_agg ca
|
||||||
|
INNER JOIN _timescaledb_catalog.hypertable h ON(h.id = ca.mat_hypertable_id)
|
||||||
|
WHERE user_view_name = 'mat_drop_test'
|
||||||
|
\gset
|
||||||
|
|
||||||
|
DROP TABLE conditions CASCADE;
|
||||||
|
|
||||||
|
--catalog entry should be gone
|
||||||
|
SELECT count(*)
|
||||||
|
FROM _timescaledb_catalog.continuous_agg ca
|
||||||
|
WHERE user_view_name = 'mat_drop_test';
|
||||||
|
|
||||||
|
--mat table, user_view, and partial view all gone
|
||||||
|
select count(*) from pg_class where relname = :'PART_VIEW_NAME';
|
||||||
|
select count(*) from pg_class where relname = :'MAT_TABLE_NAME';
|
||||||
|
select count(*) from pg_class where relname = 'mat_drop_test';
|
||||||
|
@ -152,6 +152,11 @@ test_sql_drop(List *dropped_objects)
|
|||||||
elog(NOTICE, "test_sql_drop: trigger");
|
elog(NOTICE, "test_sql_drop: trigger");
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
case EVENT_TRIGGER_DROP_VIEW:
|
||||||
|
{
|
||||||
|
elog(NOTICE, "test_sql_drop: view");
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user