CVE-2022-24128 (SQL, published 2022-03-13T18:15Z)
Description: value: Timescale TimescaleDB 1.x and 2.x before 2.5.2 may allow privilege escalation during extension installation. The installation process uses commands such as CREATE x IF NOT EXIST that allow an unprivileged user to precreate objects. These objects will be used by the installer (which executes as Superuser), leading to privilege escalation. In order to be able to take advantage of this, an unprivileged user would need to be able to create objects in a database and then get a Superuser to install TimescaleDB into their database. (In the fixed versions, the installation aborts when it finds that an object already exists.)
Severity: MEDIUM (CVSS v3 base score: 8)
Weakness: CWE-863 \u2014 Incorrect Authorization
The product performs an authorization check when an actor attempts to access a resource or perform an action, but it does not correctly perform the check. This allows attackers to bypass intended access restrictions.
Repository: https://github.com/timescale/timescaledb
Files changed:
.github/workflows/code_style.yaml
cmake/GenerateScripts.cmake
cmake/ScriptFiles.cmake
scripts/check_update_scripts.sh
sql/CMakeLists.txt
sql/bgw_startup.sql
sql/cat.cmake
sql/pre_install/cache.sql
sql/pre_install/schemas.sql
sql/pre_install/tables.sql
sql/updates/1.7.5--2.0.0-rc1.sql
sql/updates/2.0.0-rc3--2.0.0-rc4.sql
sql/updates/2.2.1--2.3.0.sql
sql/updates/2.3.1--2.4.0.sql
sql/updates/latest-dev.sql
sql/updates/reverse-dev.sql
sql/views.sql
test/expected/extension_scripts.out
test/sql/CMakeLists.txt
test/sql/extension_scripts.sql
tsl/test/expected/data_node_bootstrap.out
tsl/test/sql/data_node_bootstrap.sql
Commit message: Fix extension installation privilege escalation

TimescaleDB was vulnerable to a privilege escalation attack in
the extension installation script. An attacker could precreate
objects normally owned by the extension and get those objects
used in the installation script since the script would only try
to create them if they did not already exist. Thanks to Pedro
Gallegos for reporting the problem.

This patch changes the schema, table and function creation to fail
and abort the installation when the object already exists instead
of using the existing object.

Security: CVE-2022-24128


Vulnerable code:
    name: Check formatting, license and git hooks
  set(_downgrade_POST_FILES ${SOURCE_FILES} ${SET_POST_UPDATE_STAGE}
    pre_install/bgw_scheduler_startup.sql
    pre_install/types.functions.sql
    pre_install/fdw_functions.sql
    cache.sql
	telemetry.sql)
    # 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)
    set(CAT_CMD cat ${SRC_FILE_LIST} > ${OUTPUT_FILE})
    COMMAND ${CAT_CMD}
