mirror of
https://github.com/t8y2/dbx.git
synced 2026-11-02 00:29:30 +00:00
feat(postgres): support sequence objects
This commit is contained in:
@@ -1151,6 +1151,7 @@ fn list_objects_sql(include_timestamps: bool) -> &'static str {
|
||||
CASE c.relkind \
|
||||
WHEN 'v' THEN 'VIEW' \
|
||||
WHEN 'm' THEN 'VIEW' \
|
||||
WHEN 'S' THEN 'SEQUENCE' \
|
||||
ELSE 'TABLE' \
|
||||
END AS object_type, \
|
||||
obj_description(c.oid) AS object_comment, \
|
||||
@@ -1162,7 +1163,7 @@ fn list_objects_sql(include_timestamps: bool) -> &'static str {
|
||||
) AS updated_at, \
|
||||
CASE WHEN pc.relkind = 'p' THEN pn.nspname ELSE NULL END AS parent_schema, \
|
||||
CASE WHEN pc.relkind = 'p' THEN pc.relname ELSE NULL END AS parent_name, \
|
||||
CASE c.relkind WHEN 'v' THEN 1 WHEN 'm' THEN 1 ELSE 0 END AS sort_order \
|
||||
CASE c.relkind WHEN 'v' THEN 1 WHEN 'm' THEN 1 WHEN 'S' THEN 4 ELSE 0 END AS sort_order \
|
||||
FROM pg_catalog.pg_class c \
|
||||
JOIN pg_catalog.pg_namespace n ON n.oid = c.relnamespace \
|
||||
LEFT JOIN pg_catalog.pg_inherits i ON i.inhrelid = c.oid \
|
||||
@@ -1171,7 +1172,7 @@ fn list_objects_sql(include_timestamps: bool) -> &'static str {
|
||||
LEFT JOIN LATERAL pg_stat_file( \
|
||||
CASE WHEN c.relkind IN ('r','m','f','p') THEN pg_relation_filepath(c.oid) END, true \
|
||||
) stat ON true \
|
||||
WHERE n.nspname = $1 AND c.relkind IN ('r','v','m','f','p') \
|
||||
WHERE n.nspname = $1 AND c.relkind IN ('r','v','m','f','p','S') \
|
||||
UNION ALL \
|
||||
SELECT p.proname AS object_name, \
|
||||
CASE p.prokind WHEN 'p' THEN 'PROCEDURE' ELSE 'FUNCTION' END AS object_type, \
|
||||
@@ -1192,6 +1193,7 @@ fn list_objects_sql(include_timestamps: bool) -> &'static str {
|
||||
CASE c.relkind \
|
||||
WHEN 'v' THEN 'VIEW' \
|
||||
WHEN 'm' THEN 'VIEW' \
|
||||
WHEN 'S' THEN 'SEQUENCE' \
|
||||
ELSE 'TABLE' \
|
||||
END AS object_type, \
|
||||
obj_description(c.oid) AS object_comment, \
|
||||
@@ -1199,13 +1201,13 @@ fn list_objects_sql(include_timestamps: bool) -> &'static str {
|
||||
NULL::text AS updated_at, \
|
||||
CASE WHEN pc.relkind = 'p' THEN pn.nspname ELSE NULL END AS parent_schema, \
|
||||
CASE WHEN pc.relkind = 'p' THEN pc.relname ELSE NULL END AS parent_name, \
|
||||
CASE c.relkind WHEN 'v' THEN 1 WHEN 'm' THEN 1 ELSE 0 END AS sort_order \
|
||||
CASE c.relkind WHEN 'v' THEN 1 WHEN 'm' THEN 1 WHEN 'S' THEN 4 ELSE 0 END AS sort_order \
|
||||
FROM pg_catalog.pg_class c \
|
||||
JOIN pg_catalog.pg_namespace n ON n.oid = c.relnamespace \
|
||||
LEFT JOIN pg_catalog.pg_inherits i ON i.inhrelid = c.oid \
|
||||
LEFT JOIN pg_catalog.pg_class pc ON pc.oid = i.inhparent \
|
||||
LEFT JOIN pg_catalog.pg_namespace pn ON pn.oid = pc.relnamespace \
|
||||
WHERE n.nspname = $1 AND c.relkind IN ('r','v','m','f','p') \
|
||||
WHERE n.nspname = $1 AND c.relkind IN ('r','v','m','f','p','S') \
|
||||
UNION ALL \
|
||||
SELECT p.proname AS object_name, \
|
||||
CASE p.prokind WHEN 'p' THEN 'PROCEDURE' ELSE 'FUNCTION' END AS object_type, \
|
||||
@@ -2123,6 +2125,8 @@ mod tests {
|
||||
assert!(sql.contains("pg_xact_commit_timestamp"));
|
||||
assert!(sql.contains("'PROCEDURE'"));
|
||||
assert!(sql.contains("'FUNCTION'"));
|
||||
assert!(sql.contains("'SEQUENCE'"));
|
||||
assert!(sql.contains("'S'"));
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
||||
@@ -234,6 +234,7 @@ fn object_type_keyword(object_type: &ObjectSourceKind) -> &'static str {
|
||||
ObjectSourceKind::View => "VIEW",
|
||||
ObjectSourceKind::Procedure => "PROCEDURE",
|
||||
ObjectSourceKind::Function => "FUNCTION",
|
||||
ObjectSourceKind::Sequence => "SEQUENCE",
|
||||
ObjectSourceKind::Package => "PACKAGE",
|
||||
ObjectSourceKind::PackageBody => "PACKAGE BODY",
|
||||
}
|
||||
@@ -384,6 +385,8 @@ fn parse_object_source_kind(value: &str) -> Option<ObjectSourceKind> {
|
||||
Some(ObjectSourceKind::Procedure)
|
||||
} else if value.eq_ignore_ascii_case("FUNCTION") {
|
||||
Some(ObjectSourceKind::Function)
|
||||
} else if value.eq_ignore_ascii_case("SEQUENCE") {
|
||||
Some(ObjectSourceKind::Sequence)
|
||||
} else if value.eq_ignore_ascii_case("PACKAGE") {
|
||||
Some(ObjectSourceKind::Package)
|
||||
} else if value.eq_ignore_ascii_case("PACKAGE BODY") || value.eq_ignore_ascii_case("PACKAGE_BODY") {
|
||||
|
||||
@@ -1534,6 +1534,7 @@ fn sqlite_object_type(kind: &db::ObjectSourceKind) -> &'static str {
|
||||
db::ObjectSourceKind::View => "view",
|
||||
db::ObjectSourceKind::Procedure
|
||||
| db::ObjectSourceKind::Function
|
||||
| db::ObjectSourceKind::Sequence
|
||||
| db::ObjectSourceKind::Package
|
||||
| db::ObjectSourceKind::PackageBody => "routine",
|
||||
}
|
||||
@@ -1544,7 +1545,7 @@ fn sqlserver_object_type_filter(kind: &db::ObjectSourceKind) -> &'static str {
|
||||
db::ObjectSourceKind::View => "'V'",
|
||||
db::ObjectSourceKind::Procedure => "'P'",
|
||||
db::ObjectSourceKind::Function => "'FN','IF','TF','FS','FT'",
|
||||
db::ObjectSourceKind::Package | db::ObjectSourceKind::PackageBody => "''",
|
||||
db::ObjectSourceKind::Sequence | db::ObjectSourceKind::Package | db::ObjectSourceKind::PackageBody => "''",
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1586,6 +1587,30 @@ pub fn postgres_object_source_sql(schema: &str, name: &str, kind: &db::ObjectSou
|
||||
prokind
|
||||
)
|
||||
}
|
||||
db::ObjectSourceKind::Sequence => {
|
||||
format!(
|
||||
"SELECT concat_ws(E'\\n\\n', \
|
||||
'-- auto-generated definition' || E'\\n' || \
|
||||
'create sequence ' || quote_ident(c.relname) || E'\\n' || \
|
||||
' as ' || pg_catalog.format_type(s.seqtypid, NULL) || ';', \
|
||||
'alter sequence ' || quote_ident(c.relname) || ' owner to ' || quote_ident(pg_get_userbyid(c.relowner)) || ';', \
|
||||
CASE WHEN owned.relname IS NOT NULL AND a.attname IS NOT NULL \
|
||||
THEN 'alter sequence ' || quote_ident(c.relname) || ' owned by ' || quote_ident(owned.relname) || '.' || quote_ident(a.attname) || ';' \
|
||||
END \
|
||||
) \
|
||||
FROM pg_catalog.pg_class c \
|
||||
JOIN pg_catalog.pg_namespace n ON n.oid = c.relnamespace \
|
||||
JOIN pg_catalog.pg_sequence s ON s.seqrelid = c.oid \
|
||||
LEFT JOIN pg_catalog.pg_depend d \
|
||||
ON d.classid = 'pg_class'::regclass AND d.objid = c.oid AND d.deptype = 'a' \
|
||||
LEFT JOIN pg_catalog.pg_class owned ON owned.oid = d.refobjid \
|
||||
LEFT JOIN pg_catalog.pg_attribute a ON a.attrelid = d.refobjid AND a.attnum = d.refobjsubid \
|
||||
WHERE n.nspname = {} AND c.relname = {} AND c.relkind = 'S' \
|
||||
ORDER BY c.oid LIMIT 1",
|
||||
sql_string(schema),
|
||||
sql_string(name)
|
||||
)
|
||||
}
|
||||
db::ObjectSourceKind::Package | db::ObjectSourceKind::PackageBody => "SELECT NULL WHERE FALSE".to_string(),
|
||||
}
|
||||
}
|
||||
@@ -1595,6 +1620,7 @@ pub fn oracle_object_source_sql(schema: &str, name: &str, kind: &db::ObjectSourc
|
||||
db::ObjectSourceKind::View => "VIEW",
|
||||
db::ObjectSourceKind::Procedure => "PROCEDURE",
|
||||
db::ObjectSourceKind::Function => "FUNCTION",
|
||||
db::ObjectSourceKind::Sequence => "SEQUENCE",
|
||||
db::ObjectSourceKind::Package => "PACKAGE",
|
||||
db::ObjectSourceKind::PackageBody => "PACKAGE_BODY",
|
||||
};
|
||||
@@ -1623,7 +1649,9 @@ pub fn mysql_object_source_sql(name: &str, kind: &db::ObjectSourceKind) -> Strin
|
||||
db::ObjectSourceKind::View => format!("SHOW CREATE VIEW {}", mysql_ident(name)),
|
||||
db::ObjectSourceKind::Procedure => format!("SHOW CREATE PROCEDURE {}", mysql_ident(name)),
|
||||
db::ObjectSourceKind::Function => format!("SHOW CREATE FUNCTION {}", mysql_ident(name)),
|
||||
db::ObjectSourceKind::Package | db::ObjectSourceKind::PackageBody => String::new(),
|
||||
db::ObjectSourceKind::Sequence | db::ObjectSourceKind::Package | db::ObjectSourceKind::PackageBody => {
|
||||
String::new()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1883,6 +1911,25 @@ mod object_source_tests {
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn builds_postgres_object_source_sql_for_sequences() {
|
||||
let sql = postgres_object_source_sql("tenant's schema", "order id seq", &ObjectSourceKind::Sequence);
|
||||
|
||||
assert!(sql.contains("-- auto-generated definition"));
|
||||
assert!(sql.contains("create sequence"));
|
||||
assert!(sql.contains("alter sequence"));
|
||||
assert!(sql.contains("owner to"));
|
||||
assert!(sql.contains("owned by"));
|
||||
assert!(sql.contains("pg_catalog.pg_sequence"));
|
||||
assert!(sql.contains("n.nspname = 'tenant''s schema'"));
|
||||
assert!(sql.contains("c.relname = 'order id seq'"));
|
||||
assert!(sql.contains("c.relkind = 'S'"));
|
||||
assert!(!sql.contains("MINVALUE"));
|
||||
assert!(!sql.contains("START WITH"));
|
||||
assert!(!sql.contains("CACHE"));
|
||||
assert!(!sql.contains("NO CYCLE"));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn builds_postgres_view_source_sql_without_regclass_cast() {
|
||||
let sql = postgres_object_source_sql("tenant's schema", "active users", &ObjectSourceKind::View);
|
||||
|
||||
@@ -2960,7 +2960,9 @@ where
|
||||
rewrite_postgres_routine_schema(&object.source, &request.target_schema)
|
||||
.unwrap_or_else(|| object.source.clone())
|
||||
}
|
||||
db::ObjectSourceKind::Package | db::ObjectSourceKind::PackageBody => object.source.clone(),
|
||||
db::ObjectSourceKind::Sequence | db::ObjectSourceKind::Package | db::ObjectSourceKind::PackageBody => {
|
||||
object.source.clone()
|
||||
}
|
||||
};
|
||||
let statements = build_executable_object_source_statements(EditableObjectSourceSqlInput {
|
||||
database_type: DatabaseType::Postgres,
|
||||
|
||||
@@ -32,6 +32,7 @@ pub enum ObjectSourceKind {
|
||||
View,
|
||||
Procedure,
|
||||
Function,
|
||||
Sequence,
|
||||
Package,
|
||||
PackageBody,
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user