Use CREATE OR REPLACE AGGREGATE

From PG12 on, CREATE OR REPLACE is supported for aggregates,
therefore, since we have dropped support for PG11, we can avoid
going through the rigamarole of having our aggregates in a separate
file from the functions we define to support them. Nor do we need to
handle aggregates separately from other functions as their creation
is now idempotent.
This commit is contained in:
davidkohn88 2021-06-08 18:05:17 -04:00 committed by Mats Kindahl
parent ff5d7e42bb
commit bfd92ab822
5 changed files with 61 additions and 62 deletions

View File

@ -93,8 +93,6 @@ endfunction()
version_files("${PRE_UPDATE_FILES}" PRE_UPDATE_FILES_VERSIONED)
version_files("${POST_UPDATE_FILES}" POST_UPDATE_FILES_VERSIONED)
version_files("${PRE_INSTALL_SOURCE_FILES}" PRE_INSTALL_SOURCE_FILES_VERSIONED)
version_files("${IMMUTABLE_API_SOURCE_FILES}"
IMMUTABLE_API_SOURCE_FILES_VERSIONED)
version_files("${SOURCE_FILES}" SOURCE_FILES_VERSIONED)
version_files("${MOD_FILES}" MOD_FILES_VERSIONED)
version_files("updates/latest-dev.sql" LASTEST_MOD_VERSIONED)
@ -122,7 +120,7 @@ endfunction()
# Generate the extension file used with CREATE EXTENSION
cat_files(
"${PRE_INSTALL_SOURCE_FILES_VERSIONED};${SOURCE_FILES_VERSIONED};${IMMUTABLE_API_SOURCE_FILES_VERSIONED};${NOTICE_FILE}"
"${PRE_INSTALL_SOURCE_FILES_VERSIONED};${SOURCE_FILES_VERSIONED};${NOTICE_FILE}"
${CMAKE_CURRENT_BINARY_DIR}/${INSTALL_FILE})
add_custom_target(sqlfile ALL
DEPENDS ${CMAKE_CURRENT_BINARY_DIR}/${INSTALL_FILE})

View File

@ -1,59 +0,0 @@
-- This file and its contents are licensed under the Apache License 2.0.
-- Please see the included NOTICE for copyright information and
-- LICENSE-APACHE for a copy of the license.
-- This file is meant to contain aggregate functions that need to be created only
-- once and not recreated during updates.
-- There is no CREATE OR REPLACE AGGREGATE which means that the only way to replace
-- an aggregate is to DROP then CREATE which is problematic as it will fail
-- if the previous version of the aggregate has dependencies.
-- NOTE that WHEN CREATING NEW FUNCTIONS HERE you should also make sure they are
-- created in an update script so that both new users and people updating from a
-- previous version get the new function
--This aggregate returns the "first" element of the first argument when ordered by the second argument.
--Ex. first(temp, time) returns the temp value for the row with the lowest time
CREATE AGGREGATE first(anyelement, "any") (
SFUNC = _timescaledb_internal.first_sfunc,
STYPE = internal,
COMBINEFUNC = _timescaledb_internal.first_combinefunc,
SERIALFUNC = _timescaledb_internal.bookend_serializefunc,
DESERIALFUNC = _timescaledb_internal.bookend_deserializefunc,
PARALLEL = SAFE,
FINALFUNC = _timescaledb_internal.bookend_finalfunc,
FINALFUNC_EXTRA
);
--This aggregate returns the "last" element of the first argument when ordered by the second argument.
--Ex. last(temp, time) returns the temp value for the row with highest time
CREATE AGGREGATE last(anyelement, "any") (
SFUNC = _timescaledb_internal.last_sfunc,
STYPE = internal,
COMBINEFUNC = _timescaledb_internal.last_combinefunc,
SERIALFUNC = _timescaledb_internal.bookend_serializefunc,
DESERIALFUNC = _timescaledb_internal.bookend_deserializefunc,
PARALLEL = SAFE,
FINALFUNC = _timescaledb_internal.bookend_finalfunc,
FINALFUNC_EXTRA
);
-- This aggregate partitions the dataset into a specified number of buckets (nbuckets) ranging
-- from the inputted min to max values.
CREATE AGGREGATE histogram (DOUBLE PRECISION, DOUBLE PRECISION, DOUBLE PRECISION, INTEGER) (
SFUNC = _timescaledb_internal.hist_sfunc,
STYPE = INTERNAL,
COMBINEFUNC = _timescaledb_internal.hist_combinefunc,
SERIALFUNC = _timescaledb_internal.hist_serializefunc,
DESERIALFUNC = _timescaledb_internal.hist_deserializefunc,
PARALLEL = SAFE,
FINALFUNC = _timescaledb_internal.hist_finalfunc,
FINALFUNC_EXTRA
);
CREATE AGGREGATE _timescaledb_internal.finalize_agg(agg_name TEXT, inner_agg_collation_schema NAME, inner_agg_collation_name NAME, inner_agg_input_types NAME[][], inner_agg_serialized_state BYTEA, return_type_dummy_val anyelement) (
SFUNC = _timescaledb_internal.finalize_agg_sfunc,
STYPE = internal,
FINALFUNC = _timescaledb_internal.finalize_agg_ffunc,
FINALFUNC_EXTRA
);

