fix(app): preserve object source formatting
This commit is contained in:
1 parent
4c96aa6e40
commit
f16454a403
3 files changed
+119
-3
No files matched your search
@@ -137,6 +137,13 @@ pub fn build_executable_object_source_statements(input: EditableObjectSourceSqlI
|
||||
| DatabaseType::Questdb
|
||||
) && input.object_type == ObjectSourceKind::View
|
||||
{
|
||||
if let Some(sql) = executable_postgres_view_ddl(source) {
|
||||
return Ok(vec![sql]);
|
||||
}
|
||||
if source_starts_with_alter(source) {
|
||||
// ALTER VIEW is already executable DDL, but it is not a view body.
|
||||
return Ok(vec![ensure_semicolon(source)]);
|
||||
}
|
||||
return Ok(vec![format!(
|
||||
"CREATE OR REPLACE VIEW {} AS\n{}",
|
||||
postgres_qualified_name(input.schema.as_deref(), &input.name),
|
||||
@@ -164,6 +171,19 @@ pub fn build_executable_object_source_sql(input: EditableObjectSourceSqlInput) -
|
||||
/// statements.
|
||||
pub fn build_editable_object_source(input: EditableObjectSourceSqlInput) -> String {
|
||||
let source = input.source.clone();
|
||||
if matches!(
|
||||
input.database_type,
|
||||
DatabaseType::Postgres
|
||||
| DatabaseType::Gaussdb
|
||||
| DatabaseType::Kwdb
|
||||
| DatabaseType::OpenGauss
|
||||
| DatabaseType::Questdb
|
||||
) && input.object_type == ObjectSourceKind::View
|
||||
&& source_starts_with_create_or_alter(&source)
|
||||
{
|
||||
// Some providers return full view DDL instead of a bare SELECT body.
|
||||
return ensure_semicolon(source.trim());
|
||||
}
|
||||
match build_executable_object_source_statements(input) {
|
||||
Ok(statements) => statements.into_iter().next().unwrap_or_default(),
|
||||
Err(_) => ensure_semicolon(source.trim()),
|
||||
@@ -285,6 +305,29 @@ fn ensure_semicolon(sql: &str) -> String {
|
||||
}
|
||||
}
|
||||
|
||||
fn source_starts_with_create_or_alter(source: &str) -> bool {
|
||||
Regex::new(r"(?i)^\s*(?:CREATE|ALTER)\s+").unwrap().is_match(source)
|
||||
}
|
||||
|
||||
fn source_starts_with_alter(source: &str) -> bool {
|
||||
Regex::new(r"(?i)^\s*ALTER\s+").unwrap().is_match(source)
|
||||
}
|
||||
|
||||
fn executable_postgres_view_ddl(source: &str) -> Option<String> {
|
||||
let trimmed = source.trim();
|
||||
if Regex::new(r"(?i)^CREATE\s+OR\s+REPLACE\s+").unwrap().is_match(trimmed) {
|
||||
return Some(ensure_semicolon(trimmed));
|
||||
}
|
||||
|
||||
let create_view = Regex::new(r"(?i)^CREATE\s+((?:(?:TEMP|TEMPORARY)\s+)?(?:RECURSIVE\s+)?VIEW\s+)").unwrap();
|
||||
if create_view.is_match(trimmed) {
|
||||
let replaced = create_view.replace(trimmed, "CREATE OR REPLACE $1");
|
||||
return Some(ensure_semicolon(replaced.as_ref()));
|
||||
}
|
||||
|
||||
None
|
||||
}
|
||||
|
||||
fn postgres_qualified_name(schema: Option<&str>, name: &str) -> String {
|
||||
schema
|
||||
.into_iter()
|
||||
@@ -547,6 +590,67 @@ mod tests {
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn postgres_view_create_source_opens_without_rewrapping_or_reformatting() {
|
||||
let source = "CREATE OR REPLACE VIEW public.active_users AS SELECT id, name FROM users WHERE active = true";
|
||||
let sql = build_editable_object_source(EditableObjectSourceSqlInput {
|
||||
database_type: DatabaseType::Postgres,
|
||||
object_type: ObjectSourceKind::View,
|
||||
schema: Some("public".to_string()),
|
||||
name: "active_users".to_string(),
|
||||
source: source.to_string(),
|
||||
});
|
||||
|
||||
assert_eq!(sql, format!("{source};"));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn postgres_view_create_source_saves_as_create_or_replace_view() {
|
||||
let sql = build_executable_object_source_sql(EditableObjectSourceSqlInput {
|
||||
database_type: DatabaseType::Postgres,
|
||||
object_type: ObjectSourceKind::View,
|
||||
schema: Some("public".to_string()),
|
||||
name: "active_users".to_string(),
|
||||
source: "CREATE VIEW public.active_users AS SELECT id, name FROM users WHERE active = true".to_string(),
|
||||
})
|
||||
.unwrap();
|
||||
|
||||
assert_eq!(
|
||||
sql,
|
||||
"CREATE OR REPLACE VIEW public.active_users AS SELECT id, name FROM users WHERE active = true;"
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn postgres_view_create_or_replace_source_saves_without_rewrapping() {
|
||||
let source = "CREATE OR REPLACE VIEW public.active_users AS SELECT id, name FROM users WHERE active = true";
|
||||
let sql = build_executable_object_source_sql(EditableObjectSourceSqlInput {
|
||||
database_type: DatabaseType::Postgres,
|
||||
object_type: ObjectSourceKind::View,
|
||||
schema: Some("public".to_string()),
|
||||
name: "active_users".to_string(),
|
||||
source: source.to_string(),
|
||||
})
|
||||
.unwrap();
|
||||
|
||||
assert_eq!(sql, format!("{source};"));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn postgres_view_alter_source_saves_without_body_wrapping() {
|
||||
let source = "ALTER VIEW public.active_users SET (security_barrier = true)";
|
||||
let sql = build_executable_object_source_sql(EditableObjectSourceSqlInput {
|
||||
database_type: DatabaseType::Postgres,
|
||||
object_type: ObjectSourceKind::View,
|
||||
schema: Some("public".to_string()),
|
||||
name: "active_users".to_string(),
|
||||
source: source.to_string(),
|
||||
})
|
||||
.unwrap();
|
||||
|
||||
assert_eq!(sql, format!("{source};"));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn postgres_compatible_view_body_opens_as_create_or_replace_view() {
|
||||
for database_type in [DatabaseType::OpenGauss, DatabaseType::Kwdb] {
|
||||
|
||||
Reference in new issue
Block a user