diff --git a/.github/workflows/abi.yaml b/.github/workflows/abi.yaml
index d3b34607193..b4240ab1afb 100644
--- a/.github/workflows/abi.yaml
+++ b/.github/workflows/abi.yaml
@@ -44,43 +44,18 @@ jobs:
     strategy:
       fail-fast: false
       matrix:
-        dir: [ "forward", "backward" ]
         pg: [ 14, 15, 16, 17 ]
         include:
-          - dir: backward
-            pg: 14
-            builder: ${{ fromJson(needs.config.outputs.pg14_latest) }}-alpine3.19
-            tester: ${{ fromJson(needs.config.outputs.pg14_abi_min) }}-alpine
-            ignores: memoize
-          - dir: forward
-            pg: 14
+          - pg: 14
             builder: ${{ fromJson(needs.config.outputs.pg14_abi_min) }}-alpine
             tester: ${{ fromJson(needs.config.outputs.pg14_latest) }}-alpine3.19
-          - dir: backward
-            pg: 15
-            builder: ${{ fromJson(needs.config.outputs.pg15_latest) }}-alpine3.19
-            tester: ${{ fromJson(needs.config.outputs.pg15_abi_min) }}-alpine
-          - dir: forward
-            pg: 15
+          - pg: 15
             builder: ${{ fromJson(needs.config.outputs.pg15_abi_min) }}-alpine
             tester: ${{ fromJson(needs.config.outputs.pg15_latest) }}-alpine3.19
-          - dir: backward
-            pg: 16
-            builder: ${{ fromJson(needs.config.outputs.pg16_latest) }}-alpine3.19
-            tester: ${{ fromJson(needs.config.outputs.pg16_abi_min) }}-alpine
-            # this test has issues with 16.0 version of pg_dump binary
-            # which affects backwards test only 
-            ignores: pg_dump_unprivileged
-          - dir: forward
-            pg: 16
+          - pg: 16
             builder: ${{ fromJson(needs.config.outputs.pg16_abi_min) }}-alpine
             tester: ${{ fromJson(needs.config.outputs.pg16_latest) }}-alpine3.19
-          - dir: backward
-            pg: 17
-            builder: ${{ fromJson(needs.config.outputs.pg17_latest) }}-alpine3.19
-            tester: ${{ fromJson(needs.config.outputs.pg17_abi_min) }}-alpine
-          - dir: forward
-            pg: 17
+          - pg: 17
             builder: ${{ fromJson(needs.config.outputs.pg17_abi_min) }}-alpine
             tester: ${{ fromJson(needs.config.outputs.pg17_latest) }}-alpine3.19
 
@@ -89,7 +64,7 @@ jobs:
     - name: Checkout TimescaleDB
       uses: actions/checkout@v4
 
-    - name: Build extension
+    - name: Build extension with ${{ matrix.builder }}
       run: |
         BUILDER_IMAGE="postgres:${{matrix.builder}}"
 
@@ -113,7 +88,7 @@ jobs:
           cp `pg_config --pkglibdir`/timescaledb*.so build_abi/install_lib
         EOF
 
-    - name: Run tests
+    - name: Run tests on server ${{ matrix.tester }}
       run: |
         TEST_IMAGE="postgres:${{ matrix.tester }}"
 
diff --git a/.github/workflows/pr-approvals.yaml b/.github/workflows/pr-approvals.yaml
index 349b29638b8..32fa57001bb 100644
--- a/.github/workflows/pr-approvals.yaml
+++ b/.github/workflows/pr-approvals.yaml
@@ -25,27 +25,37 @@ jobs:
           GH_TOKEN: ${{ github.token }}
           PR_NUMBER: ${{ github.event.number }}
         run: |
-          echo "Event is: "
-          cat <<EOF
-            ${{ toJSON(github.event) }}
-          EOF
           echo "PR number is $PR_NUMBER"
           echo "$BODY" | egrep -qsi '^disable-check:.*\<approval-count\>'
           if [[ $? -ne 0 ]]; then
             # Get the list of modified files in this pull request
             echo "Modified files: "
             gh pr view $PR_NUMBER --json files
-            # Get modified files, but exclude those that are workflow
-            # files or are related to Hypercore table access
-            # method. These require only a single reviewer.
-            files=$(gh pr view $PR_NUMBER --json files --jq '.files.[].path | select(startswith(".github") or test("hypercore|columnar_scan") | not)')
+            # Get the number of modified files, but exclude those that
+            # are workflow files or are related to Hypercore table
+            # access method. These require only a single reviewer.
+            files=$(gh pr view $PR_NUMBER --json files --jq '[.files.[].path | select(startswith(".github") or test("hypercore|columnar_scan") | not)] | length')
 
             # Get the number of approvals in this pull request
             echo "Reviews: "
             gh pr view $PR_NUMBER --json reviews
-            approvals=$(gh pr view $PR_NUMBER --json reviews --jq '[.reviews.[] | select((.authorAssociation == "MEMBER" or .authorAssociation == "CONTRIBUTOR") and .state == "APPROVED")] | length')
-
-            if [[ $approvals -lt 2 ]] && [[ "${files}" ]] ; then
+            approvals=$(
+                gh pr view $PR_NUMBER --json reviews --jq '
+                    [
+                        .reviews.[]
+                        | select(
+                            (
+                                .authorAssociation == "NONE"
+                                or .authorAssociation == "MEMBER"
+                                or .authorAssociation == "CONTRIBUTOR"
+                            )
+                            and .state == "APPROVED"
+                          )
+                    ] | length
+                  '
+            )
+            echo "approvals: $approvals, files: $files"
+            if [[ $approvals -lt 2 ]] && [[ $files -gt 0 ]] ; then
               echo "This pull request requires 2 approvals before merging."
               echo
               echo "For trivial changes, you may disable this check by adding this trailer to the pull request message:"
diff --git a/.unreleased/pr_7443 b/.unreleased/pr_7443
new file mode 100644
index 00000000000..7196037db05
--- /dev/null
+++ b/.unreleased/pr_7443
@@ -0,0 +1 @@
+Implements: #7443 Add Hypercore function and view aliases
diff --git a/sql/maintenance_utils.sql b/sql/maintenance_utils.sql
index 430f62dd81c..339ea07beeb 100644
--- a/sql/maintenance_utils.sql
+++ b/sql/maintenance_utils.sql
@@ -39,11 +39,24 @@ CREATE OR REPLACE FUNCTION @extschema@.compress_chunk(
     hypercore_use_access_method BOOL = NULL
 ) RETURNS REGCLASS AS '@MODULE_PATHNAME@', 'ts_compress_chunk' LANGUAGE C VOLATILE;
 
+-- Alias for compress_chunk above.
+CREATE OR REPLACE PROCEDURE @extschema@.convert_to_columnstore(
+    chunk REGCLASS,
+    if_not_columnstore BOOLEAN = true,
+    recompress BOOLEAN = false,
+    hypercore_use_access_method BOOL = NULL
+) AS '@MODULE_PATHNAME@', 'ts_compress_chunk' LANGUAGE C;
+
 CREATE OR REPLACE FUNCTION @extschema@.decompress_chunk(
     uncompressed_chunk REGCLASS,
     if_compressed BOOLEAN = true
 ) RETURNS REGCLASS AS '@MODULE_PATHNAME@', 'ts_decompress_chunk' LANGUAGE C STRICT VOLATILE;
 