View File

@ -36,3 +36,37 @@ CREATE OR REPLACE FUNCTION _timescaledb_internal.bookend_deserializefunc(bytea,
RETURNS internal
AS '@MODULE_PATHNAME@', 'ts_bookend_deserializefunc'
LANGUAGE C IMMUTABLE STRICT PARALLEL SAFE;
-- We started using CREATE OR REPLACE AGGREGATE for aggregate creation once the syntax was fully supported
-- as it is easier to support idempotent changes this way. This will allow for changes to functions supporting
-- the aggregate, and, for instance, the definition and inclusion of inverse functions for window function
-- support. However, it should still be noted that changes to the data structures used for the internal
-- state of the aggregate must be backwards compatible and the old format must be accepted by any new functions
-- in order for them to continue working with Continuous Aggregates, where old states may have been materialized.
--This aggregate returns the "first" value of the first argument when ordered by the second argument.
--Ex. first(temp, time) returns the temp value for the row with the lowest time
CREATE OR REPLACE AGGREGATE first(anyelement, "any") (
SFUNC = _timescaledb_internal.first_sfunc,
STYPE = internal,
COMBINEFUNC = _timescaledb_internal.first_combinefunc,
SERIALFUNC = _timescaledb_internal.bookend_serializefunc,
DESERIALFUNC = _timescaledb_internal.bookend_deserializefunc,
PARALLEL = SAFE,
FINALFUNC = _timescaledb_internal.bookend_finalfunc,
FINALFUNC_EXTRA
);
--This aggregate returns the "last" value of the first argument when ordered by the second argument.
--Ex. last(temp, time) returns the temp value for the row with highest time
CREATE OR REPLACE AGGREGATE last(anyelement, "any") (
SFUNC = _timescaledb_internal.last_sfunc,
STYPE = internal,
COMBINEFUNC = _timescaledb_internal.last_combinefunc,
SERIALFUNC = _timescaledb_internal.bookend_serializefunc,
DESERIALFUNC = _timescaledb_internal.bookend_deserializefunc,
PARALLEL = SAFE,
FINALFUNC = _timescaledb_internal.bookend_finalfunc,
FINALFUNC_EXTRA
);

View File

@ -26,3 +26,23 @@ CREATE OR REPLACE FUNCTION _timescaledb_internal.hist_finalfunc(state INTERNAL,
RETURNS INTEGER[]
AS '@MODULE_PATHNAME@', 'ts_hist_finalfunc'
LANGUAGE C IMMUTABLE PARALLEL SAFE;
-- We started using CREATE OR REPLACE AGGREGATE for aggregate creation once the syntax was fully supported
-- as it is easier to support idempotent changes this way. This will allow for changes to functions supporting
-- the aggregate, and, for instance, the definition and inclusion of inverse functions for window function
-- support. However, it should still be noted that changes to the data structures used for the internal
-- state of the aggregate must be backwards compatible and the old format must be accepted by any new functions
-- in order for them to continue working with Continuous Aggregates, where old states may have been materialized.
-- This aggregate partitions the dataset into a specified number of buckets (nbuckets) ranging
-- from the inputted min to max values.
CREATE OR REPLACE AGGREGATE histogram (DOUBLE PRECISION, DOUBLE PRECISION, DOUBLE PRECISION, INTEGER) (
SFUNC = _timescaledb_internal.hist_sfunc,
STYPE = INTERNAL,
COMBINEFUNC = _timescaledb_internal.hist_combinefunc,
SERIALFUNC = _timescaledb_internal.hist_serializefunc,
DESERIALFUNC = _timescaledb_internal.hist_deserializefunc,
PARALLEL = SAFE,
FINALFUNC = _timescaledb_internal.hist_finalfunc,
FINALFUNC_EXTRA
);

View File

@ -17,3 +17,9 @@ RETURNS anyelement
AS '@MODULE_PATHNAME@', 'ts_finalize_agg_ffunc'
LANGUAGE C IMMUTABLE ;
CREATE OR REPLACE AGGREGATE _timescaledb_internal.finalize_agg(agg_name TEXT, inner_agg_collation_schema NAME, inner_agg_collation_name NAME, inner_agg_input_types NAME[][], inner_agg_serialized_state BYTEA, return_type_dummy_val anyelement) (
SFUNC = _timescaledb_internal.finalize_agg_sfunc,
STYPE = internal,
FINALFUNC = _timescaledb_internal.finalize_agg_ffunc,
FINALFUNC_EXTRA
);