1
0
mirror of https://github.com/timescale/timescaledb.git synced 2025-05-16 10:33:27 +08:00

Add support for multiple extension version in one pg instance

This PR adds the ability to have multiple different versions of the timescaledb
extension be used by different databases in the same PostgreSQL
instance (server).

This is accomplished by splitting this extension into two .so files.
1) timescaledb.so -- stuff under loader/. Really not a lot of code.
    This code MUST be backwards compatible in the future.
2) timescaledb-version.so (most of our code). Need
   not be backwards compatible.

Timescaledb.so becomes a small stub which is preloaded and whose main
reason for existing is to dynamically load the right
timescaledb-version.so when the time comes.

This change allows either of the above .so to be loaded in
shared_preload_libraries. But timescaledb.so allows for multiple
versions used on different databases in the same instance along
with smoother upgrades. Using timescaledb-version.so allows for
finer-grained control and lock-in and is appropriate in only a few
production environments.

This PR also adds version checking so that a clear failure message
will be displayed if the .so version does not match the SQL extension
version.

To support multi-version functionality we changed the way SQL update
scripts are generated. Previously, the system used a bunch of
intermediate upgrade scripts.  So with 3 versions, you would have an
update script of 1--2, 2--3.  But, this PR changes things so that we
produce direct "shortcut" update files: 1--3, 2--3.
This is done for 2 reasons:
 1) Each of the update files should point to
    $libdir/timescaledb-current_version. Since you cannot guarantee that
    Previous .so for each intermediate version has been installed.
 2) You don't want intermediate version updates installed without the
    .so. For example, if you have versions 1,2,3
    and you are installing version 3, you want the upgrade files 1--3,
    2--3 but not 1--2 because if you have 1--2
    then a user could do ALTER EXTENSION timescaledb UPDATE TO 2. But
    the .so for version 2 may not be installed.

In order to test this functionality, we add a mock extension version .so
that we can test extension loading inside the regression framework.
This commit is contained in:
Matvey Arye 2017-09-25 22:41:34 -04:00 committed by Matvey Arye
parent e8eabf4278
commit da8cc797a4
59 changed files with 1837 additions and 513 deletions

@ -1,5 +1,6 @@
cmake_minimum_required(VERSION 3.4)
configure_file("version.config" "version.config" COPYONLY)
file(READ version.config VERSION_CONFIG)
set(VERSION_REGEX "version[\t ]*=[\t ]*([0-9]+\\.[0-9]+\\.*[0-9]*)([-]([a-z]+))*\r?\nupdate_from_version[\t ]*=[\t ]*([0-9]+\\.[0-9]+\\.*[0-9]*)(\r?\n)*$")

@ -22,7 +22,8 @@ set(SQL_FILES
cache_functions.sql
size_utils.sql
histogram.sql
cache.sql)
cache.sql
)
set(EXT_SQL_EXTRA_FILES
timescaledb--0.1.0--0.2.0.sql
@ -33,48 +34,116 @@ set(EXT_SQL_EXTRA_FILES
timescaledb--0.4.2--0.5.0.sql
timescaledb--0.5.0--0.6.0.sql
timescaledb--0.6.0--0.6.1.sql
timescaledb--0.6.1--0.7.0.sql
timescaledb--0.6.1--0.7.1.sql
timescaledb--0.7.0--0.7.1.sql
timescaledb--0.7.1--0.8.0.sql)
timescaledb--0.7.1--0.8.0.sql
)
if (WIN32)
# Make list of files into string of files separated by "+"
# to make Windows copy concatenate them
string(REPLACE ";" ";+" SQL_FILES_JOINED "${SQL_FILES}")
# Windows copy command requires backslashes for relative paths
string(REPLACE "/" "\\" EXT_SQL_UPDATE_PRE_FILE "${EXT_SQL_UPDATE_PRE_FILE}")
string(REPLACE "/" "\\" EXT_SQL_UPDATE_POST_FILE "${EXT_SQL_UPDATE_POST_FILE}")
#TODO handle these manually.
set(EXT_SQL_SPECIAL_FILES
timescaledb--0.6.1--0.7.0.sql
timescaledb--0.7.0--0.7.1.sql
)
set(CAT_SQL_FILE_CMD copy /B /y ${SQL_FILES_JOINED} "\"${CMAKE_CURRENT_BINARY_DIR}/${EXT_SQL_FILE}\"" >NUL)
set(CAT_SQL_UPDATE_FILE_CMD copy /B /y ${EXT_SQL_UPDATE_PRE_FILE} + ${SQL_FILES_JOINED} + ${EXT_SQL_UPDATE_POST_FILE} "\"${CMAKE_CURRENT_BINARY_DIR}/${EXT_SQL_UPDATE_FILE}\"" >NUL)
else ()
set(CAT_SQL_FILE_CMD cat ${SQL_FILES} > ${CMAKE_CURRENT_BINARY_DIR}/${EXT_SQL_FILE})
set(CAT_SQL_UPDATE_FILE_CMD cat ${EXT_SQL_UPDATE_PRE_FILE} ${SQL_FILES} ${EXT_SQL_UPDATE_POST_FILE} > ${CMAKE_CURRENT_BINARY_DIR}/${EXT_SQL_UPDATE_FILE})
endif ()
set(EXT_SQL_UPDATE_PRE_GLOBAL_FILE updates/pre-global.sql)
set(EXT_SQL_UPDATE_POST_GLOBAL_FILE updates/post-global.sql)
set(UPDATE_FILE_LIST ${EXT_SQL_UPDATE_PRE_GLOBAL_FILE} ${EXT_SQL_UPDATE_PRE_FILE} ${SQL_FILES} ${EXT_SQL_UPDATE_POST_FILE} ${EXT_SQL_UPDATE_POST_GLOBAL_FILE})
# Command and target for the SQL file
add_custom_command(
OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/${EXT_SQL_FILE}
DEPENDS ${SQL_FILES}
WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}
COMMAND ${CAT_SQL_FILE_CMD}
COMMENT "Generating ${EXT_SQL_FILE}")
#replace MODULE PATHNAME for files making up EXT_SQL_FILE (timescaledb--version.sql) and EXT_SQL_UPDATE_FILE (timescaledb--previous_version--version.sql)
set(MODULE_PATHNAME "$libdir/timescaledb-${PROJECT_VERSION_MOD}")
set(UPDATE_FILE_LIST_VERSIONED "")
set(SQL_FILES_VERSIONED "")
foreach(update_file ${UPDATE_FILE_LIST})
set(update_file_versioned ${update_file}.${PROJECT_VERSION_MOD})
configure_file(${update_file} ${update_file_versioned} @ONLY)
list(APPEND UPDATE_FILE_LIST_VERSIONED ${CMAKE_CURRENT_BINARY_DIR}/${update_file_versioned})
if (${update_file} IN_LIST SQL_FILES)
list(APPEND SQL_FILES_VERSIONED ${CMAKE_CURRENT_BINARY_DIR}/${update_file_versioned})
endif()
endforeach(update_file)
#function to concatenate all files in SRC_FILE_LIST into file OUTPUT_FILE
function(cat_files SRC_FILE_LIST OUTPUT_FILE)
if (WIN32)
# Make list of files into string of files separated by "+"
# to make Windows copy concatenate them
file(TO_NATIVE_PATH "${SRC_FILE_LIST}" SRC_FILE_LIST_NATIVE)
string(REPLACE ";" ";+" SQL_LIST_JOINED "${SRC_FILE_LIST_NATIVE}")
file(TO_NATIVE_PATH "${OUTPUT_FILE}" OUTPUT_FILE_NATIVE)
set(CAT_CMD copy /B /y ${SQL_LIST_JOINED} "\"${OUTPUT_FILE_NATIVE}\"" >NUL)
else ()
set(CAT_CMD cat ${SRC_FILE_LIST} > ${OUTPUT_FILE})
endif ()
add_custom_command(
OUTPUT ${OUTPUT_FILE}
DEPENDS ${SRC_FILE_LIST}
WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}
COMMAND ${CAT_CMD}
COMMENT "Generating ${OUTPUT_FILE}"
)
endfunction()
cat_files("${SQL_FILES_VERSIONED}" ${CMAKE_CURRENT_BINARY_DIR}/${EXT_SQL_FILE})
add_custom_target(sqlfile ALL DEPENDS ${CMAKE_CURRENT_BINARY_DIR}/${EXT_SQL_FILE})
# Command and target for the update SQL file
add_custom_command(
OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/${EXT_SQL_UPDATE_FILE}
DEPENDS ${SQL_FILES} ${EXT_SQL_UPDATE_PRE_FILE} ${EXT_SQL_UPDATE_POST_FILE}
WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}
COMMAND ${CAT_SQL_UPDATE_FILE_CMD}
COMMENT "Generating ${EXT_SQL_UPDATE_FILE}")
cat_files("${UPDATE_FILE_LIST_VERSIONED}" ${CMAKE_CURRENT_BINARY_DIR}/${EXT_SQL_UPDATE_FILE})
add_custom_target(sqlupdatefile ALL DEPENDS ${CMAKE_CURRENT_BINARY_DIR}/${EXT_SQL_UPDATE_FILE})
add_custom_target(sqlupdatefile ALL DEPENDS ${EXT_SQL_UPDATE_FILE})
#This generates the update file without MODULE_PATHNAME replaced. This file should be copied for the release.
cat_files("${UPDATE_FILE_LIST}" ${CMAKE_CURRENT_BINARY_DIR}/${EXT_SQL_UPDATE_FILE}.release)
add_custom_target(sqlreleaseupdate ALL DEPENDS ${CMAKE_CURRENT_BINARY_DIR}/${EXT_SQL_UPDATE_FILE}.release)
#You want to create timescaledb-old_version--current_version for all possible old_versions.
#This is done for 2 reasons:
# 1) Each of the update files should point to $libdir/timescaledb-current_version. Since you cannot guarantee that
# Previous .so for each intermediate version has been installed.
# 2) You don't want intermediate version updates installed without the .so. For example, if you have versions 1,2,3
# and you are installing version 3, you want the upgrade files 1--3, 2--3 but not 1--2 because if you have 1--2
# then a user could do ALTER EXTENSION timescaledb UPDATE TO 2. But the .so for version 2 may not be installed.
#
# Note that we build these update files by concatenating intermediate files. So we should have the intermediate update
# files of 1--2, 2--3. From these we build the actual update scripts 1--3, 2--3.
#replace MODULE_PATHNAME in all the intermediate update files to point to $libdir/timescaledb-current_version
#note that intermediate update files are never installed/packaged. Rather, they are only used to build the
#update scripts below.
set(INTERMEDIATE_UPDATE_VERSIONED "")
foreach(intermediate_update_file ${EXT_SQL_EXTRA_FILES})
set(intermediate_update_file_versioned ${intermediate_update_file}.${PROJECT_VERSION_MOD})
configure_file(${intermediate_update_file} ${intermediate_update_file_versioned} @ONLY)
list(APPEND INTERMEDIATE_UPDATE_VERSIONED ${CMAKE_CURRENT_BINARY_DIR}/${intermediate_update_file_versioned})
endforeach(intermediate_update_file)
#we expect INTERMEDIATE_UPDATE_VERSIONED to be in order. For example, it should be 1--2, 2--3.
set(INTERMEDIATE_FILE_REGEX "${CMAKE_CURRENT_BINARY_DIR}/timescaledb--([0-9]+\\.[0-9]+\\.*[0-9]*)--([0-9]+\\.[0-9]+\\.*[0-9]*).sql.${PROJECT_VERSION_MOD}")
#build the actual update scripts for historic versions.
set(PREVIOUS_UPDATE_SCRIPTS "")
while(INTERMEDIATE_UPDATE_VERSIONED) #while list not empty
#start with the first (oldest) file in the list and create an update for that version to current version
list(GET INTERMEDIATE_UPDATE_VERSIONED 0 FIRST_INTERMEDIATE_FILE)
if (NOT (${FIRST_INTERMEDIATE_FILE} MATCHES ${INTERMEDIATE_FILE_REGEX}))
message(FATAL_ERROR "Cannot parse update file name ${FIRST_INTERMEDIATE_FILE}")
endif ()
set(START_VERSION ${CMAKE_MATCH_1})
set(PREV_UPDATE_FILE "${PROJECT_NAME}--${START_VERSION}--${PROJECT_VERSION_MOD}.sql")
#the files that go into this update are all the intermediate files + latest update
set(UPDATE_FILES ${INTERMEDIATE_UPDATE_VERSIONED} ${CMAKE_CURRENT_BINARY_DIR}/${EXT_SQL_UPDATE_FILE})
cat_files("${UPDATE_FILES}" ${CMAKE_CURRENT_BINARY_DIR}/${PREV_UPDATE_FILE})
list(APPEND PREVIOUS_UPDATE_SCRIPTS ${CMAKE_CURRENT_BINARY_DIR}/${PREV_UPDATE_FILE})
#drop the head and start again
list(REMOVE_AT INTERMEDIATE_UPDATE_VERSIONED 0)
endwhile(INTERMEDIATE_UPDATE_VERSIONED)
add_custom_target(sqlprevupdatescripts ALL DEPENDS ${PREVIOUS_UPDATE_SCRIPTS})
install(
FILES ${CMAKE_CURRENT_BINARY_DIR}/${EXT_SQL_FILE}
${CMAKE_CURRENT_BINARY_DIR}/${EXT_SQL_UPDATE_FILE}
${EXT_SQL_EXTRA_FILES}
${PREVIOUS_UPDATE_SCRIPTS}
DESTINATION "${PG_SHAREDIR}/extension")

@ -1,36 +1,36 @@
CREATE OR REPLACE FUNCTION _timescaledb_internal.first_sfunc(internal, anyelement, "any")
RETURNS internal
AS '$libdir/timescaledb', 'first_sfunc'
AS '@MODULE_PATHNAME@', 'first_sfunc'
LANGUAGE C IMMUTABLE PARALLEL SAFE;
CREATE OR REPLACE FUNCTION _timescaledb_internal.first_combinefunc(internal, internal)
RETURNS internal
AS '$libdir/timescaledb', 'first_combinefunc'
AS '@MODULE_PATHNAME@', 'first_combinefunc'
LANGUAGE C IMMUTABLE PARALLEL SAFE;
CREATE OR REPLACE FUNCTION _timescaledb_internal.last_sfunc(internal, anyelement, "any")
RETURNS internal
AS '$libdir/timescaledb', 'last_sfunc'
AS '@MODULE_PATHNAME@', 'last_sfunc'
LANGUAGE C IMMUTABLE PARALLEL SAFE;
CREATE OR REPLACE FUNCTION _timescaledb_internal.last_combinefunc(internal, internal)
RETURNS internal
AS '$libdir/timescaledb', 'last_combinefunc'
AS '@MODULE_PATHNAME@', 'last_combinefunc'
LANGUAGE C IMMUTABLE PARALLEL SAFE;
CREATE OR REPLACE FUNCTION _timescaledb_internal.bookend_finalfunc(internal, anyelement, "any")
RETURNS anyelement
AS '$libdir/timescaledb', 'bookend_finalfunc'
AS '@MODULE_PATHNAME@', 'bookend_finalfunc'
LANGUAGE C IMMUTABLE PARALLEL SAFE;
CREATE OR REPLACE FUNCTION _timescaledb_internal.bookend_serializefunc(internal)
RETURNS bytea
AS '$libdir/timescaledb', 'bookend_serializefunc'
AS '@MODULE_PATHNAME@', 'bookend_serializefunc'
LANGUAGE C IMMUTABLE STRICT PARALLEL SAFE;
CREATE OR REPLACE FUNCTION _timescaledb_internal.bookend_deserializefunc(bytea, internal)
RETURNS internal
AS '$libdir/timescaledb', 'bookend_deserializefunc'
AS '@MODULE_PATHNAME@', 'bookend_deserializefunc'
LANGUAGE C IMMUTABLE STRICT PARALLEL SAFE;
--This aggregate returns the "first" element of the first argument when ordered by the second argument.

@ -1,8 +1,9 @@
-- this trigger function causes an invalidation event on the table whose name is
-- passed in as the first element.
CREATE OR REPLACE FUNCTION _timescaledb_cache.invalidate_relcache_trigger()
RETURNS TRIGGER AS '$libdir/timescaledb', 'invalidate_relcache_trigger' LANGUAGE C STRICT;
RETURNS TRIGGER AS '@MODULE_PATHNAME@', 'invalidate_relcache_trigger' LANGUAGE C STRICT;
-- This function is only used for debugging
CREATE OR REPLACE FUNCTION _timescaledb_cache.invalidate_relcache(catalog_table REGCLASS)
RETURNS BOOLEAN AS '$libdir/timescaledb', 'invalidate_relcache' LANGUAGE C STRICT;
RETURNS BOOLEAN AS '@MODULE_PATHNAME@', 'invalidate_relcache' LANGUAGE C STRICT;

@ -3,11 +3,11 @@ CREATE OR REPLACE FUNCTION _timescaledb_internal.dimension_calculate_default_ran
interval_length BIGINT,
OUT range_start BIGINT,
OUT range_end BIGINT)
AS '$libdir/timescaledb', 'dimension_calculate_open_range_default' LANGUAGE C STABLE;
AS '@MODULE_PATHNAME@', 'dimension_calculate_open_range_default' LANGUAGE C STABLE;
CREATE OR REPLACE FUNCTION _timescaledb_internal.dimension_calculate_default_range_closed(
dimension_value BIGINT,
num_slices SMALLINT,
OUT range_start BIGINT,
OUT range_end BIGINT)
AS '$libdir/timescaledb', 'dimension_calculate_closed_range_default' LANGUAGE C STABLE;
AS '@MODULE_PATHNAME@', 'dimension_calculate_closed_range_default' LANGUAGE C STABLE;

@ -23,7 +23,7 @@ END
$BODY$;
CREATE OR REPLACE FUNCTION _timescaledb_internal.check_associated_schema_permissions(schema_name NAME, userid OID)
RETURNS VOID AS '$libdir/timescaledb', 'hypertable_check_associated_schema_permissions' LANGUAGE C;
RETURNS VOID AS '@MODULE_PATHNAME@', 'hypertable_check_associated_schema_permissions' LANGUAGE C;
-- Creates a hypertable row.
CREATE OR REPLACE FUNCTION _timescaledb_internal.create_hypertable(
@ -543,7 +543,7 @@ END
$BODY$;
CREATE OR REPLACE FUNCTION _timescaledb_internal.verify_hypertable_indexes(hypertable REGCLASS) RETURNS VOID
AS '$libdir/timescaledb', 'indexing_verify_hypertable_indexes' LANGUAGE C STRICT;
AS '@MODULE_PATHNAME@', 'indexing_verify_hypertable_indexes' LANGUAGE C STRICT;
CREATE OR REPLACE FUNCTION _timescaledb_internal.ddl_change_owner(main_table OID, new_table_owner NAME)
RETURNS void LANGUAGE plpgsql
@ -572,20 +572,20 @@ END
$BODY$;
CREATE OR REPLACE FUNCTION _timescaledb_internal.attach_tablespace(tablespace NAME, hypertable REGCLASS) RETURNS VOID
AS '$libdir/timescaledb', 'tablespace_attach' LANGUAGE C VOLATILE;
AS '@MODULE_PATHNAME@', 'tablespace_attach' LANGUAGE C VOLATILE;
CREATE OR REPLACE FUNCTION _timescaledb_internal.detach_tablespace(tablespace NAME, hypertable REGCLASS) RETURNS INTEGER
AS '$libdir/timescaledb', 'tablespace_detach' LANGUAGE C VOLATILE;
AS '@MODULE_PATHNAME@', 'tablespace_detach' LANGUAGE C VOLATILE;
CREATE OR REPLACE FUNCTION _timescaledb_internal.detach_tablespaces(hypertable REGCLASS) RETURNS INTEGER
AS '$libdir/timescaledb', 'tablespace_detach_all_from_hypertable' LANGUAGE C VOLATILE;
AS '@MODULE_PATHNAME@', 'tablespace_detach_all_from_hypertable' LANGUAGE C VOLATILE;
CREATE OR REPLACE FUNCTION _timescaledb_internal.show_tablespaces(hypertable REGCLASS) RETURNS SETOF NAME
AS '$libdir/timescaledb', 'tablespace_show' LANGUAGE C VOLATILE STRICT;
AS '@MODULE_PATHNAME@', 'tablespace_show' LANGUAGE C VOLATILE STRICT;
--documentation of these function located in chunk_index.h
CREATE OR REPLACE FUNCTION _timescaledb_internal.chunk_index_clone(chunk_index_oid OID) RETURNS OID
AS '$libdir/timescaledb', 'chunk_index_clone' LANGUAGE C VOLATILE STRICT;
AS '@MODULE_PATHNAME@', 'chunk_index_clone' LANGUAGE C VOLATILE STRICT;
CREATE OR REPLACE FUNCTION _timescaledb_internal.chunk_index_replace(chunk_index_oid_old OID, chunk_index_oid_new OID) RETURNS VOID
AS '$libdir/timescaledb', 'chunk_index_replace' LANGUAGE C VOLATILE STRICT;
AS '@MODULE_PATHNAME@', 'chunk_index_replace' LANGUAGE C VOLATILE STRICT;

@ -1,6 +1,8 @@
CREATE OR REPLACE FUNCTION _timescaledb_internal.ddl_command_end() RETURNS event_trigger
AS '$libdir/timescaledb', 'timescaledb_ddl_command_end' LANGUAGE C;
AS '@MODULE_PATHNAME@', 'timescaledb_ddl_command_end' LANGUAGE C;
DROP EVENT TRIGGER IF EXISTS timescaledb_ddl_command_end;
--EVENT TRIGGER MUST exclude the ALTER EXTENSION tag.
CREATE EVENT TRIGGER timescaledb_ddl_command_end ON ddl_command_end
WHEN TAG IN ('ALTER TABLE','CREATE TRIGGER','CREATE TABLE','CREATE INDEX','ALTER INDEX')
EXECUTE PROCEDURE _timescaledb_internal.ddl_command_end();

@ -1,26 +1,26 @@
CREATE OR REPLACE FUNCTION _timescaledb_internal.hist_sfunc (state INTERNAL, val DOUBLE PRECISION, MIN DOUBLE PRECISION, MAX DOUBLE PRECISION, nbuckets INTEGER)
RETURNS INTERNAL
AS '$libdir/timescaledb', 'hist_sfunc'
AS '@MODULE_PATHNAME@', 'hist_sfunc'
LANGUAGE C IMMUTABLE PARALLEL SAFE;
CREATE OR REPLACE FUNCTION _timescaledb_internal.hist_combinefunc(state1 INTERNAL, state2 INTERNAL)
RETURNS INTERNAL
AS '$libdir/timescaledb', 'hist_combinefunc'
AS '@MODULE_PATHNAME@', 'hist_combinefunc'
LANGUAGE C IMMUTABLE PARALLEL SAFE;
CREATE OR REPLACE FUNCTION _timescaledb_internal.hist_serializefunc(INTERNAL)
RETURNS bytea
AS '$libdir/timescaledb', 'hist_serializefunc'
AS '@MODULE_PATHNAME@', 'hist_serializefunc'
LANGUAGE C IMMUTABLE STRICT PARALLEL SAFE;
CREATE OR REPLACE FUNCTION _timescaledb_internal.hist_deserializefunc(bytea, INTERNAL)
RETURNS INTERNAL
AS '$libdir/timescaledb', 'hist_deserializefunc'
AS '@MODULE_PATHNAME@', 'hist_deserializefunc'
LANGUAGE C IMMUTABLE STRICT PARALLEL SAFE;
CREATE OR REPLACE FUNCTION _timescaledb_internal.hist_finalfunc(state INTERNAL, val DOUBLE PRECISION, MIN DOUBLE PRECISION, MAX DOUBLE PRECISION, nbuckets INTEGER)
RETURNS INTEGER[]
AS '$libdir/timescaledb', 'hist_finalfunc'
AS '@MODULE_PATHNAME@', 'hist_finalfunc'
LANGUAGE C IMMUTABLE PARALLEL SAFE;
-- Tell Postgres how to use the new function

@ -1,8 +1,9 @@
-- Deprecated partition hash function
CREATE OR REPLACE FUNCTION _timescaledb_internal.get_partition_for_key(val anyelement)
RETURNS int
AS '$libdir/timescaledb', 'get_partition_for_key' LANGUAGE C IMMUTABLE STRICT PARALLEL SAFE;
AS '@MODULE_PATHNAME@', 'get_partition_for_key' LANGUAGE C IMMUTABLE STRICT PARALLEL SAFE;
CREATE OR REPLACE FUNCTION _timescaledb_internal.get_partition_hash(val anyelement)
RETURNS int
AS '$libdir/timescaledb', 'get_partition_hash' LANGUAGE C IMMUTABLE STRICT PARALLEL SAFE;
AS '@MODULE_PATHNAME@', 'get_partition_hash' LANGUAGE C IMMUTABLE STRICT PARALLEL SAFE;

@ -1,15 +1,15 @@
-- time_bucket returns the left edge of the bucket where ts falls into.
-- Buckets span an interval of time equal to the bucket_width and are aligned with the epoch.
CREATE OR REPLACE FUNCTION time_bucket(bucket_width INTERVAL, ts TIMESTAMP) RETURNS TIMESTAMP
AS '$libdir/timescaledb', 'timestamp_bucket' LANGUAGE C IMMUTABLE PARALLEL SAFE;
AS '@MODULE_PATHNAME@', 'timestamp_bucket' LANGUAGE C IMMUTABLE PARALLEL SAFE;
-- bucketing of timestamptz happens at UTC time
CREATE OR REPLACE FUNCTION time_bucket(bucket_width INTERVAL, ts TIMESTAMPTZ) RETURNS TIMESTAMPTZ
AS '$libdir/timescaledb', 'timestamptz_bucket' LANGUAGE C IMMUTABLE PARALLEL SAFE;
AS '@MODULE_PATHNAME@', 'timestamptz_bucket' LANGUAGE C IMMUTABLE PARALLEL SAFE;
--bucketing on date should not do any timezone conversion
CREATE OR REPLACE FUNCTION time_bucket(bucket_width INTERVAL, ts DATE) RETURNS DATE
AS '$libdir/timescaledb', 'date_bucket' LANGUAGE C IMMUTABLE PARALLEL SAFE;
AS '@MODULE_PATHNAME@', 'date_bucket' LANGUAGE C IMMUTABLE PARALLEL SAFE;
-- If an interval is given as the third argument, the bucket alignment is offset by the interval.
CREATE OR REPLACE FUNCTION time_bucket(bucket_width INTERVAL, ts TIMESTAMP, "offset" INTERVAL)

@ -523,16 +523,16 @@ $BODY$
$BODY$;
-- This file contains utilities for time conversion.
CREATE OR REPLACE FUNCTION _timescaledb_internal.to_microseconds(ts TIMESTAMPTZ) RETURNS BIGINT
AS '$libdir/timescaledb', 'pg_timestamp_to_microseconds' LANGUAGE C IMMUTABLE STRICT;
AS '@MODULE_PATHNAME@', 'pg_timestamp_to_microseconds' LANGUAGE C IMMUTABLE STRICT;
CREATE OR REPLACE FUNCTION _timescaledb_internal.to_unix_microseconds(ts TIMESTAMPTZ) RETURNS BIGINT
AS '$libdir/timescaledb', 'pg_timestamp_to_unix_microseconds' LANGUAGE C IMMUTABLE STRICT;
AS '@MODULE_PATHNAME@', 'pg_timestamp_to_unix_microseconds' LANGUAGE C IMMUTABLE STRICT;
CREATE OR REPLACE FUNCTION _timescaledb_internal.to_timestamp(unixtime_us BIGINT) RETURNS TIMESTAMPTZ
AS '$libdir/timescaledb', 'pg_unix_microseconds_to_timestamp' LANGUAGE C IMMUTABLE STRICT;
AS '@MODULE_PATHNAME@', 'pg_unix_microseconds_to_timestamp' LANGUAGE C IMMUTABLE STRICT;
CREATE OR REPLACE FUNCTION _timescaledb_internal.to_timestamp_pg(postgres_us BIGINT) RETURNS TIMESTAMPTZ
AS '$libdir/timescaledb', 'pg_microseconds_to_timestamp' LANGUAGE C IMMUTABLE STRICT;
AS '@MODULE_PATHNAME@', 'pg_microseconds_to_timestamp' LANGUAGE C IMMUTABLE STRICT;
-- Time can be represented in a hypertable as an int* (bigint/integer/smallint) or as a timestamp type (
@ -1160,10 +1160,10 @@ $BODY$;
-- These trigger functions intercept regular inserts and implement our smart insert fastpath
CREATE OR REPLACE FUNCTION _timescaledb_internal.main_table_insert_trigger() RETURNS TRIGGER
AS '$libdir/timescaledb', 'insert_main_table_trigger' LANGUAGE C;
AS '@MODULE_PATHNAME@', 'insert_main_table_trigger' LANGUAGE C;
CREATE OR REPLACE FUNCTION _timescaledb_internal.main_table_after_insert_trigger() RETURNS TRIGGER
AS '$libdir/timescaledb', 'insert_main_table_trigger_after' LANGUAGE C;
AS '@MODULE_PATHNAME@', 'insert_main_table_trigger_after' LANGUAGE C;
-- Adds the above triggers to the main table when a hypertable is created.
CREATE OR REPLACE FUNCTION _timescaledb_internal.on_change_hypertable()
@ -1269,7 +1269,7 @@ $BODY$;
-- our default partitioning function.
-- returns a hash of val modulous the mod_factor
CREATE OR REPLACE FUNCTION _timescaledb_internal.get_partition_for_key(val text) RETURNS int
AS '$libdir/timescaledb', 'get_partition_for_key' LANGUAGE C IMMUTABLE STRICT;
AS '@MODULE_PATHNAME@', 'get_partition_for_key' LANGUAGE C IMMUTABLE STRICT;
-- This file contains functions related to getting information about the
-- schema of a hypertable, including columns, their types, etc.
@ -1801,11 +1801,11 @@ $BODY$;
CREATE OR REPLACE FUNCTION _timescaledb_internal.ddl_is_change_owner(pg_ddl_command)
RETURNS bool IMMUTABLE STRICT
AS '$libdir/timescaledb' LANGUAGE C;
AS '@MODULE_PATHNAME@' LANGUAGE C;
CREATE OR REPLACE FUNCTION _timescaledb_internal.ddl_change_owner_to(pg_ddl_command)
RETURNS name IMMUTABLE STRICT
AS '$libdir/timescaledb' LANGUAGE C;
AS '@MODULE_PATHNAME@' LANGUAGE C;
-- Handles ddl create index commands on hypertables
CREATE OR REPLACE FUNCTION _timescaledb_internal.ddl_process_create_index()
@ -2118,37 +2118,37 @@ END
$BODY$;
CREATE OR REPLACE FUNCTION _timescaledb_internal.first_sfunc(internal, anyelement, "any")
RETURNS internal
AS '$libdir/timescaledb', 'first_sfunc'
AS '@MODULE_PATHNAME@', 'first_sfunc'
LANGUAGE C IMMUTABLE;
CREATE OR REPLACE FUNCTION _timescaledb_internal.first_combinefunc(internal, internal)
RETURNS internal
AS '$libdir/timescaledb', 'first_combinefunc'
AS '@MODULE_PATHNAME@', 'first_combinefunc'
LANGUAGE C IMMUTABLE;
CREATE OR REPLACE FUNCTION _timescaledb_internal.last_sfunc(internal, anyelement, "any")
RETURNS internal
AS '$libdir/timescaledb', 'last_sfunc'
AS '@MODULE_PATHNAME@', 'last_sfunc'
LANGUAGE C IMMUTABLE;
CREATE OR REPLACE FUNCTION _timescaledb_internal.last_combinefunc(internal, internal)
RETURNS internal
AS '$libdir/timescaledb', 'last_combinefunc'
AS '@MODULE_PATHNAME@', 'last_combinefunc'
LANGUAGE C IMMUTABLE;
CREATE OR REPLACE FUNCTION _timescaledb_internal.bookend_finalfunc(internal, anyelement, "any")
RETURNS anyelement
AS '$libdir/timescaledb', 'bookend_finalfunc'
AS '@MODULE_PATHNAME@', 'bookend_finalfunc'
LANGUAGE C IMMUTABLE;
CREATE OR REPLACE FUNCTION _timescaledb_internal.bookend_serializefunc(internal)
RETURNS bytea
AS '$libdir/timescaledb', 'bookend_serializefunc'
AS '@MODULE_PATHNAME@', 'bookend_serializefunc'
LANGUAGE C IMMUTABLE;
CREATE OR REPLACE FUNCTION _timescaledb_internal.bookend_deserializefunc(bytea, internal)
RETURNS internal
AS '$libdir/timescaledb', 'bookend_deserializefunc'
AS '@MODULE_PATHNAME@', 'bookend_deserializefunc'
LANGUAGE C IMMUTABLE;
--This aggregate returns the "first" element of the first argument when ordered by the second argument.
@ -2183,11 +2183,11 @@ CREATE AGGREGATE last(anyelement, "any") (
-- time_bucket returns the left edge of the bucket where ts falls into.
-- Buckets span an interval of time equal to the bucket_width and are aligned with the epoch.
CREATE OR REPLACE FUNCTION public.time_bucket(bucket_width INTERVAL, ts TIMESTAMP) RETURNS TIMESTAMP
AS '$libdir/timescaledb', 'timestamp_bucket' LANGUAGE C IMMUTABLE PARALLEL SAFE;
AS '@MODULE_PATHNAME@', 'timestamp_bucket' LANGUAGE C IMMUTABLE PARALLEL SAFE;
-- bucketing of timestamptz happens at UTC time
CREATE OR REPLACE FUNCTION public.time_bucket(bucket_width INTERVAL, ts TIMESTAMPTZ) RETURNS TIMESTAMPTZ
AS '$libdir/timescaledb', 'timestamptz_bucket' LANGUAGE C IMMUTABLE PARALLEL SAFE;
AS '@MODULE_PATHNAME@', 'timestamptz_bucket' LANGUAGE C IMMUTABLE PARALLEL SAFE;
-- If an interval is given as the third argument, the bucket alignment is offset by the interval.
CREATE OR REPLACE FUNCTION public.time_bucket(bucket_width INTERVAL, ts TIMESTAMP, "offset" INTERVAL)
@ -2240,15 +2240,15 @@ $BODY$;
CREATE OR REPLACE FUNCTION _timescaledb_internal.get_git_commit() RETURNS TEXT
AS '$libdir/timescaledb', 'get_git_commit' LANGUAGE C IMMUTABLE STRICT;
AS '@MODULE_PATHNAME@', 'get_git_commit' LANGUAGE C IMMUTABLE STRICT;
-- this trigger function causes an invalidation event on the table whose name is
-- passed in as the first element.
CREATE OR REPLACE FUNCTION _timescaledb_cache.invalidate_relcache_trigger()
RETURNS TRIGGER AS '$libdir/timescaledb', 'invalidate_relcache_trigger' LANGUAGE C;
RETURNS TRIGGER AS '@MODULE_PATHNAME@', 'invalidate_relcache_trigger' LANGUAGE C;
-- This function is only used for debugging
CREATE OR REPLACE FUNCTION _timescaledb_cache.invalidate_relcache(proxy_oid OID)
RETURNS BOOLEAN AS '$libdir/timescaledb', 'invalidate_relcache' LANGUAGE C;
RETURNS BOOLEAN AS '@MODULE_PATHNAME@', 'invalidate_relcache' LANGUAGE C;

@ -510,16 +510,16 @@ END
$BODY$;
-- This file contains utilities for time conversion.
CREATE OR REPLACE FUNCTION _timescaledb_internal.to_microseconds(ts TIMESTAMPTZ) RETURNS BIGINT
AS '$libdir/timescaledb', 'pg_timestamp_to_microseconds' LANGUAGE C IMMUTABLE STRICT;
AS '@MODULE_PATHNAME@', 'pg_timestamp_to_microseconds' LANGUAGE C IMMUTABLE STRICT;
CREATE OR REPLACE FUNCTION _timescaledb_internal.to_unix_microseconds(ts TIMESTAMPTZ) RETURNS BIGINT
AS '$libdir/timescaledb', 'pg_timestamp_to_unix_microseconds' LANGUAGE C IMMUTABLE STRICT;
AS '@MODULE_PATHNAME@', 'pg_timestamp_to_unix_microseconds' LANGUAGE C IMMUTABLE STRICT;
CREATE OR REPLACE FUNCTION _timescaledb_internal.to_timestamp(unixtime_us BIGINT) RETURNS TIMESTAMPTZ
AS '$libdir/timescaledb', 'pg_unix_microseconds_to_timestamp' LANGUAGE C IMMUTABLE STRICT;
AS '@MODULE_PATHNAME@', 'pg_unix_microseconds_to_timestamp' LANGUAGE C IMMUTABLE STRICT;
CREATE OR REPLACE FUNCTION _timescaledb_internal.to_timestamp_pg(postgres_us BIGINT) RETURNS TIMESTAMPTZ
AS '$libdir/timescaledb', 'pg_microseconds_to_timestamp' LANGUAGE C IMMUTABLE STRICT;
AS '@MODULE_PATHNAME@', 'pg_microseconds_to_timestamp' LANGUAGE C IMMUTABLE STRICT;
-- Time can be represented in a hypertable as an int* (bigint/integer/smallint) or as a timestamp type (
@ -1232,7 +1232,7 @@ $BODY$;
-- our default partitioning function.
-- returns a hash of val modulous the mod_factor
CREATE OR REPLACE FUNCTION _timescaledb_internal.get_partition_for_key(val text) RETURNS int
AS '$libdir/timescaledb', 'get_partition_for_key' LANGUAGE C IMMUTABLE STRICT;
AS '@MODULE_PATHNAME@', 'get_partition_for_key' LANGUAGE C IMMUTABLE STRICT;
-- This file contains functions related to getting information about the
-- schema of a hypertable, including columns, their types, etc.
@ -1764,11 +1764,11 @@ $BODY$;
CREATE OR REPLACE FUNCTION _timescaledb_internal.ddl_is_change_owner(pg_ddl_command)
RETURNS bool IMMUTABLE STRICT
AS '$libdir/timescaledb' LANGUAGE C;
AS '@MODULE_PATHNAME@' LANGUAGE C;
CREATE OR REPLACE FUNCTION _timescaledb_internal.ddl_change_owner_to(pg_ddl_command)
RETURNS name IMMUTABLE STRICT
AS '$libdir/timescaledb' LANGUAGE C;
AS '@MODULE_PATHNAME@' LANGUAGE C;
-- Handles ddl create index commands on hypertables
CREATE OR REPLACE FUNCTION _timescaledb_internal.ddl_process_create_index()
@ -2079,37 +2079,37 @@ END
$BODY$;
CREATE OR REPLACE FUNCTION _timescaledb_internal.first_sfunc(internal, anyelement, "any")
RETURNS internal
AS '$libdir/timescaledb', 'first_sfunc'
AS '@MODULE_PATHNAME@', 'first_sfunc'
LANGUAGE C IMMUTABLE;
CREATE OR REPLACE FUNCTION _timescaledb_internal.first_combinefunc(internal, internal)
RETURNS internal
AS '$libdir/timescaledb', 'first_combinefunc'
AS '@MODULE_PATHNAME@', 'first_combinefunc'
LANGUAGE C IMMUTABLE;
CREATE OR REPLACE FUNCTION _timescaledb_internal.last_sfunc(internal, anyelement, "any")
RETURNS internal
AS '$libdir/timescaledb', 'last_sfunc'
AS '@MODULE_PATHNAME@', 'last_sfunc'
LANGUAGE C IMMUTABLE;
CREATE OR REPLACE FUNCTION _timescaledb_internal.last_combinefunc(internal, internal)
RETURNS internal
AS '$libdir/timescaledb', 'last_combinefunc'
AS '@MODULE_PATHNAME@', 'last_combinefunc'
LANGUAGE C IMMUTABLE;
CREATE OR REPLACE FUNCTION _timescaledb_internal.bookend_finalfunc(internal, anyelement, "any")
RETURNS anyelement
AS '$libdir/timescaledb', 'bookend_finalfunc'
AS '@MODULE_PATHNAME@', 'bookend_finalfunc'
LANGUAGE C IMMUTABLE;
CREATE OR REPLACE FUNCTION _timescaledb_internal.bookend_serializefunc(internal)
RETURNS bytea
AS '$libdir/timescaledb', 'bookend_serializefunc'
AS '@MODULE_PATHNAME@', 'bookend_serializefunc'
LANGUAGE C IMMUTABLE;
CREATE OR REPLACE FUNCTION _timescaledb_internal.bookend_deserializefunc(bytea, internal)
RETURNS internal
AS '$libdir/timescaledb', 'bookend_deserializefunc'
AS '@MODULE_PATHNAME@', 'bookend_deserializefunc'
LANGUAGE C IMMUTABLE;
--This aggregate returns the "first" element of the first argument when ordered by the second argument.
@ -2144,11 +2144,11 @@ CREATE AGGREGATE last(anyelement, "any") (
-- time_bucket returns the left edge of the bucket where ts falls into.
-- Buckets span an interval of time equal to the bucket_width and are aligned with the epoch.
CREATE OR REPLACE FUNCTION public.time_bucket(bucket_width INTERVAL, ts TIMESTAMP) RETURNS TIMESTAMP
AS '$libdir/timescaledb', 'timestamp_bucket' LANGUAGE C IMMUTABLE PARALLEL SAFE;
AS '@MODULE_PATHNAME@', 'timestamp_bucket' LANGUAGE C IMMUTABLE PARALLEL SAFE;
-- bucketing of timestamptz happens at UTC time
CREATE OR REPLACE FUNCTION public.time_bucket(bucket_width INTERVAL, ts TIMESTAMPTZ) RETURNS TIMESTAMPTZ
AS '$libdir/timescaledb', 'timestamptz_bucket' LANGUAGE C IMMUTABLE PARALLEL SAFE;
AS '@MODULE_PATHNAME@', 'timestamptz_bucket' LANGUAGE C IMMUTABLE PARALLEL SAFE;
-- If an interval is given as the third argument, the bucket alignment is offset by the interval.
CREATE OR REPLACE FUNCTION public.time_bucket(bucket_width INTERVAL, ts TIMESTAMP, "offset" INTERVAL)
@ -2201,15 +2201,15 @@ $BODY$;
CREATE OR REPLACE FUNCTION _timescaledb_internal.get_git_commit() RETURNS TEXT
AS '$libdir/timescaledb', 'get_git_commit' LANGUAGE C IMMUTABLE STRICT;
AS '@MODULE_PATHNAME@', 'get_git_commit' LANGUAGE C IMMUTABLE STRICT;
-- this trigger function causes an invalidation event on the table whose name is
-- passed in as the first element.
CREATE OR REPLACE FUNCTION _timescaledb_cache.invalidate_relcache_trigger()
RETURNS TRIGGER AS '$libdir/timescaledb', 'invalidate_relcache_trigger' LANGUAGE C;
RETURNS TRIGGER AS '@MODULE_PATHNAME@', 'invalidate_relcache_trigger' LANGUAGE C;
-- This function is only used for debugging
CREATE OR REPLACE FUNCTION _timescaledb_cache.invalidate_relcache(proxy_oid OID)
RETURNS BOOLEAN AS '$libdir/timescaledb', 'invalidate_relcache' LANGUAGE C;
RETURNS BOOLEAN AS '@MODULE_PATHNAME@', 'invalidate_relcache' LANGUAGE C;

@ -514,16 +514,16 @@ END
$BODY$;
-- This file contains utilities for time conversion.
CREATE OR REPLACE FUNCTION _timescaledb_internal.to_microseconds(ts TIMESTAMPTZ) RETURNS BIGINT
AS '$libdir/timescaledb', 'pg_timestamp_to_microseconds' LANGUAGE C IMMUTABLE STRICT;
AS '@MODULE_PATHNAME@', 'pg_timestamp_to_microseconds' LANGUAGE C IMMUTABLE STRICT;
CREATE OR REPLACE FUNCTION _timescaledb_internal.to_unix_microseconds(ts TIMESTAMPTZ) RETURNS BIGINT
AS '$libdir/timescaledb', 'pg_timestamp_to_unix_microseconds' LANGUAGE C IMMUTABLE STRICT;
AS '@MODULE_PATHNAME@', 'pg_timestamp_to_unix_microseconds' LANGUAGE C IMMUTABLE STRICT;
CREATE OR REPLACE FUNCTION _timescaledb_internal.to_timestamp(unixtime_us BIGINT) RETURNS TIMESTAMPTZ
AS '$libdir/timescaledb', 'pg_unix_microseconds_to_timestamp' LANGUAGE C IMMUTABLE STRICT;
AS '@MODULE_PATHNAME@', 'pg_unix_microseconds_to_timestamp' LANGUAGE C IMMUTABLE STRICT;
CREATE OR REPLACE FUNCTION _timescaledb_internal.to_timestamp_pg(postgres_us BIGINT) RETURNS TIMESTAMPTZ
AS '$libdir/timescaledb', 'pg_microseconds_to_timestamp' LANGUAGE C IMMUTABLE STRICT;
AS '@MODULE_PATHNAME@', 'pg_microseconds_to_timestamp' LANGUAGE C IMMUTABLE STRICT;
-- Time can be represented in a hypertable as an int* (bigint/integer/smallint) or as a timestamp type (
@ -1245,7 +1245,7 @@ $BODY$;
-- our default partitioning function.
-- returns a hash of val modulous the mod_factor
CREATE OR REPLACE FUNCTION _timescaledb_internal.get_partition_for_key(val text) RETURNS int
AS '$libdir/timescaledb', 'get_partition_for_key' LANGUAGE C IMMUTABLE STRICT;
AS '@MODULE_PATHNAME@', 'get_partition_for_key' LANGUAGE C IMMUTABLE STRICT;
-- This file contains functions related to getting information about the
-- schema of a hypertable, including columns, their types, etc.
@ -1805,11 +1805,11 @@ $BODY$;
CREATE OR REPLACE FUNCTION _timescaledb_internal.ddl_is_change_owner(pg_ddl_command)
RETURNS bool IMMUTABLE STRICT
AS '$libdir/timescaledb' LANGUAGE C;
AS '@MODULE_PATHNAME@' LANGUAGE C;
CREATE OR REPLACE FUNCTION _timescaledb_internal.ddl_change_owner_to(pg_ddl_command)
RETURNS name IMMUTABLE STRICT
AS '$libdir/timescaledb' LANGUAGE C;
AS '@MODULE_PATHNAME@' LANGUAGE C;
-- Handles ddl create index commands on hypertables
CREATE OR REPLACE FUNCTION _timescaledb_internal.ddl_process_create_index()
@ -2120,37 +2120,37 @@ END
$BODY$;
CREATE OR REPLACE FUNCTION _timescaledb_internal.first_sfunc(internal, anyelement, "any")
RETURNS internal
AS '$libdir/timescaledb', 'first_sfunc'
AS '@MODULE_PATHNAME@', 'first_sfunc'
LANGUAGE C IMMUTABLE;
CREATE OR REPLACE FUNCTION _timescaledb_internal.first_combinefunc(internal, internal)
RETURNS internal
AS '$libdir/timescaledb', 'first_combinefunc'
AS '@MODULE_PATHNAME@', 'first_combinefunc'
LANGUAGE C IMMUTABLE;
CREATE OR REPLACE FUNCTION _timescaledb_internal.last_sfunc(internal, anyelement, "any")
RETURNS internal
AS '$libdir/timescaledb', 'last_sfunc'
AS '@MODULE_PATHNAME@', 'last_sfunc'
LANGUAGE C IMMUTABLE;
CREATE OR REPLACE FUNCTION _timescaledb_internal.last_combinefunc(internal, internal)
RETURNS internal
AS '$libdir/timescaledb', 'last_combinefunc'
AS '@MODULE_PATHNAME@', 'last_combinefunc'
LANGUAGE C IMMUTABLE;
CREATE OR REPLACE FUNCTION _timescaledb_internal.bookend_finalfunc(internal, anyelement, "any")
RETURNS anyelement
AS '$libdir/timescaledb', 'bookend_finalfunc'
AS '@MODULE_PATHNAME@', 'bookend_finalfunc'
LANGUAGE C IMMUTABLE;
CREATE OR REPLACE FUNCTION _timescaledb_internal.bookend_serializefunc(internal)
RETURNS bytea
AS '$libdir/timescaledb', 'bookend_serializefunc'
AS '@MODULE_PATHNAME@', 'bookend_serializefunc'
LANGUAGE C IMMUTABLE;
CREATE OR REPLACE FUNCTION _timescaledb_internal.bookend_deserializefunc(bytea, internal)
RETURNS internal
AS '$libdir/timescaledb', 'bookend_deserializefunc'
AS '@MODULE_PATHNAME@', 'bookend_deserializefunc'
LANGUAGE C IMMUTABLE;
--This aggregate returns the "first" element of the first argument when ordered by the second argument.
@ -2185,11 +2185,11 @@ CREATE AGGREGATE last(anyelement, "any") (
-- time_bucket returns the left edge of the bucket where ts falls into.
-- Buckets span an interval of time equal to the bucket_width and are aligned with the epoch.
CREATE OR REPLACE FUNCTION public.time_bucket(bucket_width INTERVAL, ts TIMESTAMP) RETURNS TIMESTAMP
AS '$libdir/timescaledb', 'timestamp_bucket' LANGUAGE C IMMUTABLE PARALLEL SAFE;
AS '@MODULE_PATHNAME@', 'timestamp_bucket' LANGUAGE C IMMUTABLE PARALLEL SAFE;
-- bucketing of timestamptz happens at UTC time
CREATE OR REPLACE FUNCTION public.time_bucket(bucket_width INTERVAL, ts TIMESTAMPTZ) RETURNS TIMESTAMPTZ
AS '$libdir/timescaledb', 'timestamptz_bucket' LANGUAGE C IMMUTABLE PARALLEL SAFE;
AS '@MODULE_PATHNAME@', 'timestamptz_bucket' LANGUAGE C IMMUTABLE PARALLEL SAFE;
-- If an interval is given as the third argument, the bucket alignment is offset by the interval.
CREATE OR REPLACE FUNCTION public.time_bucket(bucket_width INTERVAL, ts TIMESTAMP, "offset" INTERVAL)
@ -2242,15 +2242,15 @@ $BODY$;
CREATE OR REPLACE FUNCTION _timescaledb_internal.get_git_commit() RETURNS TEXT
AS '$libdir/timescaledb', 'get_git_commit' LANGUAGE C IMMUTABLE STRICT;
AS '@MODULE_PATHNAME@', 'get_git_commit' LANGUAGE C IMMUTABLE STRICT;
-- this trigger function causes an invalidation event on the table whose name is
-- passed in as the first element.
CREATE OR REPLACE FUNCTION _timescaledb_cache.invalidate_relcache_trigger()
RETURNS TRIGGER AS '$libdir/timescaledb', 'invalidate_relcache_trigger' LANGUAGE C;
RETURNS TRIGGER AS '@MODULE_PATHNAME@', 'invalidate_relcache_trigger' LANGUAGE C;
-- This function is only used for debugging
CREATE OR REPLACE FUNCTION _timescaledb_cache.invalidate_relcache(proxy_oid OID)
RETURNS BOOLEAN AS '$libdir/timescaledb', 'invalidate_relcache' LANGUAGE C;
RETURNS BOOLEAN AS '@MODULE_PATHNAME@', 'invalidate_relcache' LANGUAGE C;

@ -511,16 +511,16 @@ END
$BODY$;
-- This file contains utilities for time conversion.
CREATE OR REPLACE FUNCTION _timescaledb_internal.to_microseconds(ts TIMESTAMPTZ) RETURNS BIGINT
AS '$libdir/timescaledb', 'pg_timestamp_to_microseconds' LANGUAGE C IMMUTABLE STRICT;
AS '@MODULE_PATHNAME@', 'pg_timestamp_to_microseconds' LANGUAGE C IMMUTABLE STRICT;
CREATE OR REPLACE FUNCTION _timescaledb_internal.to_unix_microseconds(ts TIMESTAMPTZ) RETURNS BIGINT
AS '$libdir/timescaledb', 'pg_timestamp_to_unix_microseconds' LANGUAGE C IMMUTABLE STRICT;
AS '@MODULE_PATHNAME@', 'pg_timestamp_to_unix_microseconds' LANGUAGE C IMMUTABLE STRICT;
CREATE OR REPLACE FUNCTION _timescaledb_internal.to_timestamp(unixtime_us BIGINT) RETURNS TIMESTAMPTZ
AS '$libdir/timescaledb', 'pg_unix_microseconds_to_timestamp' LANGUAGE C IMMUTABLE STRICT;
AS '@MODULE_PATHNAME@', 'pg_unix_microseconds_to_timestamp' LANGUAGE C IMMUTABLE STRICT;
CREATE OR REPLACE FUNCTION _timescaledb_internal.to_timestamp_pg(postgres_us BIGINT) RETURNS TIMESTAMPTZ
AS '$libdir/timescaledb', 'pg_microseconds_to_timestamp' LANGUAGE C IMMUTABLE STRICT;
AS '@MODULE_PATHNAME@', 'pg_microseconds_to_timestamp' LANGUAGE C IMMUTABLE STRICT;
-- Time can be represented in a hypertable as an int* (bigint/integer/smallint) or as a timestamp type (
@ -1278,7 +1278,7 @@ $BODY$;
-- our default partitioning function.
-- returns a hash of val modulous the mod_factor
CREATE OR REPLACE FUNCTION _timescaledb_internal.get_partition_for_key(val text) RETURNS int
AS '$libdir/timescaledb', 'get_partition_for_key' LANGUAGE C IMMUTABLE STRICT;
AS '@MODULE_PATHNAME@', 'get_partition_for_key' LANGUAGE C IMMUTABLE STRICT;
-- This file contains functions related to getting information about the
-- schema of a hypertable, including columns, their types, etc.
@ -1838,11 +1838,11 @@ $BODY$;
CREATE OR REPLACE FUNCTION _timescaledb_internal.ddl_is_change_owner(pg_ddl_command)
RETURNS bool IMMUTABLE STRICT
AS '$libdir/timescaledb' LANGUAGE C;
AS '@MODULE_PATHNAME@' LANGUAGE C;
CREATE OR REPLACE FUNCTION _timescaledb_internal.ddl_change_owner_to(pg_ddl_command)
RETURNS name IMMUTABLE STRICT
AS '$libdir/timescaledb' LANGUAGE C;
AS '@MODULE_PATHNAME@' LANGUAGE C;
-- Handles ddl create index commands on hypertables
CREATE OR REPLACE FUNCTION _timescaledb_internal.ddl_process_create_index()
@ -2153,37 +2153,37 @@ END
$BODY$;
CREATE OR REPLACE FUNCTION _timescaledb_internal.first_sfunc(internal, anyelement, "any")
RETURNS internal
AS '$libdir/timescaledb', 'first_sfunc'
AS '@MODULE_PATHNAME@', 'first_sfunc'
LANGUAGE C IMMUTABLE;
CREATE OR REPLACE FUNCTION _timescaledb_internal.first_combinefunc(internal, internal)
RETURNS internal
AS '$libdir/timescaledb', 'first_combinefunc'
AS '@MODULE_PATHNAME@', 'first_combinefunc'
LANGUAGE C IMMUTABLE;
CREATE OR REPLACE FUNCTION _timescaledb_internal.last_sfunc(internal, anyelement, "any")
RETURNS internal
AS '$libdir/timescaledb', 'last_sfunc'
AS '@MODULE_PATHNAME@', 'last_sfunc'
LANGUAGE C IMMUTABLE;
CREATE OR REPLACE FUNCTION _timescaledb_internal.last_combinefunc(internal, internal)
RETURNS internal
AS '$libdir/timescaledb', 'last_combinefunc'
AS '@MODULE_PATHNAME@', 'last_combinefunc'
LANGUAGE C IMMUTABLE;
CREATE OR REPLACE FUNCTION _timescaledb_internal.bookend_finalfunc(internal, anyelement, "any")
RETURNS anyelement
AS '$libdir/timescaledb', 'bookend_finalfunc'
AS '@MODULE_PATHNAME@', 'bookend_finalfunc'
LANGUAGE C IMMUTABLE;
CREATE OR REPLACE FUNCTION _timescaledb_internal.bookend_serializefunc(internal)
RETURNS bytea
AS '$libdir/timescaledb', 'bookend_serializefunc'
AS '@MODULE_PATHNAME@', 'bookend_serializefunc'
LANGUAGE C IMMUTABLE;
CREATE OR REPLACE FUNCTION _timescaledb_internal.bookend_deserializefunc(bytea, internal)
RETURNS internal
AS '$libdir/timescaledb', 'bookend_deserializefunc'
AS '@MODULE_PATHNAME@', 'bookend_deserializefunc'
LANGUAGE C IMMUTABLE;
--This aggregate returns the "first" element of the first argument when ordered by the second argument.
@ -2218,15 +2218,15 @@ CREATE AGGREGATE last(anyelement, "any") (
-- time_bucket returns the left edge of the bucket where ts falls into.
-- Buckets span an interval of time equal to the bucket_width and are aligned with the epoch.
CREATE OR REPLACE FUNCTION public.time_bucket(bucket_width INTERVAL, ts TIMESTAMP) RETURNS TIMESTAMP
AS '$libdir/timescaledb', 'timestamp_bucket' LANGUAGE C IMMUTABLE PARALLEL SAFE;
AS '@MODULE_PATHNAME@', 'timestamp_bucket' LANGUAGE C IMMUTABLE PARALLEL SAFE;
-- bucketing of timestamptz happens at UTC time
CREATE OR REPLACE FUNCTION public.time_bucket(bucket_width INTERVAL, ts TIMESTAMPTZ) RETURNS TIMESTAMPTZ
AS '$libdir/timescaledb', 'timestamptz_bucket' LANGUAGE C IMMUTABLE PARALLEL SAFE;
AS '@MODULE_PATHNAME@', 'timestamptz_bucket' LANGUAGE C IMMUTABLE PARALLEL SAFE;
--bucketing on date should not do any timezone conversion
CREATE OR REPLACE FUNCTION public.time_bucket(bucket_width INTERVAL, ts DATE) RETURNS DATE
AS '$libdir/timescaledb', 'date_bucket' LANGUAGE C IMMUTABLE PARALLEL SAFE;
AS '@MODULE_PATHNAME@', 'date_bucket' LANGUAGE C IMMUTABLE PARALLEL SAFE;
-- If an interval is given as the third argument, the bucket alignment is offset by the interval.
CREATE OR REPLACE FUNCTION public.time_bucket(bucket_width INTERVAL, ts TIMESTAMP, "offset" INTERVAL)
@ -2286,15 +2286,15 @@ $BODY$;
CREATE OR REPLACE FUNCTION _timescaledb_internal.get_git_commit() RETURNS TEXT
AS '$libdir/timescaledb', 'get_git_commit' LANGUAGE C IMMUTABLE STRICT;
AS '@MODULE_PATHNAME@', 'get_git_commit' LANGUAGE C IMMUTABLE STRICT;
-- this trigger function causes an invalidation event on the table whose name is
-- passed in as the first element.
CREATE OR REPLACE FUNCTION _timescaledb_cache.invalidate_relcache_trigger()
RETURNS TRIGGER AS '$libdir/timescaledb', 'invalidate_relcache_trigger' LANGUAGE C;
RETURNS TRIGGER AS '@MODULE_PATHNAME@', 'invalidate_relcache_trigger' LANGUAGE C;
-- This function is only used for debugging
CREATE OR REPLACE FUNCTION _timescaledb_cache.invalidate_relcache(proxy_oid OID)
RETURNS BOOLEAN AS '$libdir/timescaledb', 'invalidate_relcache' LANGUAGE C;
RETURNS BOOLEAN AS '@MODULE_PATHNAME@', 'invalidate_relcache' LANGUAGE C;

@ -511,16 +511,16 @@ END
$BODY$;
-- This file contains utilities for time conversion.
CREATE OR REPLACE FUNCTION _timescaledb_internal.to_microseconds(ts TIMESTAMPTZ) RETURNS BIGINT
AS '$libdir/timescaledb', 'pg_timestamp_to_microseconds' LANGUAGE C IMMUTABLE STRICT;
AS '@MODULE_PATHNAME@', 'pg_timestamp_to_microseconds' LANGUAGE C IMMUTABLE STRICT;
CREATE OR REPLACE FUNCTION _timescaledb_internal.to_unix_microseconds(ts TIMESTAMPTZ) RETURNS BIGINT
AS '$libdir/timescaledb', 'pg_timestamp_to_unix_microseconds' LANGUAGE C IMMUTABLE STRICT;
AS '@MODULE_PATHNAME@', 'pg_timestamp_to_unix_microseconds' LANGUAGE C IMMUTABLE STRICT;
CREATE OR REPLACE FUNCTION _timescaledb_internal.to_timestamp(unixtime_us BIGINT) RETURNS TIMESTAMPTZ
AS '$libdir/timescaledb', 'pg_unix_microseconds_to_timestamp' LANGUAGE C IMMUTABLE STRICT;
AS '@MODULE_PATHNAME@', 'pg_unix_microseconds_to_timestamp' LANGUAGE C IMMUTABLE STRICT;
CREATE OR REPLACE FUNCTION _timescaledb_internal.to_timestamp_pg(postgres_us BIGINT) RETURNS TIMESTAMPTZ
AS '$libdir/timescaledb', 'pg_microseconds_to_timestamp' LANGUAGE C IMMUTABLE STRICT;
AS '@MODULE_PATHNAME@', 'pg_microseconds_to_timestamp' LANGUAGE C IMMUTABLE STRICT;
-- Time can be represented in a hypertable as an int* (bigint/integer/smallint) or as a timestamp type (
@ -1344,7 +1344,7 @@ $BODY$;
-- our default partitioning function.
-- returns a hash of val modulous the mod_factor
CREATE OR REPLACE FUNCTION _timescaledb_internal.get_partition_for_key(val text) RETURNS int
AS '$libdir/timescaledb', 'get_partition_for_key' LANGUAGE C IMMUTABLE STRICT;
AS '@MODULE_PATHNAME@', 'get_partition_for_key' LANGUAGE C IMMUTABLE STRICT;
-- This file contains functions related to getting information about the
-- schema of a hypertable, including columns, their types, etc.
@ -1904,11 +1904,11 @@ $BODY$;
CREATE OR REPLACE FUNCTION _timescaledb_internal.ddl_is_change_owner(pg_ddl_command)
RETURNS bool IMMUTABLE STRICT
AS '$libdir/timescaledb' LANGUAGE C;
AS '@MODULE_PATHNAME@' LANGUAGE C;
CREATE OR REPLACE FUNCTION _timescaledb_internal.ddl_change_owner_to(pg_ddl_command)
RETURNS name IMMUTABLE STRICT
AS '$libdir/timescaledb' LANGUAGE C;
AS '@MODULE_PATHNAME@' LANGUAGE C;
-- Handles ddl create index commands on hypertables
CREATE OR REPLACE FUNCTION _timescaledb_internal.ddl_process_create_index()
@ -2219,37 +2219,37 @@ END
$BODY$;
CREATE OR REPLACE FUNCTION _timescaledb_internal.first_sfunc(internal, anyelement, "any")
RETURNS internal
AS '$libdir/timescaledb', 'first_sfunc'
AS '@MODULE_PATHNAME@', 'first_sfunc'
LANGUAGE C IMMUTABLE;
CREATE OR REPLACE FUNCTION _timescaledb_internal.first_combinefunc(internal, internal)
RETURNS internal
AS '$libdir/timescaledb', 'first_combinefunc'
AS '@MODULE_PATHNAME@', 'first_combinefunc'
LANGUAGE C IMMUTABLE;
CREATE OR REPLACE FUNCTION _timescaledb_internal.last_sfunc(internal, anyelement, "any")
RETURNS internal
AS '$libdir/timescaledb', 'last_sfunc'
AS '@MODULE_PATHNAME@', 'last_sfunc'
LANGUAGE C IMMUTABLE;
CREATE OR REPLACE FUNCTION _timescaledb_internal.last_combinefunc(internal, internal)
RETURNS internal
AS '$libdir/timescaledb', 'last_combinefunc'
AS '@MODULE_PATHNAME@', 'last_combinefunc'
LANGUAGE C IMMUTABLE;
CREATE OR REPLACE FUNCTION _timescaledb_internal.bookend_finalfunc(internal, anyelement, "any")
RETURNS anyelement
AS '$libdir/timescaledb', 'bookend_finalfunc'
AS '@MODULE_PATHNAME@', 'bookend_finalfunc'
LANGUAGE C IMMUTABLE;
CREATE OR REPLACE FUNCTION _timescaledb_internal.bookend_serializefunc(internal)
RETURNS bytea
AS '$libdir/timescaledb', 'bookend_serializefunc'
AS '@MODULE_PATHNAME@', 'bookend_serializefunc'
LANGUAGE C IMMUTABLE;
CREATE OR REPLACE FUNCTION _timescaledb_internal.bookend_deserializefunc(bytea, internal)
RETURNS internal
AS '$libdir/timescaledb', 'bookend_deserializefunc'
AS '@MODULE_PATHNAME@', 'bookend_deserializefunc'
LANGUAGE C IMMUTABLE;
--This aggregate returns the "first" element of the first argument when ordered by the second argument.
@ -2284,15 +2284,15 @@ CREATE AGGREGATE last(anyelement, "any") (
-- time_bucket returns the left edge of the bucket where ts falls into.
-- Buckets span an interval of time equal to the bucket_width and are aligned with the epoch.
CREATE OR REPLACE FUNCTION public.time_bucket(bucket_width INTERVAL, ts TIMESTAMP) RETURNS TIMESTAMP
AS '$libdir/timescaledb', 'timestamp_bucket' LANGUAGE C IMMUTABLE PARALLEL SAFE;
AS '@MODULE_PATHNAME@', 'timestamp_bucket' LANGUAGE C IMMUTABLE PARALLEL SAFE;
-- bucketing of timestamptz happens at UTC time
CREATE OR REPLACE FUNCTION public.time_bucket(bucket_width INTERVAL, ts TIMESTAMPTZ) RETURNS TIMESTAMPTZ
AS '$libdir/timescaledb', 'timestamptz_bucket' LANGUAGE C IMMUTABLE PARALLEL SAFE;
AS '@MODULE_PATHNAME@', 'timestamptz_bucket' LANGUAGE C IMMUTABLE PARALLEL SAFE;
--bucketing on date should not do any timezone conversion
CREATE OR REPLACE FUNCTION public.time_bucket(bucket_width INTERVAL, ts DATE) RETURNS DATE
AS '$libdir/timescaledb', 'date_bucket' LANGUAGE C IMMUTABLE PARALLEL SAFE;
AS '@MODULE_PATHNAME@', 'date_bucket' LANGUAGE C IMMUTABLE PARALLEL SAFE;
-- If an interval is given as the third argument, the bucket alignment is offset by the interval.
CREATE OR REPLACE FUNCTION public.time_bucket(bucket_width INTERVAL, ts TIMESTAMP, "offset" INTERVAL)
@ -2352,15 +2352,15 @@ $BODY$;
CREATE OR REPLACE FUNCTION _timescaledb_internal.get_git_commit() RETURNS TEXT
AS '$libdir/timescaledb', 'get_git_commit' LANGUAGE C IMMUTABLE STRICT;
AS '@MODULE_PATHNAME@', 'get_git_commit' LANGUAGE C IMMUTABLE STRICT;
-- this trigger function causes an invalidation event on the table whose name is
-- passed in as the first element.
CREATE OR REPLACE FUNCTION _timescaledb_cache.invalidate_relcache_trigger()
RETURNS TRIGGER AS '$libdir/timescaledb', 'invalidate_relcache_trigger' LANGUAGE C;
RETURNS TRIGGER AS '@MODULE_PATHNAME@', 'invalidate_relcache_trigger' LANGUAGE C;
-- This function is only used for debugging
CREATE OR REPLACE FUNCTION _timescaledb_cache.invalidate_relcache(proxy_oid OID)
RETURNS BOOLEAN AS '$libdir/timescaledb', 'invalidate_relcache' LANGUAGE C;
RETURNS BOOLEAN AS '@MODULE_PATHNAME@', 'invalidate_relcache' LANGUAGE C;

@ -72,14 +72,14 @@ CREATE OR REPLACE FUNCTION _timescaledb_internal.dimension_calculate_default_ran
interval_length BIGINT,
OUT range_start BIGINT,
OUT range_end BIGINT)
AS '$libdir/timescaledb', 'dimension_calculate_open_range_default' LANGUAGE C STABLE;
AS '@MODULE_PATHNAME@', 'dimension_calculate_open_range_default' LANGUAGE C STABLE;
CREATE OR REPLACE FUNCTION _timescaledb_internal.dimension_calculate_default_range_closed(
dimension_value BIGINT,
num_slices SMALLINT,
OUT range_start BIGINT,
OUT range_end BIGINT)
AS '$libdir/timescaledb', 'dimension_calculate_closed_range_default' LANGUAGE C STABLE;
AS '@MODULE_PATHNAME@', 'dimension_calculate_closed_range_default' LANGUAGE C STABLE;
CREATE OR REPLACE FUNCTION _timescaledb_internal.drop_chunk(
chunk_id int,
@ -693,16 +693,16 @@ END
$BODY$;
-- This file contains utilities for time conversion.
CREATE OR REPLACE FUNCTION _timescaledb_internal.to_microseconds(ts TIMESTAMPTZ) RETURNS BIGINT
AS '$libdir/timescaledb', 'pg_timestamp_to_microseconds' LANGUAGE C IMMUTABLE STRICT;
AS '@MODULE_PATHNAME@', 'pg_timestamp_to_microseconds' LANGUAGE C IMMUTABLE STRICT;
CREATE OR REPLACE FUNCTION _timescaledb_internal.to_unix_microseconds(ts TIMESTAMPTZ) RETURNS BIGINT
AS '$libdir/timescaledb', 'pg_timestamp_to_unix_microseconds' LANGUAGE C IMMUTABLE STRICT;
AS '@MODULE_PATHNAME@', 'pg_timestamp_to_unix_microseconds' LANGUAGE C IMMUTABLE STRICT;
CREATE OR REPLACE FUNCTION _timescaledb_internal.to_timestamp(unixtime_us BIGINT) RETURNS TIMESTAMPTZ
AS '$libdir/timescaledb', 'pg_unix_microseconds_to_timestamp' LANGUAGE C IMMUTABLE STRICT;
AS '@MODULE_PATHNAME@', 'pg_unix_microseconds_to_timestamp' LANGUAGE C IMMUTABLE STRICT;
CREATE OR REPLACE FUNCTION _timescaledb_internal.to_timestamp_pg(postgres_us BIGINT) RETURNS TIMESTAMPTZ
AS '$libdir/timescaledb', 'pg_microseconds_to_timestamp' LANGUAGE C IMMUTABLE STRICT;
AS '@MODULE_PATHNAME@', 'pg_microseconds_to_timestamp' LANGUAGE C IMMUTABLE STRICT;
-- Time can be represented in a hypertable as an int* (bigint/integer/smallint) or as a timestamp type (
@ -1264,7 +1264,7 @@ $BODY$;
-- our default partitioning function.
-- returns a hash of val modulous the mod_factor
CREATE OR REPLACE FUNCTION _timescaledb_internal.get_partition_for_key(val text) RETURNS int
AS '$libdir/timescaledb', 'get_partition_for_key' LANGUAGE C IMMUTABLE STRICT;
AS '@MODULE_PATHNAME@', 'get_partition_for_key' LANGUAGE C IMMUTABLE STRICT;
-- This file contains functions related to getting information about the
-- schema of a hypertable, including columns, their types, etc.
@ -2029,37 +2029,37 @@ END
$BODY$;
CREATE OR REPLACE FUNCTION _timescaledb_internal.first_sfunc(internal, anyelement, "any")
RETURNS internal
AS '$libdir/timescaledb', 'first_sfunc'
AS '@MODULE_PATHNAME@', 'first_sfunc'
LANGUAGE C IMMUTABLE;
CREATE OR REPLACE FUNCTION _timescaledb_internal.first_combinefunc(internal, internal)
RETURNS internal
AS '$libdir/timescaledb', 'first_combinefunc'
AS '@MODULE_PATHNAME@', 'first_combinefunc'
LANGUAGE C IMMUTABLE;
CREATE OR REPLACE FUNCTION _timescaledb_internal.last_sfunc(internal, anyelement, "any")
RETURNS internal
AS '$libdir/timescaledb', 'last_sfunc'
AS '@MODULE_PATHNAME@', 'last_sfunc'
LANGUAGE C IMMUTABLE;
CREATE OR REPLACE FUNCTION _timescaledb_internal.last_combinefunc(internal, internal)
RETURNS internal
AS '$libdir/timescaledb', 'last_combinefunc'
AS '@MODULE_PATHNAME@', 'last_combinefunc'
LANGUAGE C IMMUTABLE;
CREATE OR REPLACE FUNCTION _timescaledb_internal.bookend_finalfunc(internal, anyelement, "any")
RETURNS anyelement
AS '$libdir/timescaledb', 'bookend_finalfunc'
AS '@MODULE_PATHNAME@', 'bookend_finalfunc'
LANGUAGE C IMMUTABLE;
CREATE OR REPLACE FUNCTION _timescaledb_internal.bookend_serializefunc(internal)
RETURNS bytea
AS '$libdir/timescaledb', 'bookend_serializefunc'
AS '@MODULE_PATHNAME@', 'bookend_serializefunc'
LANGUAGE C IMMUTABLE;
CREATE OR REPLACE FUNCTION _timescaledb_internal.bookend_deserializefunc(bytea, internal)
RETURNS internal
AS '$libdir/timescaledb', 'bookend_deserializefunc'
AS '@MODULE_PATHNAME@', 'bookend_deserializefunc'
LANGUAGE C IMMUTABLE;
--This aggregate returns the "first" element of the first argument when ordered by the second argument.
@ -2094,15 +2094,15 @@ CREATE AGGREGATE last(anyelement, "any") (
-- time_bucket returns the left edge of the bucket where ts falls into.
-- Buckets span an interval of time equal to the bucket_width and are aligned with the epoch.
CREATE OR REPLACE FUNCTION public.time_bucket(bucket_width INTERVAL, ts TIMESTAMP) RETURNS TIMESTAMP
AS '$libdir/timescaledb', 'timestamp_bucket' LANGUAGE C IMMUTABLE PARALLEL SAFE;
AS '@MODULE_PATHNAME@', 'timestamp_bucket' LANGUAGE C IMMUTABLE PARALLEL SAFE;
-- bucketing of timestamptz happens at UTC time
CREATE OR REPLACE FUNCTION public.time_bucket(bucket_width INTERVAL, ts TIMESTAMPTZ) RETURNS TIMESTAMPTZ
AS '$libdir/timescaledb', 'timestamptz_bucket' LANGUAGE C IMMUTABLE PARALLEL SAFE;
AS '@MODULE_PATHNAME@', 'timestamptz_bucket' LANGUAGE C IMMUTABLE PARALLEL SAFE;
--bucketing on date should not do any timezone conversion
CREATE OR REPLACE FUNCTION public.time_bucket(bucket_width INTERVAL, ts DATE) RETURNS DATE
AS '$libdir/timescaledb', 'date_bucket' LANGUAGE C IMMUTABLE PARALLEL SAFE;
AS '@MODULE_PATHNAME@', 'date_bucket' LANGUAGE C IMMUTABLE PARALLEL SAFE;
-- If an interval is given as the third argument, the bucket alignment is offset by the interval.
CREATE OR REPLACE FUNCTION public.time_bucket(bucket_width INTERVAL, ts TIMESTAMP, "offset" INTERVAL)
@ -2162,15 +2162,15 @@ $BODY$;
CREATE OR REPLACE FUNCTION _timescaledb_internal.get_git_commit() RETURNS TEXT
AS '$libdir/timescaledb', 'get_git_commit' LANGUAGE C IMMUTABLE STRICT;
AS '@MODULE_PATHNAME@', 'get_git_commit' LANGUAGE C IMMUTABLE STRICT;
-- this trigger function causes an invalidation event on the table whose name is
-- passed in as the first element.
CREATE OR REPLACE FUNCTION _timescaledb_cache.invalidate_relcache_trigger()
RETURNS TRIGGER AS '$libdir/timescaledb', 'invalidate_relcache_trigger' LANGUAGE C;
RETURNS TRIGGER AS '@MODULE_PATHNAME@', 'invalidate_relcache_trigger' LANGUAGE C;
-- This function is only used for debugging
CREATE OR REPLACE FUNCTION _timescaledb_cache.invalidate_relcache(proxy_oid OID)
RETURNS BOOLEAN AS '$libdir/timescaledb', 'invalidate_relcache' LANGUAGE C;
RETURNS BOOLEAN AS '@MODULE_PATHNAME@', 'invalidate_relcache' LANGUAGE C;
@ -2590,27 +2590,27 @@ END;
$BODY$;
CREATE OR REPLACE FUNCTION _timescaledb_internal.hist_sfunc (state INTERNAL, val DOUBLE PRECISION, MIN DOUBLE PRECISION, MAX DOUBLE PRECISION, nbuckets INTEGER)
RETURNS INTERNAL
AS '$libdir/timescaledb', 'hist_sfunc'
AS '@MODULE_PATHNAME@', 'hist_sfunc'
LANGUAGE C IMMUTABLE;
CREATE OR REPLACE FUNCTION _timescaledb_internal.hist_combinefunc(state1 INTERNAL, state2 INTERNAL)
RETURNS INTERNAL
AS '$libdir/timescaledb', 'hist_combinefunc'
AS '@MODULE_PATHNAME@', 'hist_combinefunc'
LANGUAGE C IMMUTABLE;
CREATE OR REPLACE FUNCTION _timescaledb_internal.hist_serializefunc(INTERNAL)
RETURNS bytea
AS '$libdir/timescaledb', 'hist_serializefunc'
AS '@MODULE_PATHNAME@', 'hist_serializefunc'
LANGUAGE C IMMUTABLE;
CREATE OR REPLACE FUNCTION _timescaledb_internal.hist_deserializefunc(bytea, INTERNAL)
RETURNS INTERNAL
AS '$libdir/timescaledb', 'hist_deserializefunc'
AS '@MODULE_PATHNAME@', 'hist_deserializefunc'
LANGUAGE C IMMUTABLE;
CREATE OR REPLACE FUNCTION _timescaledb_internal.hist_finalfunc(state INTERNAL, val DOUBLE PRECISION, MIN DOUBLE PRECISION, MAX DOUBLE PRECISION, nbuckets INTEGER)
RETURNS INTEGER[]
AS '$libdir/timescaledb', 'hist_finalfunc'
AS '@MODULE_PATHNAME@', 'hist_finalfunc'
LANGUAGE C IMMUTABLE;
-- Tell Postgres how to use the new function

@ -222,14 +222,14 @@ CREATE OR REPLACE FUNCTION _timescaledb_internal.dimension_calculate_default_ran
interval_length BIGINT,
OUT range_start BIGINT,
OUT range_end BIGINT)
AS '$libdir/timescaledb', 'dimension_calculate_open_range_default' LANGUAGE C STABLE;
AS '@MODULE_PATHNAME@', 'dimension_calculate_open_range_default' LANGUAGE C STABLE;
CREATE OR REPLACE FUNCTION _timescaledb_internal.dimension_calculate_default_range_closed(
dimension_value BIGINT,
num_slices SMALLINT,
OUT range_start BIGINT,
OUT range_end BIGINT)
AS '$libdir/timescaledb', 'dimension_calculate_closed_range_default' LANGUAGE C STABLE;
AS '@MODULE_PATHNAME@', 'dimension_calculate_closed_range_default' LANGUAGE C STABLE;
CREATE OR REPLACE FUNCTION _timescaledb_internal.drop_chunk_metadata(
chunk_id int
@ -775,7 +775,7 @@ END
$BODY$;
CREATE OR REPLACE FUNCTION _timescaledb_internal.verify_hypertable_indexes(hypertable REGCLASS) RETURNS VOID
AS '$libdir/timescaledb', 'indexing_verify_hypertable_indexes' LANGUAGE C IMMUTABLE STRICT;
AS '@MODULE_PATHNAME@', 'indexing_verify_hypertable_indexes' LANGUAGE C IMMUTABLE STRICT;
CREATE OR REPLACE FUNCTION _timescaledb_internal.ddl_change_owner(main_table OID, new_table_owner NAME)
RETURNS void LANGUAGE plpgsql
@ -804,16 +804,16 @@ END
$BODY$;
-- This file contains utilities for time conversion.
CREATE OR REPLACE FUNCTION _timescaledb_internal.to_microseconds(ts TIMESTAMPTZ) RETURNS BIGINT
AS '$libdir/timescaledb', 'pg_timestamp_to_microseconds' LANGUAGE C IMMUTABLE STRICT;
AS '@MODULE_PATHNAME@', 'pg_timestamp_to_microseconds' LANGUAGE C IMMUTABLE STRICT;
CREATE OR REPLACE FUNCTION _timescaledb_internal.to_unix_microseconds(ts TIMESTAMPTZ) RETURNS BIGINT
AS '$libdir/timescaledb', 'pg_timestamp_to_unix_microseconds' LANGUAGE C IMMUTABLE STRICT;
AS '@MODULE_PATHNAME@', 'pg_timestamp_to_unix_microseconds' LANGUAGE C IMMUTABLE STRICT;
CREATE OR REPLACE FUNCTION _timescaledb_internal.to_timestamp(unixtime_us BIGINT) RETURNS TIMESTAMPTZ
AS '$libdir/timescaledb', 'pg_unix_microseconds_to_timestamp' LANGUAGE C IMMUTABLE STRICT;
AS '@MODULE_PATHNAME@', 'pg_unix_microseconds_to_timestamp' LANGUAGE C IMMUTABLE STRICT;
CREATE OR REPLACE FUNCTION _timescaledb_internal.to_timestamp_pg(postgres_us BIGINT) RETURNS TIMESTAMPTZ
AS '$libdir/timescaledb', 'pg_microseconds_to_timestamp' LANGUAGE C IMMUTABLE STRICT;
AS '@MODULE_PATHNAME@', 'pg_microseconds_to_timestamp' LANGUAGE C IMMUTABLE STRICT;
-- Time can be represented in a hypertable as an int* (bigint/integer/smallint) or as a timestamp type (
@ -1277,7 +1277,7 @@ $BODY$;
-- our default partitioning function.
-- returns a hash of val modulous the mod_factor
CREATE OR REPLACE FUNCTION _timescaledb_internal.get_partition_for_key(val text) RETURNS int
AS '$libdir/timescaledb', 'get_partition_for_key' LANGUAGE C IMMUTABLE STRICT;
AS '@MODULE_PATHNAME@', 'get_partition_for_key' LANGUAGE C IMMUTABLE STRICT;
-- This file contains functions related to getting information about the
-- schema of a hypertable, including columns, their types, etc.
@ -1678,7 +1678,7 @@ BEGIN
END
$BODY$;
CREATE OR REPLACE FUNCTION _timescaledb_internal.ddl_command_end() RETURNS event_trigger
AS '$libdir/timescaledb', 'timescaledb_ddl_command_end' LANGUAGE C IMMUTABLE STRICT;
AS '@MODULE_PATHNAME@', 'timescaledb_ddl_command_end' LANGUAGE C IMMUTABLE STRICT;
CREATE EVENT TRIGGER timescaledb_ddl_command_end ON ddl_command_end
EXECUTE PROCEDURE _timescaledb_internal.ddl_command_end();
@ -1805,37 +1805,37 @@ END
$BODY$;
CREATE OR REPLACE FUNCTION _timescaledb_internal.first_sfunc(internal, anyelement, "any")
RETURNS internal
AS '$libdir/timescaledb', 'first_sfunc'
AS '@MODULE_PATHNAME@', 'first_sfunc'
LANGUAGE C IMMUTABLE;
CREATE OR REPLACE FUNCTION _timescaledb_internal.first_combinefunc(internal, internal)
RETURNS internal
AS '$libdir/timescaledb', 'first_combinefunc'
AS '@MODULE_PATHNAME@', 'first_combinefunc'
LANGUAGE C IMMUTABLE;
CREATE OR REPLACE FUNCTION _timescaledb_internal.last_sfunc(internal, anyelement, "any")
RETURNS internal
AS '$libdir/timescaledb', 'last_sfunc'
AS '@MODULE_PATHNAME@', 'last_sfunc'
LANGUAGE C IMMUTABLE;
CREATE OR REPLACE FUNCTION _timescaledb_internal.last_combinefunc(internal, internal)
RETURNS internal
AS '$libdir/timescaledb', 'last_combinefunc'
AS '@MODULE_PATHNAME@', 'last_combinefunc'
LANGUAGE C IMMUTABLE;
CREATE OR REPLACE FUNCTION _timescaledb_internal.bookend_finalfunc(internal, anyelement, "any")
RETURNS anyelement
AS '$libdir/timescaledb', 'bookend_finalfunc'
AS '@MODULE_PATHNAME@', 'bookend_finalfunc'
LANGUAGE C IMMUTABLE;
CREATE OR REPLACE FUNCTION _timescaledb_internal.bookend_serializefunc(internal)
RETURNS bytea
AS '$libdir/timescaledb', 'bookend_serializefunc'
AS '@MODULE_PATHNAME@', 'bookend_serializefunc'
LANGUAGE C IMMUTABLE;
CREATE OR REPLACE FUNCTION _timescaledb_internal.bookend_deserializefunc(bytea, internal)
RETURNS internal
AS '$libdir/timescaledb', 'bookend_deserializefunc'
AS '@MODULE_PATHNAME@', 'bookend_deserializefunc'
LANGUAGE C IMMUTABLE;
--This aggregate returns the "first" element of the first argument when ordered by the second argument.
@ -1870,15 +1870,15 @@ CREATE AGGREGATE last(anyelement, "any") (
-- time_bucket returns the left edge of the bucket where ts falls into.
-- Buckets span an interval of time equal to the bucket_width and are aligned with the epoch.
CREATE OR REPLACE FUNCTION time_bucket(bucket_width INTERVAL, ts TIMESTAMP) RETURNS TIMESTAMP
AS '$libdir/timescaledb', 'timestamp_bucket' LANGUAGE C IMMUTABLE PARALLEL SAFE;
AS '@MODULE_PATHNAME@', 'timestamp_bucket' LANGUAGE C IMMUTABLE PARALLEL SAFE;
-- bucketing of timestamptz happens at UTC time
CREATE OR REPLACE FUNCTION time_bucket(bucket_width INTERVAL, ts TIMESTAMPTZ) RETURNS TIMESTAMPTZ
AS '$libdir/timescaledb', 'timestamptz_bucket' LANGUAGE C IMMUTABLE PARALLEL SAFE;
AS '@MODULE_PATHNAME@', 'timestamptz_bucket' LANGUAGE C IMMUTABLE PARALLEL SAFE;
--bucketing on date should not do any timezone conversion
CREATE OR REPLACE FUNCTION time_bucket(bucket_width INTERVAL, ts DATE) RETURNS DATE
AS '$libdir/timescaledb', 'date_bucket' LANGUAGE C IMMUTABLE PARALLEL SAFE;
AS '@MODULE_PATHNAME@', 'date_bucket' LANGUAGE C IMMUTABLE PARALLEL SAFE;
-- If an interval is given as the third argument, the bucket alignment is offset by the interval.
CREATE OR REPLACE FUNCTION time_bucket(bucket_width INTERVAL, ts TIMESTAMP, "offset" INTERVAL)
@ -1936,15 +1936,15 @@ $BODY$
SELECT (((ts-"offset") / bucket_width)*bucket_width)+"offset";
$BODY$;
CREATE OR REPLACE FUNCTION _timescaledb_internal.get_git_commit() RETURNS TEXT
AS '$libdir/timescaledb', 'get_git_commit' LANGUAGE C IMMUTABLE STRICT;
AS '@MODULE_PATHNAME@', 'get_git_commit' LANGUAGE C IMMUTABLE STRICT;
-- this trigger function causes an invalidation event on the table whose name is
-- passed in as the first element.
CREATE OR REPLACE FUNCTION _timescaledb_cache.invalidate_relcache_trigger()
RETURNS TRIGGER AS '$libdir/timescaledb', 'invalidate_relcache_trigger' LANGUAGE C;
RETURNS TRIGGER AS '@MODULE_PATHNAME@', 'invalidate_relcache_trigger' LANGUAGE C;
-- This function is only used for debugging
CREATE OR REPLACE FUNCTION _timescaledb_cache.invalidate_relcache(proxy_oid OID)
RETURNS BOOLEAN AS '$libdir/timescaledb', 'invalidate_relcache' LANGUAGE C;
RETURNS BOOLEAN AS '@MODULE_PATHNAME@', 'invalidate_relcache' LANGUAGE C;
-- This file contains utility functions to get the relation size
@ -2364,27 +2364,27 @@ END;
$BODY$;
CREATE OR REPLACE FUNCTION _timescaledb_internal.hist_sfunc (state INTERNAL, val DOUBLE PRECISION, MIN DOUBLE PRECISION, MAX DOUBLE PRECISION, nbuckets INTEGER)
RETURNS INTERNAL
AS '$libdir/timescaledb', 'hist_sfunc'
AS '@MODULE_PATHNAME@', 'hist_sfunc'
LANGUAGE C IMMUTABLE;
CREATE OR REPLACE FUNCTION _timescaledb_internal.hist_combinefunc(state1 INTERNAL, state2 INTERNAL)
RETURNS INTERNAL
AS '$libdir/timescaledb', 'hist_combinefunc'
AS '@MODULE_PATHNAME@', 'hist_combinefunc'
LANGUAGE C IMMUTABLE;
CREATE OR REPLACE FUNCTION _timescaledb_internal.hist_serializefunc(INTERNAL)
RETURNS bytea
AS '$libdir/timescaledb', 'hist_serializefunc'
AS '@MODULE_PATHNAME@', 'hist_serializefunc'
LANGUAGE C IMMUTABLE;
CREATE OR REPLACE FUNCTION _timescaledb_internal.hist_deserializefunc(bytea, INTERNAL)
RETURNS INTERNAL
AS '$libdir/timescaledb', 'hist_deserializefunc'
AS '@MODULE_PATHNAME@', 'hist_deserializefunc'
LANGUAGE C IMMUTABLE;
CREATE OR REPLACE FUNCTION _timescaledb_internal.hist_finalfunc(state INTERNAL, val DOUBLE PRECISION, MIN DOUBLE PRECISION, MAX DOUBLE PRECISION, nbuckets INTEGER)
RETURNS INTEGER[]
AS '$libdir/timescaledb', 'hist_finalfunc'
AS '@MODULE_PATHNAME@', 'hist_finalfunc'
LANGUAGE C IMMUTABLE;
-- Tell Postgres how to use the new function

@ -164,14 +164,14 @@ CREATE OR REPLACE FUNCTION _timescaledb_internal.dimension_calculate_default_ran
interval_length BIGINT,
OUT range_start BIGINT,
OUT range_end BIGINT)
AS '$libdir/timescaledb', 'dimension_calculate_open_range_default' LANGUAGE C STABLE;
AS '@MODULE_PATHNAME@', 'dimension_calculate_open_range_default' LANGUAGE C STABLE;
CREATE OR REPLACE FUNCTION _timescaledb_internal.dimension_calculate_default_range_closed(
dimension_value BIGINT,
num_slices SMALLINT,
OUT range_start BIGINT,
OUT range_end BIGINT)
AS '$libdir/timescaledb', 'dimension_calculate_closed_range_default' LANGUAGE C STABLE;
AS '@MODULE_PATHNAME@', 'dimension_calculate_closed_range_default' LANGUAGE C STABLE;
CREATE OR REPLACE FUNCTION _timescaledb_internal.drop_chunk_metadata(
chunk_id int
@ -717,7 +717,7 @@ END
$BODY$;
CREATE OR REPLACE FUNCTION _timescaledb_internal.verify_hypertable_indexes(hypertable REGCLASS) RETURNS VOID
AS '$libdir/timescaledb', 'indexing_verify_hypertable_indexes' LANGUAGE C IMMUTABLE STRICT;
AS '@MODULE_PATHNAME@', 'indexing_verify_hypertable_indexes' LANGUAGE C IMMUTABLE STRICT;
CREATE OR REPLACE FUNCTION _timescaledb_internal.ddl_change_owner(main_table OID, new_table_owner NAME)
RETURNS void LANGUAGE plpgsql
@ -746,16 +746,16 @@ END
$BODY$;
-- This file contains utilities for time conversion.
CREATE OR REPLACE FUNCTION _timescaledb_internal.to_microseconds(ts TIMESTAMPTZ) RETURNS BIGINT
AS '$libdir/timescaledb', 'pg_timestamp_to_microseconds' LANGUAGE C IMMUTABLE STRICT;
AS '@MODULE_PATHNAME@', 'pg_timestamp_to_microseconds' LANGUAGE C IMMUTABLE STRICT;
CREATE OR REPLACE FUNCTION _timescaledb_internal.to_unix_microseconds(ts TIMESTAMPTZ) RETURNS BIGINT
AS '$libdir/timescaledb', 'pg_timestamp_to_unix_microseconds' LANGUAGE C IMMUTABLE STRICT;
AS '@MODULE_PATHNAME@', 'pg_timestamp_to_unix_microseconds' LANGUAGE C IMMUTABLE STRICT;
CREATE OR REPLACE FUNCTION _timescaledb_internal.to_timestamp(unixtime_us BIGINT) RETURNS TIMESTAMPTZ
AS '$libdir/timescaledb', 'pg_unix_microseconds_to_timestamp' LANGUAGE C IMMUTABLE STRICT;
AS '@MODULE_PATHNAME@', 'pg_unix_microseconds_to_timestamp' LANGUAGE C IMMUTABLE STRICT;
CREATE OR REPLACE FUNCTION _timescaledb_internal.to_timestamp_pg(postgres_us BIGINT) RETURNS TIMESTAMPTZ
AS '$libdir/timescaledb', 'pg_microseconds_to_timestamp' LANGUAGE C IMMUTABLE STRICT;
AS '@MODULE_PATHNAME@', 'pg_microseconds_to_timestamp' LANGUAGE C IMMUTABLE STRICT;
-- Time can be represented in a hypertable as an int* (bigint/integer/smallint) or as a timestamp type (
@ -1219,7 +1219,7 @@ $BODY$;
-- our default partitioning function.
-- returns a hash of val modulous the mod_factor
CREATE OR REPLACE FUNCTION _timescaledb_internal.get_partition_for_key(val text) RETURNS int
AS '$libdir/timescaledb', 'get_partition_for_key' LANGUAGE C IMMUTABLE STRICT;
AS '@MODULE_PATHNAME@', 'get_partition_for_key' LANGUAGE C IMMUTABLE STRICT;
-- This file contains functions related to getting information about the
-- schema of a hypertable, including columns, their types, etc.
@ -1620,7 +1620,7 @@ BEGIN
END
$BODY$;
CREATE OR REPLACE FUNCTION _timescaledb_internal.ddl_command_end() RETURNS event_trigger
AS '$libdir/timescaledb', 'timescaledb_ddl_command_end' LANGUAGE C IMMUTABLE STRICT;
AS '@MODULE_PATHNAME@', 'timescaledb_ddl_command_end' LANGUAGE C IMMUTABLE STRICT;
DROP EVENT TRIGGER IF EXISTS timescaledb_ddl_command_end;
CREATE EVENT TRIGGER timescaledb_ddl_command_end ON ddl_command_end
@ -1748,37 +1748,37 @@ END
$BODY$;
CREATE OR REPLACE FUNCTION _timescaledb_internal.first_sfunc(internal, anyelement, "any")
RETURNS internal
AS '$libdir/timescaledb', 'first_sfunc'
AS '@MODULE_PATHNAME@', 'first_sfunc'
LANGUAGE C IMMUTABLE;
CREATE OR REPLACE FUNCTION _timescaledb_internal.first_combinefunc(internal, internal)
RETURNS internal
AS '$libdir/timescaledb', 'first_combinefunc'
AS '@MODULE_PATHNAME@', 'first_combinefunc'
LANGUAGE C IMMUTABLE;
CREATE OR REPLACE FUNCTION _timescaledb_internal.last_sfunc(internal, anyelement, "any")
RETURNS internal
AS '$libdir/timescaledb', 'last_sfunc'
AS '@MODULE_PATHNAME@', 'last_sfunc'
LANGUAGE C IMMUTABLE;
CREATE OR REPLACE FUNCTION _timescaledb_internal.last_combinefunc(internal, internal)
RETURNS internal
AS '$libdir/timescaledb', 'last_combinefunc'
AS '@MODULE_PATHNAME@', 'last_combinefunc'
LANGUAGE C IMMUTABLE;
CREATE OR REPLACE FUNCTION _timescaledb_internal.bookend_finalfunc(internal, anyelement, "any")
RETURNS anyelement
AS '$libdir/timescaledb', 'bookend_finalfunc'
AS '@MODULE_PATHNAME@', 'bookend_finalfunc'
LANGUAGE C IMMUTABLE;
CREATE OR REPLACE FUNCTION _timescaledb_internal.bookend_serializefunc(internal)
RETURNS bytea
AS '$libdir/timescaledb', 'bookend_serializefunc'
AS '@MODULE_PATHNAME@', 'bookend_serializefunc'
LANGUAGE C IMMUTABLE;
CREATE OR REPLACE FUNCTION _timescaledb_internal.bookend_deserializefunc(bytea, internal)
RETURNS internal
AS '$libdir/timescaledb', 'bookend_deserializefunc'
AS '@MODULE_PATHNAME@', 'bookend_deserializefunc'
LANGUAGE C IMMUTABLE;
--This aggregate returns the "first" element of the first argument when ordered by the second argument.
@ -1813,15 +1813,15 @@ CREATE AGGREGATE last(anyelement, "any") (
-- time_bucket returns the left edge of the bucket where ts falls into.
-- Buckets span an interval of time equal to the bucket_width and are aligned with the epoch.
CREATE OR REPLACE FUNCTION time_bucket(bucket_width INTERVAL, ts TIMESTAMP) RETURNS TIMESTAMP
AS '$libdir/timescaledb', 'timestamp_bucket' LANGUAGE C IMMUTABLE PARALLEL SAFE;
AS '@MODULE_PATHNAME@', 'timestamp_bucket' LANGUAGE C IMMUTABLE PARALLEL SAFE;
-- bucketing of timestamptz happens at UTC time
CREATE OR REPLACE FUNCTION time_bucket(bucket_width INTERVAL, ts TIMESTAMPTZ) RETURNS TIMESTAMPTZ
AS '$libdir/timescaledb', 'timestamptz_bucket' LANGUAGE C IMMUTABLE PARALLEL SAFE;
AS '@MODULE_PATHNAME@', 'timestamptz_bucket' LANGUAGE C IMMUTABLE PARALLEL SAFE;
--bucketing on date should not do any timezone conversion
CREATE OR REPLACE FUNCTION time_bucket(bucket_width INTERVAL, ts DATE) RETURNS DATE
AS '$libdir/timescaledb', 'date_bucket' LANGUAGE C IMMUTABLE PARALLEL SAFE;
AS '@MODULE_PATHNAME@', 'date_bucket' LANGUAGE C IMMUTABLE PARALLEL SAFE;
-- If an interval is given as the third argument, the bucket alignment is offset by the interval.
CREATE OR REPLACE FUNCTION time_bucket(bucket_width INTERVAL, ts TIMESTAMP, "offset" INTERVAL)
@ -1879,15 +1879,15 @@ $BODY$
SELECT (((ts-"offset") / bucket_width)*bucket_width)+"offset";
$BODY$;
CREATE OR REPLACE FUNCTION _timescaledb_internal.get_git_commit() RETURNS TEXT
AS '$libdir/timescaledb', 'get_git_commit' LANGUAGE C IMMUTABLE STRICT;
AS '@MODULE_PATHNAME@', 'get_git_commit' LANGUAGE C IMMUTABLE STRICT;
-- this trigger function causes an invalidation event on the table whose name is
-- passed in as the first element.
CREATE OR REPLACE FUNCTION _timescaledb_cache.invalidate_relcache_trigger()
RETURNS TRIGGER AS '$libdir/timescaledb', 'invalidate_relcache_trigger' LANGUAGE C;
RETURNS TRIGGER AS '@MODULE_PATHNAME@', 'invalidate_relcache_trigger' LANGUAGE C;
-- This function is only used for debugging
CREATE OR REPLACE FUNCTION _timescaledb_cache.invalidate_relcache(proxy_oid OID)
RETURNS BOOLEAN AS '$libdir/timescaledb', 'invalidate_relcache' LANGUAGE C;
RETURNS BOOLEAN AS '@MODULE_PATHNAME@', 'invalidate_relcache' LANGUAGE C;
-- This file contains utility functions to get the relation size
@ -2307,27 +2307,27 @@ END;
$BODY$;
CREATE OR REPLACE FUNCTION _timescaledb_internal.hist_sfunc (state INTERNAL, val DOUBLE PRECISION, MIN DOUBLE PRECISION, MAX DOUBLE PRECISION, nbuckets INTEGER)
RETURNS INTERNAL
AS '$libdir/timescaledb', 'hist_sfunc'
AS '@MODULE_PATHNAME@', 'hist_sfunc'
LANGUAGE C IMMUTABLE;
CREATE OR REPLACE FUNCTION _timescaledb_internal.hist_combinefunc(state1 INTERNAL, state2 INTERNAL)
RETURNS INTERNAL
AS '$libdir/timescaledb', 'hist_combinefunc'
AS '@MODULE_PATHNAME@', 'hist_combinefunc'
LANGUAGE C IMMUTABLE;
CREATE OR REPLACE FUNCTION _timescaledb_internal.hist_serializefunc(INTERNAL)
RETURNS bytea
AS '$libdir/timescaledb', 'hist_serializefunc'
AS '@MODULE_PATHNAME@', 'hist_serializefunc'
LANGUAGE C IMMUTABLE;
CREATE OR REPLACE FUNCTION _timescaledb_internal.hist_deserializefunc(bytea, INTERNAL)
RETURNS INTERNAL
AS '$libdir/timescaledb', 'hist_deserializefunc'
AS '@MODULE_PATHNAME@', 'hist_deserializefunc'
LANGUAGE C IMMUTABLE;
CREATE OR REPLACE FUNCTION _timescaledb_internal.hist_finalfunc(state INTERNAL, val DOUBLE PRECISION, MIN DOUBLE PRECISION, MAX DOUBLE PRECISION, nbuckets INTEGER)
RETURNS INTEGER[]
AS '$libdir/timescaledb', 'hist_finalfunc'
AS '@MODULE_PATHNAME@', 'hist_finalfunc'
LANGUAGE C IMMUTABLE;
-- Tell Postgres how to use the new function

@ -201,14 +201,14 @@ CREATE OR REPLACE FUNCTION _timescaledb_internal.dimension_calculate_default_ran
interval_length BIGINT,
OUT range_start BIGINT,
OUT range_end BIGINT)
AS '$libdir/timescaledb', 'dimension_calculate_open_range_default' LANGUAGE C STABLE;
AS '@MODULE_PATHNAME@', 'dimension_calculate_open_range_default' LANGUAGE C STABLE;
CREATE OR REPLACE FUNCTION _timescaledb_internal.dimension_calculate_default_range_closed(
dimension_value BIGINT,
num_slices SMALLINT,
OUT range_start BIGINT,
OUT range_end BIGINT)
AS '$libdir/timescaledb', 'dimension_calculate_closed_range_default' LANGUAGE C STABLE;
AS '@MODULE_PATHNAME@', 'dimension_calculate_closed_range_default' LANGUAGE C STABLE;
CREATE OR REPLACE FUNCTION _timescaledb_internal.drop_chunk_metadata(
chunk_id int
@ -812,7 +812,7 @@ END
$BODY$;
CREATE OR REPLACE FUNCTION _timescaledb_internal.verify_hypertable_indexes(hypertable REGCLASS) RETURNS VOID
AS '$libdir/timescaledb', 'indexing_verify_hypertable_indexes' LANGUAGE C STRICT;
AS '@MODULE_PATHNAME@', 'indexing_verify_hypertable_indexes' LANGUAGE C STRICT;
CREATE OR REPLACE FUNCTION _timescaledb_internal.ddl_change_owner(main_table OID, new_table_owner NAME)
RETURNS void LANGUAGE plpgsql
@ -841,16 +841,16 @@ END
$BODY$;
-- This file contains utilities for time conversion.
CREATE OR REPLACE FUNCTION _timescaledb_internal.to_microseconds(ts TIMESTAMPTZ) RETURNS BIGINT
AS '$libdir/timescaledb', 'pg_timestamp_to_microseconds' LANGUAGE C IMMUTABLE STRICT PARALLEL SAFE;
AS '@MODULE_PATHNAME@', 'pg_timestamp_to_microseconds' LANGUAGE C IMMUTABLE STRICT PARALLEL SAFE;
CREATE OR REPLACE FUNCTION _timescaledb_internal.to_unix_microseconds(ts TIMESTAMPTZ) RETURNS BIGINT
AS '$libdir/timescaledb', 'pg_timestamp_to_unix_microseconds' LANGUAGE C IMMUTABLE STRICT PARALLEL SAFE;
AS '@MODULE_PATHNAME@', 'pg_timestamp_to_unix_microseconds' LANGUAGE C IMMUTABLE STRICT PARALLEL SAFE;
CREATE OR REPLACE FUNCTION _timescaledb_internal.to_timestamp(unixtime_us BIGINT) RETURNS TIMESTAMPTZ
AS '$libdir/timescaledb', 'pg_unix_microseconds_to_timestamp' LANGUAGE C IMMUTABLE STRICT PARALLEL SAFE;
AS '@MODULE_PATHNAME@', 'pg_unix_microseconds_to_timestamp' LANGUAGE C IMMUTABLE STRICT PARALLEL SAFE;
CREATE OR REPLACE FUNCTION _timescaledb_internal.to_timestamp_pg(postgres_us BIGINT) RETURNS TIMESTAMPTZ
AS '$libdir/timescaledb', 'pg_microseconds_to_timestamp' LANGUAGE C IMMUTABLE STRICT PARALLEL SAFE;
AS '@MODULE_PATHNAME@', 'pg_microseconds_to_timestamp' LANGUAGE C IMMUTABLE STRICT PARALLEL SAFE;
-- Time can be represented in a hypertable as an int* (bigint/integer/smallint) or as a timestamp type (
@ -1193,7 +1193,7 @@ END
$BODY$;
CREATE OR REPLACE FUNCTION _timescaledb_internal.validate_triggers(main_table REGCLASS) RETURNS VOID
AS '$libdir/timescaledb', 'hypertable_validate_triggers' LANGUAGE C STRICT;
AS '@MODULE_PATHNAME@', 'hypertable_validate_triggers' LANGUAGE C STRICT;
-- Creates a constraint on a chunk.
CREATE OR REPLACE FUNCTION _timescaledb_internal.chunk_constraint_add_table_constraint(
chunk_constraint_row _timescaledb_catalog.chunk_constraint
@ -1340,11 +1340,11 @@ $BODY$;
-- Deprecated partition hash function
CREATE OR REPLACE FUNCTION _timescaledb_internal.get_partition_for_key(val anyelement)
RETURNS int
AS '$libdir/timescaledb', 'get_partition_for_key' LANGUAGE C IMMUTABLE STRICT PARALLEL SAFE;
AS '@MODULE_PATHNAME@', 'get_partition_for_key' LANGUAGE C IMMUTABLE STRICT PARALLEL SAFE;
CREATE OR REPLACE FUNCTION _timescaledb_internal.get_partition_hash(val anyelement)
RETURNS int
AS '$libdir/timescaledb', 'get_partition_hash' LANGUAGE C IMMUTABLE STRICT PARALLEL SAFE;
AS '@MODULE_PATHNAME@', 'get_partition_hash' LANGUAGE C IMMUTABLE STRICT PARALLEL SAFE;
-- This file contains functions related to getting information about the
-- schema of a hypertable, including columns, their types, etc.
@ -1752,7 +1752,7 @@ BEGIN
END
$BODY$;
CREATE OR REPLACE FUNCTION _timescaledb_internal.ddl_command_end() RETURNS event_trigger
AS '$libdir/timescaledb', 'timescaledb_ddl_command_end' LANGUAGE C;
AS '@MODULE_PATHNAME@', 'timescaledb_ddl_command_end' LANGUAGE C;
DROP EVENT TRIGGER IF EXISTS timescaledb_ddl_command_end;
CREATE EVENT TRIGGER timescaledb_ddl_command_end ON ddl_command_end
@ -1880,37 +1880,37 @@ END
$BODY$;
CREATE OR REPLACE FUNCTION _timescaledb_internal.first_sfunc(internal, anyelement, "any")
RETURNS internal
AS '$libdir/timescaledb', 'first_sfunc'
AS '@MODULE_PATHNAME@', 'first_sfunc'
LANGUAGE C IMMUTABLE PARALLEL SAFE;
CREATE OR REPLACE FUNCTION _timescaledb_internal.first_combinefunc(internal, internal)
RETURNS internal
AS '$libdir/timescaledb', 'first_combinefunc'
AS '@MODULE_PATHNAME@', 'first_combinefunc'
LANGUAGE C IMMUTABLE PARALLEL SAFE;
CREATE OR REPLACE FUNCTION _timescaledb_internal.last_sfunc(internal, anyelement, "any")
RETURNS internal
AS '$libdir/timescaledb', 'last_sfunc'
AS '@MODULE_PATHNAME@', 'last_sfunc'
LANGUAGE C IMMUTABLE PARALLEL SAFE;
CREATE OR REPLACE FUNCTION _timescaledb_internal.last_combinefunc(internal, internal)
RETURNS internal
AS '$libdir/timescaledb', 'last_combinefunc'
AS '@MODULE_PATHNAME@', 'last_combinefunc'
LANGUAGE C IMMUTABLE PARALLEL SAFE;
CREATE OR REPLACE FUNCTION _timescaledb_internal.bookend_finalfunc(internal, anyelement, "any")
RETURNS anyelement
AS '$libdir/timescaledb', 'bookend_finalfunc'
AS '@MODULE_PATHNAME@', 'bookend_finalfunc'
LANGUAGE C IMMUTABLE PARALLEL SAFE;
CREATE OR REPLACE FUNCTION _timescaledb_internal.bookend_serializefunc(internal)
RETURNS bytea
AS '$libdir/timescaledb', 'bookend_serializefunc'
AS '@MODULE_PATHNAME@', 'bookend_serializefunc'
LANGUAGE C IMMUTABLE STRICT PARALLEL SAFE;
CREATE OR REPLACE FUNCTION _timescaledb_internal.bookend_deserializefunc(bytea, internal)
RETURNS internal
AS '$libdir/timescaledb', 'bookend_deserializefunc'
AS '@MODULE_PATHNAME@', 'bookend_deserializefunc'
LANGUAGE C IMMUTABLE STRICT PARALLEL SAFE;
--This aggregate returns the "first" element of the first argument when ordered by the second argument.
@ -1943,15 +1943,15 @@ CREATE AGGREGATE last(anyelement, "any") (
-- time_bucket returns the left edge of the bucket where ts falls into.
-- Buckets span an interval of time equal to the bucket_width and are aligned with the epoch.
CREATE OR REPLACE FUNCTION time_bucket(bucket_width INTERVAL, ts TIMESTAMP) RETURNS TIMESTAMP
AS '$libdir/timescaledb', 'timestamp_bucket' LANGUAGE C IMMUTABLE PARALLEL SAFE;
AS '@MODULE_PATHNAME@', 'timestamp_bucket' LANGUAGE C IMMUTABLE PARALLEL SAFE;
-- bucketing of timestamptz happens at UTC time
CREATE OR REPLACE FUNCTION time_bucket(bucket_width INTERVAL, ts TIMESTAMPTZ) RETURNS TIMESTAMPTZ
AS '$libdir/timescaledb', 'timestamptz_bucket' LANGUAGE C IMMUTABLE PARALLEL SAFE;
AS '@MODULE_PATHNAME@', 'timestamptz_bucket' LANGUAGE C IMMUTABLE PARALLEL SAFE;
--bucketing on date should not do any timezone conversion
CREATE OR REPLACE FUNCTION time_bucket(bucket_width INTERVAL, ts DATE) RETURNS DATE
AS '$libdir/timescaledb', 'date_bucket' LANGUAGE C IMMUTABLE PARALLEL SAFE;
AS '@MODULE_PATHNAME@', 'date_bucket' LANGUAGE C IMMUTABLE PARALLEL SAFE;
-- If an interval is given as the third argument, the bucket alignment is offset by the interval.
CREATE OR REPLACE FUNCTION time_bucket(bucket_width INTERVAL, ts TIMESTAMP, "offset" INTERVAL)
@ -2009,15 +2009,15 @@ $BODY$
SELECT (((ts-"offset") / bucket_width)*bucket_width)+"offset";
$BODY$;
CREATE OR REPLACE FUNCTION _timescaledb_internal.get_git_commit() RETURNS TEXT
AS '$libdir/timescaledb', 'get_git_commit' LANGUAGE C IMMUTABLE STRICT PARALLEL SAFE;
AS '@MODULE_PATHNAME@', 'get_git_commit' LANGUAGE C IMMUTABLE STRICT PARALLEL SAFE;
-- this trigger function causes an invalidation event on the table whose name is
-- passed in as the first element.
CREATE OR REPLACE FUNCTION _timescaledb_cache.invalidate_relcache_trigger()
RETURNS TRIGGER AS '$libdir/timescaledb', 'invalidate_relcache_trigger' LANGUAGE C;
RETURNS TRIGGER AS '@MODULE_PATHNAME@', 'invalidate_relcache_trigger' LANGUAGE C;
-- This function is only used for debugging
CREATE OR REPLACE FUNCTION _timescaledb_cache.invalidate_relcache(proxy_oid OID)
RETURNS BOOLEAN AS '$libdir/timescaledb', 'invalidate_relcache' LANGUAGE C;
RETURNS BOOLEAN AS '@MODULE_PATHNAME@', 'invalidate_relcache' LANGUAGE C;
-- This file contains utility functions to get the relation size
@ -2440,27 +2440,27 @@ END;
$BODY$;
CREATE OR REPLACE FUNCTION _timescaledb_internal.hist_sfunc (state INTERNAL, val DOUBLE PRECISION, MIN DOUBLE PRECISION, MAX DOUBLE PRECISION, nbuckets INTEGER)
RETURNS INTERNAL
AS '$libdir/timescaledb', 'hist_sfunc'
AS '@MODULE_PATHNAME@', 'hist_sfunc'
LANGUAGE C IMMUTABLE PARALLEL SAFE;
CREATE OR REPLACE FUNCTION _timescaledb_internal.hist_combinefunc(state1 INTERNAL, state2 INTERNAL)
RETURNS INTERNAL
AS '$libdir/timescaledb', 'hist_combinefunc'
AS '@MODULE_PATHNAME@', 'hist_combinefunc'
LANGUAGE C IMMUTABLE PARALLEL SAFE;
CREATE OR REPLACE FUNCTION _timescaledb_internal.hist_serializefunc(INTERNAL)
RETURNS bytea
AS '$libdir/timescaledb', 'hist_serializefunc'
AS '@MODULE_PATHNAME@', 'hist_serializefunc'
LANGUAGE C IMMUTABLE STRICT PARALLEL SAFE;
CREATE OR REPLACE FUNCTION _timescaledb_internal.hist_deserializefunc(bytea, INTERNAL)
RETURNS INTERNAL
AS '$libdir/timescaledb', 'hist_deserializefunc'
AS '@MODULE_PATHNAME@', 'hist_deserializefunc'
LANGUAGE C IMMUTABLE STRICT PARALLEL SAFE;
CREATE OR REPLACE FUNCTION _timescaledb_internal.hist_finalfunc(state INTERNAL, val DOUBLE PRECISION, MIN DOUBLE PRECISION, MAX DOUBLE PRECISION, nbuckets INTEGER)
RETURNS INTEGER[]
AS '$libdir/timescaledb', 'hist_finalfunc'
AS '@MODULE_PATHNAME@', 'hist_finalfunc'
LANGUAGE C IMMUTABLE PARALLEL SAFE;
-- Tell Postgres how to use the new function

@ -210,14 +210,14 @@ CREATE OR REPLACE FUNCTION _timescaledb_internal.dimension_calculate_default_ran
interval_length BIGINT,
OUT range_start BIGINT,
OUT range_end BIGINT)
AS '$libdir/timescaledb', 'dimension_calculate_open_range_default' LANGUAGE C STABLE;
AS '@MODULE_PATHNAME@', 'dimension_calculate_open_range_default' LANGUAGE C STABLE;
CREATE OR REPLACE FUNCTION _timescaledb_internal.dimension_calculate_default_range_closed(
dimension_value BIGINT,
num_slices SMALLINT,
OUT range_start BIGINT,
OUT range_end BIGINT)
AS '$libdir/timescaledb', 'dimension_calculate_closed_range_default' LANGUAGE C STABLE;
AS '@MODULE_PATHNAME@', 'dimension_calculate_closed_range_default' LANGUAGE C STABLE;
CREATE OR REPLACE FUNCTION _timescaledb_internal.drop_chunk_metadata(
chunk_id int
@ -821,7 +821,7 @@ END
$BODY$;
CREATE OR REPLACE FUNCTION _timescaledb_internal.verify_hypertable_indexes(hypertable REGCLASS) RETURNS VOID
AS '$libdir/timescaledb', 'indexing_verify_hypertable_indexes' LANGUAGE C STRICT;
AS '@MODULE_PATHNAME@', 'indexing_verify_hypertable_indexes' LANGUAGE C STRICT;
CREATE OR REPLACE FUNCTION _timescaledb_internal.ddl_change_owner(main_table OID, new_table_owner NAME)
RETURNS void LANGUAGE plpgsql
@ -850,16 +850,16 @@ END
$BODY$;
-- This file contains utilities for time conversion.
CREATE OR REPLACE FUNCTION _timescaledb_internal.to_microseconds(ts TIMESTAMPTZ) RETURNS BIGINT
AS '$libdir/timescaledb', 'pg_timestamp_to_microseconds' LANGUAGE C IMMUTABLE STRICT PARALLEL SAFE;
AS '@MODULE_PATHNAME@', 'pg_timestamp_to_microseconds' LANGUAGE C IMMUTABLE STRICT PARALLEL SAFE;
CREATE OR REPLACE FUNCTION _timescaledb_internal.to_unix_microseconds(ts TIMESTAMPTZ) RETURNS BIGINT
AS '$libdir/timescaledb', 'pg_timestamp_to_unix_microseconds' LANGUAGE C IMMUTABLE STRICT PARALLEL SAFE;
AS '@MODULE_PATHNAME@', 'pg_timestamp_to_unix_microseconds' LANGUAGE C IMMUTABLE STRICT PARALLEL SAFE;
CREATE OR REPLACE FUNCTION _timescaledb_internal.to_timestamp(unixtime_us BIGINT) RETURNS TIMESTAMPTZ
AS '$libdir/timescaledb', 'pg_unix_microseconds_to_timestamp' LANGUAGE C IMMUTABLE STRICT PARALLEL SAFE;
AS '@MODULE_PATHNAME@', 'pg_unix_microseconds_to_timestamp' LANGUAGE C IMMUTABLE STRICT PARALLEL SAFE;
CREATE OR REPLACE FUNCTION _timescaledb_internal.to_timestamp_pg(postgres_us BIGINT) RETURNS TIMESTAMPTZ
AS '$libdir/timescaledb', 'pg_microseconds_to_timestamp' LANGUAGE C IMMUTABLE STRICT PARALLEL SAFE;
AS '@MODULE_PATHNAME@', 'pg_microseconds_to_timestamp' LANGUAGE C IMMUTABLE STRICT PARALLEL SAFE;
-- Time can be represented in a hypertable as an int* (bigint/integer/smallint) or as a timestamp type (
@ -1202,7 +1202,7 @@ END
$BODY$;
CREATE OR REPLACE FUNCTION _timescaledb_internal.validate_triggers(main_table REGCLASS) RETURNS VOID
AS '$libdir/timescaledb', 'hypertable_validate_triggers' LANGUAGE C STRICT;
AS '@MODULE_PATHNAME@', 'hypertable_validate_triggers' LANGUAGE C STRICT;
-- Creates a constraint on a chunk.
CREATE OR REPLACE FUNCTION _timescaledb_internal.chunk_constraint_add_table_constraint(
chunk_constraint_row _timescaledb_catalog.chunk_constraint
@ -1349,11 +1349,11 @@ $BODY$;
-- Deprecated partition hash function
CREATE OR REPLACE FUNCTION _timescaledb_internal.get_partition_for_key(val anyelement)
RETURNS int
AS '$libdir/timescaledb', 'get_partition_for_key' LANGUAGE C IMMUTABLE STRICT PARALLEL SAFE;
AS '@MODULE_PATHNAME@', 'get_partition_for_key' LANGUAGE C IMMUTABLE STRICT PARALLEL SAFE;
CREATE OR REPLACE FUNCTION _timescaledb_internal.get_partition_hash(val anyelement)
RETURNS int
AS '$libdir/timescaledb', 'get_partition_hash' LANGUAGE C IMMUTABLE STRICT PARALLEL SAFE;
AS '@MODULE_PATHNAME@', 'get_partition_hash' LANGUAGE C IMMUTABLE STRICT PARALLEL SAFE;
-- This file contains functions related to getting information about the
-- schema of a hypertable, including columns, their types, etc.
@ -1761,7 +1761,7 @@ BEGIN
END
$BODY$;
CREATE OR REPLACE FUNCTION _timescaledb_internal.ddl_command_end() RETURNS event_trigger
AS '$libdir/timescaledb', 'timescaledb_ddl_command_end' LANGUAGE C;
AS '@MODULE_PATHNAME@', 'timescaledb_ddl_command_end' LANGUAGE C;
DROP EVENT TRIGGER IF EXISTS timescaledb_ddl_command_end;
CREATE EVENT TRIGGER timescaledb_ddl_command_end ON ddl_command_end
@ -1889,37 +1889,37 @@ END
$BODY$;
CREATE OR REPLACE FUNCTION _timescaledb_internal.first_sfunc(internal, anyelement, "any")
RETURNS internal
AS '$libdir/timescaledb', 'first_sfunc'
AS '@MODULE_PATHNAME@', 'first_sfunc'
LANGUAGE C IMMUTABLE PARALLEL SAFE;
CREATE OR REPLACE FUNCTION _timescaledb_internal.first_combinefunc(internal, internal)
RETURNS internal
AS '$libdir/timescaledb', 'first_combinefunc'
AS '@MODULE_PATHNAME@', 'first_combinefunc'
LANGUAGE C IMMUTABLE PARALLEL SAFE;
CREATE OR REPLACE FUNCTION _timescaledb_internal.last_sfunc(internal, anyelement, "any")
RETURNS internal
AS '$libdir/timescaledb', 'last_sfunc'
AS '@MODULE_PATHNAME@', 'last_sfunc'
LANGUAGE C IMMUTABLE PARALLEL SAFE;
CREATE OR REPLACE FUNCTION _timescaledb_internal.last_combinefunc(internal, internal)
RETURNS internal
AS '$libdir/timescaledb', 'last_combinefunc'
AS '@MODULE_PATHNAME@', 'last_combinefunc'
LANGUAGE C IMMUTABLE PARALLEL SAFE;
CREATE OR REPLACE FUNCTION _timescaledb_internal.bookend_finalfunc(internal, anyelement, "any")
RETURNS anyelement
AS '$libdir/timescaledb', 'bookend_finalfunc'
AS '@MODULE_PATHNAME@', 'bookend_finalfunc'
LANGUAGE C IMMUTABLE PARALLEL SAFE;
CREATE OR REPLACE FUNCTION _timescaledb_internal.bookend_serializefunc(internal)
RETURNS bytea
AS '$libdir/timescaledb', 'bookend_serializefunc'
AS '@MODULE_PATHNAME@', 'bookend_serializefunc'
LANGUAGE C IMMUTABLE STRICT PARALLEL SAFE;
CREATE OR REPLACE FUNCTION _timescaledb_internal.bookend_deserializefunc(bytea, internal)
RETURNS internal
AS '$libdir/timescaledb', 'bookend_deserializefunc'
AS '@MODULE_PATHNAME@', 'bookend_deserializefunc'
LANGUAGE C IMMUTABLE STRICT PARALLEL SAFE;
--This aggregate returns the "first" element of the first argument when ordered by the second argument.
@ -1952,15 +1952,15 @@ CREATE AGGREGATE last(anyelement, "any") (
-- time_bucket returns the left edge of the bucket where ts falls into.
-- Buckets span an interval of time equal to the bucket_width and are aligned with the epoch.
CREATE OR REPLACE FUNCTION time_bucket(bucket_width INTERVAL, ts TIMESTAMP) RETURNS TIMESTAMP
AS '$libdir/timescaledb', 'timestamp_bucket' LANGUAGE C IMMUTABLE PARALLEL SAFE;
AS '@MODULE_PATHNAME@', 'timestamp_bucket' LANGUAGE C IMMUTABLE PARALLEL SAFE;
-- bucketing of timestamptz happens at UTC time
CREATE OR REPLACE FUNCTION time_bucket(bucket_width INTERVAL, ts TIMESTAMPTZ) RETURNS TIMESTAMPTZ
AS '$libdir/timescaledb', 'timestamptz_bucket' LANGUAGE C IMMUTABLE PARALLEL SAFE;
AS '@MODULE_PATHNAME@', 'timestamptz_bucket' LANGUAGE C IMMUTABLE PARALLEL SAFE;
--bucketing on date should not do any timezone conversion
CREATE OR REPLACE FUNCTION time_bucket(bucket_width INTERVAL, ts DATE) RETURNS DATE
AS '$libdir/timescaledb', 'date_bucket' LANGUAGE C IMMUTABLE PARALLEL SAFE;
AS '@MODULE_PATHNAME@', 'date_bucket' LANGUAGE C IMMUTABLE PARALLEL SAFE;
-- If an interval is given as the third argument, the bucket alignment is offset by the interval.
CREATE OR REPLACE FUNCTION time_bucket(bucket_width INTERVAL, ts TIMESTAMP, "offset" INTERVAL)
@ -2018,15 +2018,15 @@ $BODY$
SELECT (((ts-"offset") / bucket_width)*bucket_width)+"offset";
$BODY$;
CREATE OR REPLACE FUNCTION _timescaledb_internal.get_git_commit() RETURNS TEXT
AS '$libdir/timescaledb', 'get_git_commit' LANGUAGE C IMMUTABLE STRICT PARALLEL SAFE;
AS '@MODULE_PATHNAME@', 'get_git_commit' LANGUAGE C IMMUTABLE STRICT PARALLEL SAFE;
-- this trigger function causes an invalidation event on the table whose name is
-- passed in as the first element.
CREATE OR REPLACE FUNCTION _timescaledb_cache.invalidate_relcache_trigger()
RETURNS TRIGGER AS '$libdir/timescaledb', 'invalidate_relcache_trigger' LANGUAGE C;
RETURNS TRIGGER AS '@MODULE_PATHNAME@', 'invalidate_relcache_trigger' LANGUAGE C;
-- This function is only used for debugging
CREATE OR REPLACE FUNCTION _timescaledb_cache.invalidate_relcache(proxy_oid OID)
RETURNS BOOLEAN AS '$libdir/timescaledb', 'invalidate_relcache' LANGUAGE C;
RETURNS BOOLEAN AS '@MODULE_PATHNAME@', 'invalidate_relcache' LANGUAGE C;
-- This file contains utility functions to get the relation size
@ -2449,27 +2449,27 @@ END;
$BODY$;
CREATE OR REPLACE FUNCTION _timescaledb_internal.hist_sfunc (state INTERNAL, val DOUBLE PRECISION, MIN DOUBLE PRECISION, MAX DOUBLE PRECISION, nbuckets INTEGER)
RETURNS INTERNAL
AS '$libdir/timescaledb', 'hist_sfunc'
AS '@MODULE_PATHNAME@', 'hist_sfunc'
LANGUAGE C IMMUTABLE PARALLEL SAFE;
CREATE OR REPLACE FUNCTION _timescaledb_internal.hist_combinefunc(state1 INTERNAL, state2 INTERNAL)
RETURNS INTERNAL
AS '$libdir/timescaledb', 'hist_combinefunc'
AS '@MODULE_PATHNAME@', 'hist_combinefunc'
LANGUAGE C IMMUTABLE PARALLEL SAFE;
CREATE OR REPLACE FUNCTION _timescaledb_internal.hist_serializefunc(INTERNAL)
RETURNS bytea
AS '$libdir/timescaledb', 'hist_serializefunc'
AS '@MODULE_PATHNAME@', 'hist_serializefunc'
LANGUAGE C IMMUTABLE STRICT PARALLEL SAFE;
CREATE OR REPLACE FUNCTION _timescaledb_internal.hist_deserializefunc(bytea, INTERNAL)
RETURNS INTERNAL
AS '$libdir/timescaledb', 'hist_deserializefunc'
AS '@MODULE_PATHNAME@', 'hist_deserializefunc'
LANGUAGE C IMMUTABLE STRICT PARALLEL SAFE;
CREATE OR REPLACE FUNCTION _timescaledb_internal.hist_finalfunc(state INTERNAL, val DOUBLE PRECISION, MIN DOUBLE PRECISION, MAX DOUBLE PRECISION, nbuckets INTEGER)
RETURNS INTEGER[]
AS '$libdir/timescaledb', 'hist_finalfunc'
AS '@MODULE_PATHNAME@', 'hist_finalfunc'
LANGUAGE C IMMUTABLE PARALLEL SAFE;
-- Tell Postgres how to use the new function
@ -2752,14 +2752,14 @@ CREATE OR REPLACE FUNCTION _timescaledb_internal.dimension_calculate_default_ran
interval_length BIGINT,
OUT range_start BIGINT,
OUT range_end BIGINT)
AS '$libdir/timescaledb', 'dimension_calculate_open_range_default' LANGUAGE C STABLE;
AS '@MODULE_PATHNAME@', 'dimension_calculate_open_range_default' LANGUAGE C STABLE;
CREATE OR REPLACE FUNCTION _timescaledb_internal.dimension_calculate_default_range_closed(
dimension_value BIGINT,
num_slices SMALLINT,
OUT range_start BIGINT,
OUT range_end BIGINT)
AS '$libdir/timescaledb', 'dimension_calculate_closed_range_default' LANGUAGE C STABLE;
AS '@MODULE_PATHNAME@', 'dimension_calculate_closed_range_default' LANGUAGE C STABLE;
CREATE OR REPLACE FUNCTION _timescaledb_internal.drop_chunk_metadata(
chunk_id int
@ -3406,7 +3406,7 @@ END
$BODY$;
CREATE OR REPLACE FUNCTION _timescaledb_internal.verify_hypertable_indexes(hypertable REGCLASS) RETURNS VOID
AS '$libdir/timescaledb', 'indexing_verify_hypertable_indexes' LANGUAGE C STRICT;
AS '@MODULE_PATHNAME@', 'indexing_verify_hypertable_indexes' LANGUAGE C STRICT;
CREATE OR REPLACE FUNCTION _timescaledb_internal.ddl_change_owner(main_table OID, new_table_owner NAME)
RETURNS void LANGUAGE plpgsql
@ -3437,22 +3437,22 @@ $BODY$;
--documentation of these function located in chunk_index.h
CREATE OR REPLACE FUNCTION _timescaledb_internal.chunk_index_clone(chunk_index_oid OID) RETURNS OID
AS '$libdir/timescaledb', 'chunk_index_clone' LANGUAGE C VOLATILE STRICT;
AS '@MODULE_PATHNAME@', 'chunk_index_clone' LANGUAGE C VOLATILE STRICT;
CREATE OR REPLACE FUNCTION _timescaledb_internal.chunk_index_replace(chunk_index_oid_old OID, chunk_index_oid_new OID) RETURNS VOID
AS '$libdir/timescaledb', 'chunk_index_replace' LANGUAGE C VOLATILE STRICT;
AS '@MODULE_PATHNAME@', 'chunk_index_replace' LANGUAGE C VOLATILE STRICT;
-- This file contains utilities for time conversion.
CREATE OR REPLACE FUNCTION _timescaledb_internal.to_microseconds(ts TIMESTAMPTZ) RETURNS BIGINT
AS '$libdir/timescaledb', 'pg_timestamp_to_microseconds' LANGUAGE C IMMUTABLE STRICT PARALLEL SAFE;
AS '@MODULE_PATHNAME@', 'pg_timestamp_to_microseconds' LANGUAGE C IMMUTABLE STRICT PARALLEL SAFE;
CREATE OR REPLACE FUNCTION _timescaledb_internal.to_unix_microseconds(ts TIMESTAMPTZ) RETURNS BIGINT
AS '$libdir/timescaledb', 'pg_timestamp_to_unix_microseconds' LANGUAGE C IMMUTABLE STRICT PARALLEL SAFE;
AS '@MODULE_PATHNAME@', 'pg_timestamp_to_unix_microseconds' LANGUAGE C IMMUTABLE STRICT PARALLEL SAFE;
CREATE OR REPLACE FUNCTION _timescaledb_internal.to_timestamp(unixtime_us BIGINT) RETURNS TIMESTAMPTZ
AS '$libdir/timescaledb', 'pg_unix_microseconds_to_timestamp' LANGUAGE C IMMUTABLE STRICT PARALLEL SAFE;
AS '@MODULE_PATHNAME@', 'pg_unix_microseconds_to_timestamp' LANGUAGE C IMMUTABLE STRICT PARALLEL SAFE;
CREATE OR REPLACE FUNCTION _timescaledb_internal.to_timestamp_pg(postgres_us BIGINT) RETURNS TIMESTAMPTZ
AS '$libdir/timescaledb', 'pg_microseconds_to_timestamp' LANGUAGE C IMMUTABLE STRICT PARALLEL SAFE;
AS '@MODULE_PATHNAME@', 'pg_microseconds_to_timestamp' LANGUAGE C IMMUTABLE STRICT PARALLEL SAFE;
-- Time can be represented in a hypertable as an int* (bigint/integer/smallint) or as a timestamp type (
@ -3546,7 +3546,7 @@ END
$BODY$;
CREATE OR REPLACE FUNCTION _timescaledb_internal.time_to_internal(time_element anyelement, time_type REGTYPE) RETURNS BIGINT
AS '$libdir/timescaledb', 'time_to_internal' LANGUAGE C IMMUTABLE PARALLEL SAFE STRICT;
AS '@MODULE_PATHNAME@', 'time_to_internal' LANGUAGE C IMMUTABLE PARALLEL SAFE STRICT;
-- This file contains functions associated with creating new
-- hypertables.
@ -3798,7 +3798,7 @@ END
$BODY$;
CREATE OR REPLACE FUNCTION _timescaledb_internal.validate_triggers(main_table REGCLASS) RETURNS VOID
AS '$libdir/timescaledb', 'hypertable_validate_triggers' LANGUAGE C STRICT;
AS '@MODULE_PATHNAME@', 'hypertable_validate_triggers' LANGUAGE C STRICT;
-- Creates a constraint on a chunk.
CREATE OR REPLACE FUNCTION _timescaledb_internal.chunk_constraint_add_table_constraint(
chunk_constraint_row _timescaledb_catalog.chunk_constraint
@ -3945,11 +3945,11 @@ $BODY$;
-- Deprecated partition hash function
CREATE OR REPLACE FUNCTION _timescaledb_internal.get_partition_for_key(val anyelement)
RETURNS int
AS '$libdir/timescaledb', 'get_partition_for_key' LANGUAGE C IMMUTABLE STRICT PARALLEL SAFE;
AS '@MODULE_PATHNAME@', 'get_partition_for_key' LANGUAGE C IMMUTABLE STRICT PARALLEL SAFE;
CREATE OR REPLACE FUNCTION _timescaledb_internal.get_partition_hash(val anyelement)
RETURNS int
AS '$libdir/timescaledb', 'get_partition_hash' LANGUAGE C IMMUTABLE STRICT PARALLEL SAFE;
AS '@MODULE_PATHNAME@', 'get_partition_hash' LANGUAGE C IMMUTABLE STRICT PARALLEL SAFE;
-- This file contains functions related to getting information about the
-- schema of a hypertable, including columns, their types, etc.
@ -4345,7 +4345,7 @@ BEGIN
END
$BODY$;
CREATE OR REPLACE FUNCTION _timescaledb_internal.ddl_command_end() RETURNS event_trigger
AS '$libdir/timescaledb', 'timescaledb_ddl_command_end' LANGUAGE C;
AS '@MODULE_PATHNAME@', 'timescaledb_ddl_command_end' LANGUAGE C;
DROP EVENT TRIGGER IF EXISTS timescaledb_ddl_command_end;
CREATE EVENT TRIGGER timescaledb_ddl_command_end ON ddl_command_end
@ -4473,37 +4473,37 @@ END
$BODY$;
CREATE OR REPLACE FUNCTION _timescaledb_internal.first_sfunc(internal, anyelement, "any")
RETURNS internal
AS '$libdir/timescaledb', 'first_sfunc'
AS '@MODULE_PATHNAME@', 'first_sfunc'
LANGUAGE C IMMUTABLE PARALLEL SAFE;
CREATE OR REPLACE FUNCTION _timescaledb_internal.first_combinefunc(internal, internal)
RETURNS internal
AS '$libdir/timescaledb', 'first_combinefunc'
AS '@MODULE_PATHNAME@', 'first_combinefunc'
LANGUAGE C IMMUTABLE PARALLEL SAFE;
CREATE OR REPLACE FUNCTION _timescaledb_internal.last_sfunc(internal, anyelement, "any")
RETURNS internal
AS '$libdir/timescaledb', 'last_sfunc'
AS '@MODULE_PATHNAME@', 'last_sfunc'
LANGUAGE C IMMUTABLE PARALLEL SAFE;
CREATE OR REPLACE FUNCTION _timescaledb_internal.last_combinefunc(internal, internal)
RETURNS internal
AS '$libdir/timescaledb', 'last_combinefunc'
AS '@MODULE_PATHNAME@', 'last_combinefunc'
LANGUAGE C IMMUTABLE PARALLEL SAFE;
CREATE OR REPLACE FUNCTION _timescaledb_internal.bookend_finalfunc(internal, anyelement, "any")
RETURNS anyelement
AS '$libdir/timescaledb', 'bookend_finalfunc'
AS '@MODULE_PATHNAME@', 'bookend_finalfunc'
LANGUAGE C IMMUTABLE PARALLEL SAFE;
CREATE OR REPLACE FUNCTION _timescaledb_internal.bookend_serializefunc(internal)
RETURNS bytea
AS '$libdir/timescaledb', 'bookend_serializefunc'
AS '@MODULE_PATHNAME@', 'bookend_serializefunc'
LANGUAGE C IMMUTABLE STRICT PARALLEL SAFE;
CREATE OR REPLACE FUNCTION _timescaledb_internal.bookend_deserializefunc(bytea, internal)
RETURNS internal
AS '$libdir/timescaledb', 'bookend_deserializefunc'
AS '@MODULE_PATHNAME@', 'bookend_deserializefunc'
LANGUAGE C IMMUTABLE STRICT PARALLEL SAFE;
--This aggregate returns the "first" element of the first argument when ordered by the second argument.
@ -4536,15 +4536,15 @@ CREATE AGGREGATE last(anyelement, "any") (
-- time_bucket returns the left edge of the bucket where ts falls into.
-- Buckets span an interval of time equal to the bucket_width and are aligned with the epoch.
CREATE OR REPLACE FUNCTION time_bucket(bucket_width INTERVAL, ts TIMESTAMP) RETURNS TIMESTAMP
AS '$libdir/timescaledb', 'timestamp_bucket' LANGUAGE C IMMUTABLE PARALLEL SAFE;
AS '@MODULE_PATHNAME@', 'timestamp_bucket' LANGUAGE C IMMUTABLE PARALLEL SAFE;
-- bucketing of timestamptz happens at UTC time
CREATE OR REPLACE FUNCTION time_bucket(bucket_width INTERVAL, ts TIMESTAMPTZ) RETURNS TIMESTAMPTZ
AS '$libdir/timescaledb', 'timestamptz_bucket' LANGUAGE C IMMUTABLE PARALLEL SAFE;
AS '@MODULE_PATHNAME@', 'timestamptz_bucket' LANGUAGE C IMMUTABLE PARALLEL SAFE;
--bucketing on date should not do any timezone conversion
CREATE OR REPLACE FUNCTION time_bucket(bucket_width INTERVAL, ts DATE) RETURNS DATE
AS '$libdir/timescaledb', 'date_bucket' LANGUAGE C IMMUTABLE PARALLEL SAFE;
AS '@MODULE_PATHNAME@', 'date_bucket' LANGUAGE C IMMUTABLE PARALLEL SAFE;
-- If an interval is given as the third argument, the bucket alignment is offset by the interval.
CREATE OR REPLACE FUNCTION time_bucket(bucket_width INTERVAL, ts TIMESTAMP, "offset" INTERVAL)
@ -4602,15 +4602,15 @@ $BODY$
SELECT (((ts-"offset") / bucket_width)*bucket_width)+"offset";
$BODY$;
CREATE OR REPLACE FUNCTION _timescaledb_internal.get_git_commit() RETURNS TEXT
AS '$libdir/timescaledb', 'get_git_commit' LANGUAGE C IMMUTABLE STRICT PARALLEL SAFE;
AS '@MODULE_PATHNAME@', 'get_git_commit' LANGUAGE C IMMUTABLE STRICT PARALLEL SAFE;
-- this trigger function causes an invalidation event on the table whose name is
-- passed in as the first element.
CREATE OR REPLACE FUNCTION _timescaledb_cache.invalidate_relcache_trigger()
RETURNS TRIGGER AS '$libdir/timescaledb', 'invalidate_relcache_trigger' LANGUAGE C;
RETURNS TRIGGER AS '@MODULE_PATHNAME@', 'invalidate_relcache_trigger' LANGUAGE C;
-- This function is only used for debugging
CREATE OR REPLACE FUNCTION _timescaledb_cache.invalidate_relcache(proxy_oid OID)
RETURNS BOOLEAN AS '$libdir/timescaledb', 'invalidate_relcache' LANGUAGE C;
RETURNS BOOLEAN AS '@MODULE_PATHNAME@', 'invalidate_relcache' LANGUAGE C;
-- This file contains utility functions to get the relation size
@ -5033,27 +5033,27 @@ END;
$BODY$;
CREATE OR REPLACE FUNCTION _timescaledb_internal.hist_sfunc (state INTERNAL, val DOUBLE PRECISION, MIN DOUBLE PRECISION, MAX DOUBLE PRECISION, nbuckets INTEGER)
RETURNS INTERNAL
AS '$libdir/timescaledb', 'hist_sfunc'
AS '@MODULE_PATHNAME@', 'hist_sfunc'
LANGUAGE C IMMUTABLE PARALLEL SAFE;
CREATE OR REPLACE FUNCTION _timescaledb_internal.hist_combinefunc(state1 INTERNAL, state2 INTERNAL)
RETURNS INTERNAL
AS '$libdir/timescaledb', 'hist_combinefunc'
AS '@MODULE_PATHNAME@', 'hist_combinefunc'
LANGUAGE C IMMUTABLE PARALLEL SAFE;
CREATE OR REPLACE FUNCTION _timescaledb_internal.hist_serializefunc(INTERNAL)
RETURNS bytea
AS '$libdir/timescaledb', 'hist_serializefunc'
AS '@MODULE_PATHNAME@', 'hist_serializefunc'
LANGUAGE C IMMUTABLE STRICT PARALLEL SAFE;
CREATE OR REPLACE FUNCTION _timescaledb_internal.hist_deserializefunc(bytea, INTERNAL)
RETURNS INTERNAL
AS '$libdir/timescaledb', 'hist_deserializefunc'
AS '@MODULE_PATHNAME@', 'hist_deserializefunc'
LANGUAGE C IMMUTABLE STRICT PARALLEL SAFE;
CREATE OR REPLACE FUNCTION _timescaledb_internal.hist_finalfunc(state INTERNAL, val DOUBLE PRECISION, MIN DOUBLE PRECISION, MAX DOUBLE PRECISION, nbuckets INTEGER)
RETURNS INTEGER[]
AS '$libdir/timescaledb', 'hist_finalfunc'
AS '@MODULE_PATHNAME@', 'hist_finalfunc'
LANGUAGE C IMMUTABLE PARALLEL SAFE;
-- Tell Postgres how to use the new function

@ -188,14 +188,14 @@ CREATE OR REPLACE FUNCTION _timescaledb_internal.dimension_calculate_default_ran
interval_length BIGINT,
OUT range_start BIGINT,
OUT range_end BIGINT)
AS '$libdir/timescaledb', 'dimension_calculate_open_range_default' LANGUAGE C STABLE;
AS '@MODULE_PATHNAME@', 'dimension_calculate_open_range_default' LANGUAGE C STABLE;
CREATE OR REPLACE FUNCTION _timescaledb_internal.dimension_calculate_default_range_closed(
dimension_value BIGINT,
num_slices SMALLINT,
OUT range_start BIGINT,
OUT range_end BIGINT)
AS '$libdir/timescaledb', 'dimension_calculate_closed_range_default' LANGUAGE C STABLE;
AS '@MODULE_PATHNAME@', 'dimension_calculate_closed_range_default' LANGUAGE C STABLE;
CREATE OR REPLACE FUNCTION _timescaledb_internal.drop_chunk_metadata(
chunk_id int
@ -842,7 +842,7 @@ END
$BODY$;
CREATE OR REPLACE FUNCTION _timescaledb_internal.verify_hypertable_indexes(hypertable REGCLASS) RETURNS VOID
AS '$libdir/timescaledb', 'indexing_verify_hypertable_indexes' LANGUAGE C STRICT;
AS '@MODULE_PATHNAME@', 'indexing_verify_hypertable_indexes' LANGUAGE C STRICT;
CREATE OR REPLACE FUNCTION _timescaledb_internal.ddl_change_owner(main_table OID, new_table_owner NAME)
RETURNS void LANGUAGE plpgsql
@ -873,22 +873,22 @@ $BODY$;
--documentation of these function located in chunk_index.h
CREATE OR REPLACE FUNCTION _timescaledb_internal.chunk_index_clone(chunk_index_oid OID) RETURNS OID
AS '$libdir/timescaledb', 'chunk_index_clone' LANGUAGE C VOLATILE STRICT;
AS '@MODULE_PATHNAME@', 'chunk_index_clone' LANGUAGE C VOLATILE STRICT;
CREATE OR REPLACE FUNCTION _timescaledb_internal.chunk_index_replace(chunk_index_oid_old OID, chunk_index_oid_new OID) RETURNS VOID
AS '$libdir/timescaledb', 'chunk_index_replace' LANGUAGE C VOLATILE STRICT;
AS '@MODULE_PATHNAME@', 'chunk_index_replace' LANGUAGE C VOLATILE STRICT;
-- This file contains utilities for time conversion.
CREATE OR REPLACE FUNCTION _timescaledb_internal.to_microseconds(ts TIMESTAMPTZ) RETURNS BIGINT
AS '$libdir/timescaledb', 'pg_timestamp_to_microseconds' LANGUAGE C IMMUTABLE STRICT PARALLEL SAFE;
AS '@MODULE_PATHNAME@', 'pg_timestamp_to_microseconds' LANGUAGE C IMMUTABLE STRICT PARALLEL SAFE;
CREATE OR REPLACE FUNCTION _timescaledb_internal.to_unix_microseconds(ts TIMESTAMPTZ) RETURNS BIGINT
AS '$libdir/timescaledb', 'pg_timestamp_to_unix_microseconds' LANGUAGE C IMMUTABLE STRICT PARALLEL SAFE;
AS '@MODULE_PATHNAME@', 'pg_timestamp_to_unix_microseconds' LANGUAGE C IMMUTABLE STRICT PARALLEL SAFE;
CREATE OR REPLACE FUNCTION _timescaledb_internal.to_timestamp(unixtime_us BIGINT) RETURNS TIMESTAMPTZ
AS '$libdir/timescaledb', 'pg_unix_microseconds_to_timestamp' LANGUAGE C IMMUTABLE STRICT PARALLEL SAFE;
AS '@MODULE_PATHNAME@', 'pg_unix_microseconds_to_timestamp' LANGUAGE C IMMUTABLE STRICT PARALLEL SAFE;
CREATE OR REPLACE FUNCTION _timescaledb_internal.to_timestamp_pg(postgres_us BIGINT) RETURNS TIMESTAMPTZ
AS '$libdir/timescaledb', 'pg_microseconds_to_timestamp' LANGUAGE C IMMUTABLE STRICT PARALLEL SAFE;
AS '@MODULE_PATHNAME@', 'pg_microseconds_to_timestamp' LANGUAGE C IMMUTABLE STRICT PARALLEL SAFE;
-- Time can be represented in a hypertable as an int* (bigint/integer/smallint) or as a timestamp type (
@ -982,7 +982,7 @@ END
$BODY$;
CREATE OR REPLACE FUNCTION _timescaledb_internal.time_to_internal(time_element anyelement, time_type REGTYPE) RETURNS BIGINT
AS '$libdir/timescaledb', 'time_to_internal' LANGUAGE C IMMUTABLE PARALLEL SAFE STRICT;
AS '@MODULE_PATHNAME@', 'time_to_internal' LANGUAGE C IMMUTABLE PARALLEL SAFE STRICT;
-- This file contains functions associated with creating new
-- hypertables.
@ -1234,7 +1234,7 @@ END
$BODY$;
CREATE OR REPLACE FUNCTION _timescaledb_internal.validate_triggers(main_table REGCLASS) RETURNS VOID
AS '$libdir/timescaledb', 'hypertable_validate_triggers' LANGUAGE C STRICT;
AS '@MODULE_PATHNAME@', 'hypertable_validate_triggers' LANGUAGE C STRICT;
-- Creates a constraint on a chunk.
CREATE OR REPLACE FUNCTION _timescaledb_internal.chunk_constraint_add_table_constraint(
chunk_constraint_row _timescaledb_catalog.chunk_constraint
@ -1381,11 +1381,11 @@ $BODY$;
-- Deprecated partition hash function
CREATE OR REPLACE FUNCTION _timescaledb_internal.get_partition_for_key(val anyelement)
RETURNS int
AS '$libdir/timescaledb', 'get_partition_for_key' LANGUAGE C IMMUTABLE STRICT PARALLEL SAFE;
AS '@MODULE_PATHNAME@', 'get_partition_for_key' LANGUAGE C IMMUTABLE STRICT PARALLEL SAFE;
CREATE OR REPLACE FUNCTION _timescaledb_internal.get_partition_hash(val anyelement)
RETURNS int
AS '$libdir/timescaledb', 'get_partition_hash' LANGUAGE C IMMUTABLE STRICT PARALLEL SAFE;
AS '@MODULE_PATHNAME@', 'get_partition_hash' LANGUAGE C IMMUTABLE STRICT PARALLEL SAFE;
-- This file contains functions related to getting information about the
-- schema of a hypertable, including columns, their types, etc.
@ -1781,7 +1781,7 @@ BEGIN
END
$BODY$;
CREATE OR REPLACE FUNCTION _timescaledb_internal.ddl_command_end() RETURNS event_trigger
AS '$libdir/timescaledb', 'timescaledb_ddl_command_end' LANGUAGE C;
AS '@MODULE_PATHNAME@', 'timescaledb_ddl_command_end' LANGUAGE C;
DROP EVENT TRIGGER IF EXISTS timescaledb_ddl_command_end;
CREATE EVENT TRIGGER timescaledb_ddl_command_end ON ddl_command_end
@ -1909,37 +1909,37 @@ END
$BODY$;
CREATE OR REPLACE FUNCTION _timescaledb_internal.first_sfunc(internal, anyelement, "any")
RETURNS internal
AS '$libdir/timescaledb', 'first_sfunc'
AS '@MODULE_PATHNAME@', 'first_sfunc'
LANGUAGE C IMMUTABLE PARALLEL SAFE;
CREATE OR REPLACE FUNCTION _timescaledb_internal.first_combinefunc(internal, internal)
RETURNS internal
AS '$libdir/timescaledb', 'first_combinefunc'
AS '@MODULE_PATHNAME@', 'first_combinefunc'
LANGUAGE C IMMUTABLE PARALLEL SAFE;
CREATE OR REPLACE FUNCTION _timescaledb_internal.last_sfunc(internal, anyelement, "any")
RETURNS internal
AS '$libdir/timescaledb', 'last_sfunc'
AS '@MODULE_PATHNAME@', 'last_sfunc'
LANGUAGE C IMMUTABLE PARALLEL SAFE;
CREATE OR REPLACE FUNCTION _timescaledb_internal.last_combinefunc(internal, internal)
RETURNS internal
AS '$libdir/timescaledb', 'last_combinefunc'
AS '@MODULE_PATHNAME@', 'last_combinefunc'
LANGUAGE C IMMUTABLE PARALLEL SAFE;
CREATE OR REPLACE FUNCTION _timescaledb_internal.bookend_finalfunc(internal, anyelement, "any")
RETURNS anyelement
AS '$libdir/timescaledb', 'bookend_finalfunc'
AS '@MODULE_PATHNAME@', 'bookend_finalfunc'
LANGUAGE C IMMUTABLE PARALLEL SAFE;
CREATE OR REPLACE FUNCTION _timescaledb_internal.bookend_serializefunc(internal)
RETURNS bytea
AS '$libdir/timescaledb', 'bookend_serializefunc'
AS '@MODULE_PATHNAME@', 'bookend_serializefunc'
LANGUAGE C IMMUTABLE STRICT PARALLEL SAFE;
CREATE OR REPLACE FUNCTION _timescaledb_internal.bookend_deserializefunc(bytea, internal)
RETURNS internal
AS '$libdir/timescaledb', 'bookend_deserializefunc'
AS '@MODULE_PATHNAME@', 'bookend_deserializefunc'
LANGUAGE C IMMUTABLE STRICT PARALLEL SAFE;
--This aggregate returns the "first" element of the first argument when ordered by the second argument.
@ -1972,15 +1972,15 @@ CREATE AGGREGATE last(anyelement, "any") (
-- time_bucket returns the left edge of the bucket where ts falls into.
-- Buckets span an interval of time equal to the bucket_width and are aligned with the epoch.
CREATE OR REPLACE FUNCTION time_bucket(bucket_width INTERVAL, ts TIMESTAMP) RETURNS TIMESTAMP
AS '$libdir/timescaledb', 'timestamp_bucket' LANGUAGE C IMMUTABLE PARALLEL SAFE;
AS '@MODULE_PATHNAME@', 'timestamp_bucket' LANGUAGE C IMMUTABLE PARALLEL SAFE;
-- bucketing of timestamptz happens at UTC time
CREATE OR REPLACE FUNCTION time_bucket(bucket_width INTERVAL, ts TIMESTAMPTZ) RETURNS TIMESTAMPTZ
AS '$libdir/timescaledb', 'timestamptz_bucket' LANGUAGE C IMMUTABLE PARALLEL SAFE;
AS '@MODULE_PATHNAME@', 'timestamptz_bucket' LANGUAGE C IMMUTABLE PARALLEL SAFE;
--bucketing on date should not do any timezone conversion
CREATE OR REPLACE FUNCTION time_bucket(bucket_width INTERVAL, ts DATE) RETURNS DATE
AS '$libdir/timescaledb', 'date_bucket' LANGUAGE C IMMUTABLE PARALLEL SAFE;
AS '@MODULE_PATHNAME@', 'date_bucket' LANGUAGE C IMMUTABLE PARALLEL SAFE;
-- If an interval is given as the third argument, the bucket alignment is offset by the interval.
CREATE OR REPLACE FUNCTION time_bucket(bucket_width INTERVAL, ts TIMESTAMP, "offset" INTERVAL)
@ -2038,15 +2038,15 @@ $BODY$
SELECT (((ts-"offset") / bucket_width)*bucket_width)+"offset";
$BODY$;
CREATE OR REPLACE FUNCTION _timescaledb_internal.get_git_commit() RETURNS TEXT
AS '$libdir/timescaledb', 'get_git_commit' LANGUAGE C IMMUTABLE STRICT PARALLEL SAFE;
AS '@MODULE_PATHNAME@', 'get_git_commit' LANGUAGE C IMMUTABLE STRICT PARALLEL SAFE;
-- this trigger function causes an invalidation event on the table whose name is
-- passed in as the first element.
CREATE OR REPLACE FUNCTION _timescaledb_cache.invalidate_relcache_trigger()
RETURNS TRIGGER AS '$libdir/timescaledb', 'invalidate_relcache_trigger' LANGUAGE C;
RETURNS TRIGGER AS '@MODULE_PATHNAME@', 'invalidate_relcache_trigger' LANGUAGE C;
-- This function is only used for debugging
CREATE OR REPLACE FUNCTION _timescaledb_cache.invalidate_relcache(proxy_oid OID)
RETURNS BOOLEAN AS '$libdir/timescaledb', 'invalidate_relcache' LANGUAGE C;
RETURNS BOOLEAN AS '@MODULE_PATHNAME@', 'invalidate_relcache' LANGUAGE C;
-- This file contains utility functions to get the relation size
@ -2469,27 +2469,27 @@ END;
$BODY$;
CREATE OR REPLACE FUNCTION _timescaledb_internal.hist_sfunc (state INTERNAL, val DOUBLE PRECISION, MIN DOUBLE PRECISION, MAX DOUBLE PRECISION, nbuckets INTEGER)
RETURNS INTERNAL
AS '$libdir/timescaledb', 'hist_sfunc'
AS '@MODULE_PATHNAME@', 'hist_sfunc'
LANGUAGE C IMMUTABLE PARALLEL SAFE;
CREATE OR REPLACE FUNCTION _timescaledb_internal.hist_combinefunc(state1 INTERNAL, state2 INTERNAL)
RETURNS INTERNAL
AS '$libdir/timescaledb', 'hist_combinefunc'
AS '@MODULE_PATHNAME@', 'hist_combinefunc'
LANGUAGE C IMMUTABLE PARALLEL SAFE;
CREATE OR REPLACE FUNCTION _timescaledb_internal.hist_serializefunc(INTERNAL)
RETURNS bytea
AS '$libdir/timescaledb', 'hist_serializefunc'
AS '@MODULE_PATHNAME@', 'hist_serializefunc'
LANGUAGE C IMMUTABLE STRICT PARALLEL SAFE;
CREATE OR REPLACE FUNCTION _timescaledb_internal.hist_deserializefunc(bytea, INTERNAL)
RETURNS INTERNAL
AS '$libdir/timescaledb', 'hist_deserializefunc'
AS '@MODULE_PATHNAME@', 'hist_deserializefunc'
LANGUAGE C IMMUTABLE STRICT PARALLEL SAFE;
CREATE OR REPLACE FUNCTION _timescaledb_internal.hist_finalfunc(state INTERNAL, val DOUBLE PRECISION, MIN DOUBLE PRECISION, MAX DOUBLE PRECISION, nbuckets INTEGER)
RETURNS INTEGER[]
AS '$libdir/timescaledb', 'hist_finalfunc'
AS '@MODULE_PATHNAME@', 'hist_finalfunc'
LANGUAGE C IMMUTABLE PARALLEL SAFE;
-- Tell Postgres how to use the new function

@ -175,14 +175,14 @@ CREATE OR REPLACE FUNCTION _timescaledb_internal.dimension_calculate_default_ran
interval_length BIGINT,
OUT range_start BIGINT,
OUT range_end BIGINT)
AS '$libdir/timescaledb', 'dimension_calculate_open_range_default' LANGUAGE C STABLE;
AS '@MODULE_PATHNAME@', 'dimension_calculate_open_range_default' LANGUAGE C STABLE;
CREATE OR REPLACE FUNCTION _timescaledb_internal.dimension_calculate_default_range_closed(
dimension_value BIGINT,
num_slices SMALLINT,
OUT range_start BIGINT,
OUT range_end BIGINT)
AS '$libdir/timescaledb', 'dimension_calculate_closed_range_default' LANGUAGE C STABLE;
AS '@MODULE_PATHNAME@', 'dimension_calculate_closed_range_default' LANGUAGE C STABLE;
CREATE OR REPLACE FUNCTION _timescaledb_internal.drop_chunk_metadata(
chunk_id int
@ -838,7 +838,7 @@ END
$BODY$;
CREATE OR REPLACE FUNCTION _timescaledb_internal.verify_hypertable_indexes(hypertable REGCLASS) RETURNS VOID
AS '$libdir/timescaledb', 'indexing_verify_hypertable_indexes' LANGUAGE C STRICT;
AS '@MODULE_PATHNAME@', 'indexing_verify_hypertable_indexes' LANGUAGE C STRICT;
CREATE OR REPLACE FUNCTION _timescaledb_internal.ddl_change_owner(main_table OID, new_table_owner NAME)
RETURNS void LANGUAGE plpgsql
@ -867,35 +867,35 @@ END
$BODY$;
CREATE OR REPLACE FUNCTION _timescaledb_internal.attach_tablespace(tablespace NAME, hypertable REGCLASS) RETURNS VOID
AS '$libdir/timescaledb', 'tablespace_attach' LANGUAGE C VOLATILE;
AS '@MODULE_PATHNAME@', 'tablespace_attach' LANGUAGE C VOLATILE;
CREATE OR REPLACE FUNCTION _timescaledb_internal.detach_tablespace(tablespace NAME, hypertable REGCLASS) RETURNS INTEGER
AS '$libdir/timescaledb', 'tablespace_detach' LANGUAGE C VOLATILE;
AS '@MODULE_PATHNAME@', 'tablespace_detach' LANGUAGE C VOLATILE;
CREATE OR REPLACE FUNCTION _timescaledb_internal.detach_tablespaces(hypertable REGCLASS) RETURNS INTEGER
AS '$libdir/timescaledb', 'tablespace_detach_all_from_hypertable' LANGUAGE C VOLATILE;
AS '@MODULE_PATHNAME@', 'tablespace_detach_all_from_hypertable' LANGUAGE C VOLATILE;
CREATE OR REPLACE FUNCTION _timescaledb_internal.show_tablespaces(hypertable REGCLASS) RETURNS SETOF NAME
AS '$libdir/timescaledb', 'tablespace_show' LANGUAGE C VOLATILE STRICT;
AS '@MODULE_PATHNAME@', 'tablespace_show' LANGUAGE C VOLATILE STRICT;
--documentation of these function located in chunk_index.h
CREATE OR REPLACE FUNCTION _timescaledb_internal.chunk_index_clone(chunk_index_oid OID) RETURNS OID
AS '$libdir/timescaledb', 'chunk_index_clone' LANGUAGE C VOLATILE STRICT;
AS '@MODULE_PATHNAME@', 'chunk_index_clone' LANGUAGE C VOLATILE STRICT;
CREATE OR REPLACE FUNCTION _timescaledb_internal.chunk_index_replace(chunk_index_oid_old OID, chunk_index_oid_new OID) RETURNS VOID
AS '$libdir/timescaledb', 'chunk_index_replace' LANGUAGE C VOLATILE STRICT;
AS '@MODULE_PATHNAME@', 'chunk_index_replace' LANGUAGE C VOLATILE STRICT;
-- This file contains utilities for time conversion.
CREATE OR REPLACE FUNCTION _timescaledb_internal.to_microseconds(ts TIMESTAMPTZ) RETURNS BIGINT
AS '$libdir/timescaledb', 'pg_timestamp_to_microseconds' LANGUAGE C IMMUTABLE STRICT PARALLEL SAFE;
AS '@MODULE_PATHNAME@', 'pg_timestamp_to_microseconds' LANGUAGE C IMMUTABLE STRICT PARALLEL SAFE;
CREATE OR REPLACE FUNCTION _timescaledb_internal.to_unix_microseconds(ts TIMESTAMPTZ) RETURNS BIGINT
AS '$libdir/timescaledb', 'pg_timestamp_to_unix_microseconds' LANGUAGE C IMMUTABLE STRICT PARALLEL SAFE;
AS '@MODULE_PATHNAME@', 'pg_timestamp_to_unix_microseconds' LANGUAGE C IMMUTABLE STRICT PARALLEL SAFE;
CREATE OR REPLACE FUNCTION _timescaledb_internal.to_timestamp(unixtime_us BIGINT) RETURNS TIMESTAMPTZ
AS '$libdir/timescaledb', 'pg_unix_microseconds_to_timestamp' LANGUAGE C IMMUTABLE STRICT PARALLEL SAFE;
AS '@MODULE_PATHNAME@', 'pg_unix_microseconds_to_timestamp' LANGUAGE C IMMUTABLE STRICT PARALLEL SAFE;
CREATE OR REPLACE FUNCTION _timescaledb_internal.to_timestamp_pg(postgres_us BIGINT) RETURNS TIMESTAMPTZ
AS '$libdir/timescaledb', 'pg_microseconds_to_timestamp' LANGUAGE C IMMUTABLE STRICT PARALLEL SAFE;
AS '@MODULE_PATHNAME@', 'pg_microseconds_to_timestamp' LANGUAGE C IMMUTABLE STRICT PARALLEL SAFE;
-- Time can be represented in a hypertable as an int* (bigint/integer/smallint) or as a timestamp type (
@ -1005,7 +1005,7 @@ END
$BODY$;
CREATE OR REPLACE FUNCTION _timescaledb_internal.time_to_internal(time_element anyelement, time_type REGTYPE) RETURNS BIGINT
AS '$libdir/timescaledb', 'time_to_internal' LANGUAGE C IMMUTABLE PARALLEL SAFE STRICT;
AS '@MODULE_PATHNAME@', 'time_to_internal' LANGUAGE C IMMUTABLE PARALLEL SAFE STRICT;
-- This file contains functions associated with creating new
-- hypertables.
@ -1260,7 +1260,7 @@ END
$BODY$;
CREATE OR REPLACE FUNCTION _timescaledb_internal.validate_triggers(main_table REGCLASS) RETURNS VOID
AS '$libdir/timescaledb', 'hypertable_validate_triggers' LANGUAGE C STRICT;
AS '@MODULE_PATHNAME@', 'hypertable_validate_triggers' LANGUAGE C STRICT;
-- Creates a constraint on a chunk.
CREATE OR REPLACE FUNCTION _timescaledb_internal.chunk_constraint_add_table_constraint(
chunk_constraint_row _timescaledb_catalog.chunk_constraint
@ -1415,11 +1415,11 @@ $BODY$;
-- Deprecated partition hash function
CREATE OR REPLACE FUNCTION _timescaledb_internal.get_partition_for_key(val anyelement)
RETURNS int
AS '$libdir/timescaledb', 'get_partition_for_key' LANGUAGE C IMMUTABLE STRICT PARALLEL SAFE;
AS '@MODULE_PATHNAME@', 'get_partition_for_key' LANGUAGE C IMMUTABLE STRICT PARALLEL SAFE;
CREATE OR REPLACE FUNCTION _timescaledb_internal.get_partition_hash(val anyelement)
RETURNS int
AS '$libdir/timescaledb', 'get_partition_hash' LANGUAGE C IMMUTABLE STRICT PARALLEL SAFE;
AS '@MODULE_PATHNAME@', 'get_partition_hash' LANGUAGE C IMMUTABLE STRICT PARALLEL SAFE;
-- This file contains functions related to getting information about the
-- schema of a hypertable, including columns, their types, etc.
@ -1842,7 +1842,7 @@ $BODY$
SELECT * FROM _timescaledb_internal.show_tablespaces(hypertable);
$BODY$;
CREATE OR REPLACE FUNCTION _timescaledb_internal.ddl_command_end() RETURNS event_trigger
AS '$libdir/timescaledb', 'timescaledb_ddl_command_end' LANGUAGE C;
AS '@MODULE_PATHNAME@', 'timescaledb_ddl_command_end' LANGUAGE C;
DROP EVENT TRIGGER IF EXISTS timescaledb_ddl_command_end;
CREATE EVENT TRIGGER timescaledb_ddl_command_end ON ddl_command_end
@ -1939,37 +1939,37 @@ $BODY$
$BODY$;
CREATE OR REPLACE FUNCTION _timescaledb_internal.first_sfunc(internal, anyelement, "any")
RETURNS internal
AS '$libdir/timescaledb', 'first_sfunc'
AS '@MODULE_PATHNAME@', 'first_sfunc'
LANGUAGE C IMMUTABLE PARALLEL SAFE;
CREATE OR REPLACE FUNCTION _timescaledb_internal.first_combinefunc(internal, internal)
RETURNS internal
AS '$libdir/timescaledb', 'first_combinefunc'
AS '@MODULE_PATHNAME@', 'first_combinefunc'
LANGUAGE C IMMUTABLE PARALLEL SAFE;
CREATE OR REPLACE FUNCTION _timescaledb_internal.last_sfunc(internal, anyelement, "any")
RETURNS internal
AS '$libdir/timescaledb', 'last_sfunc'
AS '@MODULE_PATHNAME@', 'last_sfunc'
LANGUAGE C IMMUTABLE PARALLEL SAFE;
CREATE OR REPLACE FUNCTION _timescaledb_internal.last_combinefunc(internal, internal)
RETURNS internal
AS '$libdir/timescaledb', 'last_combinefunc'
AS '@MODULE_PATHNAME@', 'last_combinefunc'
LANGUAGE C IMMUTABLE PARALLEL SAFE;
CREATE OR REPLACE FUNCTION _timescaledb_internal.bookend_finalfunc(internal, anyelement, "any")
RETURNS anyelement
AS '$libdir/timescaledb', 'bookend_finalfunc'
AS '@MODULE_PATHNAME@', 'bookend_finalfunc'
LANGUAGE C IMMUTABLE PARALLEL SAFE;
CREATE OR REPLACE FUNCTION _timescaledb_internal.bookend_serializefunc(internal)
RETURNS bytea
AS '$libdir/timescaledb', 'bookend_serializefunc'
AS '@MODULE_PATHNAME@', 'bookend_serializefunc'
LANGUAGE C IMMUTABLE STRICT PARALLEL SAFE;
CREATE OR REPLACE FUNCTION _timescaledb_internal.bookend_deserializefunc(bytea, internal)
RETURNS internal
AS '$libdir/timescaledb', 'bookend_deserializefunc'
AS '@MODULE_PATHNAME@', 'bookend_deserializefunc'
LANGUAGE C IMMUTABLE STRICT PARALLEL SAFE;
--This aggregate returns the "first" element of the first argument when ordered by the second argument.
@ -2002,15 +2002,15 @@ CREATE AGGREGATE last(anyelement, "any") (
-- time_bucket returns the left edge of the bucket where ts falls into.
-- Buckets span an interval of time equal to the bucket_width and are aligned with the epoch.
CREATE OR REPLACE FUNCTION time_bucket(bucket_width INTERVAL, ts TIMESTAMP) RETURNS TIMESTAMP
AS '$libdir/timescaledb', 'timestamp_bucket' LANGUAGE C IMMUTABLE PARALLEL SAFE;
AS '@MODULE_PATHNAME@', 'timestamp_bucket' LANGUAGE C IMMUTABLE PARALLEL SAFE;
-- bucketing of timestamptz happens at UTC time
CREATE OR REPLACE FUNCTION time_bucket(bucket_width INTERVAL, ts TIMESTAMPTZ) RETURNS TIMESTAMPTZ
AS '$libdir/timescaledb', 'timestamptz_bucket' LANGUAGE C IMMUTABLE PARALLEL SAFE;
AS '@MODULE_PATHNAME@', 'timestamptz_bucket' LANGUAGE C IMMUTABLE PARALLEL SAFE;
--bucketing on date should not do any timezone conversion
CREATE OR REPLACE FUNCTION time_bucket(bucket_width INTERVAL, ts DATE) RETURNS DATE
AS '$libdir/timescaledb', 'date_bucket' LANGUAGE C IMMUTABLE PARALLEL SAFE;
AS '@MODULE_PATHNAME@', 'date_bucket' LANGUAGE C IMMUTABLE PARALLEL SAFE;
-- If an interval is given as the third argument, the bucket alignment is offset by the interval.
CREATE OR REPLACE FUNCTION time_bucket(bucket_width INTERVAL, ts TIMESTAMP, "offset" INTERVAL)
@ -2068,15 +2068,15 @@ $BODY$
SELECT (((ts-"offset") / bucket_width)*bucket_width)+"offset";
$BODY$;
CREATE OR REPLACE FUNCTION _timescaledb_internal.get_git_commit() RETURNS TEXT
AS '$libdir/timescaledb', 'get_git_commit' LANGUAGE C IMMUTABLE STRICT PARALLEL SAFE;
AS '@MODULE_PATHNAME@', 'get_git_commit' LANGUAGE C IMMUTABLE STRICT PARALLEL SAFE;
-- this trigger function causes an invalidation event on the table whose name is
-- passed in as the first element.
CREATE OR REPLACE FUNCTION _timescaledb_cache.invalidate_relcache_trigger()
RETURNS TRIGGER AS '$libdir/timescaledb', 'invalidate_relcache_trigger' LANGUAGE C STRICT;
RETURNS TRIGGER AS '@MODULE_PATHNAME@', 'invalidate_relcache_trigger' LANGUAGE C STRICT;
-- This function is only used for debugging
CREATE OR REPLACE FUNCTION _timescaledb_cache.invalidate_relcache(catalog_table REGCLASS)
RETURNS BOOLEAN AS '$libdir/timescaledb', 'invalidate_relcache' LANGUAGE C STRICT;
RETURNS BOOLEAN AS '@MODULE_PATHNAME@', 'invalidate_relcache' LANGUAGE C STRICT;
-- This file contains utility functions to get the relation size
-- of hypertables, chunks, and indexes on hypertables.
@ -2497,27 +2497,27 @@ END;
$BODY$;
CREATE OR REPLACE FUNCTION _timescaledb_internal.hist_sfunc (state INTERNAL, val DOUBLE PRECISION, MIN DOUBLE PRECISION, MAX DOUBLE PRECISION, nbuckets INTEGER)
RETURNS INTERNAL
AS '$libdir/timescaledb', 'hist_sfunc'
AS '@MODULE_PATHNAME@', 'hist_sfunc'
LANGUAGE C IMMUTABLE PARALLEL SAFE;
CREATE OR REPLACE FUNCTION _timescaledb_internal.hist_combinefunc(state1 INTERNAL, state2 INTERNAL)
RETURNS INTERNAL
AS '$libdir/timescaledb', 'hist_combinefunc'
AS '@MODULE_PATHNAME@', 'hist_combinefunc'
LANGUAGE C IMMUTABLE PARALLEL SAFE;
CREATE OR REPLACE FUNCTION _timescaledb_internal.hist_serializefunc(INTERNAL)
RETURNS bytea
AS '$libdir/timescaledb', 'hist_serializefunc'
AS '@MODULE_PATHNAME@', 'hist_serializefunc'
LANGUAGE C IMMUTABLE STRICT PARALLEL SAFE;
CREATE OR REPLACE FUNCTION _timescaledb_internal.hist_deserializefunc(bytea, INTERNAL)
RETURNS INTERNAL
AS '$libdir/timescaledb', 'hist_deserializefunc'
AS '@MODULE_PATHNAME@', 'hist_deserializefunc'
LANGUAGE C IMMUTABLE STRICT PARALLEL SAFE;
CREATE OR REPLACE FUNCTION _timescaledb_internal.hist_finalfunc(state INTERNAL, val DOUBLE PRECISION, MIN DOUBLE PRECISION, MAX DOUBLE PRECISION, nbuckets INTEGER)
RETURNS INTEGER[]
AS '$libdir/timescaledb', 'hist_finalfunc'
AS '@MODULE_PATHNAME@', 'hist_finalfunc'
LANGUAGE C IMMUTABLE PARALLEL SAFE;
-- Tell Postgres how to use the new function

@ -0,0 +1 @@
ALTER EVENT TRIGGER timescaledb_ddl_command_end ENABLE;

@ -0,0 +1,4 @@
--Disable the event trigger during updates. Two reasons:
---1- Prevents the old extension .so being loaded during upgrade to process the event trigger.
---2- Probably the right thing to do anyway since you don't necessarly know which version of the trigger will be fired during upgrade.
ALTER EVENT TRIGGER timescaledb_ddl_command_end DISABLE;

@ -252,4 +252,4 @@ END
$BODY$;
CREATE OR REPLACE FUNCTION _timescaledb_internal.validate_triggers(main_table REGCLASS) RETURNS VOID
AS '$libdir/timescaledb', 'hypertable_validate_triggers' LANGUAGE C STRICT;
AS '@MODULE_PATHNAME@', 'hypertable_validate_triggers' LANGUAGE C STRICT;

@ -1,15 +1,16 @@
-- This file contains utilities for time conversion.
CREATE OR REPLACE FUNCTION _timescaledb_internal.to_microseconds(ts TIMESTAMPTZ) RETURNS BIGINT
AS '$libdir/timescaledb', 'pg_timestamp_to_microseconds' LANGUAGE C IMMUTABLE STRICT PARALLEL SAFE;
AS '@MODULE_PATHNAME@', 'pg_timestamp_to_microseconds' LANGUAGE C IMMUTABLE STRICT PARALLEL SAFE;
CREATE OR REPLACE FUNCTION _timescaledb_internal.to_unix_microseconds(ts TIMESTAMPTZ) RETURNS BIGINT
AS '$libdir/timescaledb', 'pg_timestamp_to_unix_microseconds' LANGUAGE C IMMUTABLE STRICT PARALLEL SAFE;
AS '@MODULE_PATHNAME@', 'pg_timestamp_to_unix_microseconds' LANGUAGE C IMMUTABLE STRICT PARALLEL SAFE;
CREATE OR REPLACE FUNCTION _timescaledb_internal.to_timestamp(unixtime_us BIGINT) RETURNS TIMESTAMPTZ
AS '$libdir/timescaledb', 'pg_unix_microseconds_to_timestamp' LANGUAGE C IMMUTABLE STRICT PARALLEL SAFE;
AS '@MODULE_PATHNAME@', 'pg_unix_microseconds_to_timestamp' LANGUAGE C IMMUTABLE STRICT PARALLEL SAFE;
CREATE OR REPLACE FUNCTION _timescaledb_internal.to_timestamp_pg(postgres_us BIGINT) RETURNS TIMESTAMPTZ
AS '$libdir/timescaledb', 'pg_microseconds_to_timestamp' LANGUAGE C IMMUTABLE STRICT PARALLEL SAFE;
AS '@MODULE_PATHNAME@', 'pg_microseconds_to_timestamp' LANGUAGE C IMMUTABLE STRICT PARALLEL SAFE;
-- Time can be represented in a hypertable as an int* (bigint/integer/smallint) or as a timestamp type (
@ -119,4 +120,4 @@ END
$BODY$;
CREATE OR REPLACE FUNCTION _timescaledb_internal.time_to_internal(time_element anyelement, time_type REGTYPE) RETURNS BIGINT
AS '$libdir/timescaledb', 'time_to_internal' LANGUAGE C IMMUTABLE PARALLEL SAFE STRICT;
AS '@MODULE_PATHNAME@', 'time_to_internal' LANGUAGE C IMMUTABLE PARALLEL SAFE STRICT;

@ -1,2 +1,2 @@
CREATE OR REPLACE FUNCTION _timescaledb_internal.get_git_commit() RETURNS TEXT
AS '$libdir/timescaledb', 'get_git_commit' LANGUAGE C IMMUTABLE STRICT PARALLEL SAFE;
AS '@MODULE_PATHNAME@', 'get_git_commit' LANGUAGE C IMMUTABLE STRICT PARALLEL SAFE;

@ -146,9 +146,11 @@ endif (OBJDUMP AND PGINDENT)
add_library(${PROJECT_NAME} MODULE ${SOURCES} ${HEADERS} ${GITCOMMIT_H})
set_target_properties(${PROJECT_NAME} PROPERTIES
OUTPUT_NAME ${PROJECT_NAME}
OUTPUT_NAME ${PROJECT_NAME}-${PROJECT_VERSION_MOD}
PREFIX "")
install(
TARGETS ${PROJECT_NAME}
DESTINATION ${PG_PKGLIBDIR})
add_subdirectory(loader)

@ -56,7 +56,6 @@ typedef enum InternalFunction
#define CATALOG_SCHEMA_NAME "_timescaledb_catalog"
#define CACHE_SCHEMA_NAME "_timescaledb_cache"
#define INTERNAL_SCHEMA_NAME "_timescaledb_internal"
#define EXTENSION_NAME "timescaledb"
/******************************
*

@ -6,14 +6,23 @@
#include <utils/lsyscache.h>
#include <utils/inval.h>
#include "compat-msvc-enter.h" /* To label externs in extension.h and miscadmin.h correctly */
#include "compat-msvc-enter.h" /* To label externs in extension.h and
* miscadmin.h correctly */
#include <commands/extension.h>
#include <miscadmin.h>
#include "compat-msvc-exit.h"
#include <access/relscan.h>
#include <catalog/indexing.h>
#include <catalog/pg_extension.h>
#include <utils/builtins.h>
#include <utils/fmgroids.h>
#include "catalog.h"
#include "extension.h"
#include "guc.h"
#include "version.h"
#include "extension_utils.c"
#define EXTENSION_PROXY_TABLE "cache_inval_extension"
@ -33,76 +42,25 @@ static Oid extension_proxy_oid = InvalidOid;
* * The proxy table will be created before the extension itself.
* * The proxy table will be dropped before the extension itself.
*/
enum ExtensionState
{
/*
* NOT_INSTALLED means that this backend knows that the extension is not
* present. In this state we know that the proxy table is not present.
* Thus, the only way to get out of this state is a RelCacheInvalidation
* indicating that the proxy table was added.
*/
EXTENSION_STATE_NOT_INSTALLED,
/*
* UNKNOWN state is used only if we cannot be sure what the state is. This
* can happen in two cases: 1) at the start of a backend or 2) We got a
* relcache event outside of a transaction and thus could not check the
* cache for the presence/absence of the proxy table or extension.
*/
EXTENSION_STATE_UNKNOWN,
/*
* TRANSITIONING only occurs when the proxy table exists but the extension
* does not. This can only happen in the middle of a create or drop
* extension.
*/
EXTENSION_STATE_TRANSITIONING,
/*
* CREATED means we know the extension is loaded, metadata is up-to-date,
* and we therefore do not need a full check until a RelCacheInvalidation
* on the proxy table.
*/
EXTENSION_STATE_CREATED,
};
static enum ExtensionState extstate = EXTENSION_STATE_UNKNOWN;
static bool
proxy_table_exists()
void
extension_check_version(const char *so_version)
{
Oid nsid = get_namespace_oid(CACHE_SCHEMA_NAME, true);
Oid proxy_table = get_relname_relid(EXTENSION_PROXY_TABLE, nsid);
char *sql_version;
return OidIsValid(proxy_table);
}
static bool
extension_exists()
{
return OidIsValid(get_extension_oid(EXTENSION_NAME, true));
}
/* Returns the recomputed current state */
static enum ExtensionState
extension_new_state()
{
/*
* NormalProcessingMode necessary to avoid accessing cache before its
* ready (which may result in an infinite loop). More concretely we need
* RelationCacheInitializePhase3 to have been already called.
*/
if (!IsNormalProcessingMode() || !IsTransactionState())
return EXTENSION_STATE_UNKNOWN;
return;
if (proxy_table_exists())
sql_version = extension_version();
if (strcmp(sql_version, so_version) != 0)
{
if (!extension_exists())
return EXTENSION_STATE_TRANSITIONING;
else
return EXTENSION_STATE_CREATED;
ereport(ERROR,
(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
errmsg("Mismatched timescaledb version. Shared object file %s, SQL %s", so_version, sql_version)));
}
return EXTENSION_STATE_NOT_INSTALLED;
}
/* Sets a new state, returning whether the state has changed */
@ -119,6 +77,7 @@ extension_set_state(enum ExtensionState newstate)
case EXTENSION_STATE_UNKNOWN:
break;
case EXTENSION_STATE_CREATED:
extension_check_version(TIMESCALEDB_VERSION_MOD);
extension_proxy_oid = get_relname_relid(EXTENSION_PROXY_TABLE, get_namespace_oid(CACHE_SCHEMA_NAME, false));
catalog_reset();
break;
@ -135,7 +94,7 @@ extension_set_state(enum ExtensionState newstate)
static bool
extension_update_state()
{
return extension_set_state(extension_new_state());
return extension_set_state(extension_current_state());
}
/*
@ -181,7 +140,6 @@ extension_invalidate(Oid relid)
}
}
bool
extension_is_loaded(void)
{
@ -195,18 +153,6 @@ extension_is_loaded(void)
extension_update_state();
}
/*
* Turn off extension during upgrade scripts. This is necessary so that,
* for example, the catalog does not go looking for things that aren't yet
* there.
*/
if (creating_extension)
{
Oid extension_oid = get_extension_oid(EXTENSION_NAME, true);
if (OidIsValid(extension_oid) && extension_oid == CurrentExtensionObject)
return false;
}
switch (extstate)
{
case EXTENSION_STATE_CREATED:
@ -214,6 +160,12 @@ extension_is_loaded(void)
case EXTENSION_STATE_NOT_INSTALLED:
case EXTENSION_STATE_UNKNOWN:
case EXTENSION_STATE_TRANSITIONING:
/*
* Turn off extension during upgrade scripts. This is necessary so
* that, for example, the catalog does not go looking for things
* that aren't yet there.
*/
return false;
default:
elog(ERROR, "unknown state: %d", extstate);

@ -2,7 +2,10 @@
#define TIMESCALEDB_EXTENSION_H
#include <postgres.h>
#define EXTENSION_NAME "timescaledb"
bool extension_invalidate(Oid relid);
bool extension_is_loaded(void);
void extension_check_version(const char *so_version);
#endif /* TIMESCALEDB_EXTENSION_H */

172
src/extension_utils.c Normal file

@ -0,0 +1,172 @@
/* This file will be used by the versioned timescaledb extension and the loader
* Because we want the loader not to export symbols all files here should be static
* and be included via #include "extension_utils.c" instead of the regular linking process
*/
#include <postgres.h>
#include <access/xact.h>
#include <commands/extension.h>
#include <catalog/namespace.h>
#include <utils/lsyscache.h>
#include <miscadmin.h>
#include <parser/analyze.h>
#include <commands/extension.h>
#include <access/relscan.h>
#include <catalog/pg_extension.h>
#include <utils/fmgroids.h>
#include <utils/builtins.h>
#include <utils/rel.h>
#include <catalog/indexing.h>
#define EXTENSION_PROXY_TABLE "cache_inval_extension"
#define CACHE_SCHEMA_NAME "_timescaledb_cache"
#define MAX_SO_NAME_LEN NAMEDATALEN+NAMEDATALEN+1+1 /* extname+"-"+version */
enum ExtensionState
{
/*
* NOT_INSTALLED means that this backend knows that the extension is not
* present. In this state we know that the proxy table is not present.
* Thus, the only way to get out of this state is a RelCacheInvalidation
* indicating that the proxy table was added. This is the state returned
* during DROP EXTENSION.
*/
EXTENSION_STATE_NOT_INSTALLED,
/*
* UNKNOWN state is used only if we cannot be sure what the state is. This
* can happen in two cases: 1) at the start of a backend or 2) We got a
* relcache event outside of a transaction and thus could not check the
* cache for the presence/absence of the proxy table or extension.
*/
EXTENSION_STATE_UNKNOWN,
/*
* TRANSITIONING only occurs in the middle of a CREATE EXTENSION or ALTER
* EXTENSION UPDATE
*/
EXTENSION_STATE_TRANSITIONING,
/*
* CREATED means we know the extension is loaded, metadata is up-to-date,
* and we therefore do not need a full check until a RelCacheInvalidation
* on the proxy table.
*/
EXTENSION_STATE_CREATED,
};
static char *
extension_version(void)
{
Datum result;
Relation rel;
SysScanDesc scandesc;
HeapTuple tuple;
ScanKeyData entry[1];
bool is_null = true;
static char *sql_version = NULL;
rel = heap_open(ExtensionRelationId, AccessShareLock);
ScanKeyInit(&entry[0],
Anum_pg_extension_extname,
BTEqualStrategyNumber, F_NAMEEQ,
DirectFunctionCall1(namein, CStringGetDatum(EXTENSION_NAME))
);
scandesc = systable_beginscan(rel, ExtensionNameIndexId, true,
NULL, 1, entry);
tuple = systable_getnext(scandesc);
/* We assume that there can be at most one matching tuple */
if (HeapTupleIsValid(tuple))
{
result = heap_getattr(tuple, Anum_pg_extension_extversion, RelationGetDescr(rel), &is_null);
if (!is_null)
{
sql_version = strdup(TextDatumGetCString(result));
}
}
systable_endscan(scandesc);
heap_close(rel, AccessShareLock);
if (sql_version == NULL)
{
elog(ERROR, "Extension not found when getting version");
}
return sql_version;
}
static bool inline
proxy_table_exists()
{
Oid nsid = get_namespace_oid(CACHE_SCHEMA_NAME, true);
if (!OidIsValid(nsid))
return false;
return OidIsValid(get_relname_relid(EXTENSION_PROXY_TABLE, nsid));
}
static bool inline
extension_exists()
{
return OidIsValid(get_extension_oid(EXTENSION_NAME, true));
}
static bool inline
extension_is_transitioning()
{
/*
* Determine whether the extension is being created or upgraded (as a
* misnomer creating_extension is true during upgrades)
*/
if (creating_extension)
{
char *current_extension_name = get_extension_name(CurrentExtensionObject);
if (NULL == current_extension_name)
elog(ERROR, "Unknown current extension while creating");
if (strcmp(EXTENSION_NAME, current_extension_name) == 0)
return true;
}
return false;
}
/* Returns the recomputed current state */
static enum ExtensionState
extension_current_state()
{
/*
* NormalProcessingMode necessary to avoid accessing cache before its
* ready (which may result in an infinite loop). More concretely we need
* RelationCacheInitializePhase3 to have been already called.
*/
if (!IsNormalProcessingMode() || !IsTransactionState())
return EXTENSION_STATE_UNKNOWN;
/*
* NOTE: do not check for proxy_table_exists here. Want to be in
* TRANSITIONING state even before the proxy table is created
*/
if (extension_is_transitioning())
return EXTENSION_STATE_TRANSITIONING;
/*
* proxy_table_exists uses syscache. Must come first. NOTE: during DROP
* EXTENSION proxy_table_exists() will return false right away, while
* extension_exists will return true until the end of the command
*/
if (proxy_table_exists())
{
Assert(extension_exists());
return EXTENSION_STATE_CREATED;
}
return EXTENSION_STATE_NOT_INSTALLED;
}

@ -6,7 +6,10 @@
#include <utils/guc.h>
#include "executor.h"
#include "extension.h"
#include "guc.h"
#include "catalog.h"
#include "version.h"
#ifdef PG_MODULE_MAGIC
PG_MODULE_MAGIC;
@ -43,32 +46,12 @@ extern void PGDLLEXPORT _PG_fini(void);
void
_PG_init(void)
{
if (!process_shared_preload_libraries_in_progress)
{
/* cannot use GUC variable here since extension not yet loaded */
char *allow_install_without_preload = GetConfigOptionByName("timescaledb.allow_install_without_preload", NULL, true);
/*
* Check extension_is loaded to catch certain errors such as calls to
* functions defined on the wrong extension version
*/
extension_check_version(TIMESCALEDB_VERSION_MOD);
if (allow_install_without_preload == NULL ||
strlen(allow_install_without_preload) != 2 ||
strncmp(allow_install_without_preload, "on", 2) != 0)
{
char *config_file = GetConfigOptionByName("config_file", NULL, false);
ereport(ERROR,
(errmsg("The timescaledb library is not preloaded"),
errhint("Please preload the timescaledb library via shared_preload_libraries.\n\n"
"This can be done by editing the config file at: %1$s\n"
"and adding 'timescaledb' to the list in the shared_preload_libraries config.\n"
" # Modify postgresql.conf:\n shared_preload_libraries = 'timescaledb'\n\n"
"Another way to do this, if not preloading other libraries, is with the command:\n"
" echo \"shared_preload_libraries = 'timescaledb'\" >> %1$s \n\n"
"(Will require a database restart.)\n\n"
"If you REALLY know what you are doing and would like to load the library without preloading, you can disable this check with: \n"
" SET timescaledb.allow_install_without_preload = 'on';", config_file)));
return;
}
}
elog(INFO, "timescaledb loaded");
_chunk_dispatch_info_init();
_cache_init();
_hypertable_cache_init();

19
src/loader/CMakeLists.txt Normal file

@ -0,0 +1,19 @@
set(HEADERS
)
set(SOURCES
loader.c)
add_library(${PROJECT_NAME}-loader MODULE ${SOURCES} ${HEADERS})
set_target_properties(${PROJECT_NAME}-loader PROPERTIES
OUTPUT_NAME ${PROJECT_NAME}
PREFIX "")
install(
TARGETS ${PROJECT_NAME}-loader
DESTINATION ${PG_PKGLIBDIR})
if(CMAKE_BUILD_TYPE MATCHES Debug)
add_subdirectory(../../test/loader-mock/ "${CMAKE_CURRENT_BINARY_DIR}/mock")
endif(CMAKE_BUILD_TYPE MATCHES Debug)

290
src/loader/loader.c Normal file

@ -0,0 +1,290 @@
#include <postgres.h>
#include <pg_config.h>
#include <access/xact.h>
#include "../compat-msvc-enter.h"
#include <commands/extension.h>
#include <miscadmin.h>
#include <parser/analyze.h>
#include "../compat-msvc-exit.h"
#include <utils/guc.h>
#include <utils/inval.h>
#include <nodes/print.h>
#define EXTENSION_NAME "timescaledb"
#include "../extension_utils.c"
#define PG96 ((PG_VERSION_NUM >= 90600) && (PG_VERSION_NUM < 100000))
#define PG10 ((PG_VERSION_NUM >= 100000) && (PG_VERSION_NUM < 110000))
/*
* Some notes on design:
*
* We do not check for the installation of the extension upon loading the extension and instead rely on a hook for two reasons:
* 1) We probably can't
* - The shared_preload_libraries is called in PostmasterMain which is way before InitPostgres is called.
* (Note: This happens even before the fork of the backend) -- so we don't even know which database this is for.
* -- This means we cannot query for the existance of the extension yet because the caches are initialized in InitPostgres.
* 2) We actually don't want to load the extension in two cases:
* a) We are upgrading the extension.
* b) We set the guc timescaledb.disable_load.
*
*
*/
#ifdef PG_MODULE_MAGIC
PG_MODULE_MAGIC;
#endif
#define GUC_DISABLE_LOAD_NAME "timescaledb.disable_load"
extern void PGDLLEXPORT _PG_init(void);
extern void PGDLLEXPORT _PG_fini(void);
/* was the versioned-extension loaded*/
static bool loaded = false;
/* GUC to disable the load */
static bool guc_disable_load = false;
/* This is the hook that existed before the loader was installed */
static post_parse_analyze_hook_type prev_post_parse_analyze_hook;
/* This is timescaleDB's versioned-extension's post_parse_analyze_hook */
static post_parse_analyze_hook_type extension_post_parse_analyze_hook = NULL;
static void inline extension_check(void);
static void call_extension_post_parse_analyze_hook(ParseState *pstate,
Query *query);
static void
inval_cache_callback(Datum arg, Oid relid)
{
if (guc_disable_load)
return;
extension_check();
}
static bool
drop_statement_drops_extension(DropStmt *stmt)
{
if (stmt->removeType == OBJECT_EXTENSION)
{
if (list_length(stmt->objects) == 1)
{
char *ext_name;
#if PG96
List *names = linitial(stmt->objects);
Assert(list_length(names) == 1);
ext_name = strVal(linitial(names));
#elif PG10
void *name = linitial(stmt->objects);
ext_name = strVal(name);
#endif
if (strcmp(ext_name, EXTENSION_NAME) == 0)
return true;
}
}
return false;
}
static bool
load_utility_cmd(Node *utilityStmt)
{
switch (nodeTag(utilityStmt))
{
case T_VariableSetStmt:
if (strcmp(((VariableSetStmt *) utilityStmt)->name, GUC_DISABLE_LOAD_NAME) == 0)
/* Do not load when setting the guc */
return false;
return true;
case T_AlterExtensionStmt:
if (strcmp(((AlterExtensionStmt *) utilityStmt)->extname, EXTENSION_NAME) != 0)
return true;
/* disallow loading two .so from different versions */
if (loaded)
ereport(ERROR,
(errmsg("Cannot update the extension after the old version has already been loaded"),
errhint("You should start a new session and execute ALTER EXTENSION as the first command")));
/* do not load the current (old) version's .so */
return false;
case T_CreateExtensionStmt:
if (!loaded || strcmp(((CreateExtensionStmt *) utilityStmt)->extname, EXTENSION_NAME) != 0)
return true;
/* disallow loading two .so from different versions */
ereport(ERROR,
(errmsg("Cannot create the extension after the another version has already been loaded"),
errhint("You should start a new session and execute CREATE EXTENSION as the first command")));
case T_DropStmt:
if (drop_statement_drops_extension((DropStmt *) utilityStmt))
/* do not load when dropping */
return false;
return true;
default:
return true;
}
}
static void
post_analyze_hook(ParseState *pstate, Query *query)
{
if (!guc_disable_load && (query->commandType != CMD_UTILITY || load_utility_cmd(query->utilityStmt)))
extension_check();
/*
* Call the extension's hook. This is necessary since the extension is
* installed during the hook. If we did not do this the extension's hook
* would not be called during the first command because the extension
* would not have yet been installed. Thus the loader captures the
* extension hook and calls it explicitly after the check for installing
* the extension.
*/
call_extension_post_parse_analyze_hook(pstate, query);
if (prev_post_parse_analyze_hook != NULL)
{
prev_post_parse_analyze_hook(pstate, query);
}
}
void
_PG_init(void)
{
if (!process_shared_preload_libraries_in_progress)
{
/* cannot use GUC variable here since extension not yet loaded */
char *allow_install_without_preload = GetConfigOptionByName("timescaledb.allow_install_without_preload", NULL, true);
if (allow_install_without_preload == NULL ||
strcmp(allow_install_without_preload, "on") != 0)
{
char *config_file = GetConfigOptionByName("config_file", NULL, false);
ereport(ERROR,
(errmsg("The timescaledb library is not preloaded"),
errhint("Please preload the timescaledb library via shared_preload_libraries.\n\n"
"This can be done by editing the config file at: %1$s\n"
"and adding 'timescaledb' to the list in the shared_preload_libraries config.\n"
" # Modify postgresql.conf:\n shared_preload_libraries = 'timescaledb'\n\n"
"Another way to do this, if not preloading other libraries, is with the command:\n"
" echo \"shared_preload_libraries = 'timescaledb'\" >> %1$s \n\n"
"(Will require a database restart.)\n\n"
"If you REALLY know what you are doing and would like to load the library without preloading, you can disable this check with: \n"
" SET timescaledb.allow_install_without_preload = 'on';", config_file)));
return;
}
}
elog(INFO, "timescaledb loaded");
/* This is a safety-valve variable to prevent loading the full extension */
DefineCustomBoolVariable(GUC_DISABLE_LOAD_NAME, "Disable the loading of the actual extension",
NULL,
&guc_disable_load,
false,
PGC_USERSET,
0,
NULL,
NULL,
NULL);
/*
* cannot check for extension here since not inside a transaction yet. Nor
* do we even have an assigned database yet
*/
CacheRegisterRelcacheCallback(inval_cache_callback, PointerGetDatum(NULL));
/*
* using the post_parse_analyze_hook since it's the earliest available
* hook
*/
prev_post_parse_analyze_hook = post_parse_analyze_hook;
post_parse_analyze_hook = post_analyze_hook;
}
void
_PG_fini(void)
{
post_parse_analyze_hook = prev_post_parse_analyze_hook;
/* No way to unregister relcache callback */
}
static void inline
do_load()
{
char *version = extension_version();
char soname[MAX_SO_NAME_LEN];
post_parse_analyze_hook_type old_hook;
snprintf(soname, MAX_SO_NAME_LEN, "%s-%s", EXTENSION_NAME, version);
/*
* we need to capture the loaded extension's post analyze hook, giving it
* a NULL as previous
*/
old_hook = post_parse_analyze_hook;
post_parse_analyze_hook = NULL;
PG_TRY();
{
load_file(soname, false);
loaded = true;
}
PG_CATCH();
{
/* Assume the extension was loaded to prevent re-loading another .so */
loaded = true;
extension_post_parse_analyze_hook = post_parse_analyze_hook;
post_parse_analyze_hook = old_hook;
PG_RE_THROW();
}
PG_END_TRY();
extension_post_parse_analyze_hook = post_parse_analyze_hook;
post_parse_analyze_hook = old_hook;
}
static void inline
extension_check()
{
if (!loaded)
{
enum ExtensionState state = extension_current_state();
switch (state)
{
case EXTENSION_STATE_TRANSITIONING:
/*
* Always load as soon as the extension is transitioning. This
* is necessary so that the extension load before any CREATE
* FUNCTION calls. Otherwise, the CREATE FUNCTION calls will
* load the .so without capturing the post_parse_analyze_hook.
*/
case EXTENSION_STATE_CREATED:
do_load();
return;
case EXTENSION_STATE_UNKNOWN:
case EXTENSION_STATE_NOT_INSTALLED:
return;
}
}
}
static void
call_extension_post_parse_analyze_hook(ParseState *pstate,
Query *query)
{
if (loaded && extension_post_parse_analyze_hook != NULL)
{
extension_post_parse_analyze_hook(pstate, query);
}
}

@ -1638,8 +1638,20 @@ timescaledb_ddl_command_start(
.parsetree = parsetree,
#endif
};
bool altering_timescaledb = false;
if (!extension_is_loaded())
if (IsA(args.parsetree, AlterExtensionStmt))
{
AlterExtensionStmt *stmt = (AlterExtensionStmt *) args.parsetree;
altering_timescaledb = (strcmp(stmt->extname, EXTENSION_NAME) == 0);
}
/*
* We don't want to load the extension if we just got the command to alter
* it.
*/
if (altering_timescaledb || !extension_is_loaded())
{
prev_ProcessUtility(&args);
return;

@ -36,7 +36,7 @@ CREATE EXTENSION timescaledb;
-- Test that calling twice generates proper error
\set ON_ERROR_STOP 0
CREATE EXTENSION timescaledb;
ERROR: extension "timescaledb" already exists
ERROR: Cannot create the extension after the another version has already been loaded
\set ON_ERROR_STOP 1
\c single :ROLE_DEFAULT_PERM_USER
-- Make the table a hypertable again

434
test/expected/loader.out Normal file

@ -0,0 +1,434 @@
\c single :ROLE_SUPERUSER
DROP EXTENSION timescaledb;
--no extension
\dx
List of installed extensions
Name | Version | Schema | Description
---------+---------+------------+------------------------------
plpgsql | 1.0 | pg_catalog | PL/pgSQL procedural language
(1 row)
SELECT 1;
?column?
----------
1
(1 row)
CREATE EXTENSION timescaledb VERSION 'mock-1';
WARNING: mock init "mock-1"
--same backend as create extension;
SELECT 1;
WARNING: mock post_analyze_hook "mock-1"
?column?
----------
1
(1 row)
\dx
WARNING: mock post_analyze_hook "mock-1"
List of installed extensions
Name | Version | Schema | Description
-------------+---------+------------+-------------------------------------------------------------------
plpgsql | 1.0 | pg_catalog | PL/pgSQL procedural language
timescaledb | mock-1 | public | Enables scalable inserts and complex queries for time-series data
(2 rows)
--start new backend;
\c single :ROLE_DEFAULT_PERM_USER
SELECT 1;
WARNING: mock init "mock-1"
WARNING: mock post_analyze_hook "mock-1"
?column?
----------
1
(1 row)
SELECT 1;
WARNING: mock post_analyze_hook "mock-1"
?column?
----------
1
(1 row)
--test fn call after load
SELECT mock_function();
WARNING: mock post_analyze_hook "mock-1"
WARNING: mock function call "mock-1"
mock_function
---------------
(1 row)
\dx
WARNING: mock post_analyze_hook "mock-1"
List of installed extensions
Name | Version | Schema | Description
-------------+---------+------------+-------------------------------------------------------------------
plpgsql | 1.0 | pg_catalog | PL/pgSQL procedural language
timescaledb | mock-1 | public | Enables scalable inserts and complex queries for time-series data
(2 rows)
\c single :ROLE_DEFAULT_PERM_USER
--test fn call as first command
SELECT mock_function();
WARNING: mock init "mock-1"
WARNING: mock post_analyze_hook "mock-1"
WARNING: mock function call "mock-1"
mock_function
---------------
(1 row)
--use guc to prevent loading
\c single :ROLE_SUPERUSER
SET timescaledb.disable_load = 'on';
SELECT 1;
?column?
----------
1
(1 row)
SELECT 1;
?column?
----------
1
(1 row)
SET timescaledb.disable_load = 'off';
SELECT 1;
WARNING: mock init "mock-1"
WARNING: mock post_analyze_hook "mock-1"
?column?
----------
1
(1 row)
\set ON_ERROR_STOP 0
SET timescaledb.disable_load = 'not bool';
WARNING: mock post_analyze_hook "mock-1"
ERROR: parameter "timescaledb.disable_load" requires a Boolean value
\set ON_ERROR_STOP 1
\set ON_ERROR_STOP 0
--cannot update extension after .so of previous version already loaded
ALTER EXTENSION timescaledb UPDATE TO 'mock-2';
ERROR: Cannot update the extension after the old version has already been loaded
\set ON_ERROR_STOP 1
\c single_2 :ROLE_SUPERUSER
\dx
List of installed extensions
Name | Version | Schema | Description
---------+---------+------------+------------------------------
plpgsql | 1.0 | pg_catalog | PL/pgSQL procedural language
(1 row)
CREATE EXTENSION timescaledb VERSION 'mock-1';
WARNING: mock init "mock-1"
\dx
WARNING: mock post_analyze_hook "mock-1"
List of installed extensions
Name | Version | Schema | Description
-------------+---------+------------+-------------------------------------------------------------------
plpgsql | 1.0 | pg_catalog | PL/pgSQL procedural language
timescaledb | mock-1 | public | Enables scalable inserts and complex queries for time-series data
(2 rows)
--start a new backend to update
\c single_2 :ROLE_SUPERUSER
ALTER EXTENSION timescaledb UPDATE TO 'mock-2';
WARNING: mock init "mock-2"
SELECT 1;
WARNING: mock post_analyze_hook "mock-2"
?column?
----------
1
(1 row)
\dx
WARNING: mock post_analyze_hook "mock-2"
List of installed extensions
Name | Version | Schema | Description
-------------+---------+------------+-------------------------------------------------------------------
plpgsql | 1.0 | pg_catalog | PL/pgSQL procedural language
timescaledb | mock-2 | public | Enables scalable inserts and complex queries for time-series data
(2 rows)
--drop extension
DROP EXTENSION timescaledb;
WARNING: mock post_analyze_hook "mock-2"
SELECT 1;
?column?
----------
1
(1 row)
\dx
List of installed extensions
Name | Version | Schema | Description
---------+---------+------------+------------------------------
plpgsql | 1.0 | pg_catalog | PL/pgSQL procedural language
(1 row)
\c single_2 :ROLE_SUPERUSER
CREATE EXTENSION timescaledb VERSION 'mock-2';
WARNING: mock init "mock-2"
SELECT 1;
WARNING: mock post_analyze_hook "mock-2"
?column?
----------
1
(1 row)
\dx
WARNING: mock post_analyze_hook "mock-2"
List of installed extensions
Name | Version | Schema | Description
-------------+---------+------------+-------------------------------------------------------------------
plpgsql | 1.0 | pg_catalog | PL/pgSQL procedural language
timescaledb | mock-2 | public | Enables scalable inserts and complex queries for time-series data
(2 rows)
--single still has old version
\c single :ROLE_SUPERUSER
SELECT 1;
WARNING: mock init "mock-1"
WARNING: mock post_analyze_hook "mock-1"
?column?
----------
1
(1 row)
\dx
WARNING: mock post_analyze_hook "mock-1"
List of installed extensions
Name | Version | Schema | Description
-------------+---------+------------+-------------------------------------------------------------------
plpgsql | 1.0 | pg_catalog | PL/pgSQL procedural language
timescaledb | mock-1 | public | Enables scalable inserts and complex queries for time-series data
(2 rows)
--try a broken upgrade
\c single_2 :ROLE_SUPERUSER
\dx
WARNING: mock init "mock-2"
WARNING: mock post_analyze_hook "mock-2"
List of installed extensions
Name | Version | Schema | Description
-------------+---------+------------+-------------------------------------------------------------------
plpgsql | 1.0 | pg_catalog | PL/pgSQL procedural language
timescaledb | mock-2 | public | Enables scalable inserts and complex queries for time-series data
(2 rows)
\set ON_ERROR_STOP 0
ALTER EXTENSION timescaledb UPDATE TO 'mock-3';
ERROR: Cannot update the extension after the old version has already been loaded
\set ON_ERROR_STOP 1
--should still be on mock-2
SELECT 1;
WARNING: mock post_analyze_hook "mock-2"
?column?
----------
1
(1 row)
\dx
WARNING: mock post_analyze_hook "mock-2"
List of installed extensions
Name | Version | Schema | Description
-------------+---------+------------+-------------------------------------------------------------------
plpgsql | 1.0 | pg_catalog | PL/pgSQL procedural language
timescaledb | mock-2 | public | Enables scalable inserts and complex queries for time-series data
(2 rows)
--drop extension
DROP EXTENSION timescaledb;
WARNING: mock post_analyze_hook "mock-2"
SELECT 1;
?column?
----------
1
(1 row)
\dx
List of installed extensions
Name | Version | Schema | Description
---------+---------+------------+------------------------------
plpgsql | 1.0 | pg_catalog | PL/pgSQL procedural language
(1 row)
--create extension anew, only upgrade was broken
\c single_2 :ROLE_SUPERUSER
CREATE EXTENSION timescaledb VERSION 'mock-3';
WARNING: mock init "mock-3"
SELECT 1;
WARNING: mock post_analyze_hook "mock-3"
?column?
----------
1
(1 row)
\dx
WARNING: mock post_analyze_hook "mock-3"
List of installed extensions
Name | Version | Schema | Description
-------------+---------+------------+-------------------------------------------------------------------
plpgsql | 1.0 | pg_catalog | PL/pgSQL procedural language
timescaledb | mock-3 | public | Enables scalable inserts and complex queries for time-series data
(2 rows)
DROP EXTENSION timescaledb;
WARNING: mock post_analyze_hook "mock-3"
SELECT 1;
?column?
----------
1
(1 row)
--mismatched version errors
\c single_2 :ROLE_SUPERUSER
\set ON_ERROR_STOP 0
--mock-4 has mismatched versions, so the .so load should throw an error
CREATE EXTENSION timescaledb VERSION 'mock-4';
ERROR: Mismatched timescaledb version. Shared object file mock-4-mismatch, SQL mock-4
\set ON_ERROR_STOP 1
--mock-4 not installed.
\dx
List of installed extensions
Name | Version | Schema | Description
---------+---------+------------+------------------------------
plpgsql | 1.0 | pg_catalog | PL/pgSQL procedural language
(1 row)
\set ON_ERROR_STOP 0
--should not allow since the errored-out mock-4 above already poisoned the well.
CREATE EXTENSION timescaledb VERSION 'mock-5';
ERROR: Cannot create the extension after the another version has already been loaded
\set ON_ERROR_STOP 1
\c single_2 :ROLE_SUPERUSER
--broken version and drop
CREATE EXTENSION timescaledb VERSION 'mock-broken';
WARNING: mock init "mock-broken"
\set ON_ERROR_STOP 0
--intentional broken version
\dx
WARNING: mock post_analyze_hook "mock-broken"
ERROR: mock broken "mock-broken"
SELECT 1;
WARNING: mock post_analyze_hook "mock-broken"
ERROR: mock broken "mock-broken"
SELECT 1;
WARNING: mock post_analyze_hook "mock-broken"
ERROR: mock broken "mock-broken"
--cannot drop extension; already loaded broken version
DROP EXTENSION timescaledb;
WARNING: mock post_analyze_hook "mock-broken"
ERROR: mock broken "mock-broken"
\set ON_ERROR_STOP 1
\c single_2 :ROLE_SUPERUSER
--can drop extension now. Since drop first command.
DROP EXTENSION timescaledb;
\dx
List of installed extensions
Name | Version | Schema | Description
---------+---------+------------+------------------------------
plpgsql | 1.0 | pg_catalog | PL/pgSQL procedural language
(1 row)
--broken version and update to fixed
\c single_2 :ROLE_SUPERUSER
CREATE EXTENSION timescaledb VERSION 'mock-broken';
WARNING: mock init "mock-broken"
\set ON_ERROR_STOP 0
--intentional broken version
SELECT 1;
WARNING: mock post_analyze_hook "mock-broken"
ERROR: mock broken "mock-broken"
--cannot update extension; already loaded bad version
ALTER EXTENSION timescaledb UPDATE TO 'mock-5';
ERROR: Cannot update the extension after the old version has already been loaded
\set ON_ERROR_STOP 1
\c single_2 :ROLE_SUPERUSER
--can update extension now.
ALTER EXTENSION timescaledb UPDATE TO 'mock-5';
WARNING: mock init "mock-5"
SELECT 1;
WARNING: mock post_analyze_hook "mock-5"
?column?
----------
1
(1 row)
SELECT mock_function();
WARNING: mock post_analyze_hook "mock-5"
WARNING: mock function call "mock-5"
mock_function
---------------
(1 row)
\c single_2 :ROLE_SUPERUSER
ALTER EXTENSION timescaledb UPDATE TO 'mock-6';
WARNING: mock init "mock-6"
\set ON_ERROR_STOP 0
--The mock-5->mock_6 upgrade is intentionally broken.
--The mock_function was never changed to point to mock-6 in the update script.
--Thus mock_function is defined incorrectly to point to the mock-5.so
--This should be an error.
SELECT mock_function();
WARNING: mock post_analyze_hook "mock-6"
ERROR: Mismatched timescaledb version. Shared object file mock-5, SQL mock-6
\set ON_ERROR_STOP 1
\dx
WARNING: mock post_analyze_hook "mock-6"
List of installed extensions
Name | Version | Schema | Description
-------------+---------+------------+-------------------------------------------------------------------
plpgsql | 1.0 | pg_catalog | PL/pgSQL procedural language
timescaledb | mock-6 | public | Enables scalable inserts and complex queries for time-series data
(2 rows)
--TEST: create extension when old .so already loaded
\c single :ROLE_SUPERUSER
--force load of extension with (\dx)
\dx
WARNING: mock init "mock-1"
WARNING: mock post_analyze_hook "mock-1"
List of installed extensions
Name | Version | Schema | Description
-------------+---------+------------+-------------------------------------------------------------------
plpgsql | 1.0 | pg_catalog | PL/pgSQL procedural language
timescaledb | mock-1 | public | Enables scalable inserts and complex queries for time-series data
(2 rows)
DROP EXTENSION timescaledb;
WARNING: mock post_analyze_hook "mock-1"
\dx
List of installed extensions
Name | Version | Schema | Description
---------+---------+------------+------------------------------
plpgsql | 1.0 | pg_catalog | PL/pgSQL procedural language
(1 row)
\set ON_ERROR_STOP 0
CREATE EXTENSION timescaledb VERSION 'mock-2';
ERROR: Cannot create the extension after the another version has already been loaded
\set ON_ERROR_STOP 1
\dx
List of installed extensions
Name | Version | Schema | Description
---------+---------+------------+------------------------------
plpgsql | 1.0 | pg_catalog | PL/pgSQL procedural language
(1 row)
--can create in a new session.
\c single :ROLE_SUPERUSER
CREATE EXTENSION timescaledb VERSION 'mock-2';
WARNING: mock init "mock-2"
\dx
WARNING: mock post_analyze_hook "mock-2"
List of installed extensions
Name | Version | Schema | Description
-------------+---------+------------+-------------------------------------------------------------------
plpgsql | 1.0 | pg_catalog | PL/pgSQL procedural language
timescaledb | mock-2 | public | Enables scalable inserts and complex queries for time-series data
(2 rows)

@ -0,0 +1,2 @@
add_subdirectory(sql)
add_subdirectory(src)

@ -0,0 +1,14 @@
install(
FILES timescaledb--mock-1.sql
timescaledb--mock-2.sql
timescaledb--mock-3.sql
timescaledb--mock-4.sql
timescaledb--mock-5.sql
timescaledb--mock-6.sql
timescaledb--mock-broken.sql
timescaledb--mock-1--mock-2.sql
timescaledb--mock-2--mock-3.sql
timescaledb--mock-3--mock-4.sql
timescaledb--mock-5--mock-6.sql
timescaledb--mock-broken--mock-5.sql
DESTINATION "${PG_SHAREDIR}/extension")

@ -0,0 +1,7 @@
--test that the extension is deactivated during upgrade
SELECT 1;
SELECT 1;
SELECT 1;
SELECT 1;
CREATE OR REPLACE FUNCTION mock_function() RETURNS VOID
AS '$libdir/timescaledb-mock-2', 'mock_function' LANGUAGE C IMMUTABLE STRICT PARALLEL SAFE;

@ -0,0 +1,4 @@
CREATE SCHEMA IF NOT EXISTS _timescaledb_cache;
CREATE TABLE IF NOT EXISTS _timescaledb_cache.cache_inval_extension();
CREATE OR REPLACE FUNCTION mock_function() RETURNS VOID
AS '$libdir/timescaledb-mock-1', 'mock_function' LANGUAGE C IMMUTABLE STRICT PARALLEL SAFE;

@ -0,0 +1,3 @@
broken sql;
CREATE OR REPLACE FUNCTION mock_function() RETURNS VOID
AS '$libdir/timescaledb-mock-3', 'mock_function' LANGUAGE C IMMUTABLE STRICT PARALLEL SAFE;

@ -0,0 +1,6 @@
--create function before proxy table
CREATE OR REPLACE FUNCTION mock_function() RETURNS VOID
AS '$libdir/timescaledb-mock-2', 'mock_function' LANGUAGE C IMMUTABLE STRICT PARALLEL SAFE;
CREATE SCHEMA IF NOT EXISTS _timescaledb_cache;
CREATE TABLE IF NOT EXISTS _timescaledb_cache.cache_inval_extension();

@ -0,0 +1,7 @@
--test that the extension is deactivated during upgrade
SELECT 1;
SELECT 1;
SELECT 1;
SELECT 1;
CREATE OR REPLACE FUNCTION mock_function() RETURNS VOID
AS '$libdir/timescaledb-mock-4', 'mock_function' LANGUAGE C IMMUTABLE STRICT PARALLEL SAFE;

@ -0,0 +1,4 @@
CREATE SCHEMA IF NOT EXISTS _timescaledb_cache;
CREATE TABLE IF NOT EXISTS _timescaledb_cache.cache_inval_extension();
CREATE OR REPLACE FUNCTION mock_function() RETURNS VOID
AS '$libdir/timescaledb-mock-3', 'mock_function' LANGUAGE C IMMUTABLE STRICT PARALLEL SAFE;

@ -0,0 +1,4 @@
CREATE SCHEMA IF NOT EXISTS _timescaledb_cache;
CREATE TABLE IF NOT EXISTS _timescaledb_cache.cache_inval_extension();
CREATE OR REPLACE FUNCTION mock_function() RETURNS VOID
AS '$libdir/timescaledb-mock-4', 'mock_function' LANGUAGE C IMMUTABLE STRICT PARALLEL SAFE;

@ -0,0 +1,8 @@
--test that the extension is deactivated during upgrade
SELECT 1;
SELECT 1;
SELECT 1;
SELECT 1;
--intentionally forget to updat func
--CREATE OR REPLACE FUNCTION mock_function() RETURNS VOID
-- AS '$libdir/timescaledb-mock-6', 'mock_function' LANGUAGE C IMMUTABLE STRICT PARALLEL SAFE;

@ -0,0 +1,4 @@
CREATE SCHEMA IF NOT EXISTS _timescaledb_cache;
CREATE TABLE IF NOT EXISTS _timescaledb_cache.cache_inval_extension();
CREATE OR REPLACE FUNCTION mock_function() RETURNS VOID
AS '$libdir/timescaledb-mock-5', 'mock_function' LANGUAGE C IMMUTABLE STRICT PARALLEL SAFE;

@ -0,0 +1,4 @@
CREATE SCHEMA IF NOT EXISTS _timescaledb_cache;
CREATE TABLE IF NOT EXISTS _timescaledb_cache.cache_inval_extension();
CREATE OR REPLACE FUNCTION mock_function() RETURNS VOID
AS '$libdir/timescaledb-mock-6', 'mock_function' LANGUAGE C IMMUTABLE STRICT PARALLEL SAFE;

@ -0,0 +1,7 @@
--test that the extension is deactivated during upgrade
SELECT 1;
SELECT 1;
SELECT 1;
SELECT 1;
CREATE OR REPLACE FUNCTION mock_function() RETURNS VOID
AS '$libdir/timescaledb-mock-5', 'mock_function' LANGUAGE C IMMUTABLE STRICT PARALLEL SAFE;

@ -0,0 +1,4 @@
CREATE SCHEMA IF NOT EXISTS _timescaledb_cache;
CREATE TABLE IF NOT EXISTS _timescaledb_cache.cache_inval_extension();
CREATE OR REPLACE FUNCTION mock_function() RETURNS VOID
AS '$libdir/timescaledb-mock-broken', 'mock_function' LANGUAGE C IMMUTABLE STRICT PARALLEL SAFE;

@ -0,0 +1,38 @@
set(SOURCES
init.c
../../../src/extension.c
../../../src/guc.c
)
include_directories(BEFORE ${CMAKE_CURRENT_SOURCE_DIR})
add_library(${PROJECT_NAME}-mock-1 MODULE ${SOURCES} version.h)
add_library(${PROJECT_NAME}-mock-2 MODULE ${SOURCES} version.h)
add_library(${PROJECT_NAME}-mock-3 MODULE ${SOURCES} version.h)
#mock-4 will be broken mismatched .so
add_library(${PROJECT_NAME}-mock-4 MODULE ${SOURCES} version.h)
add_library(${PROJECT_NAME}-mock-5 MODULE ${SOURCES} version.h)
add_library(${PROJECT_NAME}-mock-broken MODULE ${SOURCES} version.h)
add_library(${PROJECT_NAME}-mock-6 MODULE ${SOURCES} version.h)
target_compile_definitions(${PROJECT_NAME}-mock-1 PRIVATE TIMESCALEDB_VERSION_MOD="mock-1" BROKEN=0)
target_compile_definitions(${PROJECT_NAME}-mock-2 PRIVATE TIMESCALEDB_VERSION_MOD="mock-2" BROKEN=0)
target_compile_definitions(${PROJECT_NAME}-mock-3 PRIVATE TIMESCALEDB_VERSION_MOD="mock-3" BROKEN=0)
#mock 4 is intentionally incorrect version mod
target_compile_definitions(${PROJECT_NAME}-mock-4 PRIVATE TIMESCALEDB_VERSION_MOD="mock-4-mismatch" BROKEN=0)
target_compile_definitions(${PROJECT_NAME}-mock-5 PRIVATE TIMESCALEDB_VERSION_MOD="mock-5" BROKEN=0)
target_compile_definitions(${PROJECT_NAME}-mock-broken PRIVATE TIMESCALEDB_VERSION_MOD="mock-broken" BROKEN=1)
target_compile_definitions(${PROJECT_NAME}-mock-6 PRIVATE TIMESCALEDB_VERSION_MOD="mock-6" BROKEN=0)
foreach(MOCK_VERSION mock-1 mock-2 mock-3 mock-4 mock-broken mock-5 mock-6)
set_target_properties(${PROJECT_NAME}-${MOCK_VERSION} PROPERTIES
OUTPUT_NAME ${PROJECT_NAME}-${MOCK_VERSION}
PREFIX "")
install(
TARGETS ${PROJECT_NAME}-${MOCK_VERSION}
DESTINATION ${PG_PKGLIBDIR} OPTIONAL)
endforeach(MOCK_VERSION)

@ -0,0 +1,86 @@
#include <postgres.h>
#include <pg_config.h>
#include <access/xact.h>
#include <commands/extension.h>
#include <miscadmin.h>
#include <utils/guc.h>
#include <utils/inval.h>
#include <parser/analyze.h>
#include <nodes/print.h>
#define STR_EXPAND(x) #x
#define STR(x) STR_EXPAND(x)
#define TS_FUNCTION_INFO_V1(fn) \
PGDLLEXPORT Datum fn(PG_FUNCTION_ARGS); \
PG_FUNCTION_INFO_V1(fn)
#ifdef PG_MODULE_MAGIC
PG_MODULE_MAGIC;
#endif
extern void PGDLLEXPORT _PG_init(void);
extern void PGDLLEXPORT _PG_fini(void);
post_parse_analyze_hook_type prev_post_parse_analyze_hook;
bool extension_invalidate(Oid relid);
bool extension_is_loaded(void);
void extension_check_version(const char *actual_version);
static void
cache_invalidate_callback(Datum arg, Oid relid)
{
extension_invalidate(relid);
}
static void
post_analyze_hook(ParseState *pstate, Query *query)
{
if (extension_is_loaded())
elog(WARNING, "mock post_analyze_hook " STR(TIMESCALEDB_VERSION_MOD));
if (prev_post_parse_analyze_hook != NULL)
elog(ERROR, "The extension called with a loader should always have a NULL prev hook");
if(BROKEN && !creating_extension)
elog(ERROR, "mock broken "STR(TIMESCALEDB_VERSION_MOD));
}
void
_PG_init(void)
{
/*
* Check extension_is loaded to catch certain errors such as calls to
* functions defined on the wrong extension version
*/
extension_check_version(TIMESCALEDB_VERSION_MOD);
elog(WARNING, "mock init " STR(TIMESCALEDB_VERSION_MOD));
prev_post_parse_analyze_hook = post_parse_analyze_hook;
if (prev_post_parse_analyze_hook != NULL)
elog(ERROR, "The extension loaded with a loader should always have a NULL prev hook");
post_parse_analyze_hook = post_analyze_hook;
CacheRegisterRelcacheCallback(cache_invalidate_callback, PointerGetDatum(NULL));
}
void
_PG_fini(void)
{
post_parse_analyze_hook = prev_post_parse_analyze_hook;
/* No way to unregister relcache callback */
}
/* mock for extension.c */
void catalog_reset(void);
void
catalog_reset()
{
}
TS_FUNCTION_INFO_V1(mock_function);
Datum
mock_function(PG_FUNCTION_ARGS)
{
elog(WARNING, "mock function call " STR(TIMESCALEDB_VERSION_MOD));
PG_RETURN_VOID();
}

@ -0,0 +1 @@
/* Overwrite main version.h so we could inject our own version #s here. */

@ -7,6 +7,7 @@ PG_REGRESS_PSQL=$1
PSQL=${PSQL:-$PG_REGRESS_PSQL}
TEST_PGUSER=${TEST_PGUSER:-postgres}
TEST_DBNAME=${TEST_DBNAME:-single}
TEST_DBNAME2=${TEST_DBNAME2:-${TEST_DBNAME}_2}
TEST_INPUT_DIR=${TEST_INPUT_DIR:-${EXE_DIR}}
TEST_OUTPUT_DIR=${TEST_OUTPUT_DIR:-${EXE_DIR}}
@ -36,9 +37,11 @@ mkdir -p ${TEST_TABLESPACE2_PATH}
mkdir -p dump
# set role permissions and reset database
${PSQL} $@ -U $USER -v ECHO=none -c "ALTER USER $TEST_ROLE_SUPERUSER WITH SUPERUSER;"
${PSQL} $@ -U $USER -d postgres -v ECHO=none -c "ALTER USER $TEST_ROLE_SUPERUSER WITH SUPERUSER;"
${PSQL} $@ -U $TEST_ROLE_SUPERUSER -d postgres -v ECHO=none -c "DROP DATABASE $TEST_DBNAME;" >/dev/null 2>&1 || :
${PSQL} $@ -U $TEST_ROLE_SUPERUSER -d postgres -v ECHO=none -c "DROP DATABASE $TEST_DBNAME2;" >/dev/null 2>&1 || :
${PSQL} $@ -U $TEST_ROLE_SUPERUSER -d postgres -v ECHO=none -c "CREATE DATABASE $TEST_DBNAME;"
${PSQL} $@ -U $TEST_ROLE_SUPERUSER -d postgres -v ECHO=none -c "CREATE DATABASE $TEST_DBNAME2;"
${PSQL} $@ -U $TEST_ROLE_SUPERUSER -d single -v ECHO=none -c "CREATE EXTENSION timescaledb;"
${PSQL} $@ -U $TEST_ROLE_SUPERUSER -d single -v ECHO=none < ${EXE_DIR}/sql/utils/testsupport.sql >/dev/null 2>&1 || :

@ -49,6 +49,11 @@ set(TEST_FILES
vacuum.sql
version.sql)
IF(CMAKE_BUILD_TYPE MATCHES Debug)
list(APPEND TEST_FILES
loader.sql)
ENDIF(CMAKE_BUILD_TYPE MATCHES Debug)
set(TEST_TEMPLATES
parallel.sql.in
partitioning.sql.in)

167
test/sql/loader.sql Normal file

@ -0,0 +1,167 @@
\c single :ROLE_SUPERUSER
DROP EXTENSION timescaledb;
--no extension
\dx
SELECT 1;
CREATE EXTENSION timescaledb VERSION 'mock-1';
--same backend as create extension;
SELECT 1;
\dx
--start new backend;
\c single :ROLE_DEFAULT_PERM_USER
SELECT 1;
SELECT 1;
--test fn call after load
SELECT mock_function();
\dx
\c single :ROLE_DEFAULT_PERM_USER
--test fn call as first command
SELECT mock_function();
--use guc to prevent loading
\c single :ROLE_SUPERUSER
SET timescaledb.disable_load = 'on';
SELECT 1;
SELECT 1;
SET timescaledb.disable_load = 'off';
SELECT 1;
\set ON_ERROR_STOP 0
SET timescaledb.disable_load = 'not bool';
\set ON_ERROR_STOP 1
\set ON_ERROR_STOP 0
--cannot update extension after .so of previous version already loaded
ALTER EXTENSION timescaledb UPDATE TO 'mock-2';
\set ON_ERROR_STOP 1
\c single_2 :ROLE_SUPERUSER
\dx
CREATE EXTENSION timescaledb VERSION 'mock-1';
\dx
--start a new backend to update
\c single_2 :ROLE_SUPERUSER
ALTER EXTENSION timescaledb UPDATE TO 'mock-2';
SELECT 1;
\dx
--drop extension
DROP EXTENSION timescaledb;
SELECT 1;
\dx
\c single_2 :ROLE_SUPERUSER
CREATE EXTENSION timescaledb VERSION 'mock-2';
SELECT 1;
\dx
--single still has old version
\c single :ROLE_SUPERUSER
SELECT 1;
\dx
--try a broken upgrade
\c single_2 :ROLE_SUPERUSER
\dx
\set ON_ERROR_STOP 0
ALTER EXTENSION timescaledb UPDATE TO 'mock-3';
\set ON_ERROR_STOP 1
--should still be on mock-2
SELECT 1;
\dx
--drop extension
DROP EXTENSION timescaledb;
SELECT 1;
\dx
--create extension anew, only upgrade was broken
\c single_2 :ROLE_SUPERUSER
CREATE EXTENSION timescaledb VERSION 'mock-3';
SELECT 1;
\dx
DROP EXTENSION timescaledb;
SELECT 1;
--mismatched version errors
\c single_2 :ROLE_SUPERUSER
\set ON_ERROR_STOP 0
--mock-4 has mismatched versions, so the .so load should throw an error
CREATE EXTENSION timescaledb VERSION 'mock-4';
\set ON_ERROR_STOP 1
--mock-4 not installed.
\dx
\set ON_ERROR_STOP 0
--should not allow since the errored-out mock-4 above already poisoned the well.
CREATE EXTENSION timescaledb VERSION 'mock-5';
\set ON_ERROR_STOP 1
\c single_2 :ROLE_SUPERUSER
--broken version and drop
CREATE EXTENSION timescaledb VERSION 'mock-broken';
\set ON_ERROR_STOP 0
--intentional broken version
\dx
SELECT 1;
SELECT 1;
--cannot drop extension; already loaded broken version
DROP EXTENSION timescaledb;
\set ON_ERROR_STOP 1
\c single_2 :ROLE_SUPERUSER
--can drop extension now. Since drop first command.
DROP EXTENSION timescaledb;
\dx
--broken version and update to fixed
\c single_2 :ROLE_SUPERUSER
CREATE EXTENSION timescaledb VERSION 'mock-broken';
\set ON_ERROR_STOP 0
--intentional broken version
SELECT 1;
--cannot update extension; already loaded bad version
ALTER EXTENSION timescaledb UPDATE TO 'mock-5';
\set ON_ERROR_STOP 1
\c single_2 :ROLE_SUPERUSER
--can update extension now.
ALTER EXTENSION timescaledb UPDATE TO 'mock-5';
SELECT 1;
SELECT mock_function();
\c single_2 :ROLE_SUPERUSER
ALTER EXTENSION timescaledb UPDATE TO 'mock-6';
\set ON_ERROR_STOP 0
--The mock-5->mock_6 upgrade is intentionally broken.
--The mock_function was never changed to point to mock-6 in the update script.
--Thus mock_function is defined incorrectly to point to the mock-5.so
--This should be an error.
SELECT mock_function();
\set ON_ERROR_STOP 1
\dx
--TEST: create extension when old .so already loaded
\c single :ROLE_SUPERUSER
--force load of extension with (\dx)
\dx
DROP EXTENSION timescaledb;
\dx
\set ON_ERROR_STOP 0
CREATE EXTENSION timescaledb VERSION 'mock-2';
\set ON_ERROR_STOP 1
\dx
--can create in a new session.
\c single :ROLE_SUPERUSER
CREATE EXTENSION timescaledb VERSION 'mock-2';
\dx

@ -1,7 +1,7 @@
# timescaledb extension
comment = 'Enables scalable inserts and complex queries for time-series data'
default_version = '@PROJECT_VERSION_MOD@'
module_pathname = '$libdir/timescaledb'
module_pathname = '$libdir/timescaledb-@PROJECT_VERSION_MOD@'
#extension cannot be relocatable once installed because it uses multiple schemas and that is forbidden by PG.
#(though this extension is relocatable during installation).
relocatable = false