Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Benoit/eng-362-update-ndc-postgres-to-ndc_models-020 #666

Open
wants to merge 44 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
44 commits
Select commit Hold shift + click to select a range
c1a0017
Update to ndc-models 0.2.0
BenoitRanque Dec 25, 2024
f4c4495
scalar type representation is no longer optional. If the configuratio…
BenoitRanque Dec 25, 2024
91e9047
We assume we don't support any capability we did not previously support.
BenoitRanque Dec 25, 2024
d206136
Foreign Keys moved from collections to object types.
BenoitRanque Dec 25, 2024
25b96a7
Count aggregates now take an expression instead of a column reference…
BenoitRanque Dec 25, 2024
96985b5
remove todo
BenoitRanque Dec 25, 2024
8f5f678
remove todo, jandle a couple additional cases as errors/unsupported
BenoitRanque Dec 25, 2024
0be15c4
add additional error types
BenoitRanque Dec 25, 2024
47245b8
add test for aggregate of nested field
BenoitRanque Dec 25, 2024
3131257
relationship mapping now have an array on the right-hand side, so for…
BenoitRanque Dec 25, 2024
7277f34
scalar type no longer optional
BenoitRanque Dec 25, 2024
8dc0211
nested field collection not supported, add error handling
BenoitRanque Dec 25, 2024
16e32fe
update filtering, aggregates, sorting, to 0.2.0
BenoitRanque Dec 25, 2024
a87ffc9
add schema files for configurations, mutations, queries
BenoitRanque Dec 25, 2024
1a1c0ce
Update translation test configurations to v5
BenoitRanque Dec 25, 2024
08612c1
add reference to query/mutation request schema json
BenoitRanque Dec 25, 2024
3740a0e
right hand side of relationship column mapping is now an array
BenoitRanque Dec 25, 2024
4b2d373
update aggregate expresion
BenoitRanque Dec 25, 2024
3694e96
use exists instead of left-hand side path
BenoitRanque Dec 25, 2024
9c4c662
update root_collection_column test to use scopes instead
BenoitRanque Dec 25, 2024
6ea5b3a
Correct sorting behavior. We use CCUNT("col") for CountStar to count …
BenoitRanque Dec 25, 2024
e947d61
use exists instead of left-hand side path
BenoitRanque Dec 31, 2024
bea5ab4
v0.2.0 schema update
BenoitRanque Dec 31, 2024
bc4138b
use exists instead of left-handed path
BenoitRanque Dec 31, 2024
67595f0
add reference to query/mutation request schema in test request files
BenoitRanque Dec 31, 2024
0598a2f
right-hand side of relationship column mapping is now an array
BenoitRanque Jan 1, 2025
14cad36
use exists instead of left-hand side path
BenoitRanque Jan 1, 2025
cf47f9c
aggregates have changed
BenoitRanque Jan 1, 2025
a874165
comparison target columns have been simplified
BenoitRanque Jan 1, 2025
0bfd425
root column comparison now replaced with scopes
BenoitRanque Jan 1, 2025
46f4ab9
update tests to new sdk
BenoitRanque Jan 1, 2025
a77fbf6
add manually triggered tests to generate schema files for test file v…
BenoitRanque Jan 1, 2025
d56fb32
remove debug print statement
BenoitRanque Jan 2, 2025
7ed4cb6
Fix aggregates for 0.2.0
BenoitRanque Jan 4, 2025
80f187e
fix: sums that return int8 should be marked with the meaning field
BenoitRanque Jan 6, 2025
dc70526
We'll need to implement filtering by aggregates later
BenoitRanque Jan 8, 2025
cb3cce7
add standard comparison operators, make no changes to defaults
BenoitRanque Jan 16, 2025
3102706
schema snapshots updated to reflect changes in sum aggregates defini…
BenoitRanque Jan 16, 2025
67d8de6
Replace RootAndCurrentTables with TableScope, which keeps track of an…
BenoitRanque Jan 16, 2025
829886f
change default introspection settings to include meaning for gt(e),lt…
BenoitRanque Jan 16, 2025
15fa6df
update Cargo.lock
BenoitRanque Jan 16, 2025
64b6ef9
update benchmark ndc request
BenoitRanque Jan 20, 2025
eed2de8
make prettier happy
BenoitRanque Jan 20, 2025
c51323e
Merge branch 'main' into benoit/eng-362-update-ndc-postgres-to-ndc_mo…
danieljharvey Jan 24, 2025
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
376 changes: 320 additions & 56 deletions Cargo.lock

