uqa_sql/schema/relation_alteration/
relocation.rs1use super::RelationAlterNames;
10use crate::{ast::RelationPersistence, SQLError};
11use uqa_core::RelationIdentity;
12
13pub fn declared_target(
14 source: &RelationIdentity,
15 schema: &str,
16) -> Result<RelationIdentity, SQLError> {
17 let (qualifier, schema) =
18 RelationIdentity::parse_reference(schema).map_err(SQLError::Internal)?;
19 if qualifier.is_some() {
20 return Err(SQLError::Internal(
21 "SET SCHEMA produced a qualified schema".into(),
22 ));
23 }
24 Ok(RelationIdentity::new(schema, &source.name))
25}
26
27pub fn validate_target(
29 catalog: &dyn RelationAlterNames,
30 source: &RelationIdentity,
31 target: &RelationIdentity,
32 persistence: RelationPersistence,
33 temporary_schema: &str,
34) -> Result<bool, SQLError> {
35 let temporary = |schema: &str| {
36 schema == temporary_schema
37 || schema.starts_with("pg_temp_")
38 || schema.starts_with("pg_toast_temp_")
39 };
40 if persistence == RelationPersistence::Temporary
41 || temporary(&source.schema)
42 || temporary(&target.schema)
43 {
44 return Err(SQLError::Routine {
45 sqlstate: "0A000".into(),
46 message: "cannot move objects into or out of temporary schemas".into(),
47 });
48 }
49 if source.schema == "pg_toast" || target.schema == "pg_toast" {
50 return Err(SQLError::Routine {
51 sqlstate: "0A000".into(),
52 message: "cannot move objects into or out of TOAST schema".into(),
53 });
54 }
55 if source == target {
56 return Ok(false);
57 }
58 ensure_name_available(catalog, target)?;
59 Ok(true)
60}
61
62pub fn ensure_name_available(
63 catalog: &dyn RelationAlterNames,
64 target: &RelationIdentity,
65) -> Result<(), SQLError> {
66 if catalog
67 .relation_kind_at(&target.qualified_name())
68 .map_err(SQLError::Internal)?
69 .is_some()
70 {
71 return Err(SQLError::Routine {
72 sqlstate: "42P07".into(),
73 message: format!(
74 "relation \"{}\" already exists in schema \"{}\"",
75 target.name, target.schema
76 ),
77 });
78 }
79 Ok(())
80}
81
82#[cfg(test)]
83mod tests;