text: -- This file contains functions associated with creating new
  -- hypertables.
  
  CREATE OR REPLACE FUNCTION _timescaledb_internal.dimension_is_finite(
      val      BIGINT
  )
      RETURNS BOOLEAN LANGUAGE SQL IMMUTABLE PARALLEL SAFE AS
  $BODY$
      --end values of bigint reserved for infinite
      SELECT val > (-9223372036854775808)::bigint AND val < 9223372036854775807::bigint
  $BODY$;
  
  
  CREATE OR REPLACE FUNCTION _timescaledb_internal.dimension_slice_get_constraint_sql(
      dimension_slice_id  INTEGER
  )
      RETURNS TEXT LANGUAGE PLPGSQL VOLATILE AS
  $BODY$
  DECLARE
      dimension_slice_row _timescaledb_catalog.dimension_slice;
      dimension_row _timescaledb_catalog.dimension;
      parts TEXT[];
  BEGIN
      SELECT * INTO STRICT dimension_slice_row
      FROM _timescaledb_catalog.dimension_slice
      WHERE id = dimension_slice_id;
  
      SELECT * INTO STRICT dimension_row
      FROM _timescaledb_catalog.dimension
      WHERE id = dimension_slice_row.dimension_id;
  
      IF dimension_row.partitioning_func IS NOT NULL THEN
  
          IF  _timescaledb_internal.dimension_is_finite(dimension_slice_row.range_start) THEN
              parts = parts || format(
              $$
                  %1$I.%2$I(%3$I) >= %4$L
              $$,
              dimension_row.partitioning_func_schema,
              dimension_row.partitioning_func,
              dimension_row.column_name,
              dimension_slice_row.range_start);
          END IF;
  
          IF _timescaledb_internal.dimension_is_finite(dimension_slice_row.range_end) THEN
              parts = parts || format(
              $$
                  %1$I.%2$I(%3$I) < %4$L
              $$,
              dimension_row.partitioning_func_schema,
              dimension_row.partitioning_func,
              dimension_row.column_name,
              dimension_slice_row.range_end);
          END IF;
  
          IF array_length(parts, 1) = 0 THEN
              RETURN NULL;
          END IF;
          return array_to_string(parts, 'AND');
      ELSE
          --TODO: only works with time for now
          IF _timescaledb_internal.time_literal_sql(dimension_slice_row.range_start, dimension_row.column_type) =
             _timescaledb_internal.time_literal_sql(dimension_slice_row.range_end, dimension_row.column_type) THEN
              RAISE 'time-based constraints have the same start and end values for column "%": %',
                      dimension_row.column_name,
                      _timescaledb_internal.time_literal_sql(dimension_slice_row.range_end, dimension_row.column_type);
          END IF;
  
          parts = ARRAY[]::text[];
  
          IF _timescaledb_internal.dimension_is_finite(dimension_slice_row.range_start) THEN
              parts = parts || format(
              $$
                   %1$I >= %2$s
              $$,
              dimension_row.column_name,
              _timescaledb_internal.time_literal_sql(dimension_slice_row.range_start, dimension_row.column_type));
          END IF;
  
          IF _timescaledb_internal.dimension_is_finite(dimension_slice_row.range_end) THEN
              parts = parts || format(
              $$
                   %1$I < %2$s
              $$,
              dimension_row.column_name,
              _timescaledb_internal.time_literal_sql(dimension_slice_row.range_end, dimension_row.column_type));
          END IF;
  
          return array_to_string(parts, 'AND');
      END IF;
  END
  $BODY$;
  
  -- Outputs the create_hypertable command to recreate the given hypertable.
  --
  -- This is currently used internally for our single hypertable backup tool
  -- so that it knows how to restore the hypertable without user intervention.
  --
  -- It only works for hypertables with up to 2 dimensions.
  CREATE OR REPLACE FUNCTION _timescaledb_internal.get_create_command(
      table_name NAME
  )
      RETURNS TEXT LANGUAGE PLPGSQL VOLATILE AS
  $BODY$
  DECLARE
      h_id             INTEGER;
      schema_name      NAME;
      time_column      NAME;
      time_interval    BIGINT;
      space_column     NAME;
      space_partitions INTEGER;
      dimension_cnt    INTEGER;
      dimension_row    record;
      ret              TEXT;
  BEGIN
      SELECT h.id, h.schema_name
      FROM _timescaledb_catalog.hypertable AS h
      WHERE h.table_name = get_create_command.table_name
      INTO h_id, schema_name;
  
      IF h_id IS NULL THEN
          RAISE EXCEPTION 'hypertable "%" not found', table_name
          USING ERRCODE = 'IO101';
      END IF;
  
      SELECT COUNT(*)
      FROM _timescaledb_catalog.dimension d
      WHERE d.hypertable_id = h_id
      INTO STRICT dimension_cnt;
  
      IF dimension_cnt > 2 THEN
          RAISE EXCEPTION 'get_create_command only supports hypertables with up to 2 dimensions'
          USING ERRCODE = 'IO101';
      END IF;
  
      FOR dimension_row IN
          SELECT *
          FROM _timescaledb_catalog.dimension d
          WHERE d.hypertable_id = h_id
          LOOP
          IF dimension_row.interval_length IS NOT NULL THEN
              time_column := dimension_row.column_name;
              time_interval := dimension_row.interval_length;
          ELSIF dimension_row.num_slices IS NOT NULL THEN
              space_column := dimension_row.column_name;
              space_partitions := dimension_row.num_slices;
          END IF;
      END LOOP;
  
      ret := format($$SELECT create_hypertable('%I.%I', '%I'$$, schema_name, table_name, time_column);
      IF space_column IS NOT NULL THEN
          ret := ret || format($$, '%I', %s$$, space_column, space_partitions);
      END IF;
      ret := ret || format($$, chunk_time_interval => %s, create_default_indexes=>FALSE);$$, time_interval);
  
      RETURN ret;
  END
  $BODY$;
  