Large diffs are not rendered by default.

13 changes: 8 additions & 5 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -31,9 +31,9 @@ similar_names = "allow"
too_many_lines = "allow"

[workspace.dependencies]
ndc-models = { git = "https://github.com/hasura/ndc-spec.git", tag = "v0.1.6" }
ndc-sdk = { git = "https://github.com/hasura/ndc-sdk-rs.git", tag = "v0.4.0" }
ndc-test = { git = "https://github.com/hasura/ndc-spec.git", tag = "v0.1.6" }
ndc-models = { git = "https://github.com/hasura/ndc-spec.git", tag = "v0.2.0-rc.2" }
ndc-sdk = { git = "https://github.com/hasura/ndc-sdk-rs.git", rev = "643b96b" }
danieljharvey marked this conversation as resolved.
Show resolved Hide resolved
ndc-test = { git = "https://github.com/hasura/ndc-spec.git", tag = "v0.2.0-rc.2" }

anyhow = "1"
async-trait = "0.1"
Expand All @@ -53,15 +53,18 @@ nonempty = "0.10"
percent-encoding = "2"
prometheus = "0.13"
ref-cast = "1"
reqwest = "0.11"
reqwest = "0.12"
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can we bump this separately before the PR goes in? Good not to mix up functional and non-functional changes.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No. ndc-test needs to be updated alongside ndc-models and ndc-sdk, and it uses reqwest 12, which is the reason for this change.

