use crate::types::describe::{FieldType, SObjectDescribe};
const CUSTOM_FIELD_LIMIT: usize = 500; const RELATIONSHIP_FIELD_LIMIT: usize = 40; const WARNING_THRESHOLD_PERCENT: f64 = 0.8;
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct SchemaLimitInsights {
pub custom_fields: usize,
pub relationship_fields: usize,
pub rollup_summary_fields: usize,
pub approaching_custom_field_limit: bool,
pub approaching_relationship_limit: bool,
}
#[must_use]
pub fn analyze_schema_limits(describe: &SObjectDescribe) -> SchemaLimitInsights {
let mut custom_fields = 0;
let mut relationship_fields = 0;
for field in &describe.fields {
if field.custom {
custom_fields += 1;
}
if matches!(field.type_, FieldType::Reference) {
relationship_fields += 1;
}
}
let approaching_custom_field_limit =
(custom_fields as f64) >= (CUSTOM_FIELD_LIMIT as f64 * WARNING_THRESHOLD_PERCENT);
let approaching_relationship_limit = (relationship_fields as f64)
>= (RELATIONSHIP_FIELD_LIMIT as f64 * WARNING_THRESHOLD_PERCENT);
SchemaLimitInsights {
custom_fields,
relationship_fields,
rollup_summary_fields: 0, approaching_custom_field_limit,
approaching_relationship_limit,
}
}
#[cfg(test)]
mod tests {
use super::*;
use crate::test_utils::must::Must;
use serde_json::json;
fn create_mock_describe(fields_json: &serde_json::Value) -> SObjectDescribe {
let describe_json = json!({
"name": "Account",
"label": "Account",
"custom": false,
"queryable": true,
"activateable": false, "createable": true, "customSetting": false, "deletable": true,
"deprecatedAndHidden": false, "feedEnabled": true, "hasSubtypes": false,
"isSubtype": false, "keyPrefix": "001", "labelPlural": "Accounts", "layoutable": true,
"mergeable": true, "mruEnabled": true, "replicateable": true, "retrieveable": true,
"searchable": true, "triggerable": true, "undeletable": true, "updateable": true,
"urls": {}, "childRelationships": [], "recordTypeInfos": [],
"fields": fields_json
});
serde_json::from_value(describe_json).must()
}
#[allow(clippy::fn_params_excessive_bools)]
fn mock_field(name: &str, field_type: &str, custom: bool) -> serde_json::Value {
json!({
"name": name,
"type": field_type,
"label": format!("{} Label", name),
"referenceTo": if field_type == "reference" { vec!["Account"] } else { vec![] },
"custom": custom,
"nillable": true,
"defaultedOnCreate": false,
"calculated": false,
"createable": true, "autoNumber": false, "aggregatable": true, "byteLength": 18,
"cascadeDelete": false, "caseSensitive": false,
"dependentPicklist": false, "deprecatedAndHidden": false,
"digits": 0, "displayLocationInDecimal": false, "encrypted": false, "externalId": false,
"filterable": true, "groupable": true, "highScaleNumber": false, "htmlFormatted": false,
"idLookup": true, "length": 18, "nameField": false, "namePointing": false,
"permissionable": false, "polymorphicForeignKey": false, "precision": 0, "queryByDistance": false,
"restrictedDelete": false, "restrictedPicklist": false, "scale": 0, "soapType": "tns:ID",
"sortable": true, "unique": false, "updateable": false, "writeRequiresMasterRead": false
})
}
#[test]
fn test_analyze_schema_limits_safe() {
let describe = create_mock_describe(&json!([
mock_field("Id", "id", false),
mock_field("Name", "string", false),
mock_field("Custom1__c", "string", true),
mock_field("Rel1__c", "reference", true)
]));
let limits = analyze_schema_limits(&describe);
assert_eq!(limits.custom_fields, 2);
assert_eq!(limits.relationship_fields, 1);
assert!(!limits.approaching_custom_field_limit);
assert!(!limits.approaching_relationship_limit);
}
#[test]
fn test_analyze_schema_limits_approaching_custom_limit() {
let mut fields = Vec::new();
for i in 0..400 {
fields.push(mock_field(&format!("Custom{}__c", i), "string", true));
}
let describe = create_mock_describe(&serde_json::Value::Array(fields));
let limits = analyze_schema_limits(&describe);
assert_eq!(limits.custom_fields, 400);
assert!(limits.approaching_custom_field_limit);
assert!(!limits.approaching_relationship_limit);
}
#[test]
fn test_analyze_schema_limits_approaching_relationship_limit() {
let mut fields = Vec::new();
for i in 0..32 {
fields.push(mock_field(&format!("Rel{}__c", i), "reference", true));
}
let describe = create_mock_describe(&serde_json::Value::Array(fields));
let limits = analyze_schema_limits(&describe);
assert_eq!(limits.relationship_fields, 32);
assert!(limits.approaching_relationship_limit);
assert!(!limits.approaching_custom_field_limit);
}
}