From da29876efa16af240634b50256a26190b0b76a23 Mon Sep 17 00:00:00 2001 From: tim markello Date: Wed, 26 Oct 2022 09:44:29 -0500 Subject: [PATCH 1/2] add schema support for view create/drop previous functionality did not support create/drop of views within a schema. This causes issues when a users is expecting the view to exist within the schema specified by the metadata object - but it is instead created in the default schema regardless. adding in fuctionality to support creation of views within a schema as provided by the metadata object. Defaults to None if no schema is present. adding in functionality to specify schema when dropping view as provided by metadata object modified: sqlalchemy_utils/view.py --- sqlalchemy_utils/view.py | 20 ++++++++++++-------- 1 file changed, 12 insertions(+), 8 deletions(-) diff --git a/sqlalchemy_utils/view.py b/sqlalchemy_utils/view.py index 96103db1..a2f4f82b 100644 --- a/sqlalchemy_utils/view.py +++ b/sqlalchemy_utils/view.py @@ -6,32 +6,36 @@ class CreateView(DDLElement): - def __init__(self, name, selectable, materialized=False): + def __init__(self, name, selectable, materialized=False, schema=None): self.name = name self.selectable = selectable self.materialized = materialized + self.schema = schema @compiler.compiles(CreateView) def compile_create_materialized_view(element, compiler, **kw): - return 'CREATE {}VIEW {} AS {}'.format( + return 'CREATE {}VIEW {}{} AS {}'.format( 'MATERIALIZED ' if element.materialized else '', + f'{compiler.dialect.identifier_preparer.quote(element.schema)}.' if element.schema else '', compiler.dialect.identifier_preparer.quote(element.name), compiler.sql_compiler.process(element.selectable, literal_binds=True), ) class DropView(DDLElement): - def __init__(self, name, materialized=False, cascade=True): + def __init__(self, name, materialized=False, cascade=True, schema=None): self.name = name self.materialized = materialized self.cascade = cascade + self.schema = schema @compiler.compiles(DropView) def compile_drop_materialized_view(element, compiler, **kw): - return 'DROP {}VIEW IF EXISTS {} {}'.format( + return 'DROP {}VIEW IF EXISTS {}{} {}'.format( 'MATERIALIZED ' if element.materialized else '', + f'{compiler.dialect.identifier_preparer.quote(element.schema)}.' if element.schema else '', compiler.dialect.identifier_preparer.quote(element.name), 'CASCADE' if element.cascade else '' ) @@ -103,7 +107,7 @@ def create_materialized_view( sa.event.listen( metadata, 'after_create', - CreateView(name, selectable, materialized=True) + CreateView(name, selectable, materialized=True, schema=metadata.schema) ) @sa.event.listens_for(metadata, 'after_create') @@ -114,7 +118,7 @@ def create_indexes(target, connection, **kw): sa.event.listen( metadata, 'before_drop', - DropView(name, materialized=True) + DropView(name, materialized=True, schema=metadata.schema) ) return table @@ -163,7 +167,7 @@ def create_view( metadata=None ) - sa.event.listen(metadata, 'after_create', CreateView(name, selectable)) + sa.event.listen(metadata, 'after_create', CreateView(name, selectable, schema=metadata.schema)) @sa.event.listens_for(metadata, 'after_create') def create_indexes(target, connection, **kw): @@ -173,7 +177,7 @@ def create_indexes(target, connection, **kw): sa.event.listen( metadata, 'before_drop', - DropView(name, cascade=cascade_on_drop) + DropView(name, cascade=cascade_on_drop, schema=metadata.schema) ) return table From 46cd4c2841f3ceca9b7fa73a772c2536fa0bde0d Mon Sep 17 00:00:00 2001 From: tim markello Date: Wed, 26 Oct 2022 10:11:58 -0500 Subject: [PATCH 2/2] make the linter happy some of the lines were longer than the linter liked modified: sqlalchemy_utils/view.py --- sqlalchemy_utils/view.py | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) diff --git a/sqlalchemy_utils/view.py b/sqlalchemy_utils/view.py index a2f4f82b..29fc7ad0 100644 --- a/sqlalchemy_utils/view.py +++ b/sqlalchemy_utils/view.py @@ -17,7 +17,9 @@ def __init__(self, name, selectable, materialized=False, schema=None): def compile_create_materialized_view(element, compiler, **kw): return 'CREATE {}VIEW {}{} AS {}'.format( 'MATERIALIZED ' if element.materialized else '', - f'{compiler.dialect.identifier_preparer.quote(element.schema)}.' if element.schema else '', + f'{compiler.dialect.identifier_preparer.quote(element.schema)}.' + if element.schema + else '', compiler.dialect.identifier_preparer.quote(element.name), compiler.sql_compiler.process(element.selectable, literal_binds=True), ) @@ -35,7 +37,9 @@ def __init__(self, name, materialized=False, cascade=True, schema=None): def compile_drop_materialized_view(element, compiler, **kw): return 'DROP {}VIEW IF EXISTS {}{} {}'.format( 'MATERIALIZED ' if element.materialized else '', - f'{compiler.dialect.identifier_preparer.quote(element.schema)}.' if element.schema else '', + f'{compiler.dialect.identifier_preparer.quote(element.schema)}.' + if element.schema + else '', compiler.dialect.identifier_preparer.quote(element.name), 'CASCADE' if element.cascade else '' ) @@ -167,7 +171,11 @@ def create_view( metadata=None ) - sa.event.listen(metadata, 'after_create', CreateView(name, selectable, schema=metadata.schema)) + sa.event.listen( + metadata, + 'after_create', + CreateView(name, selectable, schema=metadata.schema) + ) @sa.event.listens_for(metadata, 'after_create') def create_indexes(target, connection, **kw):