+CREATE OR REPLACE PROCEDURE @extschema@.convert_to_rowstore(
+    chunk REGCLASS,
+    if_columnstore BOOLEAN = true
+) AS '@MODULE_PATHNAME@', 'ts_decompress_chunk' LANGUAGE C;
+
 CREATE OR REPLACE FUNCTION _timescaledb_functions.recompress_chunk_segmentwise(
     uncompressed_chunk REGCLASS,
     if_compressed BOOLEAN = true
diff --git a/sql/policy_api.sql b/sql/policy_api.sql
index ac352e8943c..83a8a39049f 100644
--- a/sql/policy_api.sql
+++ b/sql/policy_api.sql
@@ -59,10 +59,26 @@ RETURNS INTEGER
 AS '@MODULE_PATHNAME@', 'ts_policy_compression_add'
 LANGUAGE C VOLATILE; -- not strict because we need to set different default values for schedule_interval
 
+CREATE OR REPLACE PROCEDURE @extschema@.add_columnstore_policy(
+    hypertable REGCLASS,
+    after "any" = NULL,
+    if_not_exists BOOL = false,
+    schedule_interval INTERVAL = NULL,
+    initial_start TIMESTAMPTZ = NULL,
+    timezone TEXT = NULL,
+    created_before INTERVAL = NULL,
+    hypercore_use_access_method BOOL = NULL
+) LANGUAGE C AS '@MODULE_PATHNAME@', 'ts_policy_compression_add';
+
 CREATE OR REPLACE FUNCTION @extschema@.remove_compression_policy(hypertable REGCLASS, if_exists BOOL = false) RETURNS BOOL
 AS '@MODULE_PATHNAME@', 'ts_policy_compression_remove'
 LANGUAGE C VOLATILE STRICT;
 
+CREATE OR REPLACE PROCEDURE @extschema@.remove_columnstore_policy(
+       hypertable REGCLASS,
+       if_exists BOOL = false
+) LANGUAGE C AS '@MODULE_PATHNAME@', 'ts_policy_compression_remove';
+
 /* continuous aggregates policy */
 CREATE OR REPLACE FUNCTION @extschema@.add_continuous_aggregate_policy(
     continuous_aggregate REGCLASS, start_offset "any",
diff --git a/sql/size_utils.sql b/sql/size_utils.sql
index 27bd7da9438..8dbfb49957c 100644
--- a/sql/size_utils.sql
+++ b/sql/size_utils.sql
@@ -544,6 +544,25 @@ BEGIN
 END;
 $BODY$ SET search_path TO pg_catalog, pg_temp;
 
+CREATE OR REPLACE FUNCTION @extschema@.chunk_columnstore_stats (hypertable REGCLASS)
+    RETURNS TABLE (
+        chunk_schema name,
+        chunk_name name,
+        compression_status text,
+        before_compression_table_bytes bigint,
+        before_compression_index_bytes bigint,
+        before_compression_toast_bytes bigint,
+        before_compression_total_bytes bigint,
+        after_compression_table_bytes bigint,
+        after_compression_index_bytes bigint,
+        after_compression_toast_bytes bigint,
+        after_compression_total_bytes bigint,
+        node_name name)
+    LANGUAGE SQL
+    STABLE STRICT
+    AS 'SELECT * FROM @extschema@.chunk_compression_stats($1)'
+    SET search_path TO pg_catalog, pg_temp;
+
 -- Get compression statistics for a hypertable that has
 -- compression enabled
 CREATE OR REPLACE FUNCTION @extschema@.hypertable_compression_stats (hypertable REGCLASS)
@@ -581,6 +600,24 @@ $BODY$
         ch.node_name;
 $BODY$ SET search_path TO pg_catalog, pg_temp;
 
+CREATE OR REPLACE FUNCTION @extschema@.hypertable_columnstore_stats (hypertable REGCLASS)
+    RETURNS TABLE (
+        total_chunks bigint,
+        number_compressed_chunks bigint,
+        before_compression_table_bytes bigint,
+        before_compression_index_bytes bigint,
+        before_compression_toast_bytes bigint,
+        before_compression_total_bytes bigint,
+        after_compression_table_bytes bigint,
+        after_compression_index_bytes bigint,
+        after_compression_toast_bytes bigint,
+        after_compression_total_bytes bigint,
+        node_name name)
+    LANGUAGE SQL
+    STABLE STRICT
+    AS 'SELECT * FROM @extschema@.hypertable_compression_stats($1)'
+    SET search_path TO pg_catalog, pg_temp;
+
 -------------Get index size for hypertables -------
 --schema_name      - schema_name for hypertable index
 -- index_name      - index on hyper table
diff --git a/sql/updates/latest-dev.sql b/sql/updates/latest-dev.sql
index 66ad63058fb..d233b0ae5f8 100644
--- a/sql/updates/latest-dev.sql
+++ b/sql/updates/latest-dev.sql
@@ -47,3 +47,70 @@ LANGUAGE C VOLATILE;
 DROP PROCEDURE IF EXISTS _timescaledb_functions.policy_compression_execute(job_id INTEGER, htid INTEGER, lag ANYELEMENT, maxchunks INTEGER, verbose_log BOOLEAN, recompress_enabled  BOOLEAN, use_creation_time BOOLEAN);
 
 DROP PROCEDURE IF EXISTS _timescaledb_functions.policy_compression(job_id INTEGER, config JSONB);
+
+CREATE PROCEDURE @extschema@.convert_to_columnstore(
+    chunk REGCLASS,
+    if_not_columnstore BOOLEAN = true,
+    recompress BOOLEAN = false,
+    hypercore_use_access_method BOOL = NULL)
+AS '@MODULE_PATHNAME@', 'ts_update_placeholder'
+LANGUAGE C;
+
+CREATE PROCEDURE @extschema@.convert_to_rowstore(
+    chunk REGCLASS,
+    if_columnstore BOOLEAN = true)
+AS '@MODULE_PATHNAME@', 'ts_update_placeholder'
+LANGUAGE C;
+
+CREATE PROCEDURE @extschema@.add_columnstore_policy(
+    hypertable REGCLASS,
+    after "any" = NULL,
+    if_not_exists BOOL = false,
+    schedule_interval INTERVAL = NULL,
+    initial_start TIMESTAMPTZ = NULL,
+    timezone TEXT = NULL,
+    created_before INTERVAL = NULL,
+    hypercore_use_access_method BOOL = NULL
+) LANGUAGE C AS '@MODULE_PATHNAME@', 'ts_update_placeholder';
+
+CREATE PROCEDURE @extschema@.remove_columnstore_policy(
+       hypertable REGCLASS,
+       if_exists BOOL = false
+) LANGUAGE C AS '@MODULE_PATHNAME@', 'ts_update_placeholder';
+
+CREATE FUNCTION @extschema@.chunk_columnstore_stats (hypertable REGCLASS)
+    RETURNS TABLE (
+        chunk_schema name,
+        chunk_name name,
+        compression_status text,
+        before_compression_table_bytes bigint,
+        before_compression_index_bytes bigint,
+        before_compression_toast_bytes bigint,
+        before_compression_total_bytes bigint,
+        after_compression_table_bytes bigint,
+        after_compression_index_bytes bigint,
+        after_compression_toast_bytes bigint,
+        after_compression_total_bytes bigint,
+        node_name name)
+    LANGUAGE SQL
+    STABLE STRICT
+    AS 'SELECT * FROM @extschema@.chunk_compression_stats($1)'
+    SET search_path TO pg_catalog, pg_temp;
+
+CREATE FUNCTION @extschema@.hypertable_columnstore_stats (hypertable REGCLASS)
+    RETURNS TABLE (
+        total_chunks bigint,
+        number_compressed_chunks bigint,
+        before_compression_table_bytes bigint,
+        before_compression_index_bytes bigint,
+        before_compression_toast_bytes bigint,
+        before_compression_total_bytes bigint,
+        after_compression_table_bytes bigint,
+        after_compression_index_bytes bigint,
+        after_compression_toast_bytes bigint,
+        after_compression_total_bytes bigint,
+        node_name name)
+    LANGUAGE SQL
+    STABLE STRICT
+    AS 'SELECT * FROM @extschema@.hypertable_compression_stats($1)'
+    SET search_path TO pg_catalog, pg_temp;
diff --git a/sql/updates/post-update.sql b/sql/updates/post-update.sql
index 0dd2d8a8fc7..b682305ea39 100644
--- a/sql/updates/post-update.sql
+++ b/sql/updates/post-update.sql
@@ -144,10 +144,9 @@ BEGIN
         format('%I.%I', user_view_schema, user_view_name)
       FROM _timescaledb_catalog.continuous_agg
       WHERE finalized IS FALSE
-      AND current_setting('server_version_num')::int >= 150000
       ORDER BY 1
     LOOP
-      RAISE WARNING 'Continuous Aggregate: % with old format will not be supported on PostgreSQL version greater or equal to 15. You should upgrade to the new format', cagg_name;
+      RAISE WARNING 'Continuous Aggregate "%" with old format will not be supported in the next version. You should use `cagg_migrate` procedure to migrate to the new format.', cagg_name;
     END LOOP;
 END $$;
 
diff --git a/sql/updates/reverse-dev.sql b/sql/updates/reverse-dev.sql
index e6817621d57..6b75bc1c851 100644
--- a/sql/updates/reverse-dev.sql
+++ b/sql/updates/reverse-dev.sql
@@ -44,3 +44,16 @@ LANGUAGE C VOLATILE;
 DROP PROCEDURE IF EXISTS _timescaledb_functions.policy_compression_execute(job_id INTEGER, htid INTEGER, lag ANYELEMENT, maxchunks INTEGER, verbose_log BOOLEAN, recompress_enabled  BOOLEAN, use_creation_time BOOLEAN, useam BOOLEAN);
 
 DROP PROCEDURE IF EXISTS _timescaledb_functions.policy_compression(job_id INTEGER, config JSONB);
+DROP PROCEDURE IF EXISTS @extschema@.convert_to_columnstore(REGCLASS, BOOLEAN, BOOLEAN, BOOLEAN);
+DROP PROCEDURE IF EXISTS @extschema@.convert_to_rowstore(REGCLASS, BOOLEAN);
+DROP PROCEDURE IF EXISTS @extschema@.add_columnstore_policy(REGCLASS, "any", BOOL, INTERVAL, TIMESTAMPTZ, TEXT, INTERVAL, BOOL);
+DROP PROCEDURE IF EXISTS @extschema@.remove_columnstore_policy(REGCLASS, BOOL);
+DROP FUNCTION IF EXISTS @extschema@.hypertable_columnstore_stats(REGCLASS);
+DROP FUNCTION IF EXISTS @extschema@.chunk_columnstore_stats(REGCLASS);
+
+ALTER EXTENSION timescaledb DROP VIEW timescaledb_information.hypertable_columnstore_settings;
+ALTER EXTENSION timescaledb DROP VIEW timescaledb_information.chunk_columnstore_settings;
+
+DROP VIEW timescaledb_information.hypertable_columnstore_settings;
+DROP VIEW timescaledb_information.chunk_columnstore_settings;
+
diff --git a/sql/views.sql b/sql/views.sql
index d771e624ead..b483e35c2ae 100644
--- a/sql/views.sql
+++ b/sql/views.sql
@@ -403,5 +403,12 @@ CREATE OR REPLACE VIEW timescaledb_information.chunk_compression_settings AS
 		FROM unnest(s.orderby, s.orderby_desc, s.orderby_nullsfirst) un(orderby, "desc", nullsfirst)
 	) un ON true;
 
+
+CREATE OR REPLACE VIEW timescaledb_information.hypertable_columnstore_settings
+AS SELECT * FROM timescaledb_information.hypertable_compression_settings;
+
+CREATE OR REPLACE VIEW timescaledb_information.chunk_columnstore_settings AS
+SELECT * FROM timescaledb_information.chunk_compression_settings;
+
 GRANT SELECT ON ALL TABLES IN SCHEMA timescaledb_information TO PUBLIC;
 
diff --git a/src/compression_with_clause.c b/src/compression_with_clause.c
index 4e92a5a1d1f..37ae1e97fed 100644
--- a/src/compression_with_clause.c
+++ b/src/compression_with_clause.c
@@ -25,20 +25,20 @@
 
 static const WithClauseDefinition compress_hypertable_with_clause_def[] = {
 		[CompressEnabled] = {
-			.arg_name = "compress",
+			.arg_names = {"compress", "enable_columnstore", NULL},
 			.type_id = BOOLOID,
 			.default_val = (Datum)false,
 		},
 		[CompressSegmentBy] = {
-			 .arg_name = "compress_segmentby",
+			.arg_names = {"compress_segmentby", "segmentby", NULL},
 			 .type_id = TEXTOID,
 		},
 		[CompressOrderBy] = {
-			 .arg_name = "compress_orderby",
+			.arg_names = {"compress_orderby", "orderby", NULL},
 			 .type_id = TEXTOID,
 		},
 		[CompressChunkTimeInterval] = {
-			 .arg_name = "compress_chunk_time_interval",
+			.arg_names = {"compress_chunk_time_interval", NULL},
 			 .type_id = INTERVALOID,
 		},
 };
diff --git a/src/process_utility.c b/src/process_utility.c
index 039a134ee90..54701b5e2c6 100644
--- a/src/process_utility.c
+++ b/src/process_utility.c
@@ -2960,10 +2960,10 @@ typedef enum HypertableIndexFlags
 } HypertableIndexFlags;
 
 static const WithClauseDefinition index_with_clauses[] = {
-	[HypertableIndexFlagMultiTransaction] = {.arg_name = "transaction_per_chunk", .type_id = BOOLOID,},
+	[HypertableIndexFlagMultiTransaction] = {.arg_names = {"transaction_per_chunk", NULL}, .type_id = BOOLOID,},
 #ifdef DEBUG
-	[HypertableIndexFlagBarrierTable] = {.arg_name = "barrier_table", .type_id = REGCLASSOID,},
-	[HypertableIndexFlagMaxChunks] = {.arg_name = "max_chunks", .type_id = INT4OID, .default_val = (Datum)-1},
+	[HypertableIndexFlagBarrierTable] = {.arg_names = {"barrier_table", NULL}, .type_id = REGCLASSOID,},
+	[HypertableIndexFlagMaxChunks] = {.arg_names = {"max_chunks", NULL}, .type_id = INT4OID, .default_val = (Datum)-1},
 #endif
 };
 
