From f220720dd85f8eeea45291f3c419662ed79754be Mon Sep 17 00:00:00 2001
From: Alvaro Herrera <alvherre@alvh.no-ip.org>
Date: Fri, 28 Aug 2015 15:06:34 -0300
Subject: [PATCH 09/24] add pg_class.relhascstore

This is a close parallel to relhasindex for indexes.
---
 src/backend/catalog/heap.c                 |   1 +
 src/backend/catalog/system_views.sql       |   2 +
 src/backend/rewrite/rewriteDefine.c        |   7 +
 src/backend/utils/cache/relcache.c         |   5 +-
 src/include/catalog/pg_class.h             |  46 ++--
 src/test/regress/expected/rules.out        |   2 +
 src/test/regress/expected/sanity_check.out | 326 ++++++++++++++---------------
 src/test/regress/sql/sanity_check.sql      |   2 +-
 8 files changed, 204 insertions(+), 187 deletions(-)

diff --git a/src/backend/catalog/heap.c b/src/backend/catalog/heap.c
index d04e94d..2a6c576 100644
--- a/src/backend/catalog/heap.c
+++ b/src/backend/catalog/heap.c
@@ -792,6 +792,7 @@ InsertPgClassTuple(Relation pg_class_desc,
 	values[Anum_pg_class_relallvisible - 1] = Int32GetDatum(rd_rel->relallvisible);
 	values[Anum_pg_class_reltoastrelid - 1] = ObjectIdGetDatum(rd_rel->reltoastrelid);
 	values[Anum_pg_class_relhasindex - 1] = BoolGetDatum(rd_rel->relhasindex);
+	values[Anum_pg_class_relhascstore - 1] = BoolGetDatum(rd_rel->relhascstore);
 	values[Anum_pg_class_relisshared - 1] = BoolGetDatum(rd_rel->relisshared);
 	values[Anum_pg_class_relpersistence - 1] = CharGetDatum(rd_rel->relpersistence);
 	values[Anum_pg_class_relkind - 1] = CharGetDatum(rd_rel->relkind);
diff --git a/src/backend/catalog/system_views.sql b/src/backend/catalog/system_views.sql
index ccc030f..4234f6f 100644
--- a/src/backend/catalog/system_views.sql
+++ b/src/backend/catalog/system_views.sql
@@ -117,6 +117,7 @@ CREATE VIEW pg_tables AS
         pg_get_userbyid(C.relowner) AS tableowner,
         T.spcname AS tablespace,
         C.relhasindex AS hasindexes,
+        C.relhascstore AS hascstores,
         C.relhasrules AS hasrules,
         C.relhastriggers AS hastriggers,
         C.relrowsecurity AS rowsecurity
@@ -131,6 +132,7 @@ CREATE VIEW pg_matviews AS
         pg_get_userbyid(C.relowner) AS matviewowner,
         T.spcname AS tablespace,
         C.relhasindex AS hasindexes,
+        C.relhascstore AS hascstores,
         C.relispopulated AS ispopulated,
         pg_get_viewdef(C.oid) AS definition
     FROM pg_class C LEFT JOIN pg_namespace N ON (N.oid = C.relnamespace)
diff --git a/src/backend/rewrite/rewriteDefine.c b/src/backend/rewrite/rewriteDefine.c
index 39c83a6..3c5dd5e 100644
--- a/src/backend/rewrite/rewriteDefine.c
+++ b/src/backend/rewrite/rewriteDefine.c
@@ -447,6 +447,12 @@ DefineQueryRewrite(char *rulename,
 						 errmsg("could not convert table \"%s\" to a view because it has indexes",
 								RelationGetRelationName(event_relation))));
 
