• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

getdozer / dozer / 5954012408

23 Aug 2023 04:32PM UTC coverage: 75.86% (-0.2%) from 76.088%
5954012408

push

github

web-flow
chore: Move ContractService implementation to Contract (#1899)

* chore: Split `build.rs` to several files

* chore: Remove `serde` from `dozer-cli/Cargo.toml`

* chore: Move `ContractService` implementation to `Contract`

461 of 461 new or added lines in 8 files covered. (100.0%)

46996 of 61951 relevant lines covered (75.86%)

73804.64 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

57.29
/dozer-cli/src/simple/build/contract/modify_schema.rs
1
use std::borrow::Cow;
2

3
use dozer_types::{
4
    models::api_endpoint::{
5
        ApiEndpoint, FullText, SecondaryIndex, SecondaryIndexConfig, SortedInverted,
6
    },
7
    types::{FieldDefinition, FieldType, IndexDefinition, Schema, SchemaWithIndex},
8
};
9

10
use crate::errors::BuildError;
11

12
pub fn modify_schema(
18✔
13
    schema: &Schema,
18✔
14
    api_endpoint: &ApiEndpoint,
18✔
15
) -> Result<SchemaWithIndex, BuildError> {
18✔
16
    let mut schema = schema.clone();
18✔
17
    // Generated Cache index based on api_index
18
    let configured_index = create_primary_indexes(
18✔
19
        &schema.fields,
18✔
20
        api_endpoint
18✔
21
            .index
18✔
22
            .as_ref()
18✔
23
            .map(|index| index.primary_key.as_slice()),
18✔
24
    )?;
18✔
25
    // Generated schema in SQL
26
    let upstream_index = schema.primary_index.clone();
18✔
27

28
    let index = match (configured_index.is_empty(), upstream_index.is_empty()) {
18✔
29
        (true, true) => vec![],
9✔
30
        (true, false) => upstream_index,
9✔
31
        (false, true) => configured_index,
×
32
        (false, false) => {
33
            if !upstream_index.eq(&configured_index) {
×
34
                return Err(BuildError::MismatchPrimaryKey {
×
35
                    endpoint_name: api_endpoint.name.clone(),
×
36
                    expected: get_field_names(&schema, &upstream_index),
×
37
                    actual: get_field_names(&schema, &configured_index),
×
38
                });
×
39
            }
×
40
            configured_index
×
41
        }
42
    };
43

44
    schema.primary_index = index;
18✔
45

18✔
46
    let secondary_index_config = get_secondary_index_config(api_endpoint);
18✔
47
    let secondary_indexes = generate_secondary_indexes(&schema.fields, &secondary_index_config)?;
18✔
48

49
    Ok((schema, secondary_indexes))
18✔
50
}
18✔
51

52
fn get_field_names(schema: &Schema, indexes: &[usize]) -> Vec<String> {
×
53
    indexes
×
54
        .iter()
×
55
        .map(|idx| schema.fields[*idx].name.to_owned())
×
56
        .collect()
×
57
}
×
58

59
fn get_secondary_index_config(api_endpoint: &ApiEndpoint) -> Cow<SecondaryIndexConfig> {
60
    if let Some(config) = api_endpoint
18✔
61
        .index
18✔
62
        .as_ref()
18✔
63
        .and_then(|index| index.secondary.as_ref())
18✔
64
    {
65
        Cow::Borrowed(config)
×
66
    } else {
67
        Cow::Owned(SecondaryIndexConfig::default())
18✔
68
    }
69
}
18✔
70

71
fn create_primary_indexes(
18✔
72
    field_definitions: &[FieldDefinition],
18✔
73
    primary_key: Option<&[String]>,
18✔
74
) -> Result<Vec<usize>, BuildError> {
18✔
75
    let mut primary_index = Vec::new();
18✔
76
    if let Some(primary_key) = primary_key {
18✔
77
        for name in primary_key {
×
78
            primary_index.push(field_index_from_field_name(field_definitions, name)?);
×
79
        }
80
    }
18✔
81
    Ok(primary_index)
18✔
82
}
18✔
83

84
fn generate_secondary_indexes(
18✔
85
    field_definitions: &[FieldDefinition],
18✔
86
    config: &SecondaryIndexConfig,
18✔
87
) -> Result<Vec<IndexDefinition>, BuildError> {
18✔
88
    let mut result = vec![];
18✔
89

90
    // Create default indexes unless skipped.
91
    for (index, field) in field_definitions.iter().enumerate() {
39✔
92
        if config.skip_default.contains(&field.name) {
39✔
93
            continue;
×
94
        }
39✔
95

39✔
96
        match field.typ {
39✔
97
            // Create sorted inverted indexes for these fields
98
            FieldType::UInt
99
            | FieldType::U128
100
            | FieldType::Int
101
            | FieldType::I128
102
            | FieldType::Float
103
            | FieldType::Boolean
104
            | FieldType::Decimal
105
            | FieldType::Timestamp
106
            | FieldType::Date
107
            | FieldType::Point
108
            | FieldType::Duration => result.push(IndexDefinition::SortedInverted(vec![index])),
27✔
109

110
            // Create sorted inverted and full text indexes for string fields.
111
            FieldType::String => {
12✔
112
                result.push(IndexDefinition::SortedInverted(vec![index]));
12✔
113
                result.push(IndexDefinition::FullText(index));
12✔
114
            }
12✔
115

116
            // Skip creating indexes
117
            FieldType::Text | FieldType::Binary | FieldType::Json => (),
×
118
        }
119
    }
120

121
    // Create requested indexes.
122
    for create in &config.create {
18✔
123
        if let Some(index) = &create.index {
×
124
            match index {
×
125
                SecondaryIndex::SortedInverted(SortedInverted { fields }) => {
×
126
                    let fields = fields
×
127
                        .iter()
×
128
                        .map(|field| field_index_from_field_name(field_definitions, field))
×
129
                        .collect::<Result<Vec<_>, _>>()?;
×
130
                    result.push(IndexDefinition::SortedInverted(fields));
×
131
                }
132
                SecondaryIndex::FullText(FullText { field }) => {
×
133
                    let field = field_index_from_field_name(field_definitions, field)?;
×
134
                    result.push(IndexDefinition::FullText(field));
×
135
                }
136
            }
137
        }
×
138
    }
139

140
    Ok(result)
18✔
141
}
18✔
142

143
fn field_index_from_field_name(
×
144
    fields: &[FieldDefinition],
×
145
    field_name: &str,
×
146
) -> Result<usize, BuildError> {
×
147
    fields
×
148
        .iter()
×
149
        .position(|field| field.name == field_name)
×
150
        .ok_or(BuildError::FieldNotFound(field_name.to_string()))
×
151
}
×
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc