diff --git a/crates/ndc-sqlserver/src/configuration.rs b/crates/ndc-sqlserver/src/configuration.rs deleted file mode 100644 index 82022468..00000000 --- a/crates/ndc-sqlserver/src/configuration.rs +++ /dev/null @@ -1,115 +0,0 @@ -//! Configuration and state for our connector. -use super::metrics; - -use ndc_sdk::connector; -use schemars::JsonSchema; -use serde::{Deserialize, Serialize}; -use thiserror::Error; - -const CURRENT_VERSION: u32 = 1; - -/// User configuration. -#[derive(Debug, Deserialize, Serialize, JsonSchema, Clone)] -pub struct RawConfiguration { - pub version: u32, - pub mssql_connection_string: String, - pub metadata: query_engine_metadata::metadata::Metadata, -} - -impl RawConfiguration { - pub fn empty() -> Self { - Self { - version: CURRENT_VERSION, - mssql_connection_string: "".into(), - metadata: query_engine_metadata::metadata::Metadata::default(), - } - } -} - -/// User configuration, elaborated from a 'RawConfiguration'. -#[derive(Debug, Deserialize, Serialize, JsonSchema, Clone)] -#[serde(rename_all = "camelCase")] -pub struct Configuration { - pub config: RawConfiguration, -} - -/// State for our connector. -#[derive(Debug, Clone)] -pub struct State { - pub mssql_pool: bb8::Pool, - pub metrics: metrics::Metrics, -} - -/// Validate the user configuration. -pub async fn validate_raw_configuration( - config: RawConfiguration, -) -> Result { - if config.version != 1 { - return Err(connector::ValidateError::ValidateError(vec![ - connector::InvalidRange { - path: vec![connector::KeyOrIndex::Key("version".into())], - message: format!( - "invalid configuration version, expected 1, got {0}", - config.version - ), - }, - ])); - } - Ok(Configuration { config }) -} - -/// Create a connection pool and wrap it inside a connector State. -pub async fn create_state( - configuration: &Configuration, - metrics_registry: &mut prometheus::Registry, -) -> Result { - let mssql_pool = create_mssql_pool(&configuration.config) - .await - .map_err(|e| { - connector::InitializationError::Other( - InitializationError::UnableToCreateMSSQLPool(e).into(), - ) - })?; - let metrics = metrics::initialise_metrics(metrics_registry).await?; - Ok(State { - mssql_pool, - metrics, - }) -} - -/// Create a connection pool with default settings. -async fn create_mssql_pool( - configuration: &RawConfiguration, -) -> Result, bb8_tiberius::Error> { - let mut config = tiberius::Config::from_ado_string(&configuration.mssql_connection_string)?; - - // TODO: this is bad and we need to make TLS work properly before releasing this - config.trust_cert(); - // TODO: LOOK UP LOOK UP - - let mgr = bb8_tiberius::ConnectionManager::new(config); - - bb8::Pool::builder().max_size(2).build(mgr).await -} - -/// Construct the deployment configuration by introspecting the database. -pub async fn configure( - args: &RawConfiguration, -) -> Result { - // YOU WILL NOTICE NOTHING HAPPENS HERE, WE NEED TO INSPECT THE DATABASE PLEASE - - Ok(RawConfiguration { - version: 1, - mssql_connection_string: args.mssql_connection_string.clone(), - metadata: query_engine_metadata::metadata::Metadata::default(), - }) -} - -/// State initialization error. -#[derive(Debug, Error)] -pub enum InitializationError { - #[error("unable to initialize mssql connection pool: {0}")] - UnableToCreateMSSQLPool(bb8_tiberius::Error), - #[error("error initializing Prometheus metrics: {0}")] - PrometheusError(prometheus::Error), -} diff --git a/crates/ndc-sqlserver/src/configuration/introspection.rs b/crates/ndc-sqlserver/src/configuration/introspection.rs new file mode 100644 index 00000000..993a1b70 --- /dev/null +++ b/crates/ndc-sqlserver/src/configuration/introspection.rs @@ -0,0 +1,49 @@ +//! Configuration and state for our connector. +use serde::Deserialize; + +#[derive(Deserialize, Debug)] +pub struct IntrospectionTable { + pub name: String, + pub type_desc: String, + pub joined_sys_schema: IntrospectionSchema, + pub joined_sys_column: Vec, + pub joined_sys_primary_key: Option, +} + +#[derive(Deserialize, Debug)] +pub struct IntrospectionColumn { + pub name: String, + pub is_nullable: bool, + pub is_identity: bool, + pub is_computed: bool, + pub joined_sys_type: IntrospectionType, + pub joined_foreign_key_columns: Vec, +} + +#[derive(Deserialize, Debug)] +pub struct IntrospectionType { + pub name: String, +} + +#[derive(Deserialize, Debug)] +pub struct IntrospectionPrimaryKey { + pub name: String, + pub columns: Vec, +} + +#[derive(Deserialize, Debug)] +pub struct IntrospectionPrimaryKeyColumn { + pub name: String, +} + +#[derive(Deserialize, Debug)] +pub struct IntrospectionForeignKeyColumn { + pub joined_referenced_table_name: String, + pub joined_referenced_column_name: String, + pub joined_referenced_sys_schema: IntrospectionSchema, +} + +#[derive(Deserialize, Debug)] +pub struct IntrospectionSchema { + pub name: String, +} diff --git a/crates/ndc-sqlserver/src/configuration/mod.rs b/crates/ndc-sqlserver/src/configuration/mod.rs new file mode 100644 index 00000000..44d3dd5b --- /dev/null +++ b/crates/ndc-sqlserver/src/configuration/mod.rs @@ -0,0 +1,7 @@ +pub mod introspection; +pub mod version1; + +pub use version1::{ + configure, create_state, occurring_scalar_types, validate_raw_configuration, Configuration, + InitializationError, RawConfiguration, State, +}; diff --git a/crates/ndc-sqlserver/src/configuration/table_configuration.sql b/crates/ndc-sqlserver/src/configuration/table_configuration.sql new file mode 100644 index 00000000..6894d364 --- /dev/null +++ b/crates/ndc-sqlserver/src/configuration/table_configuration.sql @@ -0,0 +1,60 @@ +-- SCHEMA_NAME(..) +SELECT ISNULL( + (SELECT object.name, object.schema_id, object.object_id, object.type_desc, + JSON_QUERY([schema].json) AS [joined_sys_schema], + JSON_QUERY([column].json) AS [joined_sys_column], + JSON_QUERY([primary_key].json) AS [joined_sys_primary_key] + FROM sys.objects object + CROSS APPLY (SELECT [column].name, [column].column_id, [column].is_nullable, [column].is_identity, [column].is_computed, [column].user_type_id, + JSON_QUERY([types].json) AS [joined_sys_type], + JSON_QUERY(ISNULL([relationships].json,'[]')) AS [joined_foreign_key_columns] + FROM sys.columns [column] + CROSS APPLY (SELECT name, schema_id, user_type_id FROM sys.types [type] + WHERE [type].user_type_id = [column].user_type_id + FOR JSON PATH, WITHOUT_ARRAY_WRAPPER) + AS [types](json) + CROSS APPLY (SELECT fk.*, + referenced_table.name AS joined_referenced_table_name, + referenced_column.name AS joined_referenced_column_name, + JSON_QUERY([schema].json) AS [joined_referenced_sys_schema] + FROM sys.foreign_key_columns AS [fk], + sys.columns AS referenced_column, + sys.objects AS referenced_table + CROSS APPLY (SELECT [schema].name, [schema].schema_id + FROM sys.schemas [schema] + WHERE [schema].schema_id = [referenced_table].schema_id + FOR JSON PATH, WITHOUT_ARRAY_WRAPPER) + AS [schema](json) + WHERE [object].object_id = fk.parent_object_id + AND [referenced_table].object_id = fk.referenced_object_id + AND [referenced_column].object_id = [referenced_table].object_id + AND [referenced_column].column_id = fk.referenced_column_id + AND [column].column_id = fk.parent_column_id + FOR JSON PATH) + AS [relationships](json) + WHERE [column].object_id = object.object_id + FOR JSON PATH) + AS [column](json) + CROSS APPLY (SELECT [schema].name, [schema].schema_id + FROM sys.schemas [schema] + WHERE [schema].schema_id = object.schema_id + FOR JSON PATH, WITHOUT_ARRAY_WRAPPER) + AS [schema](json) + CROSS APPLY (SELECT pk.name, pk.index_id, JSON_QUERY([cols].json) AS columns + FROM sys.indexes pk + CROSS APPLY (SELECT col.name + FROM sys.index_columns ic + INNER JOIN sys.columns col + ON col.column_id = ic.column_id + AND col.object_id = ic.object_id + WHERE ic.object_id = pk.object_id + AND ic.index_id = pk.index_id + FOR JSON PATH) + AS [cols](json) + WHERE pk.object_id = object.object_id + AND pk.is_primary_key = 1 + FOR JSON PATH, WITHOUT_ARRAY_WRAPPER) + AS [primary_key](json) + WHERE object.type_desc IN ('USER_TABLE', 'VIEW') + FOR JSON PATH) + , '[]') diff --git a/crates/ndc-sqlserver/src/configuration/version1.rs b/crates/ndc-sqlserver/src/configuration/version1.rs new file mode 100644 index 00000000..80b98f2e --- /dev/null +++ b/crates/ndc-sqlserver/src/configuration/version1.rs @@ -0,0 +1,273 @@ +//! Configuration and state for our connector. +use crate::metrics; + +use crate::configuration::introspection; +use ndc_sdk::connector; +use query_engine_metadata::metadata; +use query_engine_metadata::metadata::{database, Nullable}; +use schemars::JsonSchema; +use serde::{Deserialize, Serialize}; +use std::collections::BTreeMap; +use std::collections::BTreeSet; +use thiserror::Error; +use tiberius::Query; + +const TABLE_CONFIGURATION_QUERY: &str = include_str!("table_configuration.sql"); + +const CURRENT_VERSION: u32 = 1; + +/// User configuration. +#[derive(Debug, Deserialize, Serialize, JsonSchema, Clone)] +pub struct RawConfiguration { + pub version: u32, + pub mssql_connection_string: String, + pub metadata: query_engine_metadata::metadata::Metadata, +} + +impl RawConfiguration { + pub fn empty() -> Self { + Self { + version: CURRENT_VERSION, + mssql_connection_string: "".into(), + metadata: query_engine_metadata::metadata::Metadata::default(), + } + } +} + +/// User configuration, elaborated from a 'RawConfiguration'. +#[derive(Debug, Deserialize, Serialize, JsonSchema, Clone)] +#[serde(rename_all = "camelCase")] +pub struct Configuration { + pub config: RawConfiguration, +} + +/// State for our connector. +#[derive(Debug, Clone)] +pub struct State { + pub mssql_pool: bb8::Pool, + pub metrics: metrics::Metrics, +} + +/// Validate the user configuration. +pub async fn validate_raw_configuration( + config: RawConfiguration, +) -> Result { + if config.version != 1 { + return Err(connector::ValidateError::ValidateError(vec![ + connector::InvalidRange { + path: vec![connector::KeyOrIndex::Key("version".into())], + message: format!( + "invalid configuration version, expected 1, got {0}", + config.version + ), + }, + ])); + } + Ok(Configuration { config }) +} + +/// Create a connection pool and wrap it inside a connector State. +pub async fn create_state( + configuration: &Configuration, + metrics_registry: &mut prometheus::Registry, +) -> Result { + let mssql_pool = create_mssql_pool(&configuration.config) + .await + .map_err(|e| { + connector::InitializationError::Other( + InitializationError::UnableToCreateMSSQLPool(e).into(), + ) + })?; + let metrics = metrics::initialise_metrics(metrics_registry).await?; + Ok(State { + mssql_pool, + metrics, + }) +} + +/// Create a connection pool with default settings. +async fn create_mssql_pool( + configuration: &RawConfiguration, +) -> Result, bb8_tiberius::Error> { + let mut config = tiberius::Config::from_ado_string(&configuration.mssql_connection_string)?; + + // TODO: this is bad and we need to make TLS work properly before releasing this + config.trust_cert(); + // TODO: LOOK UP LOOK UP + + let mgr = bb8_tiberius::ConnectionManager::new(config); + + bb8::Pool::builder().max_size(2).build(mgr).await +} + +/// Construct the deployment configuration by introspecting the database. +pub async fn configure( + configuration: &RawConfiguration, +) -> Result { + let mssql_pool = create_mssql_pool(configuration).await.unwrap(); + + let mut connection = mssql_pool.get().await.unwrap(); + + // let's do a query to check everything is ok + let select = Query::new(TABLE_CONFIGURATION_QUERY); + + // go! + let stream = select.query(&mut connection).await.unwrap(); + + // Nothing is fetched, the first result set starts. + let row = stream.into_row().await.unwrap().unwrap(); + + let decoded: Vec = + serde_json::from_str(row.get(0).unwrap()).unwrap(); + + let mut metadata = query_engine_metadata::metadata::Metadata::default(); + + metadata.tables = get_tables_info(decoded); + + metadata.native_queries = configuration.metadata.native_queries.clone(); + + Ok(RawConfiguration { + version: 1, + mssql_connection_string: configuration.mssql_connection_string.clone(), + metadata, + }) +} + +fn get_tables_info( + introspection_tables: Vec, +) -> database::TablesInfo { + let mut tables = BTreeMap::new(); + + for introspection_table in introspection_tables { + let table_name = introspection_table.name; + + let mut columns = BTreeMap::new(); + let mut foreign_relations_inner = BTreeMap::new(); + + for introspection_column in introspection_table.joined_sys_column { + let column_name = introspection_column.name.clone(); + let (column, new_foreign_relations) = get_column_info(introspection_column); + columns.insert(column_name, column); + foreign_relations_inner.extend(new_foreign_relations); + } + + let table_info = database::TableInfo { + columns, + description: None, + foreign_relations: database::ForeignRelations(foreign_relations_inner), + table_name: table_name.clone(), + schema_name: introspection_table.joined_sys_schema.name, + uniqueness_constraints: get_uniqueness_constraints( + introspection_table.joined_sys_primary_key, + ), + }; + + tables.insert(table_name, table_info); + } + + database::TablesInfo(tables) +} + +fn get_foreign_relation( + local_column: String, + foreign_key: introspection::IntrospectionForeignKeyColumn, +) -> database::ForeignRelation { + let mut column_mapping = BTreeMap::new(); + column_mapping.insert(local_column, foreign_key.joined_referenced_column_name); + + database::ForeignRelation { + foreign_table: foreign_key.joined_referenced_table_name, + column_mapping, + } +} + +fn get_uniqueness_constraints( + opt_primary_key: Option, +) -> database::UniquenessConstraints { + let mut uniqueness_constraints_inner = BTreeMap::new(); + + if let Some(primary_key) = opt_primary_key { + let constraint_name = primary_key.name; + + let keys_set = primary_key + .columns + .iter() + .fold(BTreeSet::new(), |mut set, part| { + set.insert(part.name.clone()); + set + }); + + uniqueness_constraints_inner + .insert(constraint_name, database::UniquenessConstraint(keys_set)); + } + + database::UniquenessConstraints(uniqueness_constraints_inner) +} + +fn get_column_info( + introspection_column: introspection::IntrospectionColumn, +) -> ( + database::ColumnInfo, + BTreeMap, +) { + let mut foreign_relations = BTreeMap::new(); + introspection_column + .joined_foreign_key_columns + .into_iter() + .enumerate() + .for_each(|(index, foreign_key)| { + let fancy_key = format!("FK_{}{}", introspection_column.name, index); + foreign_relations.insert( + fancy_key, + get_foreign_relation(introspection_column.name.clone(), foreign_key), + ); + }); + + let column_info = database::ColumnInfo { + description: None, + name: introspection_column.name, + nullable: if introspection_column.is_nullable { + Nullable::Nullable + } else { + Nullable::NonNullable + }, + r#type: database::ScalarType(introspection_column.joined_sys_type.name), + }; + (column_info, foreign_relations) +} + +/// State initialization error. +#[derive(Debug, Error)] +pub enum InitializationError { + #[error("unable to initialize mssql connection pool: {0}")] + UnableToCreateMSSQLPool(bb8_tiberius::Error), + #[error("error initializing Prometheus metrics: {0}")] + PrometheusError(prometheus::Error), +} + +/// Collect all the types that can occur in the metadata. This is a bit circumstantial. A better +/// approach is likely to record scalar type names directly in the metadata via configuration.sql. +pub fn occurring_scalar_types( + tables: &metadata::TablesInfo, + native_queries: &metadata::NativeQueries, +) -> BTreeSet { + let tables_column_types = tables + .0 + .values() + .flat_map(|v| v.columns.values().map(|c| c.r#type.clone())); + + let native_queries_column_types = native_queries + .0 + .values() + .flat_map(|v| v.columns.values().map(|c| c.r#type.clone())); + + let native_queries_arguments_types = native_queries + .0 + .values() + .flat_map(|v| v.arguments.values().map(|c| c.r#type.clone())); + + tables_column_types + .chain(native_queries_column_types) + .chain(native_queries_arguments_types) + .collect::>() +} diff --git a/crates/ndc-sqlserver/src/connector.rs b/crates/ndc-sqlserver/src/connector.rs index 6d5eacd4..6793123b 100644 --- a/crates/ndc-sqlserver/src/connector.rs +++ b/crates/ndc-sqlserver/src/connector.rs @@ -15,6 +15,7 @@ use query_engine_execution::execution; use query_engine_translation::translation; use super::configuration; +use super::schema; #[derive(Clone, Default)] pub struct SQLServer {} @@ -116,9 +117,9 @@ impl connector::Connector for SQLServer { /// This function implements the [schema endpoint](https://hasura.github.io/ndc-spec/specification/schema/index.html) /// from the NDC specification. async fn get_schema( - _configuration: &Self::Configuration, + configuration: &Self::Configuration, ) -> Result, connector::SchemaError> { - todo!("get_schema") + schema::get_schema(configuration).await.map(Into::into) } /// Explain a query by creating an execution plan diff --git a/crates/ndc-sqlserver/src/lib.rs b/crates/ndc-sqlserver/src/lib.rs index 8f09365f..1d98c5e8 100644 --- a/crates/ndc-sqlserver/src/lib.rs +++ b/crates/ndc-sqlserver/src/lib.rs @@ -1,3 +1,4 @@ pub mod configuration; pub mod connector; pub mod metrics; +pub mod schema; diff --git a/crates/ndc-sqlserver/src/schema.rs b/crates/ndc-sqlserver/src/schema.rs new file mode 100644 index 00000000..57e11d1e --- /dev/null +++ b/crates/ndc-sqlserver/src/schema.rs @@ -0,0 +1,209 @@ +//! Implement the `/schema` endpoint to return the connector's schema. +//! See the Hasura +//! [Native Data Connector Specification](https://hasura.github.io/ndc-spec/specification/schema/index.html) +//! for further details. + +use std::collections::BTreeMap; + +use ndc_sdk::connector; +use ndc_sdk::models; +use query_engine_metadata::metadata; + +use super::configuration; + +/// Get the connector's schema. +/// +/// This function implements the [schema endpoint](https://hasura.github.io/ndc-spec/specification/schema/index.html) +/// from the NDC specification. +pub async fn get_schema( + configuration::Configuration { config, .. }: &configuration::Configuration, +) -> Result { + let configuration::RawConfiguration { metadata, .. } = config; + let scalar_types: BTreeMap = + configuration::occurring_scalar_types(&metadata.tables, &metadata.native_queries) + .iter() + .map(|scalar_type| { + ( + scalar_type.0.clone(), + models::ScalarType { + aggregate_functions: metadata + .aggregate_functions + .0 + .get(scalar_type) + .unwrap_or(&BTreeMap::new()) + .iter() + .map(|(function_name, function_definition)| { + ( + function_name.clone(), + models::AggregateFunctionDefinition { + result_type: models::Type::Named { + name: function_definition.return_type.0.clone(), + }, + }, + ) + }) + .collect(), + comparison_operators: metadata + .comparison_operators + .0 + .get(scalar_type) + .unwrap_or(&BTreeMap::new()) + .iter() + .map(|(op_name, op_def)| { + ( + op_name.clone(), + models::ComparisonOperatorDefinition { + argument_type: models::Type::Named { + name: op_def.argument_type.0.clone(), + }, + }, + ) + }) + .collect(), + update_operators: BTreeMap::new(), + }, + ) + }) + .collect(); + + let tables: Vec = metadata + .tables + .0 + .iter() + .map(|(table_name, table)| models::CollectionInfo { + name: table_name.clone(), + description: table.description.clone(), + arguments: BTreeMap::new(), + collection_type: table_name.clone(), + insertable_columns: None, + updatable_columns: None, + deletable: false, + uniqueness_constraints: table + .uniqueness_constraints + .0 + .iter() + .map( + |(constraint_name, metadata::UniquenessConstraint(constraint_columns))| { + ( + constraint_name.clone(), + models::UniquenessConstraint { + unique_columns: constraint_columns.iter().cloned().collect(), + }, + ) + }, + ) + .collect(), + foreign_keys: table + .foreign_relations + .0 + .iter() + .map( + |( + constraint_name, + metadata::ForeignRelation { + foreign_table, + column_mapping, + }, + )| { + ( + constraint_name.clone(), + models::ForeignKeyConstraint { + foreign_collection: foreign_table.clone(), + column_mapping: column_mapping.clone(), + }, + ) + }, + ) + .collect(), + }) + .collect(); + + let native_queries: Vec = metadata + .native_queries + .0 + .iter() + .map(|(name, info)| models::CollectionInfo { + name: name.clone(), + description: info.description.clone(), + arguments: info + .arguments + .iter() + .map(|(name, column_info)| { + ( + name.clone(), + models::ArgumentInfo { + description: column_info.description.clone(), + argument_type: column_to_type(column_info), + }, + ) + }) + .collect(), + collection_type: name.clone(), + insertable_columns: None, + updatable_columns: None, + deletable: false, + uniqueness_constraints: BTreeMap::new(), + foreign_keys: BTreeMap::new(), + }) + .collect(); + + let mut collections = tables; + collections.extend(native_queries); + + let table_types = BTreeMap::from_iter(metadata.tables.0.iter().map(|(table_name, table)| { + let object_type = models::ObjectType { + description: table.description.clone(), + fields: BTreeMap::from_iter(table.columns.values().map(|column| { + ( + column.name.clone(), + models::ObjectField { + description: column.description.clone(), + r#type: column_to_type(column), + }, + ) + })), + }; + (table_name.clone(), object_type) + })); + + let native_queries_types = + BTreeMap::from_iter(metadata.native_queries.0.iter().map(|(name, info)| { + let object_type = models::ObjectType { + description: info.description.clone(), + fields: BTreeMap::from_iter(info.columns.values().map(|column| { + ( + column.name.clone(), + models::ObjectField { + description: column.description.clone(), + r#type: column_to_type(column), + }, + ) + })), + }; + (name.clone(), object_type) + })); + + let mut object_types = table_types; + object_types.extend(native_queries_types); + + Ok(models::SchemaResponse { + collections, + procedures: vec![], + functions: vec![], + object_types, + scalar_types, + }) +} + +fn column_to_type(column: &metadata::ColumnInfo) -> models::Type { + match &column.nullable { + metadata::Nullable::NonNullable => models::Type::Named { + name: column.r#type.0.clone(), + }, + metadata::Nullable::Nullable => models::Type::Nullable { + underlying_type: Box::new(models::Type::Named { + name: column.r#type.0.clone(), + }), + }, + } +} diff --git a/crates/ndc-sqlserver/tests/schema_tests.rs b/crates/ndc-sqlserver/tests/schema_tests.rs index 26fe5d0b..3684d8a1 100644 --- a/crates/ndc-sqlserver/tests/schema_tests.rs +++ b/crates/ndc-sqlserver/tests/schema_tests.rs @@ -1,4 +1,3 @@ -/* pub mod common; #[tokio::test] @@ -6,4 +5,3 @@ async fn get_schema() { let result = common::get_schema().await; insta::assert_json_snapshot!(result); } -*/ diff --git a/crates/ndc-sqlserver/tests/snapshots/schema_tests__get_schema.snap b/crates/ndc-sqlserver/tests/snapshots/schema_tests__get_schema.snap index abb914f4..c3a6cf59 100644 --- a/crates/ndc-sqlserver/tests/snapshots/schema_tests__get_schema.snap +++ b/crates/ndc-sqlserver/tests/snapshots/schema_tests__get_schema.snap @@ -1,307 +1,1591 @@ --- source: crates/ndc-sqlserver/tests/schema_tests.rs -assertion_line: 6 expression: result --- { "scalar_types": { - "Int": { + "bool": { + "aggregate_functions": { + "bool_and": { + "result_type": { + "type": "named", + "name": "bool" + } + }, + "bool_or": { + "result_type": { + "type": "named", + "name": "bool" + } + }, + "every": { + "result_type": { + "type": "named", + "name": "bool" + } + } + }, + "comparison_operators": { + "_eq": { + "argument_type": { + "type": "named", + "name": "bool" + } + }, + "_gt": { + "argument_type": { + "type": "named", + "name": "bool" + } + }, + "_gte": { + "argument_type": { + "type": "named", + "name": "bool" + } + }, + "_lt": { + "argument_type": { + "type": "named", + "name": "bool" + } + }, + "_lte": { + "argument_type": { + "type": "named", + "name": "bool" + } + }, + "_neq": { + "argument_type": { + "type": "named", + "name": "bool" + } + } + }, + "update_operators": {} + }, + "char": { + "aggregate_functions": {}, + "comparison_operators": { + "_eq": { + "argument_type": { + "type": "named", + "name": "char" + } + }, + "_gt": { + "argument_type": { + "type": "named", + "name": "char" + } + }, + "_gte": { + "argument_type": { + "type": "named", + "name": "char" + } + }, + "_ilike": { + "argument_type": { + "type": "named", + "name": "char" + } + }, + "_iregex": { + "argument_type": { + "type": "named", + "name": "char" + } + }, + "_like": { + "argument_type": { + "type": "named", + "name": "char" + } + }, + "_lt": { + "argument_type": { + "type": "named", + "name": "char" + } + }, + "_lte": { + "argument_type": { + "type": "named", + "name": "char" + } + }, + "_neq": { + "argument_type": { + "type": "named", + "name": "char" + } + }, + "_nilike": { + "argument_type": { + "type": "named", + "name": "char" + } + }, + "_niregex": { + "argument_type": { + "type": "named", + "name": "char" + } + }, + "_nlike": { + "argument_type": { + "type": "named", + "name": "char" + } + }, + "_nregex": { + "argument_type": { + "type": "named", + "name": "char" + } + }, + "_regex": { + "argument_type": { + "type": "named", + "name": "char" + } + } + }, + "update_operators": {} + }, + "date": { + "aggregate_functions": { + "max": { + "result_type": { + "type": "named", + "name": "date" + } + }, + "min": { + "result_type": { + "type": "named", + "name": "date" + } + } + }, + "comparison_operators": { + "_eq": { + "argument_type": { + "type": "named", + "name": "date" + } + }, + "_gt": { + "argument_type": { + "type": "named", + "name": "date" + } + }, + "_gte": { + "argument_type": { + "type": "named", + "name": "date" + } + }, + "_lt": { + "argument_type": { + "type": "named", + "name": "date" + } + }, + "_lte": { + "argument_type": { + "type": "named", + "name": "date" + } + }, + "_neq": { + "argument_type": { + "type": "named", + "name": "date" + } + } + }, + "update_operators": {} + }, + "float4": { + "aggregate_functions": { + "avg": { + "result_type": { + "type": "named", + "name": "float8" + } + }, + "max": { + "result_type": { + "type": "named", + "name": "float4" + } + }, + "min": { + "result_type": { + "type": "named", + "name": "float4" + } + }, + "stddev": { + "result_type": { + "type": "named", + "name": "float8" + } + }, + "stddev_pop": { + "result_type": { + "type": "named", + "name": "float8" + } + }, + "stddev_samp": { + "result_type": { + "type": "named", + "name": "float8" + } + }, + "sum": { + "result_type": { + "type": "named", + "name": "float4" + } + }, + "var_pop": { + "result_type": { + "type": "named", + "name": "float8" + } + }, + "var_samp": { + "result_type": { + "type": "named", + "name": "float8" + } + }, + "variance": { + "result_type": { + "type": "named", + "name": "float8" + } + } + }, + "comparison_operators": { + "_eq": { + "argument_type": { + "type": "named", + "name": "float4" + } + }, + "_gt": { + "argument_type": { + "type": "named", + "name": "float4" + } + }, + "_gte": { + "argument_type": { + "type": "named", + "name": "float4" + } + }, + "_lt": { + "argument_type": { + "type": "named", + "name": "float4" + } + }, + "_lte": { + "argument_type": { + "type": "named", + "name": "float4" + } + }, + "_neq": { + "argument_type": { + "type": "named", + "name": "float4" + } + } + }, + "update_operators": {} + }, + "float8": { + "aggregate_functions": { + "avg": { + "result_type": { + "type": "named", + "name": "float8" + } + }, + "max": { + "result_type": { + "type": "named", + "name": "float8" + } + }, + "min": { + "result_type": { + "type": "named", + "name": "float8" + } + }, + "stddev": { + "result_type": { + "type": "named", + "name": "float8" + } + }, + "stddev_pop": { + "result_type": { + "type": "named", + "name": "float8" + } + }, + "stddev_samp": { + "result_type": { + "type": "named", + "name": "float8" + } + }, + "sum": { + "result_type": { + "type": "named", + "name": "float8" + } + }, + "var_pop": { + "result_type": { + "type": "named", + "name": "float8" + } + }, + "var_samp": { + "result_type": { + "type": "named", + "name": "float8" + } + }, + "variance": { + "result_type": { + "type": "named", + "name": "float8" + } + } + }, + "comparison_operators": { + "_eq": { + "argument_type": { + "type": "named", + "name": "float8" + } + }, + "_gt": { + "argument_type": { + "type": "named", + "name": "float8" + } + }, + "_gte": { + "argument_type": { + "type": "named", + "name": "float8" + } + }, + "_lt": { + "argument_type": { + "type": "named", + "name": "float8" + } + }, + "_lte": { + "argument_type": { + "type": "named", + "name": "float8" + } + }, + "_neq": { + "argument_type": { + "type": "named", + "name": "float8" + } + } + }, + "update_operators": {} + }, + "int": { + "aggregate_functions": { + "avg": { + "result_type": { + "type": "named", + "name": "numeric" + } + }, + "bit_and": { + "result_type": { + "type": "named", + "name": "int" + } + }, + "bit_or": { + "result_type": { + "type": "named", + "name": "int" + } + }, + "bit_xor": { + "result_type": { + "type": "named", + "name": "int" + } + }, + "max": { + "result_type": { + "type": "named", + "name": "int" + } + }, + "min": { + "result_type": { + "type": "named", + "name": "int" + } + }, + "stddev": { + "result_type": { + "type": "named", + "name": "numeric" + } + }, + "stddev_pop": { + "result_type": { + "type": "named", + "name": "numeric" + } + }, + "stddev_samp": { + "result_type": { + "type": "named", + "name": "numeric" + } + }, + "sum": { + "result_type": { + "type": "named", + "name": "int8" + } + }, + "var_pop": { + "result_type": { + "type": "named", + "name": "numeric" + } + }, + "var_samp": { + "result_type": { + "type": "named", + "name": "numeric" + } + }, + "variance": { + "result_type": { + "type": "named", + "name": "numeric" + } + } + }, + "comparison_operators": { + "_eq": { + "argument_type": { + "type": "named", + "name": "int" + } + }, + "_gt": { + "argument_type": { + "type": "named", + "name": "int" + } + }, + "_gte": { + "argument_type": { + "type": "named", + "name": "int" + } + }, + "_lt": { + "argument_type": { + "type": "named", + "name": "int" + } + }, + "_lte": { + "argument_type": { + "type": "named", + "name": "int" + } + }, + "_neq": { + "argument_type": { + "type": "named", + "name": "int" + } + } + }, + "update_operators": {} + }, + "int2": { + "aggregate_functions": { + "avg": { + "result_type": { + "type": "named", + "name": "numeric" + } + }, + "bit_and": { + "result_type": { + "type": "named", + "name": "int2" + } + }, + "bit_or": { + "result_type": { + "type": "named", + "name": "int2" + } + }, + "bit_xor": { + "result_type": { + "type": "named", + "name": "int2" + } + }, + "max": { + "result_type": { + "type": "named", + "name": "int2" + } + }, + "min": { + "result_type": { + "type": "named", + "name": "int2" + } + }, + "stddev": { + "result_type": { + "type": "named", + "name": "numeric" + } + }, + "stddev_pop": { + "result_type": { + "type": "named", + "name": "numeric" + } + }, + "stddev_samp": { + "result_type": { + "type": "named", + "name": "numeric" + } + }, + "sum": { + "result_type": { + "type": "named", + "name": "int8" + } + }, + "var_pop": { + "result_type": { + "type": "named", + "name": "numeric" + } + }, + "var_samp": { + "result_type": { + "type": "named", + "name": "numeric" + } + }, + "variance": { + "result_type": { + "type": "named", + "name": "numeric" + } + } + }, + "comparison_operators": { + "_eq": { + "argument_type": { + "type": "named", + "name": "int2" + } + }, + "_gt": { + "argument_type": { + "type": "named", + "name": "int2" + } + }, + "_gte": { + "argument_type": { + "type": "named", + "name": "int2" + } + }, + "_lt": { + "argument_type": { + "type": "named", + "name": "int2" + } + }, + "_lte": { + "argument_type": { + "type": "named", + "name": "int2" + } + }, + "_neq": { + "argument_type": { + "type": "named", + "name": "int2" + } + } + }, + "update_operators": {} + }, + "int8": { + "aggregate_functions": { + "avg": { + "result_type": { + "type": "named", + "name": "numeric" + } + }, + "bit_and": { + "result_type": { + "type": "named", + "name": "int8" + } + }, + "bit_or": { + "result_type": { + "type": "named", + "name": "int8" + } + }, + "bit_xor": { + "result_type": { + "type": "named", + "name": "int8" + } + }, + "max": { + "result_type": { + "type": "named", + "name": "int8" + } + }, + "min": { + "result_type": { + "type": "named", + "name": "int8" + } + }, + "stddev": { + "result_type": { + "type": "named", + "name": "numeric" + } + }, + "stddev_pop": { + "result_type": { + "type": "named", + "name": "numeric" + } + }, + "stddev_samp": { + "result_type": { + "type": "named", + "name": "numeric" + } + }, + "sum": { + "result_type": { + "type": "named", + "name": "numeric" + } + }, + "var_pop": { + "result_type": { + "type": "named", + "name": "numeric" + } + }, + "var_samp": { + "result_type": { + "type": "named", + "name": "numeric" + } + }, + "variance": { + "result_type": { + "type": "named", + "name": "numeric" + } + } + }, + "comparison_operators": { + "_eq": { + "argument_type": { + "type": "named", + "name": "int8" + } + }, + "_gt": { + "argument_type": { + "type": "named", + "name": "int8" + } + }, + "_gte": { + "argument_type": { + "type": "named", + "name": "int8" + } + }, + "_lt": { + "argument_type": { + "type": "named", + "name": "int8" + } + }, + "_lte": { + "argument_type": { + "type": "named", + "name": "int8" + } + }, + "_neq": { + "argument_type": { + "type": "named", + "name": "int8" + } + } + }, + "update_operators": {} + }, + "name": { + "aggregate_functions": {}, + "comparison_operators": { + "_eq": { + "argument_type": { + "type": "named", + "name": "name" + } + }, + "_gt": { + "argument_type": { + "type": "named", + "name": "name" + } + }, + "_gte": { + "argument_type": { + "type": "named", + "name": "name" + } + }, + "_ilike": { + "argument_type": { + "type": "named", + "name": "name" + } + }, + "_iregex": { + "argument_type": { + "type": "named", + "name": "name" + } + }, + "_like": { + "argument_type": { + "type": "named", + "name": "name" + } + }, + "_lt": { + "argument_type": { + "type": "named", + "name": "name" + } + }, + "_lte": { + "argument_type": { + "type": "named", + "name": "name" + } + }, + "_neq": { + "argument_type": { + "type": "named", + "name": "name" + } + }, + "_nilike": { + "argument_type": { + "type": "named", + "name": "name" + } + }, + "_niregex": { + "argument_type": { + "type": "named", + "name": "name" + } + }, + "_nlike": { + "argument_type": { + "type": "named", + "name": "name" + } + }, + "_nregex": { + "argument_type": { + "type": "named", + "name": "name" + } + }, + "_regex": { + "argument_type": { + "type": "named", + "name": "name" + } + } + }, + "update_operators": {} + }, + "numeric": { "aggregate_functions": { "avg": { "result_type": { "type": "named", - "name": "Int" + "name": "numeric" } }, - "bit_and": { + "max": { "result_type": { "type": "named", - "name": "Int" + "name": "numeric" } }, - "bit_or": { + "min": { "result_type": { "type": "named", - "name": "Int" + "name": "numeric" } }, - "bit_xor": { + "stddev": { + "result_type": { + "type": "named", + "name": "numeric" + } + }, + "stddev_pop": { + "result_type": { + "type": "named", + "name": "numeric" + } + }, + "stddev_samp": { + "result_type": { + "type": "named", + "name": "numeric" + } + }, + "sum": { + "result_type": { + "type": "named", + "name": "numeric" + } + }, + "var_pop": { + "result_type": { + "type": "named", + "name": "numeric" + } + }, + "var_samp": { + "result_type": { + "type": "named", + "name": "numeric" + } + }, + "variance": { + "result_type": { + "type": "named", + "name": "numeric" + } + } + }, + "comparison_operators": { + "_eq": { + "argument_type": { + "type": "named", + "name": "numeric" + } + }, + "_gt": { + "argument_type": { + "type": "named", + "name": "numeric" + } + }, + "_gte": { + "argument_type": { + "type": "named", + "name": "numeric" + } + }, + "_lt": { + "argument_type": { + "type": "named", + "name": "numeric" + } + }, + "_lte": { + "argument_type": { + "type": "named", + "name": "numeric" + } + }, + "_neq": { + "argument_type": { + "type": "named", + "name": "numeric" + } + } + }, + "update_operators": {} + }, + "text": { + "aggregate_functions": { + "max": { + "result_type": { + "type": "named", + "name": "text" + } + }, + "min": { + "result_type": { + "type": "named", + "name": "text" + } + } + }, + "comparison_operators": { + "_eq": { + "argument_type": { + "type": "named", + "name": "text" + } + }, + "_gt": { + "argument_type": { + "type": "named", + "name": "text" + } + }, + "_gte": { + "argument_type": { + "type": "named", + "name": "text" + } + }, + "_ilike": { + "argument_type": { + "type": "named", + "name": "text" + } + }, + "_iregex": { + "argument_type": { + "type": "named", + "name": "text" + } + }, + "_like": { + "argument_type": { + "type": "named", + "name": "text" + } + }, + "_lt": { + "argument_type": { + "type": "named", + "name": "text" + } + }, + "_lte": { + "argument_type": { + "type": "named", + "name": "text" + } + }, + "_neq": { + "argument_type": { + "type": "named", + "name": "text" + } + }, + "_nilike": { + "argument_type": { + "type": "named", + "name": "text" + } + }, + "_niregex": { + "argument_type": { + "type": "named", + "name": "text" + } + }, + "_nlike": { + "argument_type": { + "type": "named", + "name": "text" + } + }, + "_nregex": { + "argument_type": { + "type": "named", + "name": "text" + } + }, + "_regex": { + "argument_type": { + "type": "named", + "name": "text" + } + } + }, + "update_operators": {} + }, + "time": { + "aggregate_functions": { + "max": { + "result_type": { + "type": "named", + "name": "time" + } + }, + "min": { + "result_type": { + "type": "named", + "name": "time" + } + } + }, + "comparison_operators": { + "_eq": { + "argument_type": { + "type": "named", + "name": "time" + } + }, + "_gt": { + "argument_type": { + "type": "named", + "name": "time" + } + }, + "_gte": { + "argument_type": { + "type": "named", + "name": "time" + } + }, + "_lt": { + "argument_type": { + "type": "named", + "name": "time" + } + }, + "_lte": { + "argument_type": { + "type": "named", + "name": "time" + } + }, + "_neq": { + "argument_type": { + "type": "named", + "name": "time" + } + } + }, + "update_operators": {} + }, + "timestamp": { + "aggregate_functions": { + "max": { + "result_type": { + "type": "named", + "name": "timestamp" + } + }, + "min": { "result_type": { "type": "named", - "name": "Int" + "name": "timestamp" + } + } + }, + "comparison_operators": { + "_eq": { + "argument_type": { + "type": "named", + "name": "timestamp" + } + }, + "_gt": { + "argument_type": { + "type": "named", + "name": "timestamp" + } + }, + "_gte": { + "argument_type": { + "type": "named", + "name": "timestamp" } }, - "count": { + "_lt": { + "argument_type": { + "type": "named", + "name": "timestamp" + } + }, + "_lte": { + "argument_type": { + "type": "named", + "name": "timestamp" + } + }, + "_neq": { + "argument_type": { + "type": "named", + "name": "timestamp" + } + } + }, + "update_operators": {} + }, + "timestamptz": { + "aggregate_functions": { + "max": { "result_type": { "type": "named", - "name": "Int" + "name": "timestamptz" } }, - "dense_rank": { + "min": { "result_type": { "type": "named", - "name": "Int" + "name": "timestamptz" + } + } + }, + "comparison_operators": { + "_eq": { + "argument_type": { + "type": "named", + "name": "timestamptz" + } + }, + "_gt": { + "argument_type": { + "type": "named", + "name": "timestamptz" + } + }, + "_gte": { + "argument_type": { + "type": "named", + "name": "timestamptz" + } + }, + "_lt": { + "argument_type": { + "type": "named", + "name": "timestamptz" } }, + "_lte": { + "argument_type": { + "type": "named", + "name": "timestamptz" + } + }, + "_neq": { + "argument_type": { + "type": "named", + "name": "timestamptz" + } + } + }, + "update_operators": {} + }, + "timetz": { + "aggregate_functions": { "max": { "result_type": { "type": "named", - "name": "Int" + "name": "timetz" + } + }, + "min": { + "result_type": { + "type": "named", + "name": "timetz" + } + } + }, + "comparison_operators": { + "_eq": { + "argument_type": { + "type": "named", + "name": "timetz" + } + }, + "_gt": { + "argument_type": { + "type": "named", + "name": "timetz" + } + }, + "_gte": { + "argument_type": { + "type": "named", + "name": "timetz" + } + }, + "_lt": { + "argument_type": { + "type": "named", + "name": "timetz" + } + }, + "_lte": { + "argument_type": { + "type": "named", + "name": "timetz" + } + }, + "_neq": { + "argument_type": { + "type": "named", + "name": "timetz" + } + } + }, + "update_operators": {} + }, + "uuid": { + "aggregate_functions": {}, + "comparison_operators": { + "_eq": { + "argument_type": { + "type": "named", + "name": "uuid" + } + }, + "_gt": { + "argument_type": { + "type": "named", + "name": "uuid" } }, - "min": { - "result_type": { + "_gte": { + "argument_type": { "type": "named", - "name": "Int" + "name": "uuid" } }, - "ntile": { - "result_type": { + "_lt": { + "argument_type": { "type": "named", - "name": "Int" + "name": "uuid" } }, - "rank": { - "result_type": { + "_lte": { + "argument_type": { "type": "named", - "name": "Int" + "name": "uuid" } }, - "regr_count": { - "result_type": { + "_neq": { + "argument_type": { + "type": "named", + "name": "uuid" + } + } + }, + "update_operators": {} + }, + "varchar": { + "aggregate_functions": {}, + "comparison_operators": { + "_eq": { + "argument_type": { "type": "named", - "name": "Int" + "name": "varchar" } }, - "row_number": { - "result_type": { + "_gt": { + "argument_type": { "type": "named", - "name": "Int" + "name": "varchar" } }, - "st_clusterdbscan": { - "result_type": { + "_gte": { + "argument_type": { "type": "named", - "name": "Int" + "name": "varchar" } }, - "st_clusterkmeans": { - "result_type": { + "_ilike": { + "argument_type": { "type": "named", - "name": "Int" + "name": "varchar" } }, - "stddev": { - "result_type": { + "_iregex": { + "argument_type": { "type": "named", - "name": "Int" + "name": "varchar" } }, - "stddev_pop": { - "result_type": { + "_like": { + "argument_type": { "type": "named", - "name": "Int" + "name": "varchar" } }, - "stddev_samp": { - "result_type": { + "_lt": { + "argument_type": { "type": "named", - "name": "Int" + "name": "varchar" } }, - "sum": { - "result_type": { + "_lte": { + "argument_type": { "type": "named", - "name": "Int" + "name": "varchar" } }, - "var_pop": { - "result_type": { + "_neq": { + "argument_type": { "type": "named", - "name": "Int" + "name": "varchar" } }, - "var_samp": { - "result_type": { + "_nilike": { + "argument_type": { "type": "named", - "name": "Int" + "name": "varchar" } }, - "variance": { - "result_type": { + "_niregex": { + "argument_type": { "type": "named", - "name": "Int" + "name": "varchar" } - } - }, - "comparison_operators": {}, - "update_operators": {} - }, - "String": { - "aggregate_functions": { - "max": { - "result_type": { + }, + "_nlike": { + "argument_type": { "type": "named", - "name": "String" + "name": "varchar" } }, - "min": { - "result_type": { + "_nregex": { + "argument_type": { "type": "named", - "name": "String" + "name": "varchar" } }, - "string_agg": { - "result_type": { + "_regex": { + "argument_type": { "type": "named", - "name": "String" + "name": "varchar" } } }, - "comparison_operators": {}, - "update_operators": {} - }, - "any": { - "aggregate_functions": {}, - "comparison_operators": {}, "update_operators": {} } }, "object_types": { "Album": { + "description": "The record of all albums", "fields": { "AlbumId": { - "arguments": {}, + "description": "The identifier of an album", "type": { "type": "named", - "name": "any" + "name": "int" } }, "ArtistId": { - "arguments": {}, + "description": "The id of the artist that authored the album", "type": { "type": "named", - "name": "any" + "name": "int" } }, "Title": { - "arguments": {}, + "description": "The title of an album", "type": { "type": "named", - "name": "any" + "name": "varchar" } } } }, "Artist": { + "description": "The record of all artists", "fields": { "ArtistId": { - "arguments": {}, + "description": "The identifier of an artist", "type": { "type": "named", - "name": "any" + "name": "int" } }, "Name": { - "arguments": {}, + "description": "The name of an artist", "type": { - "type": "named", - "name": "any" + "type": "nullable", + "underlying_type": { + "type": "named", + "name": "varchar" + } } } } }, "Customer": { + "description": "The record of all customers", "fields": { "Address": { - "arguments": {}, "type": { - "type": "named", - "name": "any" + "type": "nullable", + "underlying_type": { + "type": "named", + "name": "varchar" + } } }, "City": { - "arguments": {}, "type": { - "type": "named", - "name": "any" + "type": "nullable", + "underlying_type": { + "type": "named", + "name": "varchar" + } } }, "Company": { - "arguments": {}, "type": { - "type": "named", - "name": "any" + "type": "nullable", + "underlying_type": { + "type": "named", + "name": "varchar" + } } }, "Country": { - "arguments": {}, "type": { - "type": "named", - "name": "any" + "type": "nullable", + "underlying_type": { + "type": "named", + "name": "varchar" + } } }, "CustomerId": { - "arguments": {}, + "description": "The identifier of customer", "type": { "type": "named", - "name": "any" + "name": "int" } }, "Email": { - "arguments": {}, "type": { "type": "named", - "name": "any" + "name": "varchar" } }, "Fax": { - "arguments": {}, "type": { - "type": "named", - "name": "any" + "type": "nullable", + "underlying_type": { + "type": "named", + "name": "varchar" + } } }, "FirstName": { - "arguments": {}, + "description": "The first name of a customer", "type": { "type": "named", - "name": "any" + "name": "varchar" } }, "LastName": { - "arguments": {}, + "description": "The last name of a customer", "type": { "type": "named", - "name": "any" + "name": "varchar" } }, "Phone": { - "arguments": {}, "type": { - "type": "named", - "name": "any" + "type": "nullable", + "underlying_type": { + "type": "named", + "name": "varchar" + } } }, "PostalCode": { - "arguments": {}, "type": { - "type": "named", - "name": "any" + "type": "nullable", + "underlying_type": { + "type": "named", + "name": "varchar" + } } }, "State": { - "arguments": {}, "type": { - "type": "named", - "name": "any" + "type": "nullable", + "underlying_type": { + "type": "named", + "name": "varchar" + } } }, "SupportRepId": { - "arguments": {}, "type": { - "type": "named", - "name": "any" + "type": "nullable", + "underlying_type": { + "type": "named", + "name": "int" + } } } } @@ -309,108 +1593,129 @@ expression: result "Employee": { "fields": { "Address": { - "arguments": {}, "type": { - "type": "named", - "name": "any" + "type": "nullable", + "underlying_type": { + "type": "named", + "name": "varchar" + } } }, "BirthDate": { - "arguments": {}, "type": { - "type": "named", - "name": "any" + "type": "nullable", + "underlying_type": { + "type": "named", + "name": "timestamp" + } } }, "City": { - "arguments": {}, "type": { - "type": "named", - "name": "any" + "type": "nullable", + "underlying_type": { + "type": "named", + "name": "varchar" + } } }, "Country": { - "arguments": {}, "type": { - "type": "named", - "name": "any" + "type": "nullable", + "underlying_type": { + "type": "named", + "name": "varchar" + } } }, "Email": { - "arguments": {}, "type": { - "type": "named", - "name": "any" + "type": "nullable", + "underlying_type": { + "type": "named", + "name": "varchar" + } } }, "EmployeeId": { - "arguments": {}, "type": { "type": "named", - "name": "any" + "name": "int" } }, "Fax": { - "arguments": {}, "type": { - "type": "named", - "name": "any" + "type": "nullable", + "underlying_type": { + "type": "named", + "name": "varchar" + } } }, "FirstName": { - "arguments": {}, "type": { "type": "named", - "name": "any" + "name": "varchar" } }, "HireDate": { - "arguments": {}, "type": { - "type": "named", - "name": "any" + "type": "nullable", + "underlying_type": { + "type": "named", + "name": "timestamp" + } } }, "LastName": { - "arguments": {}, "type": { "type": "named", - "name": "any" + "name": "varchar" } }, "Phone": { - "arguments": {}, "type": { - "type": "named", - "name": "any" + "type": "nullable", + "underlying_type": { + "type": "named", + "name": "varchar" + } } }, "PostalCode": { - "arguments": {}, "type": { - "type": "named", - "name": "any" + "type": "nullable", + "underlying_type": { + "type": "named", + "name": "varchar" + } } }, "ReportsTo": { - "arguments": {}, "type": { - "type": "named", - "name": "any" + "type": "nullable", + "underlying_type": { + "type": "named", + "name": "int" + } } }, "State": { - "arguments": {}, "type": { - "type": "named", - "name": "any" + "type": "nullable", + "underlying_type": { + "type": "named", + "name": "varchar" + } } }, "Title": { - "arguments": {}, "type": { - "type": "named", - "name": "any" + "type": "nullable", + "underlying_type": { + "type": "named", + "name": "varchar" + } } } } @@ -418,17 +1723,18 @@ expression: result "Genre": { "fields": { "GenreId": { - "arguments": {}, "type": { "type": "named", - "name": "any" + "name": "int" } }, "Name": { - "arguments": {}, "type": { - "type": "named", - "name": "any" + "type": "nullable", + "underlying_type": { + "type": "named", + "name": "varchar" + } } } } @@ -436,371 +1742,722 @@ expression: result "Invoice": { "fields": { "BillingAddress": { - "arguments": {}, "type": { - "type": "named", - "name": "any" + "type": "nullable", + "underlying_type": { + "type": "named", + "name": "varchar" + } } }, "BillingCity": { - "arguments": {}, "type": { - "type": "named", - "name": "any" + "type": "nullable", + "underlying_type": { + "type": "named", + "name": "varchar" + } } }, "BillingCountry": { - "arguments": {}, "type": { - "type": "named", - "name": "any" + "type": "nullable", + "underlying_type": { + "type": "named", + "name": "varchar" + } } }, "BillingPostalCode": { - "arguments": {}, "type": { - "type": "named", - "name": "any" + "type": "nullable", + "underlying_type": { + "type": "named", + "name": "varchar" + } } }, "BillingState": { - "arguments": {}, "type": { - "type": "named", - "name": "any" + "type": "nullable", + "underlying_type": { + "type": "named", + "name": "varchar" + } } }, "CustomerId": { - "arguments": {}, "type": { "type": "named", - "name": "any" + "name": "int" } }, "InvoiceDate": { - "arguments": {}, "type": { "type": "named", - "name": "any" + "name": "timestamp" + } + }, + "InvoiceId": { + "type": { + "type": "named", + "name": "int" + } + }, + "Total": { + "type": { + "type": "named", + "name": "numeric" + } + } + } + }, + "InvoiceLine": { + "fields": { + "InvoiceId": { + "type": { + "type": "named", + "name": "int" + } + }, + "InvoiceLineId": { + "type": { + "type": "named", + "name": "int" + } + }, + "Quantity": { + "type": { + "type": "named", + "name": "int" + } + }, + "TrackId": { + "type": { + "type": "named", + "name": "int" + } + }, + "UnitPrice": { + "type": { + "type": "named", + "name": "numeric" + } + } + } + }, + "MediaType": { + "fields": { + "MediaTypeId": { + "type": { + "type": "named", + "name": "int" + } + }, + "Name": { + "type": { + "type": "nullable", + "underlying_type": { + "type": "named", + "name": "varchar" + } + } + } + } + }, + "Playlist": { + "fields": { + "Name": { + "type": { + "type": "nullable", + "underlying_type": { + "type": "named", + "name": "varchar" + } + } + }, + "PlaylistId": { + "type": { + "type": "named", + "name": "int" + } + } + } + }, + "PlaylistTrack": { + "fields": { + "PlaylistId": { + "type": { + "type": "named", + "name": "int" + } + }, + "TrackId": { + "type": { + "type": "named", + "name": "int" + } + } + } + }, + "Track": { + "fields": { + "AlbumId": { + "type": { + "type": "nullable", + "underlying_type": { + "type": "named", + "name": "int" + } + } + }, + "Bytes": { + "type": { + "type": "nullable", + "underlying_type": { + "type": "named", + "name": "int" + } + } + }, + "Composer": { + "type": { + "type": "nullable", + "underlying_type": { + "type": "named", + "name": "varchar" + } + } + }, + "GenreId": { + "type": { + "type": "nullable", + "underlying_type": { + "type": "named", + "name": "int" + } + } + }, + "MediaTypeId": { + "type": { + "type": "named", + "name": "int" + } + }, + "Milliseconds": { + "type": { + "type": "named", + "name": "int" + } + }, + "Name": { + "type": { + "type": "named", + "name": "varchar" + } + }, + "TrackId": { + "type": { + "type": "named", + "name": "int" + } + }, + "UnitPrice": { + "type": { + "type": "named", + "name": "numeric" + } + } + } + }, + "album_by_title": { + "fields": { + "AlbumId": { + "type": { + "type": "nullable", + "underlying_type": { + "type": "named", + "name": "int" + } + } + }, + "ArtistId": { + "type": { + "type": "nullable", + "underlying_type": { + "type": "named", + "name": "int" + } + } + }, + "Title": { + "type": { + "type": "nullable", + "underlying_type": { + "type": "named", + "name": "varchar" + } + } + } + } + }, + "artist": { + "fields": { + "ArtistId": { + "type": { + "type": "nullable", + "underlying_type": { + "type": "named", + "name": "int" + } + } + }, + "Name": { + "type": { + "type": "nullable", + "underlying_type": { + "type": "named", + "name": "varchar" + } + } + } + } + }, + "artist_below_id": { + "fields": { + "ArtistId": { + "type": { + "type": "nullable", + "underlying_type": { + "type": "named", + "name": "int" + } + } + }, + "Name": { + "type": { + "type": "nullable", + "underlying_type": { + "type": "named", + "name": "varchar" + } + } + } + } + }, + "geography_columns": { + "fields": { + "coord_dimension": { + "type": { + "type": "nullable", + "underlying_type": { + "type": "named", + "name": "int" + } + } + }, + "f_geography_column": { + "type": { + "type": "nullable", + "underlying_type": { + "type": "named", + "name": "name" + } + } + }, + "f_table_catalog": { + "type": { + "type": "nullable", + "underlying_type": { + "type": "named", + "name": "name" + } + } + }, + "f_table_name": { + "type": { + "type": "nullable", + "underlying_type": { + "type": "named", + "name": "name" + } + } + }, + "f_table_schema": { + "type": { + "type": "nullable", + "underlying_type": { + "type": "named", + "name": "name" + } } }, - "InvoiceId": { - "arguments": {}, + "srid": { "type": { - "type": "named", - "name": "any" + "type": "nullable", + "underlying_type": { + "type": "named", + "name": "int" + } } }, - "Total": { - "arguments": {}, + "type": { "type": { - "type": "named", - "name": "any" + "type": "nullable", + "underlying_type": { + "type": "named", + "name": "text" + } } } } }, - "InvoiceLine": { + "geometry_columns": { "fields": { - "InvoiceId": { - "arguments": {}, + "coord_dimension": { "type": { - "type": "named", - "name": "any" + "type": "nullable", + "underlying_type": { + "type": "named", + "name": "int" + } } }, - "InvoiceLineId": { - "arguments": {}, + "f_geometry_column": { "type": { - "type": "named", - "name": "any" + "type": "nullable", + "underlying_type": { + "type": "named", + "name": "name" + } } }, - "Quantity": { - "arguments": {}, + "f_table_catalog": { "type": { - "type": "named", - "name": "any" + "type": "nullable", + "underlying_type": { + "type": "named", + "name": "varchar" + } } }, - "TrackId": { - "arguments": {}, + "f_table_name": { "type": { - "type": "named", - "name": "any" + "type": "nullable", + "underlying_type": { + "type": "named", + "name": "name" + } } }, - "UnitPrice": { - "arguments": {}, + "f_table_schema": { "type": { - "type": "named", - "name": "any" + "type": "nullable", + "underlying_type": { + "type": "named", + "name": "name" + } } - } - } - }, - "MediaType": { - "fields": { - "MediaTypeId": { - "arguments": {}, + }, + "srid": { "type": { - "type": "named", - "name": "any" + "type": "nullable", + "underlying_type": { + "type": "named", + "name": "int" + } } }, - "Name": { - "arguments": {}, + "type": { "type": { - "type": "named", - "name": "any" + "type": "nullable", + "underlying_type": { + "type": "named", + "name": "varchar" + } } } } }, - "Playlist": { + "layer": { "fields": { - "Name": { - "arguments": {}, + "child_id": { "type": { - "type": "named", - "name": "any" + "type": "nullable", + "underlying_type": { + "type": "named", + "name": "int" + } } }, - "PlaylistId": { - "arguments": {}, + "feature_column": { "type": { "type": "named", - "name": "any" + "name": "varchar" } - } - } - }, - "PlaylistTrack": { - "fields": { - "PlaylistId": { - "arguments": {}, + }, + "feature_type": { "type": { "type": "named", - "name": "any" + "name": "int" } }, - "TrackId": { - "arguments": {}, + "layer_id": { "type": { "type": "named", - "name": "any" + "name": "int" } - } - } - }, - "Track": { - "fields": { - "AlbumId": { - "arguments": {}, + }, + "level": { "type": { "type": "named", - "name": "any" + "name": "int" } }, - "Bytes": { - "arguments": {}, + "schema_name": { "type": { "type": "named", - "name": "any" + "name": "varchar" } }, - "Composer": { - "arguments": {}, + "table_name": { "type": { "type": "named", - "name": "any" + "name": "varchar" } }, - "GenreId": { - "arguments": {}, + "topology_id": { "type": { "type": "named", - "name": "any" + "name": "int" } - }, - "MediaTypeId": { - "arguments": {}, + } + } + }, + "spatial_ref_sys": { + "fields": { + "auth_name": { "type": { - "type": "named", - "name": "any" + "type": "nullable", + "underlying_type": { + "type": "named", + "name": "varchar" + } } }, - "Milliseconds": { - "arguments": {}, + "auth_srid": { "type": { - "type": "named", - "name": "any" + "type": "nullable", + "underlying_type": { + "type": "named", + "name": "int" + } } }, - "Name": { - "arguments": {}, + "proj4text": { "type": { - "type": "named", - "name": "any" + "type": "nullable", + "underlying_type": { + "type": "named", + "name": "varchar" + } } }, - "TrackId": { - "arguments": {}, + "srid": { "type": { "type": "named", - "name": "any" + "name": "int" } }, - "UnitPrice": { - "arguments": {}, + "srtext": { "type": { - "type": "named", - "name": "any" + "type": "nullable", + "underlying_type": { + "type": "named", + "name": "varchar" + } } } } }, - "geography_columns": { + "topology": { "fields": { - "coord_dimension": { - "arguments": {}, + "hasz": { "type": { "type": "named", - "name": "any" + "name": "bool" } }, - "f_geography_column": { - "arguments": {}, + "id": { "type": { "type": "named", - "name": "any" + "name": "int" } }, - "f_table_catalog": { - "arguments": {}, + "name": { "type": { "type": "named", - "name": "any" + "name": "varchar" } }, - "f_table_name": { - "arguments": {}, + "precision": { "type": { "type": "named", - "name": "any" + "name": "float8" } }, - "f_table_schema": { - "arguments": {}, + "srid": { "type": { "type": "named", - "name": "any" + "name": "int" + } + } + } + }, + "value_types": { + "fields": { + "bool": { + "type": { + "type": "nullable", + "underlying_type": { + "type": "named", + "name": "bool" + } } }, - "srid": { - "arguments": {}, + "char": { "type": { - "type": "named", - "name": "any" + "type": "nullable", + "underlying_type": { + "type": "named", + "name": "char" + } } }, - "type": { - "arguments": {}, + "date": { "type": { - "type": "named", - "name": "any" + "type": "nullable", + "underlying_type": { + "type": "named", + "name": "date" + } } - } - } - }, - "geometry_columns": { - "fields": { - "coord_dimension": { - "arguments": {}, + }, + "float4": { "type": { - "type": "named", - "name": "any" + "type": "nullable", + "underlying_type": { + "type": "named", + "name": "float4" + } } }, - "f_geometry_column": { - "arguments": {}, + "float8": { "type": { - "type": "named", - "name": "any" + "type": "nullable", + "underlying_type": { + "type": "named", + "name": "float8" + } } }, - "f_table_catalog": { - "arguments": {}, + "int": { "type": { - "type": "named", - "name": "any" + "type": "nullable", + "underlying_type": { + "type": "named", + "name": "int" + } } }, - "f_table_name": { - "arguments": {}, + "int2": { "type": { - "type": "named", - "name": "any" + "type": "nullable", + "underlying_type": { + "type": "named", + "name": "int2" + } } }, - "f_table_schema": { - "arguments": {}, + "int8": { "type": { - "type": "named", - "name": "any" + "type": "nullable", + "underlying_type": { + "type": "named", + "name": "int8" + } } }, - "srid": { - "arguments": {}, + "numeric": { "type": { - "type": "named", - "name": "any" + "type": "nullable", + "underlying_type": { + "type": "named", + "name": "numeric" + } } }, - "type": { - "arguments": {}, + "text": { "type": { - "type": "named", - "name": "any" + "type": "nullable", + "underlying_type": { + "type": "named", + "name": "text" + } } - } - } - }, - "spatial_ref_sys": { - "fields": { - "auth_name": { - "arguments": {}, + }, + "time": { "type": { - "type": "named", - "name": "any" + "type": "nullable", + "underlying_type": { + "type": "named", + "name": "time" + } } }, - "auth_srid": { - "arguments": {}, + "timestamp": { "type": { - "type": "named", - "name": "any" + "type": "nullable", + "underlying_type": { + "type": "named", + "name": "timestamp" + } } }, - "proj4text": { - "arguments": {}, + "timestamptz": { "type": { - "type": "named", - "name": "any" + "type": "nullable", + "underlying_type": { + "type": "named", + "name": "timestamptz" + } } }, - "srid": { - "arguments": {}, + "timetz": { "type": { - "type": "named", - "name": "any" + "type": "nullable", + "underlying_type": { + "type": "named", + "name": "timetz" + } } }, - "srtext": { - "arguments": {}, + "uuid": { "type": { - "type": "named", - "name": "any" + "type": "nullable", + "underlying_type": { + "type": "named", + "name": "uuid" + } + } + }, + "varchar": { + "type": { + "type": "nullable", + "underlying_type": { + "type": "named", + "name": "varchar" + } } } } @@ -809,6 +2466,7 @@ expression: result "collections": [ { "name": "Album", + "description": "The record of all albums", "arguments": {}, "type": "Album", "deletable": false, @@ -824,12 +2482,13 @@ expression: result "column_mapping": { "ArtistId": "ArtistId" }, - "foreign_collection": "Album" + "foreign_collection": "Artist" } } }, { "name": "Artist", + "description": "The record of all artists", "arguments": {}, "type": "Artist", "deletable": false, @@ -844,6 +2503,7 @@ expression: result }, { "name": "Customer", + "description": "The record of all customers", "arguments": {}, "type": "Customer", "deletable": false, @@ -859,7 +2519,7 @@ expression: result "column_mapping": { "SupportRepId": "EmployeeId" }, - "foreign_collection": "Customer" + "foreign_collection": "Employee" } } }, @@ -915,7 +2575,7 @@ expression: result "column_mapping": { "CustomerId": "CustomerId" }, - "foreign_collection": "Invoice" + "foreign_collection": "Customer" } } }, @@ -936,13 +2596,13 @@ expression: result "column_mapping": { "InvoiceId": "InvoiceId" }, - "foreign_collection": "InvoiceLine" + "foreign_collection": "Invoice" }, "FK_InvoiceLineTrackId": { "column_mapping": { "TrackId": "TrackId" }, - "foreign_collection": "InvoiceLine" + "foreign_collection": "Track" } } }, @@ -992,13 +2652,13 @@ expression: result "column_mapping": { "PlaylistId": "PlaylistId" }, - "foreign_collection": "PlaylistTrack" + "foreign_collection": "Playlist" }, "FK_PlaylistTrackTrackId": { "column_mapping": { "TrackId": "TrackId" }, - "foreign_collection": "PlaylistTrack" + "foreign_collection": "Track" } } }, @@ -1019,19 +2679,19 @@ expression: result "column_mapping": { "AlbumId": "AlbumId" }, - "foreign_collection": "Track" + "foreign_collection": "Album" }, "FK_TrackGenreId": { "column_mapping": { "GenreId": "GenreId" }, - "foreign_collection": "Track" + "foreign_collection": "Genre" }, "FK_TrackMediaTypeId": { "column_mapping": { "MediaTypeId": "MediaTypeId" }, - "foreign_collection": "Track" + "foreign_collection": "MediaType" } } }, @@ -1051,6 +2711,35 @@ expression: result "uniqueness_constraints": {}, "foreign_keys": {} }, + { + "name": "layer", + "arguments": {}, + "type": "layer", + "deletable": false, + "uniqueness_constraints": { + "layer_pkey": { + "unique_columns": [ + "layer_id", + "topology_id" + ] + }, + "layer_schema_name_table_name_feature_column_key": { + "unique_columns": [ + "feature_column", + "schema_name", + "table_name" + ] + } + }, + "foreign_keys": { + "layer_topology_id_fkey": { + "column_mapping": { + "topology_id": "id" + }, + "foreign_collection": "topology" + } + } + }, { "name": "spatial_ref_sys", "arguments": {}, @@ -1064,6 +2753,231 @@ expression: result } }, "foreign_keys": {} + }, + { + "name": "topology", + "arguments": {}, + "type": "topology", + "deletable": false, + "uniqueness_constraints": { + "topology_name_key": { + "unique_columns": [ + "name" + ] + }, + "topology_pkey": { + "unique_columns": [ + "id" + ] + } + }, + "foreign_keys": {} + }, + { + "name": "album_by_title", + "arguments": { + "id": { + "type": { + "type": "nullable", + "underlying_type": { + "type": "named", + "name": "int" + } + } + }, + "title": { + "type": { + "type": "nullable", + "underlying_type": { + "type": "named", + "name": "varchar" + } + } + } + }, + "type": "album_by_title", + "deletable": false, + "uniqueness_constraints": {}, + "foreign_keys": {} + }, + { + "name": "artist", + "arguments": {}, + "type": "artist", + "deletable": false, + "uniqueness_constraints": {}, + "foreign_keys": {} + }, + { + "name": "artist_below_id", + "arguments": { + "id": { + "type": { + "type": "nullable", + "underlying_type": { + "type": "named", + "name": "int" + } + } + } + }, + "type": "artist_below_id", + "deletable": false, + "uniqueness_constraints": {}, + "foreign_keys": {} + }, + { + "name": "value_types", + "arguments": { + "bool": { + "type": { + "type": "nullable", + "underlying_type": { + "type": "named", + "name": "bool" + } + } + }, + "char": { + "type": { + "type": "nullable", + "underlying_type": { + "type": "named", + "name": "char" + } + } + }, + "date": { + "type": { + "type": "nullable", + "underlying_type": { + "type": "named", + "name": "date" + } + } + }, + "float4": { + "type": { + "type": "nullable", + "underlying_type": { + "type": "named", + "name": "float4" + } + } + }, + "float8": { + "type": { + "type": "nullable", + "underlying_type": { + "type": "named", + "name": "float8" + } + } + }, + "int": { + "type": { + "type": "nullable", + "underlying_type": { + "type": "named", + "name": "int" + } + } + }, + "int2": { + "type": { + "type": "nullable", + "underlying_type": { + "type": "named", + "name": "int2" + } + } + }, + "int8": { + "type": { + "type": "nullable", + "underlying_type": { + "type": "named", + "name": "int8" + } + } + }, + "numeric": { + "type": { + "type": "nullable", + "underlying_type": { + "type": "named", + "name": "numeric" + } + } + }, + "text": { + "type": { + "type": "nullable", + "underlying_type": { + "type": "named", + "name": "text" + } + } + }, + "time": { + "type": { + "type": "nullable", + "underlying_type": { + "type": "named", + "name": "time" + } + } + }, + "timestamp": { + "type": { + "type": "nullable", + "underlying_type": { + "type": "named", + "name": "timestamp" + } + } + }, + "timestamptz": { + "type": { + "type": "nullable", + "underlying_type": { + "type": "named", + "name": "timestamptz" + } + } + }, + "timetz": { + "type": { + "type": "nullable", + "underlying_type": { + "type": "named", + "name": "timetz" + } + } + }, + "uuid": { + "type": { + "type": "nullable", + "underlying_type": { + "type": "named", + "name": "uuid" + } + } + }, + "varchar": { + "type": { + "type": "nullable", + "underlying_type": { + "type": "named", + "name": "varchar" + } + } + } + }, + "type": "value_types", + "deletable": false, + "uniqueness_constraints": {}, + "foreign_keys": {} } ], "functions": [], diff --git a/justfile b/justfile index 4386f50e..388ee532 100644 --- a/justfile +++ b/justfile @@ -3,9 +3,8 @@ set shell := ["bash", "-c"] CONNECTOR_IMAGE_NAME := "ghcr.io/hasura/sqlserver-agent-rs" CONNECTOR_IMAGE_TAG := "dev" CONNECTOR_IMAGE := CONNECTOR_IMAGE_NAME + ":" + CONNECTOR_IMAGE_TAG -POSTGRESQL_CONNECTION_STRING := "sqlserverql://sqlserver:password@localhost:64002" CHINOOK_DEPLOYMENT := "static/chinook-deployment.json" - +SQLSERVER_CONNECTION_STRING := "DRIVER={ODBC Driver 18 for SQL Server};SERVER=127.0.0.1,64003;Uid=SA;Database=Chinook;Pwd=Password!" # check everything check: format-check find-unused-dependencies build lint test @@ -21,47 +20,6 @@ run: start-dependencies RUST_LOG=INFO \ cargo run --release -- serve --configuration {{CHINOOK_DEPLOYMENT}} -# run the connector inside a Docker image -run-in-docker: build-docker-with-nix start-dependencies - #!/usr/bin/env bash - set -e -u -o pipefail - - configuration_file="$(mktemp)" - trap 'rm -f "$configuration_file"' EXIT - - echo '> Generating the configuration...' - docker run \ - --name=sqlserver-ndc-configuration \ - --rm \ - --detach \ - --platform=linux/amd64 \ - --net='sqlserver-ndc_default' \ - --publish='9100:9100' \ - {{CONNECTOR_IMAGE}} \ - configuration serve - trap 'docker stop sqlserver-ndc-configuration' EXIT - CONFIGURATION_SERVER_URL='http://localhost:9100/' - ./scripts/wait-until --timeout=30 --report -- nc -z localhost 9100 - curl -fsS "$CONFIGURATION_SERVER_URL" \ - | jq --arg sqlserver_database_url 'sqlserverql://sqlserver:password@sqlserver' '. + {"sqlserver_database_url": $sqlserver_database_url}' \ - | curl -fsS "$CONFIGURATION_SERVER_URL" -H 'Content-Type: application/json' -d @- \ - > "$configuration_file" - - echo '> Starting the server...' - docker run \ - --name=sqlserver-ndc \ - --rm \ - --interactive \ - --tty \ - --platform=linux/amd64 \ - --net='sqlserver-ndc_default' \ - --publish='8100:8100' \ - --env=RUST_LOG='INFO' \ - --mount="type=bind,source=${configuration_file},target=/deployment.json,readonly=true" \ - {{CONNECTOR_IMAGE}} \ - serve \ - --configuration='/deployment.json' - # watch the code, then test and re-run on changes dev: start-dependencies RUST_LOG=INFO \ @@ -71,6 +29,23 @@ dev: start-dependencies -x clippy \ -x 'run -- serve --configuration {{CHINOOK_DEPLOYMENT}}' +# watch the code, then test and re-run config server ron changes +dev-config: start-dependencies + RUST_LOG=DEBUG \ + cargo watch -i "tests/snapshots/*" \ + -c \ + -x test \ + -x clippy \ + -x 'run -- configuration serve' + +test-introspection: + #!/bin/bash + + CONFIGURATION_SERVER_URL='http://localhost:9100/' + curl -fsS "$CONFIGURATION_SERVER_URL" \ + | jq --arg sqlserver_database_url '{{ SQLSERVER_CONNECTION_STRING }}' '. + {"mssql_connection_string": $sqlserver_database_url}' \ + | curl -fsS "$CONFIGURATION_SERVER_URL" -H 'Content-Type: application/json' -d @- \ + # watch the code, and re-run on changes watch-run: start-dependencies RUST_LOG=DEBUG \ @@ -107,25 +82,6 @@ test-integrated: http://localhost:3000/graphql \ -d '{ "query": "query { AlbumByID(AlbumId: 1) { Title } } " }' -# re-generate the deployment configuration file -generate-chinook-configuration: build - #!/usr/bin/env bash - set -e -u - - cargo run --quiet -- configuration serve & - CONFIGURATION_SERVER_PID=$! - trap "kill $CONFIGURATION_SERVER_PID" EXIT - ./scripts/wait-until --timeout=30 --report -- nc -z localhost 9100 - if ! kill -0 "$CONFIGURATION_SERVER_PID"; then - echo >&2 'The server stopped abruptly.' - exit 1 - fi - curl -fsS http://localhost:9100 \ - | jq --arg sqlserver_database_url '{{POSTGRESQL_CONNECTION_STRING}}' '. + {"sqlserver_database_url": $sqlserver_database_url}' \ - | curl -fsS http://localhost:9100 -H 'Content-Type: application/json' -d @- \ - | jq . \ - > '{{CHINOOK_DEPLOYMENT}}' - # run sqlserver start-dependencies: # start sqlserver