diff --git a/schemainspect/inspected.py b/schemainspect/inspected.py index db89a14..f601935 100644 --- a/schemainspect/inspected.py +++ b/schemainspect/inspected.py @@ -53,6 +53,9 @@ def __init__( is_generated=False, is_inherited=False, can_drop_generated=False, + attoptions=None, + attstattarget=None, + attcompression=None, ): self.name = name or "" self.dbtype = dbtype @@ -68,6 +71,9 @@ def __init__( self.is_generated = is_generated self.is_inherited = is_inherited self.can_drop_generated = can_drop_generated + self.attoptions = attoptions.split(";") if attoptions else None + self.attstattarget = attstattarget + self.attcompression = attcompression def __eq__(self, other): return ( @@ -82,6 +88,9 @@ def __eq__(self, other): and self.is_identity_always == other.is_identity_always and self.is_generated == other.is_generated and self.is_inherited == other.is_inherited + and self.attoptions == other.attoptions + and self.attstattarget == other.attstattarget + and self.attcompression == other.attcompression ) def alter_clauses(self, other): @@ -128,11 +137,52 @@ def alter_clauses(self, other): else: clauses.append(self.alter_data_type_clause) + if self.attoptions != other.attoptions: + pfx, areset, aset = self.alter_options_clause(other) + if areset: + clauses.append(pfx + areset) + if aset: + clauses.append(pfx + aset) + + if self.attstattarget != other.attstattarget: + clauses.append(self.alter_stat_clause(other)) + + if self.attcompression != other.attcompression: + clauses.append(self.alter_compression_clause(other)) + return clauses + COMPRESSIONS = {"": "default", "l": "lz4", "p": "pglz"} + + def alter_compression_clause(self, other): + if self.attcompression == other.attcompression: + return "" # NOP, just for sanity + comp = self.COMPRESSIONS.get(self.attcompression, + "default; -- actually unknown {!r}" + .format(self.attcompression)) + return "alter column {} set compression {}".format(self.quoted_name, comp) + + def alter_stat_clause(self, other): + if self.attstattarget == other.attstattarget: + return "" # NOP, just for sanity + return "alter column {} set statistics {}".format(self.quoted_name, + self.attstattarget) + + def alter_options_clause(self, other): + if self.attoptions == other.attoptions: + return "" # NOP, just for sanity + prefix = "alter column {} ".format(self.quoted_name) + action_set = "set ({})".format(",".join(self.attoptions)) \ + if self.attoptions else None + action_reset = "reset ({})".format( + ",".join(o.split("=", 1)[0] for o in other.attoptions) + ) if other.attoptions else None + return prefix, action_reset, action_set + def change_enum_to_string_statement(self, table_name): if self.is_enum: - return "alter table {} alter column {} set data type varchar using {}::varchar;".format( + return ("alter table {} alter column {}" + " set data type varchar using {}::varchar;").format( table_name, self.quoted_name, self.quoted_name ) @@ -142,7 +192,8 @@ def change_enum_to_string_statement(self, table_name): def change_string_to_enum_statement(self, table_name): if self.is_enum: return ( - "alter table {} alter column {} set data type {} using {}::{};".format( + "alter table {} alter column {} set data type {} using {}::{};" + .format( table_name, self.quoted_name, self.dbtypestr, @@ -155,12 +206,15 @@ def change_string_to_enum_statement(self, table_name): def change_enum_statement(self, table_name): if self.is_enum: - return "alter table {} alter column {} type {} using {}::text::{};".format( - table_name, - self.name, - self.enum.quoted_full_name, - self.name, - self.enum.quoted_full_name, + return ( + "alter table {} alter column {} type {} using {}::text::{};" + .format( + table_name, + self.name, + self.enum.quoted_full_name, + self.name, + self.enum.quoted_full_name, + ) ) else: raise ValueError @@ -327,3 +381,4 @@ def __eq__(self, other): self.persistence == other.persistence, ) return all(equalities) +# vim:set ai et ts=4 sts=4 sw=4 cc=80:EOF # diff --git a/schemainspect/pg/obj.py b/schemainspect/pg/obj.py index bc8639a..9aa8d93 100644 --- a/schemainspect/pg/obj.py +++ b/schemainspect/pg/obj.py @@ -1114,10 +1114,14 @@ def processed(q): if pg_version >= 12: replace = "-- 12_ONLY" + if pg_version >= 15: + replace2 = "-- 15_ONLY" else: replace = "-- PRE_12" + replace2 = "-- PRE_15" - all_relations_query = all_relations_query.replace(replace, "") + all_relations_query = all_relations_query \ + .replace(replace, "").replace(replace2, "") self.ALL_RELATIONS_QUERY = processed(all_relations_query) self.COLLATIONS_QUERY = processed(COLLATIONS_QUERY) self.RLSPOLICIES_QUERY = processed(RLSPOLICIES_QUERY) @@ -1422,6 +1426,9 @@ def get_enum(name, schema): is_identity_always=c.is_identity_always, is_generated=c.is_generated, can_drop_generated=self.pg_version >= 13, + attoptions=c.attoptions, + attstattarget=c.attstattarget, + attcompression=c.attcompression, ) for c in clist if c.position_number @@ -1766,3 +1773,4 @@ def __eq__(self, other): and self.collations == other.collations and self.rlspolicies == other.rlspolicies ) +# vim:set ai et ts=4 sts=4 sw=4 cc=80:EOF # diff --git a/schemainspect/pg/sql/relations.sql b/schemainspect/pg/sql/relations.sql index 92f5f94..0ed0b4b 100644 --- a/schemainspect/pg/sql/relations.sql +++ b/schemainspect/pg/sql/relations.sql @@ -75,6 +75,10 @@ select a.atttypid::regtype AS datatype, a.attidentity != '' as is_identity, a.attidentity = 'a' as is_identity_always, + array_to_string(a.attoptions, ';') as attoptions, + a.attstattarget as attstattarget, + -- PRE_15 null as attcompression, + -- 15_ONLY a.attcompression as attcompression, -- PRE_12 false as is_generated, -- 12_ONLY a.attgenerated != '' as is_generated, (SELECT c.collname FROM pg_catalog.pg_collation c, pg_catalog.pg_type t