1use serde::{Deserialize, Serialize};
4
5use crate::*;
6
7#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
8pub struct MigrationPreview {
9 pub preview: String,
10 pub ir_json: String,
11 pub redacted_ir_json: String,
12 pub normalized_sql: String,
13 pub parameter_types: Vec<DataTypeDescriptor>,
14 pub shape_fingerprint: String,
15}
16
17impl MigrationPreview {
18 pub fn from_builder(builder: &impl OrmBuilder) -> Result<Self, MigrationPreviewError> {
19 let document = builder.document()?;
20 let ir_json = document.to_json()?;
21 let redacted_ir_json = document.to_redacted_json()?;
22 let compiled = document.to_sql()?;
23 Ok(Self {
24 preview: "radixdb.orm.preview.v1".to_string(),
25 ir_json,
26 redacted_ir_json,
27 normalized_sql: compiled.sql,
28 parameter_types: compiled
29 .parameters
30 .iter()
31 .map(TypedValue::data_type)
32 .collect(),
33 shape_fingerprint: compiled.shape_fingerprint,
34 })
35 }
36
37 pub fn to_json(&self) -> Result<String, serde_json::Error> {
38 serde_json::to_string(self)
39 }
40}
41
42#[derive(Debug, thiserror::Error)]
43pub enum MigrationPreviewError {
44 #[error(transparent)]
45 Build(#[from] BuilderError),
46 #[error(transparent)]
47 Ir(#[from] IrError),
48 #[error(transparent)]
49 Render(#[from] RenderError),
50}
51
52#[cfg(test)]
53mod tests {
54 use super::*;
55
56 #[test]
57 fn preview_separates_redacted_values() {
58 let migration =
59 DdlBuilder::create_table("secrets").column(Column::text("token").default("do-not-log"));
60 let preview = MigrationPreview::from_builder(&migration).unwrap();
61 assert!(preview.ir_json.contains("do-not-log"));
62 assert!(!preview.redacted_ir_json.contains("do-not-log"));
63 assert!(!preview.normalized_sql.contains("do-not-log"));
64 assert_eq!(preview.parameter_types, vec![DataTypeDescriptor::Text]);
65 }
66}