schemars = "0.8"
serde = "1"
serde_json = "1"
serde_yaml = "0.9"
similar-asserts = "1"
smol_str = "0.1"
sqlformat = "0.2"
sqlx = { version = "0.8", default-features = false, features = ["postgres", "derive"] }
sqlx = { version = "0.8", default-features = false, features = [
"postgres",
"derive",
] }
tempfile = "3"
test-each = "0.2"
thiserror = "1"
Expand Down
2 changes: 1 addition & 1 deletion benchmarks/component/benchmarks/select-order-by.js
Original file line number Diff line number Diff line change
Expand Up @@ -84,7 +84,7 @@ const data = {
collection_relationships: {
TrackAlbum: {
column_mapping: {
AlbumId: "AlbumId",
AlbumId: ["AlbumId"],
},
relationship_type: "object",
source_collection_or_type: "Track",
Expand Down
8 changes: 4 additions & 4 deletions crates/configuration/src/version3/comparison.rs
Original file line number Diff line number Diff line change
Expand Up @@ -29,22 +29,22 @@ impl ComparisonOperatorMapping {
ComparisonOperatorMapping {
operator_name: "<=".to_string(),
exposed_name: "_lte".to_string(),
operator_kind: OperatorKind::Custom,
operator_kind: OperatorKind::LessThanOrEqual,
},
ComparisonOperatorMapping {
operator_name: ">".to_string(),
exposed_name: "_gt".to_string(),
operator_kind: OperatorKind::Custom,
operator_kind: OperatorKind::GreaterThan,
},
ComparisonOperatorMapping {
operator_name: ">=".to_string(),
exposed_name: "_gte".to_string(),
operator_kind: OperatorKind::Custom,
operator_kind: OperatorKind::GreaterThanOrEqual,
},
ComparisonOperatorMapping {
operator_name: "<".to_string(),
exposed_name: "_lt".to_string(),
operator_kind: OperatorKind::Custom,
operator_kind: OperatorKind::LessThan,
},
ComparisonOperatorMapping {
operator_name: "<>".to_string(),
Expand Down
4 changes: 4 additions & 0 deletions crates/configuration/src/version3/metadata/database.rs
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,10 @@ pub struct ComparisonOperator {
pub enum OperatorKind {
Equal,
In,
LessThan,
LessThanOrEqual,
GreaterThan,
GreaterThanOrEqual,
Custom,
}

Expand Down
48 changes: 46 additions & 2 deletions crates/configuration/src/version3/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ pub mod connection_settings;
pub mod metadata;
pub(crate) mod options;

use ndc_models::{self as models, CollectionName, TypeName};
use ndc_models::{self as models, CollectionName, ScalarTypeName, TypeName};
use std::borrow::Cow;
use std::collections::{BTreeMap, BTreeSet, HashSet};
use std::path::Path;
Expand Down Expand Up @@ -714,14 +714,48 @@ fn convert_scalar_types(
.cloned()
.unwrap_or(BTreeMap::new()),

type_representation: representations.0.get(&t).cloned(),
type_representation: convert_or_infer_type_representation(
representations.0.get(&t).cloned(),
&t,
),
},
)
})
.collect(),
)
}

/// Infer scalar type representation from scalar type name, if necessary. Defaults to JSON representation
fn convert_or_infer_type_representation(
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

V0.2.0 requires type representation, but configuration did not require configuration to be present.

To maximize compatibility with older configuration versions, we infer missing type representations based on scalar type name. If missing, we default to JSON representation.

representation: Option<query_engine_metadata::metadata::TypeRepresentation>,
scalar_type_name: &ScalarTypeName,
) -> query_engine_metadata::metadata::TypeRepresentation {
if let Some(representation) = representation {
representation
} else {
match scalar_type_name.as_str() {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We already have the default_base_type_representations to do this mapping from scalar type name to TypeRepresentation. If this function adds any more mappings we should add them there rather than adding a new layer of indirection. The idea that whatever mappings are in the configuration are what will be returned in the schema is a useful property for understanding all this, and we would need a compelling reason to remove that property.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

v0.2 requires type representation in schema responses, however type representation is optional in the configuration itself.

So this is a piece of backwards compatiblity code, to allow for configurations that are missing type representation.

We could instead create configuration v6, and refuse to run with older configuration versions.

As for the use of default_base_type_representations: this mapping only exists for configurations v4 and v5. Here in v3 we replicate that functionality instead.
I prefered copying the code but keeping the different modules separate.

And yes it's a bit cheaty: we have a default when creating a new config, and reuse that default when type representation is missing.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's probably best to leave version 3 configs doing whatever they were before, ie falling back to JSON where they have no TypeRepresentation, or where they used the deprecated Number or Integer types.

Also, there is no need for a version 6, it looks like we were already making any mention of Number and Integer fallback to JSON before this PR, and since we have our own type exposed in the config type, we won't be removing any items and thus making any breaking changes.

Copy link
Contributor Author

@BenoitRanque BenoitRanque Jan 30, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Defaulting to JSON is a behavior change. Representation was optional in both configuration and schema response, so we just returned it as-is.

This applies to configurations 3,4,5

Confirm we'd rather default to JSON if representation missing, without first trying to infer based on type name?

"bit" => query_engine_metadata::metadata::TypeRepresentation::String,
"bool" => query_engine_metadata::metadata::TypeRepresentation::Boolean,
"bpchar" | "char" | "varchar" | "text" => {
query_engine_metadata::metadata::TypeRepresentation::String
}
"date" => query_engine_metadata::metadata::TypeRepresentation::Date,
"float4" => query_engine_metadata::metadata::TypeRepresentation::Float32,
"float8" => query_engine_metadata::metadata::TypeRepresentation::Float64,
"int2" => query_engine_metadata::metadata::TypeRepresentation::Int16,
"int4" => query_engine_metadata::metadata::TypeRepresentation::Int32,
"int8" => query_engine_metadata::metadata::TypeRepresentation::Int64AsString,
"numeric" => query_engine_metadata::metadata::TypeRepresentation::BigDecimalAsString,
"time" => query_engine_metadata::metadata::TypeRepresentation::Time,
"timestamp" => query_engine_metadata::metadata::TypeRepresentation::Timestamp,
"timestamptz" => query_engine_metadata::metadata::TypeRepresentation::Timestamptz,
"timetz" => query_engine_metadata::metadata::TypeRepresentation::Timetz,
"uuid" => query_engine_metadata::metadata::TypeRepresentation::UUID,
_ => query_engine_metadata::metadata::TypeRepresentation::Json,
}
}
}

fn convert_aggregate_functions(
aggregate_functions: metadata::AggregateFunctions,
) -> BTreeMap<
Expand Down Expand Up @@ -1020,6 +1054,16 @@ fn convert_operator_kind(
match operator_kind {
metadata::OperatorKind::Equal => query_engine_metadata::metadata::OperatorKind::Equal,
metadata::OperatorKind::In => query_engine_metadata::metadata::OperatorKind::In,
metadata::OperatorKind::LessThan => query_engine_metadata::metadata::OperatorKind::LessThan,
danieljharvey marked this conversation as resolved.
Show resolved Hide resolved
metadata::OperatorKind::LessThanOrEqual => {
query_engine_metadata::metadata::OperatorKind::LessThanOrEqual
}
metadata::OperatorKind::GreaterThan => {
query_engine_metadata::metadata::OperatorKind::GreaterThan
}
metadata::OperatorKind::GreaterThanOrEqual => {
query_engine_metadata::metadata::OperatorKind::GreaterThanOrEqual
}
metadata::OperatorKind::Custom => query_engine_metadata::metadata::OperatorKind::Custom,
}
}
Expand Down
8 changes: 4 additions & 4 deletions crates/configuration/src/version4/comparison.rs
Original file line number Diff line number Diff line change
Expand Up @@ -29,22 +29,22 @@ impl ComparisonOperatorMapping {
ComparisonOperatorMapping {
operator_name: "<=".to_string(),
exposed_name: "_lte".to_string(),
operator_kind: OperatorKind::Custom,
operator_kind: OperatorKind::LessThanOrEqual,
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Default introspection configuration changed to tag lt(e),gt(e) operators.

This will only affect new configurations, so any deployments with existing configuration will see no change in behavior.

},
ComparisonOperatorMapping {
operator_name: ">".to_string(),
exposed_name: "_gt".to_string(),
operator_kind: OperatorKind::Custom,
operator_kind: OperatorKind::GreaterThan,
},
ComparisonOperatorMapping {
operator_name: ">=".to_string(),
exposed_name: "_gte".to_string(),
operator_kind: OperatorKind::Custom,
operator_kind: OperatorKind::GreaterThanOrEqual,
},
ComparisonOperatorMapping {
operator_name: "<".to_string(),
exposed_name: "_lt".to_string(),
operator_kind: OperatorKind::Custom,
operator_kind: OperatorKind::LessThan,
},
ComparisonOperatorMapping {
operator_name: "<>".to_string(),
Expand Down
4 changes: 4 additions & 0 deletions crates/configuration/src/version4/metadata/database.rs
Original file line number Diff line number Diff line change
Expand Up @@ -79,6 +79,10 @@ pub struct ComparisonOperator {
pub enum OperatorKind {
Equal,
In,
LessThan,
LessThanOrEqual,
GreaterThan,
GreaterThanOrEqual,
Custom,
}

Expand Down
40 changes: 36 additions & 4 deletions crates/configuration/src/version4/to_runtime_configuration.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,10 @@

use std::collections::BTreeMap;

use ndc_models::ScalarTypeName;

use super::metadata;
use super::options::IntrospectionOptions;
use super::ParsedConfiguration;
use crate::environment::Environment;
use crate::error::MakeRuntimeConfigurationError;
Expand Down Expand Up @@ -58,7 +61,7 @@ fn convert_scalar_types(
.into_iter()
.map(|(scalar_type_name, scalar_type)| {
(
scalar_type_name,
scalar_type_name.clone(),
query_engine_metadata::metadata::ScalarType {
type_name: scalar_type.type_name,
schema_name: Some(scalar_type.schema_name),
Expand All @@ -73,16 +76,35 @@ fn convert_scalar_types(
.into_iter()
.map(|(k, v)| (k, convert_comparison_operator(v)))
.collect(),
type_representation: scalar_type
.type_representation
.map(convert_type_representation),
type_representation: convert_or_infer_type_representation(
scalar_type.type_representation,
&scalar_type_name,
),
},
)
})
.collect(),
)
}

/// Infer scalar type representation from scalar type name, if necessary. Defaults to JSON representation
fn convert_or_infer_type_representation(
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

V0.2.0 requires type representation.

Type representation comes from introspection configuration, and may be absent.

So, if type representation is missing, we infer the type based on the name and fetch the corresponding type representation from the default introspection configuration.

representation: Option<metadata::TypeRepresentation>,
scalar_type_name: &ScalarTypeName,
) -> query_engine_metadata::metadata::TypeRepresentation {
if let Some(representation) = representation {
convert_type_representation(representation)
} else if let Some(representation) = IntrospectionOptions::default()
.type_representations
.0
.get(scalar_type_name)
{
convert_type_representation(representation.to_owned())
} else {
query_engine_metadata::metadata::TypeRepresentation::Json
}
}

fn convert_aggregate_function(
aggregate_function: metadata::AggregateFunction,
) -> query_engine_metadata::metadata::AggregateFunction {
Expand Down Expand Up @@ -327,6 +349,16 @@ fn convert_operator_kind(
match operator_kind {
metadata::OperatorKind::Equal => query_engine_metadata::metadata::OperatorKind::Equal,
metadata::OperatorKind::In => query_engine_metadata::metadata::OperatorKind::In,
metadata::OperatorKind::LessThan => query_engine_metadata::metadata::OperatorKind::LessThan,
metadata::OperatorKind::LessThanOrEqual => {
query_engine_metadata::metadata::OperatorKind::LessThanOrEqual
}
metadata::OperatorKind::GreaterThan => {
query_engine_metadata::metadata::OperatorKind::GreaterThan
}
metadata::OperatorKind::GreaterThanOrEqual => {
query_engine_metadata::metadata::OperatorKind::GreaterThanOrEqual
}
metadata::OperatorKind::Custom => query_engine_metadata::metadata::OperatorKind::Custom,
}
}
Expand Down
8 changes: 8 additions & 0 deletions crates/configuration/src/version4/upgrade_from_v3.rs
Original file line number Diff line number Diff line change
Expand Up @@ -156,6 +156,14 @@ fn upgrade_operator_kind(
match operator_kind {
version3::metadata::OperatorKind::Equal => metadata::OperatorKind::Equal,
version3::metadata::OperatorKind::In => metadata::OperatorKind::In,
version3::metadata::OperatorKind::LessThan => metadata::OperatorKind::LessThan,
version3::metadata::OperatorKind::LessThanOrEqual => {
metadata::OperatorKind::LessThanOrEqual
}
version3::metadata::OperatorKind::GreaterThan => metadata::OperatorKind::GreaterThan,
version3::metadata::OperatorKind::GreaterThanOrEqual => {
metadata::OperatorKind::GreaterThanOrEqual
}
version3::metadata::OperatorKind::Custom => metadata::OperatorKind::Custom,
}
}
Expand Down
8 changes: 4 additions & 4 deletions crates/configuration/src/version5/comparison.rs
Original file line number Diff line number Diff line change
Expand Up @@ -29,22 +29,22 @@ impl ComparisonOperatorMapping {
ComparisonOperatorMapping {
operator_name: "<=".to_string(),
exposed_name: "_lte".to_string(),
operator_kind: OperatorKind::Custom,
operator_kind: OperatorKind::LessThanOrEqual,
},
ComparisonOperatorMapping {
operator_name: ">".to_string(),
exposed_name: "_gt".to_string(),
operator_kind: OperatorKind::Custom,
operator_kind: OperatorKind::GreaterThan,
},
ComparisonOperatorMapping {
operator_name: ">=".to_string(),
exposed_name: "_gte".to_string(),
operator_kind: OperatorKind::Custom,
operator_kind: OperatorKind::GreaterThanOrEqual,
},
ComparisonOperatorMapping {
operator_name: "<".to_string(),
exposed_name: "_lt".to_string(),
operator_kind: OperatorKind::Custom,
operator_kind: OperatorKind::LessThan,
},
ComparisonOperatorMapping {
operator_name: "<>".to_string(),
Expand Down
4 changes: 4 additions & 0 deletions crates/configuration/src/version5/metadata/database.rs
Original file line number Diff line number Diff line change
Expand Up @@ -85,6 +85,10 @@ pub struct ComparisonOperator {
pub enum OperatorKind {
Equal,
In,
LessThan,
LessThanOrEqual,
GreaterThan,
GreaterThanOrEqual,
Custom,
}

Expand Down
40 changes: 36 additions & 4 deletions crates/configuration/src/version5/to_runtime_configuration.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,10 @@

use std::collections::BTreeMap;

use ndc_models::ScalarTypeName;

use super::metadata;
use super::options::IntrospectionOptions;
use super::ParsedConfiguration;
use crate::environment::Environment;
use crate::error::MakeRuntimeConfigurationError;
Expand Down Expand Up @@ -58,7 +61,7 @@ fn convert_scalar_types(
.into_iter()
.map(|(scalar_type_name, scalar_type)| {
(
scalar_type_name,
scalar_type_name.clone(),
query_engine_metadata::metadata::ScalarType {
type_name: scalar_type.type_name,
schema_name: Some(scalar_type.schema_name),
Expand All @@ -73,16 +76,35 @@ fn convert_scalar_types(
.into_iter()
.map(|(k, v)| (k, convert_comparison_operator(v)))
.collect(),
type_representation: scalar_type
.type_representation
.map(convert_type_representation),
type_representation: convert_or_infer_type_representation(
scalar_type.type_representation,
&scalar_type_name,
),
},
)
})
.collect(),
)
}

/// Infer scalar type representation from scalar type name, if necessary. Defaults to JSON representation
fn convert_or_infer_type_representation(
representation: Option<metadata::TypeRepresentation>,
scalar_type_name: &ScalarTypeName,
) -> query_engine_metadata::metadata::TypeRepresentation {
if let Some(representation) = representation {
convert_type_representation(representation)
} else if let Some(representation) = IntrospectionOptions::default()
.type_representations
.0
.get(scalar_type_name)
{
convert_type_representation(representation.to_owned())
} else {
query_engine_metadata::metadata::TypeRepresentation::Json
}
}

fn convert_aggregate_function(
aggregate_function: metadata::AggregateFunction,
) -> query_engine_metadata::metadata::AggregateFunction {
Expand Down Expand Up @@ -324,6 +346,16 @@ fn convert_operator_kind(
match operator_kind {
metadata::OperatorKind::Equal => query_engine_metadata::metadata::OperatorKind::Equal,
metadata::OperatorKind::In => query_engine_metadata::metadata::OperatorKind::In,
metadata::OperatorKind::LessThan => query_engine_metadata::metadata::OperatorKind::LessThan,
metadata::OperatorKind::LessThanOrEqual => {
query_engine_metadata::metadata::OperatorKind::LessThanOrEqual
}
metadata::OperatorKind::GreaterThan => {
query_engine_metadata::metadata::OperatorKind::GreaterThan
}
metadata::OperatorKind::GreaterThanOrEqual => {
query_engine_metadata::metadata::OperatorKind::GreaterThanOrEqual
}
metadata::OperatorKind::Custom => query_engine_metadata::metadata::OperatorKind::Custom,
}
}
Expand Down
Loading
Loading