+			if (event_relation->rd_rel->relhascstore)
+				ereport(ERROR,
+						(errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),
+						 errmsg("could not convert table \"%s\" to a view because it has column stores",
+								RelationGetRelationName(event_relation))));
+
 			if (event_relation->rd_rel->relhassubclass)
 				ereport(ERROR,
 						(errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),
@@ -606,6 +612,7 @@ DefineQueryRewrite(char *rulename,
 		classForm->relallvisible = 0;
 		classForm->reltoastrelid = InvalidOid;
 		classForm->relhasindex = false;
+		classForm->relhascstore = false;
 		classForm->relkind = RELKIND_VIEW;
 		classForm->relhasoids = false;
 		classForm->relhaspkey = false;
diff --git a/src/backend/utils/cache/relcache.c b/src/backend/utils/cache/relcache.c
index 5ca4e2f6..ddb1fc0 100644
--- a/src/backend/utils/cache/relcache.c
+++ b/src/backend/utils/cache/relcache.c
@@ -1691,7 +1691,7 @@ formrdesc(const char *relationName, Oid relationReltype,
 	 */
 	if (IsBootstrapProcessingMode())
 	{
-		/* In bootstrap mode, we have no indexes */
+		/* In bootstrap mode, we have no indexes or column stores */
 		relation->rd_rel->relhasindex = false;
 	}
 	else
@@ -1700,6 +1700,9 @@ formrdesc(const char *relationName, Oid relationReltype,
 		relation->rd_rel->relhasindex = true;
 	}
 
+	/* this is used for catalogs only, so no column stores */
+	relation->rd_rel->relhascstore = false;
+
 	/*
 	 * add new reldesc to relcache
 	 */
diff --git a/src/include/catalog/pg_class.h b/src/include/catalog/pg_class.h
index 83bf8f3..310b51b 100644
--- a/src/include/catalog/pg_class.h
+++ b/src/include/catalog/pg_class.h
@@ -49,6 +49,7 @@ CATALOG(pg_class,1259) BKI_BOOTSTRAP BKI_ROWTYPE_OID(83) BKI_SCHEMA_MACRO
 								 * up-to-date) */
 	Oid			reltoastrelid;	/* OID of toast table; 0 if none */
 	bool		relhasindex;	/* T if has (or has had) any indexes */
+	bool		relhascstore;	/* T if has (or has had) any column stores */
 	bool		relisshared;	/* T if shared across databases */
 	char		relpersistence; /* see RELPERSISTENCE_xxx constants below */
 	char		relkind;		/* see RELKIND_xxx constants below */
@@ -95,7 +96,7 @@ typedef FormData_pg_class *Form_pg_class;
  * ----------------
  */
 
-#define Natts_pg_class					30
+#define Natts_pg_class					31
 #define Anum_pg_class_relname			1
 #define Anum_pg_class_relnamespace		2
 #define Anum_pg_class_reltype			3
@@ -109,23 +110,24 @@ typedef FormData_pg_class *Form_pg_class;
 #define Anum_pg_class_relallvisible		11
 #define Anum_pg_class_reltoastrelid		12
 #define Anum_pg_class_relhasindex		13
-#define Anum_pg_class_relisshared		14
-#define Anum_pg_class_relpersistence	15
-#define Anum_pg_class_relkind			16
-#define Anum_pg_class_relnatts			17
-#define Anum_pg_class_relchecks			18
-#define Anum_pg_class_relhasoids		19
-#define Anum_pg_class_relhaspkey		20
-#define Anum_pg_class_relhasrules		21
-#define Anum_pg_class_relhastriggers	22
-#define Anum_pg_class_relhassubclass	23
-#define Anum_pg_class_relrowsecurity	24
-#define Anum_pg_class_relispopulated	25
-#define Anum_pg_class_relreplident		26
-#define Anum_pg_class_relfrozenxid		27
-#define Anum_pg_class_relminmxid		28
-#define Anum_pg_class_relacl			29
-#define Anum_pg_class_reloptions		30
+#define Anum_pg_class_relhascstore		14
+#define Anum_pg_class_relisshared		15
+#define Anum_pg_class_relpersistence	16
+#define Anum_pg_class_relkind			17
+#define Anum_pg_class_relnatts			18
+#define Anum_pg_class_relchecks			19
+#define Anum_pg_class_relhasoids		20
+#define Anum_pg_class_relhaspkey		21
+#define Anum_pg_class_relhasrules		22
+#define Anum_pg_class_relhastriggers	23
+#define Anum_pg_class_relhassubclass	24
+#define Anum_pg_class_relrowsecurity	25
+#define Anum_pg_class_relispopulated	26
+#define Anum_pg_class_relreplident		27
+#define Anum_pg_class_relfrozenxid		28
+#define Anum_pg_class_relminmxid		29
+#define Anum_pg_class_relacl			30
+#define Anum_pg_class_reloptions		31
 
 /* ----------------
  *		initial contents of pg_class
@@ -140,13 +142,13 @@ typedef FormData_pg_class *Form_pg_class;
  * Note: "3" in the relfrozenxid column stands for FirstNormalTransactionId;
  * similarly, "1" in relminmxid stands for FirstMultiXactId
  */
-DATA(insert OID = 1247 (  pg_type		PGNSP 71 0 PGUID 0 0 0 0 0 0 0 f f p r 30 0 t f f f f f t n 3 1 _null_ _null_ ));
+DATA(insert OID = 1247 (  pg_type		PGNSP 71 0 PGUID 0 0 0 0 0 0 0 f f f p r 30 0 t f f f f f t n 3 1 _null_ _null_ ));
 DESCR("");
-DATA(insert OID = 1249 (  pg_attribute	PGNSP 75 0 PGUID 0 0 0 0 0 0 0 f f p r 21 0 f f f f f f t n 3 1 _null_ _null_ ));
+DATA(insert OID = 1249 (  pg_attribute	PGNSP 75 0 PGUID 0 0 0 0 0 0 0 f f f p r 21 0 f f f f f f t n 3 1 _null_ _null_ ));
 DESCR("");
-DATA(insert OID = 1255 (  pg_proc		PGNSP 81 0 PGUID 0 0 0 0 0 0 0 f f p r 28 0 t f f f f f t n 3 1 _null_ _null_ ));
+DATA(insert OID = 1255 (  pg_proc		PGNSP 81 0 PGUID 0 0 0 0 0 0 0 f f f p r 28 0 t f f f f f t n 3 1 _null_ _null_ ));
 DESCR("");
-DATA(insert OID = 1259 (  pg_class		PGNSP 83 0 PGUID 0 0 0 0 0 0 0 f f p r 30 0 t f f f f f t n 3 1 _null_ _null_ ));
+DATA(insert OID = 1259 (  pg_class		PGNSP 83 0 PGUID 0 0 0 0 0 0 0 f f f p r 31 0 t f f f f f t n 3 1 _null_ _null_ ));
 DESCR("");
 
 
diff --git a/src/test/regress/expected/rules.out b/src/test/regress/expected/rules.out
index 44c6740..8a1c43a 100644
--- a/src/test/regress/expected/rules.out
+++ b/src/test/regress/expected/rules.out
@@ -1359,6 +1359,7 @@ pg_matviews| SELECT n.nspname AS schemaname,
     pg_get_userbyid(c.relowner) AS matviewowner,
     t.spcname AS tablespace,
     c.relhasindex AS hasindexes,
+    c.relhascstore AS hascstores,
     c.relispopulated AS ispopulated,
     pg_get_viewdef(c.oid) AS definition
    FROM ((pg_class c
@@ -2068,6 +2069,7 @@ pg_tables| SELECT n.nspname AS schemaname,
     pg_get_userbyid(c.relowner) AS tableowner,
     t.spcname AS tablespace,
     c.relhasindex AS hasindexes,
+    c.relhascstore AS hascstores,
     c.relhasrules AS hasrules,
     c.relhastriggers AS hastriggers,
     c.relrowsecurity AS rowsecurity
diff --git a/src/test/regress/expected/sanity_check.out b/src/test/regress/expected/sanity_check.out
index b05061a..6abdab7 100644
--- a/src/test/regress/expected/sanity_check.out
+++ b/src/test/regress/expected/sanity_check.out
@@ -7,172 +7,172 @@ VACUUM;
 --
 -- temporarily disable fancy output, so catalog changes create less diff noise
 \a\t
-SELECT relname, relhasindex
+SELECT relname, relhasindex, relhascstore
    FROM pg_class c LEFT JOIN pg_namespace n ON n.oid = relnamespace
    WHERE relkind = 'r' AND (nspname ~ '^pg_temp_') IS NOT TRUE
    ORDER BY relname;
-a|f
-a_star|f
-abstime_tbl|f
-aggtest|f
-array_index_op_test|t
-array_op_test|f
-b|f
-b_star|f
-box_tbl|f
-bprime|f
-bt_f8_heap|t
-bt_i4_heap|t
-bt_name_heap|t
-bt_txt_heap|t
-c|f
-c_star|f
-char_tbl|f
-check2_tbl|f
-check_tbl|f
-circle_tbl|t
-city|f
-copy_tbl|f
-d|f
-d_star|f
-date_tbl|f
-default_tbl|f
-defaultexpr_tbl|f
-dept|f
-dupindexcols|t
-e_star|f
-emp|f
-equipment_r|f
-f_star|f
-fast_emp4000|t
-float4_tbl|f
-float8_tbl|f
-func_index_heap|t
-hash_f8_heap|t
-hash_i4_heap|t
-hash_name_heap|t
-hash_txt_heap|t
-hobbies_r|f
-ihighway|t
-inet_tbl|f
-inhf|f
-inhx|t
-insert_tbl|f
-int2_tbl|f
-int4_tbl|f
-int8_tbl|f
-interval_tbl|f
-iportaltest|f
-kd_point_tbl|t
-line_tbl|f
-log_table|f
-lseg_tbl|f
-main_table|f
-money_data|f
-num_data|f
-num_exp_add|t
-num_exp_div|t
-num_exp_ln|t
-num_exp_log10|t
-num_exp_mul|t
-num_exp_power_10_ln|t
-num_exp_sqrt|t
-num_exp_sub|t
-num_input_test|f
-num_result|f
-onek|t
-onek2|t
-path_tbl|f
-person|f
-pg_aggregate|t
-pg_am|t
-pg_amop|t
-pg_amproc|t
-pg_attrdef|t
-pg_attribute|t
-pg_auth_members|t
-pg_authid|t
-pg_cast|t
-pg_class|t
-pg_collation|t
-pg_constraint|t
-pg_conversion|t
-pg_cstore|t
-pg_cstore_am|t
-pg_database|t
-pg_db_role_setting|t
-pg_default_acl|t
-pg_depend|t
-pg_description|t
-pg_enum|t
-pg_event_trigger|t
-pg_extension|t
-pg_foreign_data_wrapper|t
-pg_foreign_server|t
-pg_foreign_table|t
-pg_index|t
-pg_inherits|t
-pg_language|t
-pg_largeobject|t
-pg_largeobject_metadata|t
-pg_namespace|t
-pg_opclass|t
-pg_operator|t
-pg_opfamily|t
-pg_pltemplate|t
-pg_policy|t
-pg_proc|t
-pg_range|t
-pg_replication_origin|t
-pg_rewrite|t
-pg_seclabel|t
-pg_shdepend|t
-pg_shdescription|t
-pg_shseclabel|t
-pg_statistic|t
-pg_tablespace|t
-pg_transform|t
-pg_trigger|t
-pg_ts_config|t
-pg_ts_config_map|t
-pg_ts_dict|t
-pg_ts_parser|t
-pg_ts_template|t
-pg_type|t
-pg_user_mapping|t
-point_tbl|t
-polygon_tbl|t
-quad_point_tbl|t
-radix_text_tbl|t
-ramp|f
-real_city|f
-reltime_tbl|f
-road|t
-shighway|t
-slow_emp4000|f
-sql_features|f
-sql_implementation_info|f
-sql_languages|f
-sql_packages|f
-sql_parts|f
-sql_sizing|f
-sql_sizing_profiles|f
-stud_emp|f
-student|f
-tenk1|t
-tenk2|t
-test_range_excl|t
-test_range_gist|t
-test_range_spgist|t
-test_tsvector|f
-testjsonb|f
-text_tbl|f
-time_tbl|f
-timestamp_tbl|f
-timestamptz_tbl|f
-timetz_tbl|f
-tinterval_tbl|f
-varchar_tbl|f
+a|f|f
+a_star|f|f
+abstime_tbl|f|f
+aggtest|f|f
+array_index_op_test|t|f
+array_op_test|f|f
+b|f|f
+b_star|f|f
+box_tbl|f|f
+bprime|f|f
+bt_f8_heap|t|f
+bt_i4_heap|t|f
+bt_name_heap|t|f
+bt_txt_heap|t|f
+c|f|f
+c_star|f|f
+char_tbl|f|f
+check2_tbl|f|f
+check_tbl|f|f
+circle_tbl|t|f
+city|f|f
+copy_tbl|f|f
+d|f|f
+d_star|f|f
+date_tbl|f|f
+default_tbl|f|f
+defaultexpr_tbl|f|f
+dept|f|f
+dupindexcols|t|f
+e_star|f|f
+emp|f|f
+equipment_r|f|f
+f_star|f|f
+fast_emp4000|t|f
+float4_tbl|f|f
+float8_tbl|f|f
+func_index_heap|t|f
+hash_f8_heap|t|f
+hash_i4_heap|t|f
+hash_name_heap|t|f
+hash_txt_heap|t|f
+hobbies_r|f|f
+ihighway|t|f
+inet_tbl|f|f
+inhf|f|f
+inhx|t|f
+insert_tbl|f|f
+int2_tbl|f|f
+int4_tbl|f|f
+int8_tbl|f|f
+interval_tbl|f|f
+iportaltest|f|f
+kd_point_tbl|t|f
+line_tbl|f|f
+log_table|f|f
+lseg_tbl|f|f
+main_table|f|f
+money_data|f|f
+num_data|f|f
+num_exp_add|t|f
+num_exp_div|t|f
+num_exp_ln|t|f
+num_exp_log10|t|f
+num_exp_mul|t|f
+num_exp_power_10_ln|t|f
+num_exp_sqrt|t|f
+num_exp_sub|t|f
+num_input_test|f|f
+num_result|f|f
+onek|t|f
+onek2|t|f
+path_tbl|f|f
+person|f|f
+pg_aggregate|t|f
+pg_am|t|f
+pg_amop|t|f
+pg_amproc|t|f
+pg_attrdef|t|f
+pg_attribute|t|f
+pg_auth_members|t|f
+pg_authid|t|f
+pg_cast|t|f
+pg_class|t|f
+pg_collation|t|f
+pg_constraint|t|f
+pg_conversion|t|f
+pg_cstore|t|f
+pg_cstore_am|t|f
+pg_database|t|f
+pg_db_role_setting|t|f
+pg_default_acl|t|f
+pg_depend|t|f
+pg_description|t|f
+pg_enum|t|f
+pg_event_trigger|t|f
+pg_extension|t|f
+pg_foreign_data_wrapper|t|f
+pg_foreign_server|t|f
+pg_foreign_table|t|f
+pg_index|t|f
+pg_inherits|t|f
+pg_language|t|f
+pg_largeobject|t|f
+pg_largeobject_metadata|t|f
+pg_namespace|t|f
+pg_opclass|t|f
+pg_operator|t|f
+pg_opfamily|t|f
+pg_pltemplate|t|f
+pg_policy|t|f
+pg_proc|t|f
+pg_range|t|f
+pg_replication_origin|t|f
+pg_rewrite|t|f
+pg_seclabel|t|f
+pg_shdepend|t|f
+pg_shdescription|t|f
+pg_shseclabel|t|f
+pg_statistic|t|f
+pg_tablespace|t|f
+pg_transform|t|f
+pg_trigger|t|f
+pg_ts_config|t|f
+pg_ts_config_map|t|f
+pg_ts_dict|t|f
+pg_ts_parser|t|f
+pg_ts_template|t|f
+pg_type|t|f
+pg_user_mapping|t|f
+point_tbl|t|f
+polygon_tbl|t|f
+quad_point_tbl|t|f
+radix_text_tbl|t|f
+ramp|f|f
+real_city|f|f
+reltime_tbl|f|f
+road|t|f
+shighway|t|f
+slow_emp4000|f|f
+sql_features|f|f
+sql_implementation_info|f|f
+sql_languages|f|f
+sql_packages|f|f
+sql_parts|f|f
+sql_sizing|f|f
+sql_sizing_profiles|f|f
+stud_emp|f|f
+student|f|f
+tenk1|t|f
+tenk2|t|f
+test_range_excl|t|f
+test_range_gist|t|f
+test_range_spgist|t|f
+test_tsvector|f|f
+testjsonb|f|f
+text_tbl|f|f
+time_tbl|f|f
+timestamp_tbl|f|f
+timestamptz_tbl|f|f
+timetz_tbl|f|f
+tinterval_tbl|f|f
+varchar_tbl|f|f
 -- restore normal output mode
 \a\t
 --
diff --git a/src/test/regress/sql/sanity_check.sql b/src/test/regress/sql/sanity_check.sql
index 0da838e..ca87cbc 100644
--- a/src/test/regress/sql/sanity_check.sql
+++ b/src/test/regress/sql/sanity_check.sql
@@ -10,7 +10,7 @@ VACUUM;
 -- temporarily disable fancy output, so catalog changes create less diff noise
 \a\t
 
-SELECT relname, relhasindex
+SELECT relname, relhasindex, relhascstore
    FROM pg_class c LEFT JOIN pg_namespace n ON n.oid = relnamespace
    WHERE relkind = 'r' AND (nspname ~ '^pg_temp_') IS NOT TRUE
    ORDER BY relname;
-- 
2.1.4