diff --git a/src/ts_catalog/continuous_agg.c b/src/ts_catalog/continuous_agg.c
index f9612dc0070..a786b4bf44a 100644
--- a/src/ts_catalog/continuous_agg.c
+++ b/src/ts_catalog/continuous_agg.c
@@ -48,39 +48,39 @@
 
 static const WithClauseDefinition continuous_aggregate_with_clause_def[] = {
 		[ContinuousEnabled] = {
-			.arg_name = "continuous",
+			.arg_names = {"continuous", NULL},
 			.type_id = BOOLOID,
 			.default_val = (Datum)false,
 		},
 		[ContinuousViewOptionCreateGroupIndex] = {
-			.arg_name = "create_group_indexes",
+			.arg_names = {"create_group_indexes", NULL},
 			.type_id = BOOLOID,
 			.default_val = (Datum)true,
 		},
 		[ContinuousViewOptionMaterializedOnly] = {
-			.arg_name = "materialized_only",
+			.arg_names = {"materialized_only", NULL},
 			.type_id = BOOLOID,
 			.default_val = (Datum)true,
 		},
 		[ContinuousViewOptionCompress] = {
-			.arg_name = "compress",
+			.arg_names = {"enable_columnstore", "compress", NULL},
 			.type_id = BOOLOID,
 		},
 		[ContinuousViewOptionFinalized] = {
-			.arg_name = "finalized",
+			.arg_names = {"finalized", NULL},
 			.type_id = BOOLOID,
 			.default_val = (Datum)true,
 		},
 		[ContinuousViewOptionCompressSegmentBy] = {
-			 .arg_name = "compress_segmentby",
-			 .type_id = TEXTOID,
+			.arg_names = {"segmentby", "compress_segmentby", NULL},
+			.type_id = TEXTOID,
 		},
 		[ContinuousViewOptionCompressOrderBy] = {
-			 .arg_name = "compress_orderby",
+			.arg_names = {"orderby", "compress_orderby", NULL},
 			 .type_id = TEXTOID,
 		},
 		[ContinuousViewOptionCompressChunkTimeInterval] = {
-			 .arg_name = "compress_chunk_time_interval",
+			.arg_names = {"compress_chunk_time_interval", NULL},
 			 .type_id = INTERVALOID,
 		},
 };
@@ -127,7 +127,7 @@ ts_continuous_agg_get_compression_defelems(const WithClauseResult *with_clauses)
 		{
 			Node *value = (Node *) makeString(ts_with_clause_result_deparse_value(input));
 			DefElem *elem = makeDefElemExtended(EXTENSION_NAMESPACE,
-												(char *) def.arg_name,
+												(char *) def.arg_names[0],
 												value,
 												DEFELEM_UNSPEC,
 												-1);
diff --git a/src/ts_catalog/continuous_aggs_watermark.c b/src/ts_catalog/continuous_aggs_watermark.c
index d7a9becb7b4..c022745f21c 100644
--- a/src/ts_catalog/continuous_aggs_watermark.c
+++ b/src/ts_catalog/continuous_aggs_watermark.c
@@ -17,6 +17,7 @@
 #include <utils/snapmgr.h>
 
 #include "debug_point.h"
+#include "guc.h"
 #include "hypertable.h"
 #include "ts_catalog/continuous_agg.h"
 #include "ts_catalog/continuous_aggs_watermark.h"
@@ -321,8 +322,10 @@ ts_cagg_watermark_update(Hypertable *mat_ht, int64 watermark, bool watermark_isn
 
 	/* If we have a real-time CAgg, it uses a watermark function. So, we have to invalidate the rel
 	 * cache to force a replanning of prepared statements. See cagg_watermark_update_internal for
-	 * more information. */
-	bool invalidate_rel_cache = !cagg->data.materialized_only;
+	 * more information. If the GUC enable_cagg_watermark_constify=false then it's not necessary
+	 * to invalidate relation cache. */
+	bool invalidate_rel_cache =
+		!cagg->data.materialized_only && ts_guc_enable_cagg_watermark_constify;
 
 	watermark = cagg_compute_watermark(cagg, watermark, watermark_isnull);
 	cagg_watermark_update_internal(mat_ht->fd.id,
diff --git a/src/with_clause_parser.c b/src/with_clause_parser.c
index 715c65a386c..790cb2dd718 100644
--- a/src/with_clause_parser.c
+++ b/src/with_clause_parser.c
@@ -86,20 +86,23 @@ ts_with_clauses_parse(const List *def_elems, const WithClauseDefinition *args, S
 
 		for (i = 0; i < nargs; i++)
 		{
-			if (pg_strcasecmp(def->defname, args[i].arg_name) == 0)
+			for (int j = 0; args[i].arg_names[j] != NULL; ++j)
 			{
-				argument_recognized = true;
-
-				if (!results[i].is_default)
-					ereport(ERROR,
-							(errcode(ERRCODE_AMBIGUOUS_PARAMETER),
-							 errmsg("duplicate parameter \"%s.%s\"",
-									def->defnamespace,
-									def->defname)));
-
-				results[i].parsed = parse_arg(args[i], def);
-				results[i].is_default = false;
-				break;
+				if (pg_strcasecmp(def->defname, args[i].arg_names[j]) == 0)
+				{
+					argument_recognized = true;
+
+					if (!results[i].is_default)
+						ereport(ERROR,
+								(errcode(ERRCODE_AMBIGUOUS_PARAMETER),
+								 errmsg("duplicate parameter \"%s.%s\"",
+										def->defnamespace,
+										def->defname)));
+
+					results[i].parsed = parse_arg(args[i], def);
+					results[i].is_default = false;
+					break;
+				}
 			}
 		}
 
diff --git a/src/with_clause_parser.h b/src/with_clause_parser.h
index 52e8fe2cdfb..b75bded9487 100644
--- a/src/with_clause_parser.h
+++ b/src/with_clause_parser.h
@@ -14,7 +14,9 @@
 
 typedef struct WithClauseDefinition
 {
-	const char *arg_name;
+	/* Alternative names for the parameters. The first one is the "main" one
+	 * when it comes to printouts.*/
+	const char *arg_names[5];
 	Oid type_id;
 	Datum default_val;
 } WithClauseDefinition;
diff --git a/test/expected/pg_dump.out b/test/expected/pg_dump.out
index 2245563d970..0f477faa982 100644
--- a/test/expected/pg_dump.out
+++ b/test/expected/pg_dump.out
@@ -571,18 +571,20 @@ WHERE   refclassid = 'pg_catalog.pg_extension'::pg_catalog.regclass AND
  _timescaledb_internal.compressed_chunk_stats
  _timescaledb_internal.hypertable_chunk_local_size
  timescaledb_experimental.policies
+ timescaledb_information.chunk_columnstore_settings
  timescaledb_information.chunk_compression_settings
  timescaledb_information.chunks
  timescaledb_information.compression_settings
  timescaledb_information.continuous_aggregates
  timescaledb_information.dimensions
+ timescaledb_information.hypertable_columnstore_settings
  timescaledb_information.hypertable_compression_settings
  timescaledb_information.hypertables
  timescaledb_information.job_errors
  timescaledb_information.job_history
  timescaledb_information.job_stats
  timescaledb_information.jobs
-(24 rows)
+(26 rows)
 
 -- Make sure we can't run our restoring functions as a normal perm user as that would disable functionality for the whole db
 \c :TEST_DBNAME :ROLE_DEFAULT_PERM_USER
diff --git a/test/src/test_with_clause_parser.c b/test/src/test_with_clause_parser.c
index e4a637b87f2..7e5d8bd5a71 100644
--- a/test/src/test_with_clause_parser.c
+++ b/test/src/test_with_clause_parser.c
@@ -180,15 +180,15 @@ typedef enum TestArgs
 } TestArgs;
 
 static WithClauseDefinition test_args[] = {
-	[TestArgUnimpl] = { .arg_name = "unimplemented",
+	[TestArgUnimpl] = { .arg_names = {"unimplemented", NULL},
 						.type_id = InvalidOid, },
-	[TestArgBool] = { .arg_name = "bool", .type_id = BOOLOID, },
-	[TestArgInt32] = { .arg_name = "int32", .type_id = INT4OID, },
-	[TestArgDefault] = { .arg_name = "default",
+	[TestArgBool] = { .arg_names = {"bool", NULL}, .type_id = BOOLOID, },
+	[TestArgInt32] = { .arg_names = {"int32", NULL}, .type_id = INT4OID, },
+	[TestArgDefault] = { .arg_names = {"default", NULL},
 						 .type_id = INT4OID,
 						 .default_val = (Datum)-100 },
-	[TestArgName] = { .arg_name = "name", .type_id = NAMEOID, },
-	[TestArgRegclass] = { .arg_name = "regclass",
+	[TestArgName] = { .arg_names = {"name", NULL}, .type_id = NAMEOID, },
+	[TestArgRegclass] = { .arg_names = {"regclass", NULL},
 						  .type_id = REGCLASSOID },
 };
 
@@ -247,7 +247,7 @@ TS_TEST_FN(ts_test_with_clause_parse)
 	nulls = palloc(sizeof(*nulls) * funcctx->tuple_desc->natts);
 	memset(nulls, true, sizeof(*nulls) * funcctx->tuple_desc->natts);
 
-	values[0] = CStringGetTextDatum(test_args[result->i].arg_name);
+	values[0] = CStringGetTextDatum(test_args[result->i].arg_names[0]);
 	nulls[0] = false;
 	if (!result->parsed[result->i].is_default || result->i == TestArgDefault)
 	{
diff --git a/tsl/src/continuous_aggs/options.c b/tsl/src/continuous_aggs/options.c
index cefa73b0e45..ab333f79b33 100644
--- a/tsl/src/continuous_aggs/options.c
+++ b/tsl/src/continuous_aggs/options.c
@@ -142,7 +142,7 @@ cagg_alter_compression(ContinuousAgg *agg, Hypertable *mat_ht, List *compress_de
 				with_clause_options[i] = default_with_clause_options[i];
 				elog(NOTICE,
 					 "defaulting %s to %s",
-					 with_clause_options[i].definition->arg_name,
+					 with_clause_options[i].definition->arg_names[0],
 					 ts_with_clause_result_deparse_value(&with_clause_options[i]));
 			}
 		}
diff --git a/tsl/test/expected/cagg_permissions-14.out b/tsl/test/expected/cagg_permissions-14.out
index 3b2f6f4bc1b..04c399acbba 100644
--- a/tsl/test/expected/cagg_permissions-14.out
+++ b/tsl/test/expected/cagg_permissions-14.out
@@ -64,6 +64,7 @@ CREATE USER not_priv;
 \set ON_ERROR_STOP 0
 CREATE INDEX cagg_idx on mat_refresh_test(humidity);
 ERROR:  must be owner of hypertable "_materialized_hypertable_2"
+\set ON_ERROR_STOP 1
 \c :TEST_DBNAME :ROLE_SUPERUSER
 DROP USER not_priv;
 \c :TEST_DBNAME :ROLE_DEFAULT_PERM_USER
@@ -193,6 +194,7 @@ group by time_bucket(100, timec), location WITH NO DATA;
 CALL refresh_continuous_aggregate('mat_perm_view_test', NULL, NULL);
 ERROR:  permission denied for function get_constant
 DROP MATERIALIZED VIEW mat_perm_view_test;
+\set ON_ERROR_STOP 1
 --can create a mat view on something with select and trigger grants
 CREATE MATERIALIZED VIEW mat_perm_view_test
 WITH ( timescaledb.continuous, timescaledb.materialized_only=true)
@@ -213,9 +215,11 @@ REVOKE SELECT ON conditions_for_perm_check_w_grant FROM public;
 insert into conditions_for_perm_check_w_grant
 select generate_series(100, 130, 10), 'POR', 65, 85, 30, 90, NULL;
 \c  :TEST_DBNAME :ROLE_DEFAULT_PERM_USER_2
+\set ON_ERROR_STOP 0
 --refresh mat view should now fail due to lack of permissions
 CALL refresh_continuous_aggregate('mat_perm_view_test', NULL, NULL);
 ERROR:  permission denied for table conditions_for_perm_check_w_grant
+\set ON_ERROR_STOP 1
 --but the old data will still be there
 SELECT * FROM mat_perm_view_test;
  location | max 
diff --git a/tsl/test/expected/cagg_permissions-15.out b/tsl/test/expected/cagg_permissions-15.out
index 3b2f6f4bc1b..04c399acbba 100644
--- a/tsl/test/expected/cagg_permissions-15.out
+++ b/tsl/test/expected/cagg_permissions-15.out
@@ -64,6 +64,7 @@ CREATE USER not_priv;
 \set ON_ERROR_STOP 0
 CREATE INDEX cagg_idx on mat_refresh_test(humidity);
 ERROR:  must be owner of hypertable "_materialized_hypertable_2"
+\set ON_ERROR_STOP 1
 \c :TEST_DBNAME :ROLE_SUPERUSER
 DROP USER not_priv;
 \c :TEST_DBNAME :ROLE_DEFAULT_PERM_USER
@@ -193,6 +194,7 @@ group by time_bucket(100, timec), location WITH NO DATA;
 CALL refresh_continuous_aggregate('mat_perm_view_test', NULL, NULL);
 ERROR:  permission denied for function get_constant
 DROP MATERIALIZED VIEW mat_perm_view_test;
+\set ON_ERROR_STOP 1
 --can create a mat view on something with select and trigger grants
 CREATE MATERIALIZED VIEW mat_perm_view_test
 WITH ( timescaledb.continuous, timescaledb.materialized_only=true)
@@ -213,9 +215,11 @@ REVOKE SELECT ON conditions_for_perm_check_w_grant FROM public;
 insert into conditions_for_perm_check_w_grant
 select generate_series(100, 130, 10), 'POR', 65, 85, 30, 90, NULL;
 \c  :TEST_DBNAME :ROLE_DEFAULT_PERM_USER_2
+\set ON_ERROR_STOP 0
 --refresh mat view should now fail due to lack of permissions
 CALL refresh_continuous_aggregate('mat_perm_view_test', NULL, NULL);
 ERROR:  permission denied for table conditions_for_perm_check_w_grant
+\set ON_ERROR_STOP 1
 --but the old data will still be there
 SELECT * FROM mat_perm_view_test;
  location | max 
diff --git a/tsl/test/expected/cagg_permissions-16.out b/tsl/test/expected/cagg_permissions-16.out
index 3b2f6f4bc1b..04c399acbba 100644
--- a/tsl/test/expected/cagg_permissions-16.out
+++ b/tsl/test/expected/cagg_permissions-16.out
@@ -64,6 +64,7 @@ CREATE USER not_priv;
 \set ON_ERROR_STOP 0
 CREATE INDEX cagg_idx on mat_refresh_test(humidity);
 ERROR:  must be owner of hypertable "_materialized_hypertable_2"
+\set ON_ERROR_STOP 1
 \c :TEST_DBNAME :ROLE_SUPERUSER
 DROP USER not_priv;
 \c :TEST_DBNAME :ROLE_DEFAULT_PERM_USER
@@ -193,6 +194,7 @@ group by time_bucket(100, timec), location WITH NO DATA;
 CALL refresh_continuous_aggregate('mat_perm_view_test', NULL, NULL);
 ERROR:  permission denied for function get_constant
 DROP MATERIALIZED VIEW mat_perm_view_test;
+\set ON_ERROR_STOP 1
 --can create a mat view on something with select and trigger grants
 CREATE MATERIALIZED VIEW mat_perm_view_test
 WITH ( timescaledb.continuous, timescaledb.materialized_only=true)
@@ -213,9 +215,11 @@ REVOKE SELECT ON conditions_for_perm_check_w_grant FROM public;
 insert into conditions_for_perm_check_w_grant
 select generate_series(100, 130, 10), 'POR', 65, 85, 30, 90, NULL;
 \c  :TEST_DBNAME :ROLE_DEFAULT_PERM_USER_2
+\set ON_ERROR_STOP 0
 --refresh mat view should now fail due to lack of permissions
 CALL refresh_continuous_aggregate('mat_perm_view_test', NULL, NULL);
 ERROR:  permission denied for table conditions_for_perm_check_w_grant
+\set ON_ERROR_STOP 1
 --but the old data will still be there
 SELECT * FROM mat_perm_view_test;
  location | max 
diff --git a/tsl/test/expected/cagg_permissions-17.out b/tsl/test/expected/cagg_permissions-17.out
index 82b74755ed9..ec4f177f699 100644
--- a/tsl/test/expected/cagg_permissions-17.out
+++ b/tsl/test/expected/cagg_permissions-17.out
@@ -64,6 +64,7 @@ CREATE USER not_priv;
 \set ON_ERROR_STOP 0
 CREATE INDEX cagg_idx on mat_refresh_test(humidity);
 ERROR:  must be owner of hypertable "_materialized_hypertable_2"
+\set ON_ERROR_STOP 1
 \c :TEST_DBNAME :ROLE_SUPERUSER
 DROP USER not_priv;
 \c :TEST_DBNAME :ROLE_DEFAULT_PERM_USER
@@ -193,6 +194,7 @@ group by time_bucket(100, timec), location WITH NO DATA;
 CALL refresh_continuous_aggregate('mat_perm_view_test', NULL, NULL);
 ERROR:  permission denied for function get_constant
 DROP MATERIALIZED VIEW mat_perm_view_test;
+\set ON_ERROR_STOP 1
 --can create a mat view on something with select and trigger grants
 CREATE MATERIALIZED VIEW mat_perm_view_test
 WITH ( timescaledb.continuous, timescaledb.materialized_only=true)
@@ -213,9 +215,11 @@ REVOKE SELECT ON conditions_for_perm_check_w_grant FROM public;
 insert into conditions_for_perm_check_w_grant
 select generate_series(100, 130, 10), 'POR', 65, 85, 30, 90, NULL;
 \c  :TEST_DBNAME :ROLE_DEFAULT_PERM_USER_2
+\set ON_ERROR_STOP 0
 --refresh mat view should now fail due to lack of permissions
 CALL refresh_continuous_aggregate('mat_perm_view_test', NULL, NULL);
 ERROR:  permission denied for table conditions_for_perm_check_w_grant
+\set ON_ERROR_STOP 1
 --but the old data will still be there
 SELECT * FROM mat_perm_view_test;
  location | max 
diff --git a/tsl/test/expected/columnstore_aliases.out b/tsl/test/expected/columnstore_aliases.out
new file mode 100644
index 00000000000..bdd25c31a6f
--- /dev/null
+++ b/tsl/test/expected/columnstore_aliases.out
@@ -0,0 +1,87 @@
+-- This file and its contents are licensed under the Timescale License.
+-- Please see the included NOTICE for copyright information and
+-- LICENSE-TIMESCALE for a copy of the license.
+CREATE PROCEDURE
+       convert_hypertable_to_columnstore(regclass)
+LANGUAGE plpgsql AS $$
+DECLARE
+  chunk REGCLASS;
+BEGIN
+   FOR chunk IN SELECT show_chunks($1)
+   LOOP
+      CALL convert_to_columnstore(chunk);
+   END LOOP;
+END
+$$;
+CREATE PROCEDURE
+       convert_hypertable_to_rowstore(regclass)
+LANGUAGE plpgsql AS $$
+DECLARE
+  chunk REGCLASS;
+BEGIN
+   FOR chunk IN SELECT show_chunks($1)
+   LOOP
+      CALL convert_to_rowstore(chunk);
+   END LOOP;
+END
+$$;
+-- These are mostly taken from compression_ddl.sql and are only
+-- intended to check that aliases work. In that sense, the actual
+-- result of each query is not particularly important.
+CREATE TABLE test1 (ts timestamptz, i integer, b bigint, t text);
+SELECT * FROM create_hypertable('test1', 'ts');
+NOTICE:  adding not-null constraint to column "ts"
+ hypertable_id | schema_name | table_name | created 
+---------------+-------------+------------+---------
+             1 | public      | test1      | t
+(1 row)
+
+INSERT INTO test1 SELECT t,  random(), random(), random()::text
+FROM generate_series('2018-03-02 1:00'::TIMESTAMPTZ, '2018-03-28 1:00', '1 hour') t;
+ALTER TABLE test1 set (
+      timescaledb.enable_columnstore,
+      timescaledb.segmentby = 'b',
+      timescaledb.orderby = 'ts desc'
+);
+CALL convert_hypertable_to_columnstore('test1');
+CALL convert_hypertable_to_rowstore('test1');
+CALL convert_hypertable_to_columnstore('test1');
+-- Pick one chunk to play with and test option names. We mostly use
+-- default since we are only interested in that the option names are
+-- accepted.
+SELECT chunk FROM show_chunks('test1') tbl(chunk) LIMIT 1 \gset
+CALL convert_to_rowstore(:'chunk', if_columnstore => true);
+CALL convert_to_columnstore(:'chunk',
+     if_not_columnstore => true,
+     recompress => false,
+     hypercore_use_access_method => false);
+CALL add_columnstore_policy('test1', interval '1 day');
+CALL remove_columnstore_policy('test1');
+SELECT * FROM timescaledb_information.hypertable_columnstore_settings;
+ hypertable | segmentby | orderby | compress_interval_length 
+------------+-----------+---------+--------------------------
+ test1      | b         | ts DESC | 
+(1 row)
+
+SELECT * FROM timescaledb_information.chunk_columnstore_settings ORDER BY chunk;
+ hypertable |                 chunk                  | segmentby | orderby 
+------------+----------------------------------------+-----------+---------
+ test1      | _timescaledb_internal._hyper_1_1_chunk | b         | ts DESC
+ test1      | _timescaledb_internal._hyper_1_2_chunk | b         | ts DESC
+ test1      | _timescaledb_internal._hyper_1_3_chunk | b         | ts DESC
+ test1      | _timescaledb_internal._hyper_1_4_chunk | b         | ts DESC
+(4 rows)
+
+VACUUM FULL test1;
+-- We only care about the column names for the result. They should be
+-- the same as for the original function.
+SELECT * FROM chunk_columnstore_stats('test1') where 1 = 2 order by chunk_name;
+ chunk_schema | chunk_name | compression_status | before_compression_table_bytes | before_compression_index_bytes | before_compression_toast_bytes | before_compression_total_bytes | after_compression_table_bytes | after_compression_index_bytes | after_compression_toast_bytes | after_compression_total_bytes | node_name 
+--------------+------------+--------------------+--------------------------------+--------------------------------+--------------------------------+--------------------------------+-------------------------------+-------------------------------+-------------------------------+-------------------------------+-----------
+(0 rows)
+
+SELECT * FROM hypertable_columnstore_stats('test1') where 1 = 2;
+ total_chunks | number_compressed_chunks | before_compression_table_bytes | before_compression_index_bytes | before_compression_toast_bytes | before_compression_total_bytes | after_compression_table_bytes | after_compression_index_bytes | after_compression_toast_bytes | after_compression_total_bytes | node_name 
+--------------+--------------------------+--------------------------------+--------------------------------+--------------------------------+--------------------------------+-------------------------------+-------------------------------+-------------------------------+-------------------------------+-----------
+(0 rows)
+
diff --git a/tsl/test/expected/jit.out b/tsl/test/expected/jit.out
index e9b1d3bcd48..8ea39bdf390 100644
--- a/tsl/test/expected/jit.out
+++ b/tsl/test/expected/jit.out
@@ -17,6 +17,7 @@ SET jit_above_cost=0;
 SET jit_inline_above_cost=0;
 SET jit_optimize_above_cost=0;
 SET jit_tuple_deforming=on;
+SET enable_hashagg=off;
 \ir :TEST_LOAD_NAME
 -- This file and its contents are licensed under the Timescale License.
 -- Please see the included NOTICE for copyright information and
@@ -198,16 +199,19 @@ SELECT * FROM jit_device_summary WHERE metric_spread = 1800 ORDER BY bucket DESC
                      Output: _hyper_4_6_chunk.bucket, _hyper_4_6_chunk.device_id, _hyper_4_6_chunk.metric_avg, _hyper_4_6_chunk.metric_spread
                      Index Cond: (_hyper_4_6_chunk.bucket < 'Mon Dec 31 01:00:00 2018 PST'::timestamp with time zone)
                      Filter: (_hyper_4_6_chunk.metric_spread = '1800'::double precision)
-               ->  HashAggregate
+               ->  GroupAggregate
                      Output: (time_bucket('@ 1 hour'::interval, _hyper_3_5_chunk.observation_time)), _hyper_3_5_chunk.device_id, avg(_hyper_3_5_chunk.metric), (max(_hyper_3_5_chunk.metric) - min(_hyper_3_5_chunk.metric))
-                     Group Key: time_bucket('@ 1 hour'::interval, _hyper_3_5_chunk.observation_time), _hyper_3_5_chunk.device_id
+                     Group Key: (time_bucket('@ 1 hour'::interval, _hyper_3_5_chunk.observation_time)), _hyper_3_5_chunk.device_id
                      Filter: ((max(_hyper_3_5_chunk.metric) - min(_hyper_3_5_chunk.metric)) = '1800'::double precision)
-                     ->  Result
-                           Output: time_bucket('@ 1 hour'::interval, _hyper_3_5_chunk.observation_time), _hyper_3_5_chunk.device_id, _hyper_3_5_chunk.metric
-                           ->  Index Scan using _hyper_3_5_chunk_jit_test_contagg_observation_time_idx on _timescaledb_internal._hyper_3_5_chunk
-                                 Output: _hyper_3_5_chunk.observation_time, _hyper_3_5_chunk.device_id, _hyper_3_5_chunk.metric
-                                 Index Cond: (_hyper_3_5_chunk.observation_time >= 'Mon Dec 31 01:00:00 2018 PST'::timestamp with time zone)
-(19 rows)
+                     ->  Sort
+                           Output: (time_bucket('@ 1 hour'::interval, _hyper_3_5_chunk.observation_time)), _hyper_3_5_chunk.device_id, _hyper_3_5_chunk.metric
+                           Sort Key: (time_bucket('@ 1 hour'::interval, _hyper_3_5_chunk.observation_time)), _hyper_3_5_chunk.device_id
+                           ->  Result
+                                 Output: time_bucket('@ 1 hour'::interval, _hyper_3_5_chunk.observation_time), _hyper_3_5_chunk.device_id, _hyper_3_5_chunk.metric
+                                 ->  Index Scan using _hyper_3_5_chunk_jit_test_contagg_observation_time_idx on _timescaledb_internal._hyper_3_5_chunk
+                                       Output: _hyper_3_5_chunk.observation_time, _hyper_3_5_chunk.device_id, _hyper_3_5_chunk.metric
+                                       Index Cond: (_hyper_3_5_chunk.observation_time >= 'Mon Dec 31 01:00:00 2018 PST'::timestamp with time zone)
+(22 rows)
 
 -- generate the results into two different files
 \set ECHO errors
diff --git a/tsl/test/expected/reorder.out b/tsl/test/expected/reorder.out
index 9933a3f61e0..6b7257125ad 100644
--- a/tsl/test/expected/reorder.out
+++ b/tsl/test/expected/reorder.out
@@ -1273,9 +1273,10 @@ CREATE INDEX ct2_time_idx ON ct2(time DESC);
 CLUSTER ct2 USING ct2_time_idx;
 -- deleted chunks are removed correctly
 DELETE FROM ct2 where time < 2 OR val < 2;
+VACUUM ct2;
 SELECT reorder_chunk('_timescaledb_internal._hyper_2_3_chunk', verbose => TRUE);
 INFO:  reordering "_timescaledb_internal._hyper_2_3_chunk" using sequential scan and sort
-INFO:  "_hyper_2_3_chunk": found 2 removable, 3 nonremovable row versions in 1 pages
+INFO:  "_hyper_2_3_chunk": found 0 removable, 3 nonremovable row versions in 1 pages
  reorder_chunk 
 ---------------
  
diff --git a/tsl/test/shared/expected/extension.out b/tsl/test/shared/expected/extension.out
index 0e70e20d99a..81c34114f72 100644
--- a/tsl/test/shared/expected/extension.out
+++ b/tsl/test/shared/expected/extension.out
@@ -210,6 +210,7 @@ ORDER BY pronamespace::regnamespace::text COLLATE "C", p.oid::regprocedure::text
  ts_hypercore_handler(internal)
  ts_hypercore_proxy_handler(internal)
  ts_now_mock()
+ add_columnstore_policy(regclass,"any",boolean,interval,timestamp with time zone,text,interval,boolean)
  add_compression_policy(regclass,"any",boolean,interval,timestamp with time zone,text,interval,boolean)
  add_continuous_aggregate_policy(regclass,"any","any",interval,boolean,timestamp with time zone,text)
  add_dimension(regclass,_timescaledb_internal.dimension_info,boolean)
@@ -223,9 +224,12 @@ ORDER BY pronamespace::regnamespace::text COLLATE "C", p.oid::regprocedure::text
  by_hash(name,integer,regproc)
  by_range(name,anyelement,regproc)
  cagg_migrate(regclass,boolean,boolean)
+ chunk_columnstore_stats(regclass)
  chunk_compression_stats(regclass)
  chunks_detailed_size(regclass)
  compress_chunk(regclass,boolean,boolean,boolean)
+ convert_to_columnstore(regclass,boolean,boolean,boolean)
+ convert_to_rowstore(regclass,boolean)
  create_hypertable(regclass,_timescaledb_internal.dimension_info,boolean,boolean,boolean)
  create_hypertable(regclass,name,name,integer,name,name,anyelement,boolean,boolean,regproc,boolean,text,regproc,regproc)
  decompress_chunk(regclass,boolean)
@@ -239,6 +243,7 @@ ORDER BY pronamespace::regnamespace::text COLLATE "C", p.oid::regprocedure::text
  histogram(double precision,double precision,double precision,integer)
  hypertable_approximate_detailed_size(regclass)
  hypertable_approximate_size(regclass)
+ hypertable_columnstore_stats(regclass)
  hypertable_compression_stats(regclass)
  hypertable_detailed_size(regclass)
  hypertable_index_size(regclass)
@@ -253,6 +258,7 @@ ORDER BY pronamespace::regnamespace::text COLLATE "C", p.oid::regprocedure::text
  move_chunk(regclass,name,name,regclass,boolean)
  recompress_chunk(regclass,boolean)
  refresh_continuous_aggregate(regclass,"any","any")
+ remove_columnstore_policy(regclass,boolean)
  remove_compression_policy(regclass,boolean)
  remove_continuous_aggregate_policy(regclass,boolean,boolean)
  remove_reorder_policy(regclass,boolean)
diff --git a/tsl/test/sql/CMakeLists.txt b/tsl/test/sql/CMakeLists.txt
index bae570319dc..35ab0747ed0 100644
--- a/tsl/test/sql/CMakeLists.txt
+++ b/tsl/test/sql/CMakeLists.txt
@@ -4,9 +4,9 @@ include(GenerateTestSchedule)
 # so unless you have a good reason, add new test files here.
 set(TEST_FILES
     agg_partials_pushdown.sql
-    bgw_security.sql
-    bgw_policy.sql
     bgw_job_ddl.sql
+    bgw_policy.sql
+    bgw_security.sql
     cagg_deprecated_bucket_ng.sql
     cagg_errors.sql
     cagg_invalidation.sql
@@ -14,24 +14,25 @@ set(TEST_FILES
     cagg_refresh.sql
     cagg_utils.sql
     cagg_watermark.sql
+    columnstore_aliases.sql
     compress_auto_sparse_index.sql
     compress_default.sql
     compress_dml_copy.sql
     compress_float8_corrupt.sql
-    compressed_detoaster.sql
     compressed_collation.sql
+    compressed_detoaster.sql
     compression.sql
-    compression_create_compressed_table.sql
     compression_conflicts.sql
+    compression_create_compressed_table.sql
     compression_defaults.sql
     compression_fks.sql
     compression_insert.sql
     compression_policy.sql
     compression_qualpushdown.sql
-    compression_settings.sql
     compression_sequence_num_removal.sql
-    compression_sorted_merge_distinct.sql
+    compression_settings.sql
     compression_sorted_merge_columns.sql
+    compression_sorted_merge_distinct.sql
     decompress_index.sql
     foreign_keys.sql
     move.sql
diff --git a/tsl/test/sql/cagg_permissions.sql.in b/tsl/test/sql/cagg_permissions.sql.in
index f0a3d140ebe..dd1d3c54a72 100644
--- a/tsl/test/sql/cagg_permissions.sql.in
+++ b/tsl/test/sql/cagg_permissions.sql.in
@@ -62,6 +62,7 @@ CREATE USER not_priv;
 -- A user with no ownership on the Cagg cannot create index on it. -- This should fail
 \set ON_ERROR_STOP 0
 CREATE INDEX cagg_idx on mat_refresh_test(humidity);
+\set ON_ERROR_STOP 1
 \c :TEST_DBNAME :ROLE_SUPERUSER
 DROP USER not_priv;
 \c :TEST_DBNAME :ROLE_DEFAULT_PERM_USER
@@ -182,6 +183,7 @@ group by time_bucket(100, timec), location WITH NO DATA;
 --this should fail
 CALL refresh_continuous_aggregate('mat_perm_view_test', NULL, NULL);
 DROP MATERIALIZED VIEW mat_perm_view_test;
+\set ON_ERROR_STOP 1
 
 --can create a mat view on something with select and trigger grants
 CREATE MATERIALIZED VIEW mat_perm_view_test
@@ -202,8 +204,10 @@ insert into conditions_for_perm_check_w_grant
 select generate_series(100, 130, 10), 'POR', 65, 85, 30, 90, NULL;
 
 \c  :TEST_DBNAME :ROLE_DEFAULT_PERM_USER_2
+\set ON_ERROR_STOP 0
 --refresh mat view should now fail due to lack of permissions
 CALL refresh_continuous_aggregate('mat_perm_view_test', NULL, NULL);
+\set ON_ERROR_STOP 1
 
 --but the old data will still be there
 SELECT * FROM mat_perm_view_test;
diff --git a/tsl/test/sql/columnstore_aliases.sql b/tsl/test/sql/columnstore_aliases.sql
new file mode 100644
index 00000000000..adebabf5888
--- /dev/null
+++ b/tsl/test/sql/columnstore_aliases.sql
@@ -0,0 +1,69 @@
+-- This file and its contents are licensed under the Timescale License.
+-- Please see the included NOTICE for copyright information and
+-- LICENSE-TIMESCALE for a copy of the license.
+
+CREATE PROCEDURE
+       convert_hypertable_to_columnstore(regclass)
+LANGUAGE plpgsql AS $$
+DECLARE
+  chunk REGCLASS;
+BEGIN
+   FOR chunk IN SELECT show_chunks($1)
+   LOOP
+      CALL convert_to_columnstore(chunk);
+   END LOOP;
+END
+$$;
+
+CREATE PROCEDURE
+       convert_hypertable_to_rowstore(regclass)
+LANGUAGE plpgsql AS $$
+DECLARE
+  chunk REGCLASS;
+BEGIN
+   FOR chunk IN SELECT show_chunks($1)
+   LOOP
+      CALL convert_to_rowstore(chunk);
+   END LOOP;
+END
+$$;
+
+-- These are mostly taken from compression_ddl.sql and are only
+-- intended to check that aliases work. In that sense, the actual
+-- result of each query is not particularly important.
+CREATE TABLE test1 (ts timestamptz, i integer, b bigint, t text);
+SELECT * FROM create_hypertable('test1', 'ts');
+INSERT INTO test1 SELECT t,  random(), random(), random()::text
+FROM generate_series('2018-03-02 1:00'::TIMESTAMPTZ, '2018-03-28 1:00', '1 hour') t;
+ALTER TABLE test1 set (
+      timescaledb.enable_columnstore,
+      timescaledb.segmentby = 'b',
+      timescaledb.orderby = 'ts desc'
+);
+
+CALL convert_hypertable_to_columnstore('test1');
+CALL convert_hypertable_to_rowstore('test1');
+CALL convert_hypertable_to_columnstore('test1');
+
+-- Pick one chunk to play with and test option names. We mostly use
+-- default since we are only interested in that the option names are
+-- accepted.
+SELECT chunk FROM show_chunks('test1') tbl(chunk) LIMIT 1 \gset
+CALL convert_to_rowstore(:'chunk', if_columnstore => true);
+CALL convert_to_columnstore(:'chunk',
+     if_not_columnstore => true,
+     recompress => false,
+     hypercore_use_access_method => false);
+
+CALL add_columnstore_policy('test1', interval '1 day');
+CALL remove_columnstore_policy('test1');
+
+SELECT * FROM timescaledb_information.hypertable_columnstore_settings;
+SELECT * FROM timescaledb_information.chunk_columnstore_settings ORDER BY chunk;
+
+VACUUM FULL test1;
+
+-- We only care about the column names for the result. They should be
+-- the same as for the original function.
+SELECT * FROM chunk_columnstore_stats('test1') where 1 = 2 order by chunk_name;
+SELECT * FROM hypertable_columnstore_stats('test1') where 1 = 2;
diff --git a/tsl/test/sql/jit.sql b/tsl/test/sql/jit.sql
index 4f6ade3a9c0..3b57d9c5740 100644
--- a/tsl/test/sql/jit.sql
+++ b/tsl/test/sql/jit.sql
@@ -20,6 +20,7 @@ SET jit_above_cost=0;
 SET jit_inline_above_cost=0;
 SET jit_optimize_above_cost=0;
 SET jit_tuple_deforming=on;
+SET enable_hashagg=off;
 
 \ir :TEST_LOAD_NAME
 \set PREFIX 'EXPLAIN (VERBOSE, TIMING OFF, COSTS OFF, SUMMARY OFF)'
diff --git a/tsl/test/sql/reorder.sql b/tsl/test/sql/reorder.sql
index 768c2b5b0f7..dda69fafc2d 100644
--- a/tsl/test/sql/reorder.sql
+++ b/tsl/test/sql/reorder.sql
@@ -200,6 +200,7 @@ CLUSTER ct2 USING ct2_time_idx;
 
 -- deleted chunks are removed correctly
 DELETE FROM ct2 where time < 2 OR val < 2;
+VACUUM ct2;
 
 SELECT reorder_chunk('_timescaledb_internal._hyper_2_3_chunk', verbose => TRUE);
 SELECT ctid, time, val FROM _timescaledb_internal._hyper_2_3_chunk ORDER BY time;