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

vortex-data / vortex / 17008093231

16 Aug 2025 11:54AM UTC coverage: 87.913% (+0.06%) from 87.855%
17008093231

push

github

web-flow
fix(deps): update slf4j monorepo to v2.0.17 (patch) (#4258)

This PR contains the following updates:

| Package | Change | Age | Confidence |
|---|---|---|---|
| [org.slf4j:slf4j-api](http://www.slf4j.org)
([source](https://redirect.github.com/qos-ch/slf4j),
[changelog](https://www.slf4j.org/news.html)) | `2.0.9` -> `2.0.17` |
[![age](https://developer.mend.io/api/mc/badges/age/maven/org.slf4j:slf4j-api/2.0.17?slim=true)](https://docs.renovatebot.com/merge-confidence/)
|
[![confidence](https://developer.mend.io/api/mc/badges/confidence/maven/org.slf4j:slf4j-api/2.0.9/2.0.17?slim=true)](https://docs.renovatebot.com/merge-confidence/)
|
| [org.slf4j:slf4j-simple](http://www.slf4j.org)
([source](https://redirect.github.com/qos-ch/slf4j),
[changelog](https://www.slf4j.org/news.html)) | `2.0.9` -> `2.0.17` |
[![age](https://developer.mend.io/api/mc/badges/age/maven/org.slf4j:slf4j-simple/2.0.17?slim=true)](https://docs.renovatebot.com/merge-confidence/)
|
[![confidence](https://developer.mend.io/api/mc/badges/confidence/maven/org.slf4j:slf4j-simple/2.0.9/2.0.17?slim=true)](https://docs.renovatebot.com/merge-confidence/)
|

---

### Configuration

📅 **Schedule**: Branch creation - At any time (no schedule defined),
Automerge - At any time (no schedule defined).

🚦 **Automerge**: Enabled.

â™» **Rebasing**: Whenever PR becomes conflicted, or you tick the
rebase/retry checkbox.

🔕 **Ignore**: Close this PR and you won't be reminded about these
updates again.

---

- [ ] <!-- rebase-check -->If you want to rebase/retry this PR, check
this box

---

This PR was generated by [Mend Renovate](https://mend.io/renovate/).
View the [repository job
log](https://developer.mend.io/github/vortex-data/vortex).

<!--renovate-debug:eyJjcmVhdGVkSW5WZXIiOiI0MS43MS4xIiwidXBkYXRlZEluVmVyIjoiNDEuNzEuMSIsInRhcmdldEJyYW5jaCI6ImRldmVsb3AiLCJsYWJlbHMiOlsiY2hvcmUiXX0=-->

Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>

56580 of 64359 relevant lines covered (87.91%)

628739.98 hits per line

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

88.74
/vortex-expr/src/exprs/select.rs
1
// SPDX-License-Identifier: Apache-2.0
2
// SPDX-FileCopyrightText: Copyright the Vortex contributors
3

4
use std::fmt::Display;
5

6
use itertools::Itertools;
7
use vortex_array::{ArrayRef, DeserializeMetadata, IntoArray, ProstMetadata, ToCanonical};
8
use vortex_dtype::{DType, FieldNames};
9
use vortex_error::{VortexExpect, VortexResult, vortex_bail, vortex_err};
10
use vortex_proto::expr::select_opts::Opts;
11
use vortex_proto::expr::{FieldNames as ProtoFieldNames, SelectOpts};
12

13
use crate::field::DisplayFieldNames;
14
use crate::{AnalysisExpr, ExprEncodingRef, ExprId, ExprRef, IntoExpr, Scope, VTable, vtable};
15

16
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
17
pub enum SelectField {
18
    Include(FieldNames),
19
    Exclude(FieldNames),
20
}
21

22
vtable!(Select);
23

24
#[derive(Debug, Clone, Hash, Eq)]
25
#[allow(clippy::derived_hash_with_manual_eq)]
26
pub struct SelectExpr {
27
    fields: SelectField,
28
    child: ExprRef,
29
}
30

31
impl PartialEq for SelectExpr {
32
    fn eq(&self, other: &Self) -> bool {
3✔
33
        self.fields == other.fields && self.child.eq(&other.child)
3✔
34
    }
3✔
35
}
36

37
pub struct SelectExprEncoding;
38

39
impl VTable for SelectVTable {
40
    type Expr = SelectExpr;
41
    type Encoding = SelectExprEncoding;
42
    type Metadata = ProstMetadata<SelectOpts>;
43

44
    fn id(_encoding: &Self::Encoding) -> ExprId {
232✔
45
        ExprId::new_ref("select")
232✔
46
    }
232✔
47

48
    fn encoding(_expr: &Self::Expr) -> ExprEncodingRef {
2✔
49
        ExprEncodingRef::new_ref(SelectExprEncoding.as_ref())
2✔
50
    }
2✔
51

52
    fn metadata(expr: &Self::Expr) -> Option<Self::Metadata> {
2✔
53
        let names = expr
2✔
54
            .fields()
2✔
55
            .fields()
2✔
56
            .iter()
2✔
57
            .map(|f| f.to_string())
4✔
58
            .collect_vec();
2✔
59

60
        let opts = if expr.fields().is_include() {
2✔
61
            Opts::Include(ProtoFieldNames { names })
1✔
62
        } else {
63
            Opts::Exclude(ProtoFieldNames { names })
1✔
64
        };
65

66
        Some(ProstMetadata(SelectOpts { opts: Some(opts) }))
2✔
67
    }
2✔
68

69
    fn children(expr: &Self::Expr) -> Vec<&ExprRef> {
2,975✔
70
        vec![&expr.child]
2,975✔
71
    }
2,975✔
72

73
    fn with_children(expr: &Self::Expr, children: Vec<ExprRef>) -> VortexResult<Self::Expr> {
×
74
        Ok(SelectExpr {
×
75
            fields: expr.fields.clone(),
×
76
            child: children[0].clone(),
×
77
        })
×
78
    }
×
79

80
    fn build(
2✔
81
        _encoding: &Self::Encoding,
2✔
82
        metadata: &<Self::Metadata as DeserializeMetadata>::Output,
2✔
83
        mut children: Vec<ExprRef>,
2✔
84
    ) -> VortexResult<Self::Expr> {
2✔
85
        if children.len() != 1 {
2✔
86
            vortex_bail!("Select expression must have exactly one child");
×
87
        }
2✔
88

89
        let fields = match metadata.opts.as_ref() {
2✔
90
            Some(opts) => match opts {
2✔
91
                Opts::Include(field_names) => SelectField::Include(FieldNames::from_iter(
1✔
92
                    field_names.names.iter().map(|s| s.as_str()),
2✔
93
                )),
94
                Opts::Exclude(field_names) => SelectField::Exclude(FieldNames::from_iter(
1✔
95
                    field_names.names.iter().map(|s| s.as_str()),
2✔
96
                )),
97
            },
98
            None => {
99
                vortex_bail!("Select expressions must be provided with fields to select or exclude")
×
100
            }
101
        };
102

103
        let child = children
2✔
104
            .drain(..)
2✔
105
            .next()
2✔
106
            .vortex_expect("number of children validated to be one");
2✔
107

108
        Ok(SelectExpr { fields, child })
2✔
109
    }
2✔
110

111
    fn evaluate(expr: &Self::Expr, scope: &Scope) -> VortexResult<ArrayRef> {
2✔
112
        let batch = expr.child.unchecked_evaluate(scope)?.to_struct()?;
2✔
113
        Ok(match &expr.fields {
2✔
114
            SelectField::Include(f) => batch.project(f.as_ref()),
1✔
115
            SelectField::Exclude(names) => {
1✔
116
                let included_names = batch
1✔
117
                    .names()
1✔
118
                    .iter()
1✔
119
                    .filter(|&f| !names.as_ref().contains(f))
2✔
120
                    .cloned()
1✔
121
                    .collect::<Vec<_>>();
1✔
122
                batch.project(included_names.as_slice())
1✔
123
            }
124
        }?
×
125
        .into_array())
2✔
126
    }
2✔
127

128
    fn return_dtype(expr: &Self::Expr, scope: &DType) -> VortexResult<DType> {
68✔
129
        let child_dtype = expr.child.return_dtype(scope)?;
68✔
130
        let child_struct_dtype = child_dtype
68✔
131
            .as_struct()
68✔
132
            .ok_or_else(|| vortex_err!("Select child not a struct dtype"))?;
68✔
133

134
        let projected = match &expr.fields {
68✔
135
            SelectField::Include(fields) => child_struct_dtype.project(fields.as_ref())?,
65✔
136
            SelectField::Exclude(fields) => child_struct_dtype
3✔
137
                .names()
3✔
138
                .iter()
3✔
139
                .cloned()
3✔
140
                .zip_eq(child_struct_dtype.fields())
3✔
141
                .filter(|(name, _)| !fields.as_ref().contains(name))
12✔
142
                .collect(),
3✔
143
        };
144

145
        Ok(DType::Struct(projected, child_dtype.nullability()))
68✔
146
    }
68✔
147
}
148

149
/// Creates an expression that selects (includes) specific fields from an array.
150
///
151
/// Projects only the specified fields from the child expression, which must be of DType struct.
152
/// ```rust
153
/// # use vortex_expr::{select, root};
154
/// let expr = select(["name", "age"], root());
155
/// ```
156
pub fn select(fields: impl Into<FieldNames>, child: ExprRef) -> ExprRef {
770✔
157
    SelectExpr::include_expr(fields.into(), child)
770✔
158
}
770✔
159

160
/// Creates an expression that excludes specific fields from an array.
161
///
162
/// Projects all fields except the specified ones from the input struct expression.
163
///
164
/// ```rust
165
/// # use vortex_expr::{select_exclude, root};
166
/// let expr = select_exclude(["internal_id", "metadata"], root());
167
/// ```
168
pub fn select_exclude(fields: impl Into<FieldNames>, child: ExprRef) -> ExprRef {
5✔
169
    SelectExpr::exclude_expr(fields.into(), child)
5✔
170
}
5✔
171

172
impl SelectExpr {
173
    pub fn new(fields: SelectField, child: ExprRef) -> Self {
1,480✔
174
        Self { fields, child }
1,480✔
175
    }
1,480✔
176

177
    pub fn new_expr(fields: SelectField, child: ExprRef) -> ExprRef {
×
178
        Self::new(fields, child).into_expr()
×
179
    }
×
180

181
    pub fn include_expr(columns: FieldNames, child: ExprRef) -> ExprRef {
1,471✔
182
        Self::new(SelectField::Include(columns), child).into_expr()
1,471✔
183
    }
1,471✔
184

185
    pub fn exclude_expr(columns: FieldNames, child: ExprRef) -> ExprRef {
5✔
186
        Self::new(SelectField::Exclude(columns), child).into_expr()
5✔
187
    }
5✔
188

189
    pub fn fields(&self) -> &SelectField {
1,491✔
190
        &self.fields
1,491✔
191
    }
1,491✔
192

193
    pub fn child(&self) -> &ExprRef {
1,487✔
194
        &self.child
1,487✔
195
    }
1,487✔
196

197
    /// Turn the select expression into an `include`, relative to a provided array of field names.
198
    ///
199
    /// For example:
200
    /// ```rust
201
    /// # use vortex_expr::root;
202
    /// # use vortex_expr::{SelectExpr, SelectField};
203
    /// # use vortex_dtype::FieldNames;
204
    /// let field_names = FieldNames::from(["a", "b", "c"]);
205
    /// let include = SelectExpr::new(SelectField::Include(["a"].into()), root());
206
    /// let exclude = SelectExpr::new(SelectField::Exclude(["b", "c"].into()), root());
207
    /// assert_eq!(
208
    ///     &include.as_include(&field_names).unwrap(),
209
    ///     &exclude.as_include(&field_names).unwrap()
210
    /// );
211
    /// ```
212
    pub fn as_include(&self, field_names: &FieldNames) -> VortexResult<ExprRef> {
2✔
213
        Ok(Self::new(
2✔
214
            SelectField::Include(self.fields.as_include_names(field_names)?),
2✔
215
            self.child.clone(),
2✔
216
        )
217
        .into_expr())
2✔
218
    }
2✔
219
}
220

221
impl SelectField {
222
    pub fn include(columns: FieldNames) -> Self {
×
223
        assert_eq!(columns.iter().unique().collect_vec().len(), columns.len());
×
224
        Self::Include(columns)
×
225
    }
×
226

227
    pub fn exclude(columns: FieldNames) -> Self {
×
228
        assert_eq!(columns.iter().unique().collect_vec().len(), columns.len());
×
229
        Self::Exclude(columns)
×
230
    }
×
231

232
    pub fn is_include(&self) -> bool {
2✔
233
        matches!(self, Self::Include(_))
2✔
234
    }
2✔
235

236
    pub fn is_exclude(&self) -> bool {
×
237
        matches!(self, Self::Exclude(_))
×
238
    }
×
239

240
    pub fn fields(&self) -> &FieldNames {
1,491✔
241
        let (SelectField::Include(fields) | SelectField::Exclude(fields)) = self;
1,491✔
242

243
        fields
1,491✔
244
    }
1,491✔
245

246
    pub fn as_include_names(&self, field_names: &FieldNames) -> VortexResult<FieldNames> {
1,489✔
247
        if self
1,489✔
248
            .fields()
1,489✔
249
            .iter()
1,489✔
250
            .any(|f| !field_names.iter().contains(f))
3,283✔
251
        {
252
            vortex_bail!(
×
253
                "Field {:?} in select not in field names {:?}",
×
254
                self,
255
                field_names
256
            );
257
        }
1,489✔
258
        match self {
1,489✔
259
            SelectField::Include(fields) => Ok(fields.clone()),
1,488✔
260
            SelectField::Exclude(exc_fields) => Ok(field_names
1✔
261
                .iter()
1✔
262
                .filter(|f| !exc_fields.iter().contains(f))
3✔
263
                .cloned()
1✔
264
                .collect()),
1✔
265
        }
266
    }
1,489✔
267
}
268

269
impl Display for SelectField {
270
    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
3✔
271
        match self {
3✔
272
            SelectField::Include(fields) => write!(f, "{{{}}}", DisplayFieldNames(fields)),
2✔
273
            SelectField::Exclude(fields) => write!(f, "~{{{}}}", DisplayFieldNames(fields)),
1✔
274
        }
275
    }
3✔
276
}
277

278
impl Display for SelectExpr {
279
    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
3✔
280
        write!(f, "{}{}", self.child, self.fields)
3✔
281
    }
3✔
282
}
283

284
impl AnalysisExpr for SelectExpr {}
285

286
#[cfg(test)]
287
mod tests {
288

289
    use vortex_array::arrays::StructArray;
290
    use vortex_array::{IntoArray, ToCanonical};
291
    use vortex_buffer::buffer;
292
    use vortex_dtype::{DType, FieldName, FieldNames, Nullability};
293

294
    use crate::{Scope, SelectExpr, SelectField, root, select, select_exclude, test_harness};
295

296
    fn test_array() -> StructArray {
2✔
297
        StructArray::from_fields(&[
2✔
298
            ("a", buffer![0, 1, 2].into_array()),
2✔
299
            ("b", buffer![4, 5, 6].into_array()),
2✔
300
        ])
2✔
301
        .unwrap()
2✔
302
    }
2✔
303

304
    #[test]
305
    pub fn include_columns() {
1✔
306
        let st = test_array();
1✔
307
        let select = select(vec![FieldName::from("a")], root());
1✔
308
        let selected = select
1✔
309
            .evaluate(&Scope::new(st.to_array()))
1✔
310
            .unwrap()
1✔
311
            .to_struct()
1✔
312
            .unwrap();
1✔
313
        let selected_names = selected.names().clone();
1✔
314
        assert_eq!(selected_names.as_ref(), &["a".into()]);
1✔
315
    }
1✔
316

317
    #[test]
318
    pub fn exclude_columns() {
1✔
319
        let st = test_array();
1✔
320
        let select = select_exclude(vec![FieldName::from("a")], root());
1✔
321
        let selected = select
1✔
322
            .evaluate(&Scope::new(st.to_array()))
1✔
323
            .unwrap()
1✔
324
            .to_struct()
1✔
325
            .unwrap();
1✔
326
        let selected_names = selected.names().clone();
1✔
327
        assert_eq!(selected_names.as_ref(), &["b".into()]);
1✔
328
    }
1✔
329

330
    #[test]
331
    fn dtype() {
1✔
332
        let dtype = test_harness::struct_dtype();
1✔
333

334
        let select_expr = select(vec![FieldName::from("a")], root());
1✔
335
        let expected_dtype = DType::Struct(
1✔
336
            dtype.as_struct().unwrap().project(&["a".into()]).unwrap(),
1✔
337
            Nullability::NonNullable,
1✔
338
        );
1✔
339
        assert_eq!(select_expr.return_dtype(&dtype).unwrap(), expected_dtype);
1✔
340

341
        let select_expr_exclude = select_exclude(
1✔
342
            vec![
1✔
343
                FieldName::from("col1"),
1✔
344
                FieldName::from("col2"),
1✔
345
                FieldName::from("bool1"),
1✔
346
                FieldName::from("bool2"),
1✔
347
            ],
348
            root(),
1✔
349
        );
350
        assert_eq!(
1✔
351
            select_expr_exclude.return_dtype(&dtype).unwrap(),
1✔
352
            expected_dtype
353
        );
354

355
        let select_expr_exclude = select_exclude(
1✔
356
            vec![FieldName::from("col1"), FieldName::from("col2")],
1✔
357
            root(),
1✔
358
        );
359
        assert_eq!(
1✔
360
            select_expr_exclude.return_dtype(&dtype).unwrap(),
1✔
361
            DType::Struct(
1✔
362
                dtype
1✔
363
                    .as_struct()
1✔
364
                    .unwrap()
1✔
365
                    .project(&["a".into(), "bool1".into(), "bool2".into()])
1✔
366
                    .unwrap(),
1✔
367
                Nullability::NonNullable
1✔
368
            )
1✔
369
        );
370
    }
1✔
371

372
    #[test]
373
    fn test_as_include_names() {
1✔
374
        let field_names = FieldNames::from(["a", "b", "c"]);
1✔
375
        let include = SelectExpr::new(SelectField::Include(["a"].into()), root());
1✔
376
        let exclude = SelectExpr::new(SelectField::Exclude(["b", "c"].into()), root());
1✔
377
        assert_eq!(
1✔
378
            &include.as_include(&field_names).unwrap(),
1✔
379
            &exclude.as_include(&field_names).unwrap()
1✔
380
        );
381
    }
1✔
382
}
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