cat_files(
      "${PRE_FILES};${CURR_MOD_FILES};${SOURCE_FILES_VERSIONED};${POST_FILES_PROCESSED}"
    cat_files("${PRE_FILES};${SOURCE_FILES_VERSIONED};${POST_FILES_PROCESSED}"
              ${UPDATE_SCRIPT})
CREATE OR REPLACE FUNCTION _timescaledb_internal.restart_background_workers()
RETURNS BOOL 
AS '@LOADER_PATHNAME@', 'ts_bgw_db_workers_restart'
LANGUAGE C VOLATILE;

CREATE TABLE IF NOT EXISTS  _timescaledb_cache.cache_inval_hypertable();
CREATE TABLE IF NOT EXISTS  _timescaledb_cache.cache_inval_bgw_job();
CREATE TABLE IF NOT EXISTS  _timescaledb_cache.cache_inval_extension();
CREATE SCHEMA IF NOT EXISTS _timescaledb_catalog;
CREATE SCHEMA IF NOT EXISTS _timescaledb_internal;
CREATE SCHEMA IF NOT EXISTS _timescaledb_cache;
CREATE SCHEMA IF NOT EXISTS _timescaledb_config;
CREATE SCHEMA IF NOT EXISTS timescaledb_experimental;
GRANT USAGE ON SCHEMA _timescaledb_cache, _timescaledb_catalog, _timescaledb_internal, _timescaledb_config TO PUBLIC;
GRANT USAGE ON SCHEMA timescaledb_experimental TO PUBLIC;
CREATE SEQUENCE IF NOT EXISTS _timescaledb_catalog.hypertable_id_seq MINVALUE 1;
CREATE TABLE IF NOT EXISTS _timescaledb_catalog.hypertable (
CREATE TABLE IF NOT EXISTS _timescaledb_catalog.hypertable_data_node (
CREATE TABLE IF NOT EXISTS _timescaledb_catalog.tablespace (
CREATE TABLE IF NOT EXISTS _timescaledb_catalog.dimension (
CREATE TABLE IF NOT EXISTS _timescaledb_catalog.dimension_slice (
CREATE SEQUENCE IF NOT EXISTS _timescaledb_catalog.chunk_id_seq MINVALUE 1;
CREATE TABLE IF NOT EXISTS _timescaledb_catalog.chunk (
CREATE INDEX IF NOT EXISTS chunk_hypertable_id_idx ON _timescaledb_catalog.chunk (hypertable_id);
CREATE INDEX IF NOT EXISTS chunk_compressed_chunk_id_idx ON _timescaledb_catalog.chunk (compressed_chunk_id);
CREATE TABLE IF NOT EXISTS _timescaledb_catalog.chunk_constraint (
CREATE INDEX IF NOT EXISTS chunk_constraint_chunk_id_dimension_slice_id_idx ON _timescaledb_catalog.chunk_constraint (chunk_id, dimension_slice_id);
CREATE SEQUENCE IF NOT EXISTS _timescaledb_catalog.chunk_constraint_name;
CREATE TABLE IF NOT EXISTS _timescaledb_catalog.chunk_index (
CREATE INDEX IF NOT EXISTS chunk_index_hypertable_id_hypertable_index_name_idx ON _timescaledb_catalog.chunk_index (hypertable_id, hypertable_index_name);
CREATE TABLE IF NOT EXISTS _timescaledb_catalog.chunk_data_node (
CREATE SEQUENCE IF NOT EXISTS _timescaledb_config.bgw_job_id_seq
CREATE TABLE IF NOT EXISTS _timescaledb_config.bgw_job (
CREATE INDEX IF NOT EXISTS bgw_job_proc_hypertable_id_idx ON _timescaledb_config.bgw_job (proc_schema, proc_name, hypertable_id);
CREATE TABLE IF NOT EXISTS _timescaledb_internal.bgw_job_stat (
CREATE TABLE IF NOT EXISTS _timescaledb_internal.bgw_policy_chunk_stats (
CREATE TABLE IF NOT EXISTS _timescaledb_catalog.metadata (
CREATE TABLE IF NOT EXISTS _timescaledb_catalog.continuous_agg (
CREATE INDEX IF NOT EXISTS continuous_agg_raw_hypertable_id_idx ON _timescaledb_catalog.continuous_agg (raw_hypertable_id);
CREATE TABLE IF NOT EXISTS _timescaledb_catalog.continuous_aggs_bucket_function(
CREATE TABLE IF NOT EXISTS _timescaledb_catalog.continuous_aggs_invalidation_threshold (
CREATE TABLE IF NOT EXISTS _timescaledb_catalog.continuous_aggs_hypertable_invalidation_log (
CREATE TABLE IF NOT EXISTS _timescaledb_catalog.continuous_aggs_materialization_invalidation_log (
CREATE TABLE IF NOT EXISTS _timescaledb_catalog.compression_algorithm (
CREATE TABLE IF NOT EXISTS _timescaledb_catalog.hypertable_compression (
CREATE TABLE IF NOT EXISTS _timescaledb_catalog.compression_chunk_size (
CREATE INDEX IF NOT EXISTS remote_txn_data_node_name_idx ON _timescaledb_catalog.remote_txn (data_node_name);
CREATE SEQUENCE IF NOT EXISTS _timescaledb_catalog.chunk_copy_operation_id_seq MINVALUE 1;
CREATE TABLE IF NOT EXISTS _timescaledb_catalog.chunk_copy_operation (
CREATE TABLE IF NOT EXISTS _timescaledb_catalog.hypertable_data_node (
CREATE TABLE IF NOT EXISTS _timescaledb_catalog.chunk_data_node (
CREATE INDEX IF NOT EXISTS remote_txn_data_node_name_idx
ALTER TABLE IF EXISTS _timescaledb_catalog.compression_chunk_size ADD COLUMN IF NOT EXISTS numrows_pre_compression BIGINT;
ALTER TABLE IF EXISTS _timescaledb_catalog.compression_chunk_size ADD COLUMN IF NOT EXISTS numrows_post_compression BIGINT;
CREATE SEQUENCE IF NOT EXISTS _timescaledb_config.bgw_job_id_seq MINVALUE 1000;
CREATE TABLE IF NOT EXISTS _timescaledb_config.bgw_job (
CREATE INDEX IF NOT EXISTS bgw_job_proc_hypertable_id_idx ON _timescaledb_config.bgw_job(proc_schema,proc_name,hypertable_id);
CREATE TABLE IF NOT EXISTS _timescaledb_catalog.continuous_agg (
CREATE INDEX IF NOT EXISTS continuous_agg_raw_hypertable_id_idx
CREATE SEQUENCE IF NOT EXISTS _timescaledb_catalog.hypertable_id_seq MINVALUE 1;
CREATE TABLE IF NOT EXISTS _timescaledb_catalog.hypertable(
CREATE SEQUENCE IF NOT EXISTS _timescaledb_catalog.chunk_id_seq MINVALUE 1;
CREATE TABLE IF NOT EXISTS _timescaledb_catalog.chunk (
CREATE INDEX IF NOT EXISTS chunk_hypertable_id_idx ON _timescaledb_catalog.chunk (hypertable_id);
CREATE INDEX IF NOT EXISTS chunk_compressed_chunk_id_idx ON _timescaledb_catalog.chunk (compressed_chunk_id);
CREATE SCHEMA IF NOT EXISTS timescaledb_experimental;
CREATE SEQUENCE IF NOT EXISTS _timescaledb_catalog.chunk_copy_operation_id_seq MINVALUE 1;
CREATE TABLE IF NOT EXISTS _timescaledb_catalog.chunk_copy_operation (
CREATE TABLE IF NOT EXISTS _timescaledb_catalog.continuous_aggs_bucket_function(
    -- It's safe to drop the table.
    -- ALTER EXTENSION is required to revert the effect of pg_extension_config_dump()
    -- See "The list of tables configured to be dumped" test in test/sql/updates/post.catalog.sql
    ALTER EXTENSION timescaledb DROP TABLE _timescaledb_catalog.continuous_aggs_bucket_function;
    -- Actually drop the table.
    -- ALTER EXTENSION only removes the table from the extension but doesn't drop it.
    DROP TABLE IF EXISTS _timescaledb_catalog.continuous_aggs_bucket_function;
    -- Drop overloaded versions of invalidation_process_hypertable_log() and invalidation_process_cagg_log()
    -- with bucket_functions argument.
    ALTER EXTENSION timescaledb DROP FUNCTION _timescaledb_internal.invalidation_process_hypertable_log(
        mat_hypertable_id INTEGER,
        raw_hypertable_id INTEGER,
        dimtype REGTYPE,
        mat_hypertable_ids INTEGER[],
        bucket_widths BIGINT[],
        max_bucket_widths BIGINT[],
        bucket_functions TEXT[]
    );
    DROP FUNCTION IF EXISTS _timescaledb_internal.invalidation_process_hypertable_log(
        mat_hypertable_id INTEGER,
        raw_hypertable_id INTEGER,
        dimtype REGTYPE,
        mat_hypertable_ids INTEGER[],
        bucket_widths BIGINT[],
        max_bucket_widths BIGINT[],
        bucket_functions TEXT[]
    );
    ALTER EXTENSION timescaledb DROP FUNCTION _timescaledb_internal.invalidation_process_cagg_log(
        mat_hypertable_id INTEGER,
        raw_hypertable_id INTEGER,
        dimtype REGTYPE,
        window_start BIGINT,
        window_end BIGINT,
        mat_hypertable_ids INTEGER[],
        bucket_widths BIGINT[],
        max_bucket_widths BIGINT[],
        bucket_functions TEXT[],
        OUT ret_window_start BIGINT,
        OUT ret_window_end BIGINT
    );
    DROP FUNCTION IF EXISTS _timescaledb_internal.invalidation_process_cagg_log(
        mat_hypertable_id INTEGER,
        raw_hypertable_id INTEGER,
        dimtype REGTYPE,
        window_start BIGINT,
        window_end BIGINT,
        mat_hypertable_ids INTEGER[],
        bucket_widths BIGINT[],
        max_bucket_widths BIGINT[],
        bucket_functions TEXT[],
        OUT ret_window_start BIGINT,
        OUT ret_window_end BIGINT
    );
END
$$ LANGUAGE 'plpgsql';
        SELECT view_name, 
               materialization_hypertable_schema ,
               materialization_hypertable_name   
        cnt := cnt + 1; 
            HINT = ('To disable compression, call decompress_chunk to decompress chunks, then drop any existing compression policy on the continuous aggregate, and finally run ALTER MATERIALIZED VIEW % SET timescaledb.compress = ''false'' ');
DROP VIEW IF EXISTS timescaledb_information.continuous_aggregates;
CREATE SCHEMA IF NOT EXISTS timescaledb_information;

GRANT USAGE ON SCHEMA timescaledb_information TO PUBLIC;

CREATE SCHEMA _timescaledb_catalog AUTHORIZATION :ROLE_CLUSTER_SUPERUSER;
CREATE EXTENSION timescaledb WITH SCHEMA _timescaledb_catalog CASCADE;
CREATE SCHEMA _timescaledb_catalog AUTHORIZATION :ROLE_CLUSTER_SUPERUSER;
CREATE EXTENSION timescaledb WITH SCHEMA _timescaledb_catalog CASCADE;
CREATE SCHEMA _timescaledb_catalog AUTHORIZATION :ROLE_CLUSTER_SUPERUSER;
CREATE EXTENSION timescaledb WITH SCHEMA _timescaledb_catalog CASCADE;
CREATE SCHEMA _timescaledb_catalog AUTHORIZATION :ROLE_CLUSTER_SUPERUSER;
CREATE EXTENSION timescaledb WITH SCHEMA _timescaledb_catalog CASCADE;
CREATE SCHEMA _timescaledb_catalog AUTHORIZATION :ROLE_CLUSTER_SUPERUSER;
CREATE EXTENSION timescaledb WITH SCHEMA _timescaledb_catalog CASCADE;
CREATE SCHEMA _timescaledb_catalog AUTHORIZATION :ROLE_CLUSTER_SUPERUSER;
CREATE EXTENSION timescaledb WITH SCHEMA _timescaledb_catalog CASCADE;
CREATE SCHEMA _timescaledb_catalog AUTHORIZATION :ROLE_CLUSTER_SUPERUSER;
SELECT * FROM _timescaledb_catalog.add_data_node(
ERROR:  schema "_timescaledb_catalog" already exists in database, aborting
SELECT * FROM _timescaledb_catalog.delete_data_node('bootstrap_test');
CREATE SCHEMA _timescaledb_catalog AUTHORIZATION :ROLE_CLUSTER_SUPERUSER;
CREATE EXTENSION timescaledb WITH SCHEMA _timescaledb_catalog CASCADE;
CREATE SCHEMA _timescaledb_catalog AUTHORIZATION :ROLE_CLUSTER_SUPERUSER;
CREATE EXTENSION timescaledb WITH SCHEMA _timescaledb_catalog CASCADE;
CREATE SCHEMA _timescaledb_catalog AUTHORIZATION :ROLE_CLUSTER_SUPERUSER;
CREATE EXTENSION timescaledb WITH SCHEMA _timescaledb_catalog CASCADE;
CREATE SCHEMA _timescaledb_catalog AUTHORIZATION :ROLE_CLUSTER_SUPERUSER;
CREATE EXTENSION timescaledb WITH SCHEMA _timescaledb_catalog CASCADE;
CREATE SCHEMA _timescaledb_catalog AUTHORIZATION :ROLE_CLUSTER_SUPERUSER;
CREATE EXTENSION timescaledb WITH SCHEMA _timescaledb_catalog CASCADE;
CREATE SCHEMA _timescaledb_catalog AUTHORIZATION :ROLE_CLUSTER_SUPERUSER;
CREATE EXTENSION timescaledb WITH SCHEMA _timescaledb_catalog CASCADE;
CREATE SCHEMA _timescaledb_catalog AUTHORIZATION :ROLE_CLUSTER_SUPERUSER;
SELECT * FROM _timescaledb_catalog.add_data_node(
SELECT * FROM _timescaledb_catalog.delete_data_node('bootstrap_test');

Fixed code:
    name: Check formatting, license, update scripts and git hooks
    - name: Check update scripts
      if: always()
      run: ./scripts/check_update_scripts.sh
  set(_downgrade_POST_FILES "${PRE_INSTALL_FUNCTION_FILES};${SOURCE_FILES}" ${SET_POST_UPDATE_STAGE}
    pre_install/cache.sql
# Source files that define functions and need to be rerun in update
set(PRE_INSTALL_FUNCTION_FILES
    pre_install/types.functions.sql
    pre_install/fdw_functions.sql)

	  telemetry.sql
    bgw_startup.sql)
#! /bin/bash

SCRIPT_DIR=$(dirname ${0})
SRC_DIR=$(dirname ${SCRIPT_DIR})

if grep -ir "IF NOT EXISTS" ${SRC_DIR}/sql; then
  cat <<EOF

Update scripts must unconditionally add new objects and fail when the object
already exists otherwise this might enable privilege escalation attacks where
an attacker can precreate objects that get used in later parts of the scripts
instead of the objects created by timescaledb.

EOF
  exit 1
fi
version_files("${PRE_INSTALL_FUNCTION_FILES}"
              PRE_INSTALL_FUNCTION_FILES_VERSIONED)
    set("SRC_ARG" "-DSRC_FILE_LIST=${SRC_FILE_LIST}")
    set("SRC_ARG" "'-DSRC_FILE_LIST=${SRC_FILE_LIST}'")
    COMMAND ${CMAKE_COMMAND} "${SRC_ARG}" "-DOUTPUT_FILE=${OUTPUT_FILE}" -P
            cat.cmake
# Concatenate all files in SRC_FILE_LIST into file OUTPUT_FILE Additionally
# strips out `OR REPLACE` from the generated file as this would allow a
# privilege escalation attack when present in the CREATE script
function(cat_create_files SRC_FILE_LIST OUTPUT_FILE)
  if(WIN32)
    set("SRC_ARG" "-DSRC_FILE_LIST=${SRC_FILE_LIST}")
  else()
    set("SRC_ARG" "'-DSRC_FILE_LIST=${SRC_FILE_LIST}'")
  endif()
  if(WIN32)
    add_custom_command(
      OUTPUT ${OUTPUT_FILE}
      DEPENDS ${SRC_FILE_LIST}
      WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}
      COMMAND ${CMAKE_COMMAND} "${SRC_ARG}" "-DOUTPUT_FILE=${OUTPUT_FILE}"
              "-DSTRIP_REPLACE=ON" -P cat.cmake
      COMMENT "Generating ${OUTPUT_FILE}")
  else()
    add_custom_command(
      OUTPUT ${OUTPUT_FILE}
      DEPENDS ${SRC_FILE_LIST}
      WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}
      COMMAND ${CMAKE_COMMAND} "'-DSRC_FILE_LIST=${SRC_FILE_LIST}'"
              "-DOUTPUT_FILE=${OUTPUT_FILE}" "-DSTRIP_REPLACE=ON" -P cat.cmake
      COMMENT "Generating ${OUTPUT_FILE}")
  endif()
endfunction()

cat_create_files(
      "${PRE_FILES};${CURR_MOD_FILES};${PRE_INSTALL_FUNCTION_FILES_VERSIONED};${SOURCE_FILES_VERSIONED};${POST_FILES_PROCESSED}"
    cat_files(
      "${PRE_FILES};${PRE_INSTALL_FUNCTION_FILES_VERSIONED};${SOURCE_FILES_VERSIONED};${POST_FILES_PROCESSED}"
      ${UPDATE_SCRIPT})

IF(POLICY CMP0012)
  CMAKE_POLICY(SET CMP0012 NEW)
ENDIF()

if (NOT DEFINED STRIP_REPLACE)
  set(STRIP_REPLACE OFF)
endif()

function(append_file IN_FILE OUT_FILE STRIP_REPLACE)
  file(READ ${IN_FILE} CONTENTS)
  if (${STRIP_REPLACE})
    string(REPLACE " OR REPLACE " " " CONTENTS "${CONTENTS}")
  endif()
  file(APPEND ${OUT_FILE} "${CONTENTS}")
endfunction()

# Function to concatenate all files in SRC_FILE_LIST into file OUTPUT_FILE
function(cat SRC_FILE_LIST OUTPUT_FILE STRIP_REPLACE)
  file(WRITE ${OUTPUT_FILE} "")
  foreach(SRC_FILE ${SRC_FILE_LIST})
    append_file(${SRC_FILE} ${OUTPUT_FILE} ${STRIP_REPLACE})
  endforeach()
endfunction()

cat("${SRC_FILE_LIST}" "${OUTPUT_FILE}" "${STRIP_REPLACE}")
CREATE TABLE _timescaledb_cache.cache_inval_hypertable();
CREATE TABLE _timescaledb_cache.cache_inval_bgw_job();
CREATE TABLE _timescaledb_cache.cache_inval_extension();
CREATE SCHEMA _timescaledb_catalog;
CREATE SCHEMA _timescaledb_internal;
CREATE SCHEMA _timescaledb_cache;
CREATE SCHEMA _timescaledb_config;
CREATE SCHEMA timescaledb_experimental;
CREATE SCHEMA timescaledb_information;

GRANT USAGE ON SCHEMA _timescaledb_cache, _timescaledb_catalog, _timescaledb_internal, _timescaledb_config, timescaledb_information, timescaledb_experimental TO PUBLIC;
CREATE SEQUENCE _timescaledb_catalog.hypertable_id_seq MINVALUE 1;
CREATE TABLE _timescaledb_catalog.hypertable (
CREATE TABLE _timescaledb_catalog.hypertable_data_node (
CREATE TABLE _timescaledb_catalog.tablespace (
CREATE TABLE _timescaledb_catalog.dimension (
CREATE TABLE _timescaledb_catalog.dimension_slice (
CREATE SEQUENCE _timescaledb_catalog.chunk_id_seq MINVALUE 1;
CREATE TABLE _timescaledb_catalog.chunk (
CREATE INDEX chunk_hypertable_id_idx ON _timescaledb_catalog.chunk (hypertable_id);
CREATE INDEX chunk_compressed_chunk_id_idx ON _timescaledb_catalog.chunk (compressed_chunk_id);
CREATE TABLE _timescaledb_catalog.chunk_constraint (
CREATE INDEX chunk_constraint_chunk_id_dimension_slice_id_idx ON _timescaledb_catalog.chunk_constraint (chunk_id, dimension_slice_id);
CREATE SEQUENCE _timescaledb_catalog.chunk_constraint_name;
CREATE TABLE _timescaledb_catalog.chunk_index (
CREATE INDEX chunk_index_hypertable_id_hypertable_index_name_idx ON _timescaledb_catalog.chunk_index (hypertable_id, hypertable_index_name);
CREATE TABLE _timescaledb_catalog.chunk_data_node (
CREATE SEQUENCE _timescaledb_config.bgw_job_id_seq
CREATE TABLE _timescaledb_config.bgw_job (
CREATE INDEX bgw_job_proc_hypertable_id_idx ON _timescaledb_config.bgw_job (proc_schema, proc_name, hypertable_id);
CREATE TABLE _timescaledb_internal.bgw_job_stat (
CREATE TABLE _timescaledb_internal.bgw_policy_chunk_stats (
CREATE TABLE _timescaledb_catalog.metadata (
CREATE TABLE _timescaledb_catalog.continuous_agg (
CREATE INDEX continuous_agg_raw_hypertable_id_idx ON _timescaledb_catalog.continuous_agg (raw_hypertable_id);
CREATE TABLE _timescaledb_catalog.continuous_aggs_bucket_function(
CREATE TABLE _timescaledb_catalog.continuous_aggs_invalidation_threshold (
CREATE TABLE _timescaledb_catalog.continuous_aggs_hypertable_invalidation_log (
CREATE TABLE _timescaledb_catalog.continuous_aggs_materialization_invalidation_log (
CREATE TABLE _timescaledb_catalog.compression_algorithm (
CREATE TABLE _timescaledb_catalog.hypertable_compression (
CREATE TABLE _timescaledb_catalog.compression_chunk_size (
CREATE INDEX remote_txn_data_node_name_idx ON _timescaledb_catalog.remote_txn (data_node_name);
CREATE SEQUENCE _timescaledb_catalog.chunk_copy_operation_id_seq MINVALUE 1;
CREATE TABLE _timescaledb_catalog.chunk_copy_operation (
CREATE TABLE _timescaledb_catalog.hypertable_data_node (
CREATE TABLE _timescaledb_catalog.chunk_data_node (
CREATE INDEX remote_txn_data_node_name_idx
ALTER TABLE IF EXISTS _timescaledb_catalog.compression_chunk_size ADD COLUMN numrows_pre_compression BIGINT;
ALTER TABLE IF EXISTS _timescaledb_catalog.compression_chunk_size ADD COLUMN numrows_post_compression BIGINT;
CREATE SEQUENCE _timescaledb_config.bgw_job_id_seq MINVALUE 1000;
CREATE TABLE _timescaledb_config.bgw_job (
CREATE INDEX bgw_job_proc_hypertable_id_idx ON _timescaledb_config.bgw_job(proc_schema,proc_name,hypertable_id);
CREATE TABLE _timescaledb_catalog.continuous_agg (
CREATE INDEX continuous_agg_raw_hypertable_id_idx
CREATE SEQUENCE _timescaledb_catalog.hypertable_id_seq MINVALUE 1;
CREATE TABLE _timescaledb_catalog.hypertable(
CREATE SEQUENCE _timescaledb_catalog.chunk_id_seq MINVALUE 1;
CREATE TABLE _timescaledb_catalog.chunk (
CREATE INDEX chunk_hypertable_id_idx ON _timescaledb_catalog.chunk (hypertable_id);
CREATE INDEX chunk_compressed_chunk_id_idx ON _timescaledb_catalog.chunk (compressed_chunk_id);
CREATE SCHEMA timescaledb_experimental;
CREATE SEQUENCE _timescaledb_catalog.chunk_copy_operation_id_seq MINVALUE 1;
CREATE TABLE _timescaledb_catalog.chunk_copy_operation (
CREATE TABLE _timescaledb_catalog.continuous_aggs_bucket_function(
END
$$ LANGUAGE 'plpgsql';
-- It's safe to drop the table.
-- ALTER EXTENSION is required to revert the effect of pg_extension_config_dump()
-- See "The list of tables configured to be dumped" test in test/sql/updates/post.catalog.sql
ALTER EXTENSION timescaledb DROP TABLE _timescaledb_catalog.continuous_aggs_bucket_function;
-- Actually drop the table.
-- ALTER EXTENSION only removes the table from the extension but doesn't drop it.
DROP TABLE _timescaledb_catalog.continuous_aggs_bucket_function;
-- Drop overloaded versions of invalidation_process_hypertable_log() and invalidation_process_cagg_log()
-- with bucket_functions argument.
ALTER EXTENSION timescaledb DROP FUNCTION _timescaledb_internal.invalidation_process_hypertable_log(
    mat_hypertable_id INTEGER,
    raw_hypertable_id INTEGER,
    dimtype REGTYPE,
    mat_hypertable_ids INTEGER[],
    bucket_widths BIGINT[],
    max_bucket_widths BIGINT[],
    bucket_functions TEXT[]
);
DROP FUNCTION _timescaledb_internal.invalidation_process_hypertable_log(
    mat_hypertable_id INTEGER,
    raw_hypertable_id INTEGER,
    dimtype REGTYPE,
    mat_hypertable_ids INTEGER[],
    bucket_widths BIGINT[],
    max_bucket_widths BIGINT[],
    bucket_functions TEXT[]
);
ALTER EXTENSION timescaledb DROP FUNCTION _timescaledb_internal.invalidation_process_cagg_log(
    mat_hypertable_id INTEGER,
    raw_hypertable_id INTEGER,
    dimtype REGTYPE,
    window_start BIGINT,
    window_end BIGINT,
    mat_hypertable_ids INTEGER[],
    bucket_widths BIGINT[],
    max_bucket_widths BIGINT[],
    bucket_functions TEXT[],
    OUT ret_window_start BIGINT,
    OUT ret_window_end BIGINT
);
DROP FUNCTION _timescaledb_internal.invalidation_process_cagg_log(
    mat_hypertable_id INTEGER,
    raw_hypertable_id INTEGER,
    dimtype REGTYPE,
    window_start BIGINT,
    window_end BIGINT,
    mat_hypertable_ids INTEGER[],
    bucket_widths BIGINT[],
    max_bucket_widths BIGINT[],
    bucket_functions TEXT[],
    OUT ret_window_start BIGINT,
    OUT ret_window_end BIGINT
);
        SELECT view_name,
               materialization_hypertable_schema,
               materialization_hypertable_name
        cnt := cnt + 1;
            HINT = 'To disable compression, call decompress_chunk to decompress chunks, then drop any existing compression policy on the continuous aggregate, and finally run ALTER MATERIALIZED VIEW % SET timescaledb.compress = ''false'' ';
DROP VIEW timescaledb_information.continuous_aggregates;
-- This file and its contents are licensed under the Apache License 2.0.
-- Please see the included NOTICE for copyright information and
-- LICENSE-APACHE for a copy of the license.
\c :TEST_DBNAME :ROLE_SUPERUSER
DROP EXTENSION timescaledb;
-- test that installation script errors when any of our internal schemas already exists
\set ON_ERROR_STOP 0
CREATE SCHEMA _timescaledb_catalog;
CREATE EXTENSION timescaledb;
ERROR:  schema "_timescaledb_catalog" already exists
DROP SCHEMA _timescaledb_catalog;
\c :TEST_DBNAME :ROLE_SUPERUSER
CREATE SCHEMA _timescaledb_internal;
CREATE EXTENSION timescaledb;
ERROR:  schema "_timescaledb_internal" already exists
DROP SCHEMA _timescaledb_internal;
\c :TEST_DBNAME :ROLE_SUPERUSER
CREATE SCHEMA _timescaledb_cache;
CREATE EXTENSION timescaledb;
ERROR:  schema "_timescaledb_cache" already exists
DROP SCHEMA _timescaledb_cache;
\c :TEST_DBNAME :ROLE_SUPERUSER
CREATE SCHEMA _timescaledb_config;
CREATE EXTENSION timescaledb;
ERROR:  schema "_timescaledb_config" already exists
DROP SCHEMA _timescaledb_config;
\c :TEST_DBNAME :ROLE_SUPERUSER
CREATE SCHEMA timescaledb_experimental;
CREATE EXTENSION timescaledb;
ERROR:  schema "timescaledb_experimental" already exists
DROP SCHEMA timescaledb_experimental;
\c :TEST_DBNAME :ROLE_SUPERUSER
CREATE SCHEMA timescaledb_information;
CREATE EXTENSION timescaledb;
ERROR:  schema "timescaledb_information" already exists
DROP SCHEMA timescaledb_information;
-- test that installation script errors when any of the function in public schema already exists
-- we don't test every public function but just a few common ones
\c :TEST_DBNAME :ROLE_SUPERUSER
CREATE FUNCTION get_telemetry_report() RETURNS JSONB LANGUAGE SQL AS $$ SELECT NULL::jsonb; $$;
CREATE EXTENSION timescaledb;
ERROR:  function "get_telemetry_report" already exists with same argument types
DROP FUNCTION get_telemetry_report;
\c :TEST_DBNAME :ROLE_SUPERUSER
CREATE FUNCTION time_bucket(int,int) RETURNS int LANGUAGE SQL AS $$ SELECT 1::int; $$;
CREATE EXTENSION timescaledb;
ERROR:  function "time_bucket" already exists with same argument types
DROP FUNCTION time_bucket;
\c :TEST_DBNAME :ROLE_SUPERUSER
CREATE OR REPLACE FUNCTION show_chunks(relation regclass, older_than "any" DEFAULT NULL, newer_than "any" DEFAULT NULL) RETURNS SETOF regclass language internal as 'pg_partition_ancestors';
CREATE EXTENSION timescaledb;
ERROR:  function "show_chunks" already exists with same argument types
DROP FUNCTION show_chunks;
\c :TEST_DBNAME :ROLE_SUPERUSER
SET client_min_messages TO ERROR;
CREATE EXTENSION timescaledb;
    extension_scripts.sql
-- This file and its contents are licensed under the Apache License 2.0.
-- Please see the included NOTICE for copyright information and
-- LICENSE-APACHE for a copy of the license.

\c :TEST_DBNAME :ROLE_SUPERUSER
DROP EXTENSION timescaledb;

-- test that installation script errors when any of our internal schemas already exists
\set ON_ERROR_STOP 0
CREATE SCHEMA _timescaledb_catalog;
CREATE EXTENSION timescaledb;
DROP SCHEMA _timescaledb_catalog;

\c :TEST_DBNAME :ROLE_SUPERUSER
CREATE SCHEMA _timescaledb_internal;
CREATE EXTENSION timescaledb;
DROP SCHEMA _timescaledb_internal;

\c :TEST_DBNAME :ROLE_SUPERUSER
CREATE SCHEMA _timescaledb_cache;
CREATE EXTENSION timescaledb;
DROP SCHEMA _timescaledb_cache;

\c :TEST_DBNAME :ROLE_SUPERUSER
CREATE SCHEMA _timescaledb_config;
CREATE EXTENSION timescaledb;
DROP SCHEMA _timescaledb_config;

\c :TEST_DBNAME :ROLE_SUPERUSER
CREATE SCHEMA timescaledb_experimental;
CREATE EXTENSION timescaledb;
DROP SCHEMA timescaledb_experimental;

\c :TEST_DBNAME :ROLE_SUPERUSER
CREATE SCHEMA timescaledb_information;
CREATE EXTENSION timescaledb;
DROP SCHEMA timescaledb_information;

-- test that installation script errors when any of the function in public schema already exists
-- we don't test every public function but just a few common ones
\c :TEST_DBNAME :ROLE_SUPERUSER
CREATE FUNCTION get_telemetry_report() RETURNS JSONB LANGUAGE SQL AS $$ SELECT NULL::jsonb; $$;
CREATE EXTENSION timescaledb;
DROP FUNCTION get_telemetry_report;

\c :TEST_DBNAME :ROLE_SUPERUSER
CREATE FUNCTION time_bucket(int,int) RETURNS int LANGUAGE SQL AS $$ SELECT 1::int; $$;
CREATE EXTENSION timescaledb;
DROP FUNCTION time_bucket;

\c :TEST_DBNAME :ROLE_SUPERUSER
CREATE OR REPLACE FUNCTION show_chunks(relation regclass, older_than "any" DEFAULT NULL, newer_than "any" DEFAULT NULL) RETURNS SETOF regclass language internal as 'pg_partition_ancestors';
CREATE EXTENSION timescaledb;
DROP FUNCTION show_chunks;

\c :TEST_DBNAME :ROLE_SUPERUSER
SET client_min_messages TO ERROR;
CREATE EXTENSION timescaledb;

CREATE EXTENSION timescaledb;
CREATE EXTENSION timescaledb;
CREATE EXTENSION timescaledb;
CREATE EXTENSION timescaledb;
CREATE EXTENSION timescaledb;
CREATE SCHEMA ts_non_default AUTHORIZATION :ROLE_CLUSTER_SUPERUSER;
CREATE EXTENSION timescaledb WITH SCHEMA ts_non_default CASCADE;
CREATE SCHEMA ts_non_default AUTHORIZATION :ROLE_CLUSTER_SUPERUSER;
SELECT * FROM ts_non_default.add_data_node(
ERROR:  schema "ts_non_default" already exists in database, aborting
SELECT * FROM ts_non_default.delete_data_node('bootstrap_test');
CREATE EXTENSION timescaledb;
CREATE EXTENSION timescaledb;
CREATE EXTENSION timescaledb;
CREATE EXTENSION timescaledb;
CREATE EXTENSION timescaledb;
CREATE SCHEMA ts_non_default AUTHORIZATION :ROLE_CLUSTER_SUPERUSER;
CREATE EXTENSION timescaledb WITH SCHEMA ts_non_default CASCADE;
CREATE SCHEMA ts_non_default AUTHORIZATION :ROLE_CLUSTER_SUPERUSER;
SELECT * FROM ts_non_default.add_data_node(
SELECT * FROM ts_non_default.delete_data_node('bootstrap_test');