use crate::types::describe::{FieldType, SObjectDescribe};
#[must_use]
pub fn generate_ddl(describe: &SObjectDescribe) -> String {
let mut ddl = String::with_capacity(1024);
write_ddl(&mut ddl, describe);
ddl
}
pub fn write_ddl(ddl: &mut String, describe: &SObjectDescribe) {
use std::fmt::Write;
let _ = writeln!(ddl, "CREATE TABLE {} (", describe.name);
let mut fields: Vec<&_> = describe.fields.iter().collect();
fields.sort_by(|a, b| crate::schema::cmp_field_names(&a.name, &b.name));
let mut first = true;
for field in fields {
if !first {
ddl.push_str(",\n");
}
first = false;
let _ = write!(ddl, " {} ", field.name);
write_field_type(ddl, &field.type_, field.length);
if field.name == "Id" {
ddl.push_str(" PRIMARY KEY");
} else if !field.nillable && !field.defaulted_on_create {
ddl.push_str(" NOT NULL");
}
}
ddl.push_str("\n);");
}
fn write_field_type(out: &mut String, field_type: &FieldType, length: i32) {
use std::fmt::Write;
match field_type {
FieldType::Id | FieldType::Reference => out.push_str("VARCHAR(18)"),
FieldType::String
| FieldType::Email
| FieldType::Phone
| FieldType::Url
| FieldType::Picklist
| FieldType::Multipicklist
| FieldType::Combobox => {
if length > 0 {
let _ = write!(out, "VARCHAR({})", length);
} else {
out.push_str("VARCHAR(255)");
}
}
FieldType::Boolean => out.push_str("BOOLEAN"),
FieldType::Int => out.push_str("INTEGER"),
FieldType::Double | FieldType::Currency | FieldType::Percent => {
out.push_str("DOUBLE PRECISION");
}
FieldType::Date => out.push_str("DATE"),
FieldType::Datetime => out.push_str("TIMESTAMP"),
FieldType::Time => out.push_str("TIME"),
_ => out.push_str("TEXT"), }
}
#[cfg(test)]
mod tests {
use super::*;
use crate::types::describe::FieldDescribe;
fn mock_field(
name: &str,
type_: FieldType,
length: i32,
nillable: bool,
defaulted: bool,
) -> FieldDescribe {
FieldDescribe {
aggregatable: true,
auto_number: false,
byte_length: length,
calculated: false,
calculated_formula: None,
cascade_delete: false,
case_sensitive: false,
compound_field_name: None,
controller_name: None,
createable: true,
custom: false,
default_value: None,
default_value_formula: None,
defaulted_on_create: defaulted,
dependent_picklist: false,
deprecated_and_hidden: false,
digits: 0,
display_location_in_decimal: false,
encrypted: false,
external_id: false,
extra_type_info: None,
filterable: true,
filtered_lookup_info: None,
formula_treat_blanks_as: None,
groupable: true,
high_scale_number: false,
html_formatted: false,
id_lookup: name == "Id",
inline_help_text: None,
label: name.to_string(),
length,
mask: None,
mask_type: None,
name: name.to_string(),
name_field: name == "Name",
name_pointing: false,
nillable,
permissionable: false,
picklist_values: None,
polymorphic_foreign_key: false,
precision: 0,
query_by_distance: false,
reference_target_field: None,
reference_to: vec![],
relationship_name: None,
relationship_order: None,
restricted_delete: false,
restricted_picklist: false,
scale: 0,
search_prefixes_supported: None,
soap_type: "xsd:string".to_string(),
sortable: true,
type_,
unique: false,
updateable: true,
write_requires_master_read: false,
}
}
#[test]
fn test_generate_ddl() {
let describe = SObjectDescribe {
activateable: false,
createable: true,
custom: false,
custom_setting: false,
deletable: true,
deprecated_and_hidden: false,
feed_enabled: false,
has_subtypes: false,
is_subtype: false,
key_prefix: Some("001".to_string()),
label: "Account".to_string(),
label_plural: "Accounts".to_string(),
layoutable: true,
mergeable: true,
mru_enabled: true,
name: "Account".to_string(),
queryable: true,
replicateable: true,
retrieveable: true,
searchable: true,
triggerable: true,
undeletable: true,
updateable: true,
urls: std::collections::HashMap::new(),
child_relationships: vec![],
record_type_infos: vec![],
fields: vec![
mock_field("Id", FieldType::Id, 18, false, true),
mock_field("Name", FieldType::String, 255, false, false),
mock_field("NumberOfEmployees", FieldType::Int, 0, true, false),
mock_field("AnnualRevenue", FieldType::Currency, 0, true, false),
mock_field("IsActive", FieldType::Boolean, 0, false, true),
],
};
let ddl = generate_ddl(&describe);
let expected = "CREATE TABLE Account (\n Id VARCHAR(18) PRIMARY KEY,\n AnnualRevenue DOUBLE PRECISION,\n IsActive BOOLEAN,\n Name VARCHAR(255) NOT NULL,\n NumberOfEmployees INTEGER\n);";
assert_eq!(ddl, expected);
}
}