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

gluesql / gluesql / 17021222400

17 Aug 2025 12:49PM UTC coverage: 97.834% (-0.2%) from 98.008%
17021222400

push

github

web-flow
Bump Rust toolchain to 1.88 (#1747)

Update format! macros to use direct variable interpolation instead of
positional arguments for improved readability and Rust 1.88 compliance.

- Fixed clippy warnings across core, cli, storages, and test packages
- Changed format!("{}", var) to format!("{var}") pattern
- Applied fixes consistently throughout the entire workspace
- Updated rust-toolchain.toml to use Rust 1.88

Signed-off-by: john <meenseek5929@naver.com>

92 of 122 new or added lines in 48 files covered. (75.41%)

60 existing lines in 20 files now uncovered.

37086 of 37907 relevant lines covered (97.83%)

127441.63 hits per line

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

97.76
/core/src/executor/insert.rs
1
use {
2
    super::{
3
        select::select,
4
        validate::{ColumnValidation, validate_unique},
5
    },
6
    crate::{
7
        ast::{ColumnDef, ColumnUniqueOption, Expr, ForeignKey, Query, SetExpr, Values},
8
        data::{Key, Row, Schema, Value},
9
        executor::{evaluate::evaluate_stateless, limit::Limit},
10
        result::Result,
11
        store::{DataRow, GStore, GStoreMut},
12
    },
13
    futures::stream::{self, StreamExt, TryStreamExt},
14
    serde::Serialize,
15
    std::{fmt::Debug, sync::Arc},
16
    thiserror::Error as ThisError,
17
};
18

19
#[derive(ThisError, Serialize, Debug, PartialEq, Eq)]
20
pub enum InsertError {
21
    #[error("table not found: {0}")]
22
    TableNotFound(String),
23

24
    #[error("lack of required column: {0}")]
25
    LackOfRequiredColumn(String),
26

27
    #[error("wrong column name: {0}")]
28
    WrongColumnName(String),
29

30
    #[error("column and values not matched")]
31
    ColumnAndValuesNotMatched,
32

33
    #[error("literals have more values than target columns")]
34
    TooManyValues,
35

36
    #[error("only single value accepted for schemaless row insert")]
37
    OnlySingleValueAcceptedForSchemalessRow,
38

39
    #[error("map type required: {0}")]
40
    MapTypeValueRequired(String),
41

42
    #[error(
43
        "cannot find referenced value on {table_name}.{column_name} with value {referenced_value:?}"
44
    )]
45
    CannotFindReferencedValue {
46
        table_name: String,
47
        column_name: String,
48
        referenced_value: String,
49
    },
50

51
    #[error("unreachable referencing column name: {0}")]
52
    ConflictReferencingColumnName(String),
53
}
54

55
enum RowsData {
56
    Append(Vec<DataRow>),
57
    Insert(Vec<(Key, DataRow)>),
58
}
59

60
pub async fn insert<T: GStore + GStoreMut>(
19,140✔
61
    storage: &mut T,
19,140✔
62
    table_name: &str,
19,140✔
63
    columns: &[String],
19,140✔
64
    source: &Query,
19,140✔
65
) -> Result<usize> {
19,140✔
66
    let Schema {
67
        column_defs,
19,084✔
68
        foreign_keys,
19,084✔
69
        ..
70
    } = storage
19,140✔
71
        .fetch_schema(table_name)
19,140✔
72
        .await?
19,140✔
73
        .ok_or_else(|| InsertError::TableNotFound(table_name.to_owned()))?;
19,140✔
74

75
    let rows = match column_defs {
19,084✔
76
        Some(column_defs) => {
18,312✔
77
            fetch_vec_rows(
18,312✔
78
                storage,
18,312✔
79
                table_name,
18,312✔
80
                column_defs,
18,312✔
81
                columns,
18,312✔
82
                source,
18,312✔
83
                foreign_keys,
18,312✔
84
            )
18,312✔
85
            .await
86
        }
87
        None => fetch_map_rows(storage, source).await.map(RowsData::Append),
772✔
88
    }?;
3,472✔
89

90
    match rows {
15,612✔
91
        RowsData::Append(rows) => {
13,624✔
92
            let num_rows = rows.len();
13,624✔
93

94
            storage
13,624✔
95
                .append_data(table_name, rows)
13,624✔
96
                .await
97
                .map(|_| num_rows)
13,624✔
98
        }
99
        RowsData::Insert(rows) => {
1,988✔
100
            let num_rows = rows.len();
1,988✔
101

102
            storage
1,988✔
103
                .insert_data(table_name, rows)
1,988✔
104
                .await
105
                .map(|_| num_rows)
1,988✔
106
        }
107
    }
108
}
19,140✔
109

110
async fn fetch_vec_rows<T: GStore>(
18,312✔
111
    storage: &T,
18,312✔
112
    table_name: &str,
18,312✔
113
    column_defs: Vec<ColumnDef>,
18,312✔
114
    columns: &[String],
18,312✔
115
    source: &Query,
18,312✔
116
    foreign_keys: Vec<ForeignKey>,
18,312✔
117
) -> Result<RowsData> {
18,312✔
118
    let labels = Arc::from(
18,312✔
119
        column_defs
18,312✔
120
            .iter()
18,312✔
121
            .map(|column_def| column_def.name.to_owned())
42,176✔
122
            .collect::<Vec<_>>(),
18,312✔
123
    );
124
    let column_defs = Arc::from(column_defs);
18,312✔
125
    let column_validation = ColumnValidation::All(&column_defs);
18,312✔
126

127
    #[derive(futures_enum::Stream)]
128
    enum Rows<I1, I2> {
129
        Values(I1),
130
        Select(I2),
131
    }
132

133
    let rows = match &source.body {
18,312✔
134
        SetExpr::Values(Values(values_list)) => {
17,808✔
135
            let limit = Limit::new(source.limit.as_ref(), source.offset.as_ref()).await?;
17,808✔
136
            let rows = stream::iter(values_list).then(|values| {
39,870✔
137
                let column_defs = Arc::clone(&column_defs);
39,870✔
138
                let labels = Arc::clone(&labels);
39,870✔
139

140
                async move {
39,870✔
141
                    Ok(Row::Vec {
142
                        columns: labels,
39,870✔
143
                        values: fill_values(&column_defs, columns, values).await?,
39,870✔
144
                    })
145
                }
39,870✔
146
            });
39,870✔
147
            let rows = limit.apply(rows);
17,808✔
148
            let rows = rows.map(|row| row?.try_into_vec());
39,702✔
149

150
            Rows::Values(rows)
17,808✔
151
        }
152
        SetExpr::Select(_) => {
153
            let rows = select(storage, source, None).await?.map(|row| {
1,568✔
154
                let values = row?.try_into_vec()?;
1,568✔
155

156
                column_defs
1,568✔
157
                    .iter()
1,568✔
158
                    .zip(values.iter())
1,568✔
159
                    .try_for_each(|(column_def, value)| {
3,360✔
160
                        let ColumnDef {
161
                            data_type,
3,360✔
162
                            nullable,
3,360✔
163
                            ..
164
                        } = column_def;
3,360✔
165

166
                        value.validate_type(data_type)?;
3,360✔
167
                        value.validate_null(*nullable)
3,304✔
168
                    })?;
3,360✔
169

170
                Ok(values)
1,456✔
171
            });
1,568✔
172

173
            Rows::Select(rows)
504✔
174
        }
175
    }
176
    .try_collect::<Vec<Vec<Value>>>()
18,312✔
177
    .await?;
18,312✔
178

179
    validate_unique(
15,680✔
180
        storage,
15,680✔
181
        table_name,
15,680✔
182
        column_validation,
15,680✔
183
        rows.iter().map(|values| values.as_slice()),
15,680✔
184
    )
185
    .await?;
15,680✔
186

187
    validate_foreign_key(storage, &column_defs, foreign_keys, &rows).await?;
15,232✔
188

189
    let primary_key = column_defs.iter().position(|ColumnDef { unique, .. }| {
32,916✔
190
        unique == &Some(ColumnUniqueOption { is_primary: true })
32,916✔
191
    });
32,916✔
192

193
    match primary_key {
15,176✔
194
        Some(i) => rows
1,988✔
195
            .into_iter()
1,988✔
196
            .filter_map(|values| {
3,832✔
197
                values
3,832✔
198
                    .get(i)
3,832✔
199
                    .map(Key::try_from)
3,832✔
200
                    .map(|result| result.map(|key| (key, values.into())))
3,832✔
201
            })
3,832✔
202
            .collect::<Result<Vec<_>>>()
1,988✔
203
            .map(RowsData::Insert),
1,988✔
204
        None => Ok(RowsData::Append(rows.into_iter().map(Into::into).collect())),
13,188✔
205
    }
206
}
18,312✔
207

208
async fn validate_foreign_key<T: GStore>(
15,232✔
209
    storage: &T,
15,232✔
210
    column_defs: &Arc<[ColumnDef]>,
15,232✔
211
    foreign_keys: Vec<ForeignKey>,
15,232✔
212
    rows: &[Vec<Value>],
15,232✔
213
) -> Result<()> {
15,232✔
214
    for foreign_key in foreign_keys {
15,456✔
215
        let ForeignKey {
216
            referencing_column_name,
280✔
217
            referenced_table_name,
280✔
218
            referenced_column_name,
280✔
219
            ..
220
        } = &foreign_key;
280✔
221

222
        let target_index = column_defs
280✔
223
            .iter()
280✔
224
            .enumerate()
280✔
225
            .find(|(_, c)| &c.name == referencing_column_name)
896✔
226
            .ok_or_else(|| {
280✔
227
                InsertError::ConflictReferencingColumnName(referencing_column_name.to_owned())
×
UNCOV
228
            })?;
×
229

230
        for row in rows.iter() {
280✔
231
            let value =
280✔
232
                row.get(target_index.0)
280✔
233
                    .ok_or(InsertError::ConflictReferencingColumnName(
280✔
234
                        referencing_column_name.to_owned(),
280✔
235
                    ))?;
280✔
236

237
            if value == &Value::Null {
280✔
238
                continue;
56✔
239
            }
224✔
240

241
            let no_referenced = storage
224✔
242
                .fetch_data(referenced_table_name, &Key::try_from(value)?)
224✔
243
                .await?
224✔
244
                .is_none();
224✔
245

246
            if no_referenced {
224✔
247
                return Err(InsertError::CannotFindReferencedValue {
56✔
248
                    table_name: referenced_table_name.to_owned(),
56✔
249
                    column_name: referenced_column_name.to_owned(),
56✔
250
                    referenced_value: String::from(value),
56✔
251
                }
56✔
252
                .into());
56✔
253
            }
168✔
254
        }
255
    }
256

257
    Ok(())
15,176✔
258
}
15,232✔
259

260
async fn fetch_map_rows<T: GStore>(storage: &T, source: &Query) -> Result<Vec<DataRow>> {
772✔
261
    #[derive(futures_enum::Stream)]
262
    enum Rows<I1, I2> {
263
        Values(I1),
264
        Select(I2),
265
    }
266

267
    let rows = match &source.body {
772✔
268
        SetExpr::Values(Values(values_list)) => {
660✔
269
            let limit = Limit::new(source.limit.as_ref(), source.offset.as_ref()).await?;
660✔
270
            let rows = stream::iter(values_list).then(|values| async move {
1,032✔
271
                if values.len() > 1 {
1,032✔
272
                    return Err(InsertError::OnlySingleValueAcceptedForSchemalessRow.into());
56✔
273
                }
976✔
274

275
                evaluate_stateless(None, &values[0])
976✔
276
                    .await?
976✔
277
                    .try_into()
976✔
278
                    .map(Row::Map)
976✔
279
            });
2,064✔
280
            let rows = limit.apply(rows);
660✔
281
            let rows = rows.map_ok(Into::into);
660✔
282

283
            Rows::Values(rows)
660✔
284
        }
285
        SetExpr::Select(_) => {
286
            let rows = select(storage, source, None).await?.map(|row| {
112✔
287
                let row = row?;
112✔
288

289
                if let Row::Vec { values, .. } = &row {
112✔
290
                    if values.len() > 1 {
112✔
291
                        return Err(InsertError::OnlySingleValueAcceptedForSchemalessRow.into());
56✔
292
                    } else if !matches!(&values[0], Value::Map(_)) {
56✔
293
                        return Err(InsertError::MapTypeValueRequired((&values[0]).into()).into());
56✔
294
                    }
×
295
                }
×
296

297
                Ok(row.into())
×
298
            });
112✔
299

300
            Rows::Select(rows)
112✔
301
        }
302
    }
303
    .try_collect::<Vec<DataRow>>()
772✔
304
    .await?;
772✔
305

306
    Ok(rows)
436✔
307
}
772✔
308

309
async fn fill_values(
1,378,820✔
310
    column_defs: &[ColumnDef],
1,378,820✔
311
    columns: &[String],
1,378,820✔
312
    values: &[Expr],
1,378,820✔
313
) -> Result<Vec<Value>> {
1,398,240✔
314
    if !columns.is_empty() && values.len() != columns.len() {
39,870✔
315
        return Err(InsertError::ColumnAndValuesNotMatched.into());
56✔
316
    } else if values.len() > column_defs.len() {
39,814✔
317
        return Err(InsertError::TooManyValues.into());
56✔
318
    }
39,758✔
319

320
    if let Some(wrong_column_name) = columns.iter().find(|column_name| {
46,946✔
321
        !column_defs
45,332✔
322
            .iter()
45,332✔
323
            .any(|column_def| &&column_def.name == column_name)
94,640✔
324
    }) {
45,332✔
325
        return Err(InsertError::WrongColumnName(wrong_column_name.to_owned()).into());
56✔
326
    }
39,702✔
327

328
    #[derive(iter_enum::Iterator)]
329
    enum Columns<I1, I2> {
330
        All(I1),
331
        Specified(I2),
332
    }
333

334
    let columns = if columns.is_empty() {
39,702✔
335
        Columns::All(column_defs.iter().map(|ColumnDef { name, .. }| name))
23,778✔
336
    } else {
337
        Columns::Specified(columns.iter())
15,924✔
338
    };
339

340
    let column_name_value_list = columns.zip(values.iter()).collect::<Vec<(_, _)>>();
39,702✔
341

342
    let values = stream::iter(column_defs)
39,702✔
343
        .then(|column_def| {
93,518✔
344
            let column_name_value_list = &column_name_value_list;
93,518✔
345

346
            async move {
93,518✔
347
                let ColumnDef {
348
                    name: def_name,
93,518✔
349
                    data_type,
93,518✔
350
                    nullable,
93,518✔
351
                    ..
352
                } = column_def;
93,518✔
353

354
                let value = column_name_value_list
93,518✔
355
                    .iter()
93,518✔
356
                    .find(|(name, _)| name == &def_name)
182,286✔
357
                    .map(|(_, value)| value);
93,518✔
358

359
                match (value, &column_def.default, nullable) {
93,518✔
360
                    (Some(&expr), _, _) | (None, Some(expr), _) => evaluate_stateless(None, expr)
93,014✔
361
                        .await?
93,014✔
362
                        .try_into_value(data_type, *nullable),
92,790✔
363
                    (None, None, true) => Ok(Value::Null),
392✔
364
                    (None, None, false) => {
365
                        Err(InsertError::LackOfRequiredColumn(def_name.to_owned()).into())
112✔
366
                    }
367
                }
368
            }
93,518✔
369
        })
93,518✔
370
        .try_collect::<Vec<Value>>()
39,702✔
371
        .await?;
39,702✔
372

373
    Ok(values)
37,350✔
374
}
39,870✔
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE TRIAL · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc