datafusion_common/
lib.rs

1// Licensed to the Apache Software Foundation (ASF) under one
2// or more contributor license agreements.  See the NOTICE file
3// distributed with this work for additional information
4// regarding copyright ownership.  The ASF licenses this file
5// to you under the Apache License, Version 2.0 (the
6// "License"); you may not use this file except in compliance
7// with the License.  You may obtain a copy of the License at
8//
9//   http://www.apache.org/licenses/LICENSE-2.0
10//
11// Unless required by applicable law or agreed to in writing,
12// software distributed under the License is distributed on an
13// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
14// KIND, either express or implied.  See the License for the
15// specific language governing permissions and limitations
16// under the License.
17
18#![doc(
19    html_logo_url = "https://raw.githubusercontent.com/apache/datafusion/19fe44cf2f30cbdd63d4a4f52c74055163c6cc38/docs/logos/standalone_logo/logo_original.svg",
20    html_favicon_url = "https://raw.githubusercontent.com/apache/datafusion/19fe44cf2f30cbdd63d4a4f52c74055163c6cc38/docs/logos/standalone_logo/logo_original.svg"
21)]
22#![cfg_attr(docsrs, feature(doc_auto_cfg))]
23// Make cheap clones clear: https://github.com/apache/datafusion/issues/11143
24#![deny(clippy::clone_on_ref_ptr)]
25
26mod column;
27mod dfschema;
28mod functional_dependencies;
29mod join_type;
30mod param_value;
31#[cfg(feature = "pyarrow")]
32mod pyarrow;
33mod schema_reference;
34mod table_reference;
35mod unnest;
36
37pub mod alias;
38pub mod cast;
39pub mod config;
40pub mod cse;
41pub mod diagnostic;
42pub mod display;
43pub mod error;
44pub mod file_options;
45pub mod format;
46pub mod hash_utils;
47pub mod instant;
48pub mod parsers;
49pub mod rounding;
50pub mod scalar;
51pub mod spans;
52pub mod stats;
53pub mod test_util;
54pub mod tree_node;
55pub mod types;
56pub mod utils;
57
58/// Reexport arrow crate
59pub use arrow;
60pub use column::Column;
61pub use dfschema::{
62    qualified_name, DFSchema, DFSchemaRef, ExprSchema, SchemaExt, ToDFSchema,
63};
64pub use diagnostic::Diagnostic;
65pub use error::{
66    field_not_found, unqualified_field_not_found, DataFusionError, Result, SchemaError,
67    SharedResult,
68};
69pub use file_options::file_type::{
70    GetExt, DEFAULT_ARROW_EXTENSION, DEFAULT_AVRO_EXTENSION, DEFAULT_CSV_EXTENSION,
71    DEFAULT_JSON_EXTENSION, DEFAULT_PARQUET_EXTENSION,
72};
73pub use functional_dependencies::{
74    aggregate_functional_dependencies, get_required_group_by_exprs_indices,
75    get_target_functional_dependencies, Constraint, Constraints, Dependency,
76    FunctionalDependence, FunctionalDependencies,
77};
78use hashbrown::hash_map::DefaultHashBuilder;
79pub use join_type::{JoinConstraint, JoinSide, JoinType};
80pub use param_value::ParamValues;
81pub use scalar::{ScalarType, ScalarValue};
82pub use schema_reference::SchemaReference;
83pub use spans::{Location, Span, Spans};
84pub use stats::{ColumnStatistics, Statistics};
85pub use table_reference::{ResolvedTableReference, TableReference};
86pub use unnest::{RecursionUnnestOption, UnnestOptions};
87pub use utils::project_schema;
88
89// These are hidden from docs purely to avoid polluting the public view of what this crate exports.
90// These are just re-exports of macros by the same name, which gets around the 'cannot refer to
91// macro-expanded macro_export macros by their full path' error.
92// The design to get around this comes from this comment:
93// https://github.com/rust-lang/rust/pull/52234#issuecomment-976702997
94#[doc(hidden)]
95pub use error::{
96    _config_datafusion_err, _exec_datafusion_err, _internal_datafusion_err,
97    _not_impl_datafusion_err, _plan_datafusion_err, _resources_datafusion_err,
98    _substrait_datafusion_err,
99};
100
101// The HashMap and HashSet implementations that should be used as the uniform defaults
102pub type HashMap<K, V, S = DefaultHashBuilder> = hashbrown::HashMap<K, V, S>;
103pub type HashSet<T, S = DefaultHashBuilder> = hashbrown::HashSet<T, S>;
104
105/// Downcast an Arrow Array to a concrete type, return an `DataFusionError::Internal` if the cast is
106/// not possible. In normal usage of DataFusion the downcast should always succeed.
107///
108/// Example: `let array = downcast_value!(values, Int32Array)`
109#[macro_export]
110macro_rules! downcast_value {
111    ($Value: expr, $Type: ident) => {{
112        use $crate::__private::DowncastArrayHelper;
113        $Value.downcast_array_helper::<$Type>()?
114    }};
115    ($Value: expr, $Type: ident, $T: tt) => {{
116        use $crate::__private::DowncastArrayHelper;
117        $Value.downcast_array_helper::<$Type<$T>>()?
118    }};
119}
120
121// Not public API.
122#[doc(hidden)]
123pub mod __private {
124    use crate::error::_internal_datafusion_err;
125    use crate::Result;
126    use arrow::array::Array;
127    use std::any::{type_name, Any};
128
129    #[doc(hidden)]
130    pub trait DowncastArrayHelper {
131        fn downcast_array_helper<U: Any>(&self) -> Result<&U>;
132    }
133
134    impl<T: Array + ?Sized> DowncastArrayHelper for T {
135        fn downcast_array_helper<U: Any>(&self) -> Result<&U> {
136            self.as_any().downcast_ref().ok_or_else(|| {
137                _internal_datafusion_err!(
138                    "could not cast array of type {} to {}",
139                    self.data_type(),
140                    type_name::<U>()
141                )
142            })
143        }
144    }
145}
146
147#[cfg(test)]
148mod tests {
149    use arrow::array::{ArrayRef, Int32Array, UInt64Array};
150    use std::any::{type_name, type_name_of_val};
151    use std::sync::Arc;
152
153    #[test]
154    fn test_downcast_value() -> crate::Result<()> {
155        let boxed: ArrayRef = Arc::new(Int32Array::from(vec![1, 2, 3]));
156        let array = downcast_value!(&boxed, Int32Array);
157        assert_eq!(type_name_of_val(&array), type_name::<&Int32Array>());
158
159        let expected: Int32Array = vec![1, 2, 3].into_iter().map(Some).collect();
160        assert_eq!(array, &expected);
161        Ok(())
162    }
163
164    #[test]
165    fn test_downcast_value_err_message() {
166        let boxed: ArrayRef = Arc::new(Int32Array::from(vec![1, 2, 3]));
167        let error: crate::DataFusionError = (|| {
168            downcast_value!(&boxed, UInt64Array);
169            Ok(())
170        })()
171        .err()
172        .unwrap();
173
174        assert_starts_with(
175            error.to_string(),
176            "Internal error: could not cast array of type Int32 to arrow_array::array::primitive_array::PrimitiveArray<arrow_array::types::UInt64Type>"
177        );
178    }
179
180    // `err.to_string()` depends on backtrace being present (may have backtrace appended)
181    // `err.strip_backtrace()` also depends on backtrace being present (may have "This was likely caused by ..." stripped)
182    fn assert_starts_with(actual: impl AsRef<str>, expected_prefix: impl AsRef<str>) {
183        let actual = actual.as_ref();
184        let expected_prefix = expected_prefix.as_ref();
185        assert!(
186            actual.starts_with(expected_prefix),
187            "Expected '{}' to start with '{}'",
188            actual,
189            expected_prefix
190        );
191    }
192}