1212from django .db .backends .ddl_references import Statement
1313from django .db .models import Field , Model
1414
15+ from psqlextra .settings import (
16+ postgres_prepend_local_search_path ,
17+ postgres_reset_local_search_path ,
18+ )
1519from psqlextra .type_assertions import is_sql_with_params
1620from psqlextra .types import PostgresPartitioningMethod
1721
@@ -40,6 +44,8 @@ class PostgresSchemaEditor(SchemaEditor):
4044 sql_alter_table_storage_setting = "ALTER TABLE %s SET (%s = %s)"
4145 sql_reset_table_storage_setting = "ALTER TABLE %s RESET (%s)"
4246
47+ sql_alter_table_schema = "ALTER TABLE %s SET SCHEMA %s"
48+
4349 sql_create_view = "CREATE VIEW %s AS (%s)"
4450 sql_replace_view = "CREATE OR REPLACE VIEW %s AS (%s)"
4551 sql_drop_view = "DROP VIEW IF EXISTS %s"
@@ -203,8 +209,8 @@ def clone_model_constraints_and_indexes_to_schema(
203209 resides.
204210 """
205211
206- with self . introspection . in_search_path (
207- [schema_name , self .connection .ops . default_schema_name ()]
212+ with postgres_prepend_local_search_path (
213+ [schema_name ], using = self .connection .alias
208214 ):
209215 for constraint in model ._meta .constraints :
210216 self .add_constraint (model , constraint )
@@ -226,8 +232,8 @@ def clone_model_constraints_and_indexes_to_schema(
226232 # Django creates primary keys later added to the model with
227233 # a custom name. We want the name as it was created originally.
228234 if field .primary_key :
229- with self . introspection . in_search_path (
230- [ self .connection .ops . default_schema_name ()]
235+ with postgres_reset_local_search_path (
236+ using = self .connection .alias
231237 ):
232238 [primary_key_name ] = self ._constraint_names (
233239 model , primary_key = True
@@ -251,8 +257,8 @@ def clone_model_constraints_and_indexes_to_schema(
251257 # a separate transaction later to validate the entries without
252258 # acquiring a AccessExclusiveLock.
253259 if field .remote_field :
254- with self . introspection . in_search_path (
255- [ self .connection .ops . default_schema_name ()]
260+ with postgres_reset_local_search_path (
261+ using = self .connection .alias
256262 ):
257263 [fk_name ] = self ._constraint_names (
258264 model , [field .column ], foreign_key = True
@@ -277,8 +283,8 @@ def clone_model_constraints_and_indexes_to_schema(
277283 # manually.
278284 field_check = field .db_parameters (self .connection ).get ("check" )
279285 if field_check :
280- with self . introspection . in_search_path (
281- [ self .connection .ops . default_schema_name ()]
286+ with postgres_reset_local_search_path (
287+ using = self .connection .alias
282288 ):
283289 [field_check_name ] = self ._constraint_names (
284290 model ,
@@ -337,10 +343,12 @@ def clone_model_foreign_keys_to_schema(
337343 resides.
338344 """
339345
340- with self .introspection .in_search_path (
341- [schema_name , self .connection .ops .default_schema_name ()]
346+ constraint_names = self ._constraint_names (model , foreign_key = True )
347+
348+ with postgres_prepend_local_search_path (
349+ [schema_name ], using = self .connection .alias
342350 ):
343- for fk_name in self . _constraint_names ( model , foreign_key = True ) :
351+ for fk_name in constraint_names :
344352 self .execute (
345353 self .sql_validate_fk
346354 % (
@@ -438,6 +446,47 @@ def reset_model_storage_setting(
438446
439447 self .reset_table_storage_setting (model ._meta .db_table , name )
440448
449+ def alter_table_schema (self , table_name : str , schema_name : str ) -> None :
450+ """Moves the specified table into the specified schema.
451+
452+ WARNING: Moving models into a different schema than the default
453+ will break querying the model.
454+
455+ Arguments:
456+ table_name:
457+ Name of the table to move into the specified schema.
458+
459+ schema_name:
460+ Name of the schema to move the table to.
461+ """
462+
463+ self .execute (
464+ self .sql_alter_table_schema
465+ % (self .quote_name (table_name ), self .quote_name (schema_name ))
466+ )
467+
468+ def alter_model_schema (self , model : Type [Model ], schema_name : str ) -> None :
469+ """Moves the specified model's table into the specified schema.
470+
471+ WARNING: Moving models into a different schema than the default
472+ will break querying the model.
473+
474+ Arguments:
475+ model:
476+ Model of which to move the table.
477+
478+ schema_name:
479+ Name of the schema to move the model's table to.
480+ """
481+
482+ self .execute (
483+ self .sql_alter_table_schema
484+ % (
485+ self .quote_name (model ._meta .db_table ),
486+ self .quote_name (schema_name ),
487+ )
488+ )
489+
441490 def refresh_materialized_view_model (
442491 self , model : Type [Model ], concurrently : bool = False
443492 ) -> None :
0 commit comments