diff --git a/Cargo.lock b/Cargo.lock
index ba3bf32..e11c28a 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -17,6 +17,20 @@ version = "1.0.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f26201604c87b1e01bd3d98f8d5d9a8fcbb815e8cedb41ffccbeb4bf593a35fe"
+[[package]]
+name = "ahash"
+version = "0.8.11"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "e89da841a80418a9b391ebaea17f5c112ffaaa96f621d2c285b5174da76b9011"
+dependencies = [
+ "cfg-if",
+ "getrandom",
+ "once_cell",
+ "serde",
+ "version_check",
+ "zerocopy 0.7.35",
+]
+
[[package]]
name = "aho-corasick"
version = "1.1.3"
@@ -26,6 +40,12 @@ dependencies = [
"memchr",
]
+[[package]]
+name = "allocator-api2"
+version = "0.2.18"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "5c6cb57a04249c6480766f7f7cef5467412af1490f8d1e243141daddada3264f"
+
[[package]]
name = "android-tzdata"
version = "0.1.1"
@@ -115,7 +135,7 @@ checksum = "16e62a023e7c117e27523144c5d2459f4397fcc3cab0085af8e2224f643a0193"
dependencies = [
"proc-macro2",
"quote",
- "syn",
+ "syn 2.0.72",
]
[[package]]
@@ -126,7 +146,16 @@ checksum = "6e0c28dcc82d7c8ead5cb13beb15405b57b8546e93215673ff8ca0349a028107"
dependencies = [
"proc-macro2",
"quote",
- "syn",
+ "syn 2.0.72",
+]
+
+[[package]]
+name = "atoi"
+version = "2.0.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "f28d99ec8bfea296261ca1af174f24225171fea9664ba9003cbebee704810528"
+dependencies = [
+ "num-traits",
]
[[package]]
@@ -250,6 +279,27 @@ version = "0.22.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "72b3254f16251a8381aa12e40e3c4d2f0199f8c6508fbecb9d91f575e0fbb8c6"
+[[package]]
+name = "base64ct"
+version = "1.6.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "8c3c1a368f70d6cf7302d78f8f7093da241fb8e8807c05cc9e51a125895a6d5b"
+
+[[package]]
+name = "bit-set"
+version = "0.5.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "0700ddab506f33b20a03b13996eccd309a48e5ff77d0d95926aa0210fb4e95f1"
+dependencies = [
+ "bit-vec",
+]
+
+[[package]]
+name = "bit-vec"
+version = "0.6.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "349f9b6a179ed607305526ca489b34ad0a41aed5f7980fa90eb03160b69598fb"
+
[[package]]
name = "bitflags"
version = "1.3.2"
@@ -261,6 +311,18 @@ name = "bitflags"
version = "2.6.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b048fb63fd8b5923fc5aa7b340d8e156aec7ec02f0c78fa8a6ddc2613f6f71de"
+dependencies = [
+ "serde",
+]
+
+[[package]]
+name = "block-buffer"
+version = "0.10.4"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "3078c7629b62d3f0439517fa394996acacc5cbc91c5a20d8c658e77abd503a71"
+dependencies = [
+ "generic-array",
+]
[[package]]
name = "build-data"
@@ -278,6 +340,12 @@ version = "3.16.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "79296716171880943b8470b5f8d03aa55eb2e645a4874bdbb28adb49162e012c"
+[[package]]
+name = "bytecount"
+version = "0.6.8"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "5ce89b21cab1437276d2650d57e971f9d548a2d9037cc231abdc0562b97498ce"
+
[[package]]
name = "byteorder"
version = "1.5.0"
@@ -349,10 +417,10 @@ version = "4.5.11"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5d029b67f89d30bbb547c89fd5161293c0aec155fc691d7924b64550662db93e"
dependencies = [
- "heck",
+ "heck 0.5.0",
"proc-macro2",
"quote",
- "syn",
+ "syn 2.0.72",
]
[[package]]
@@ -395,6 +463,12 @@ dependencies = [
"windows-sys 0.52.0",
]
+[[package]]
+name = "const-oid"
+version = "0.9.6"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "c2459377285ad874054d797f3ccebf984978aa39129f6eafde5cdc8315b612f8"
+
[[package]]
name = "core-foundation"
version = "0.9.4"
@@ -411,6 +485,30 @@ version = "0.8.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "06ea2b9bc92be3c2baa9334a323ebca2d6f074ff852cd1d7b11064035cd3868f"
+[[package]]
+name = "cpufeatures"
+version = "0.2.13"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "51e852e6dc9a5bed1fae92dd2375037bf2b768725bf3be87811edee3249d09ad"
+dependencies = [
+ "libc",
+]
+
+[[package]]
+name = "crc"
+version = "3.2.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "69e6e4d7b33a94f0991c26729976b10ebde1d34c3ee82408fb536164fa10d636"
+dependencies = [
+ "crc-catalog",
+]
+
+[[package]]
+name = "crc-catalog"
+version = "2.4.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "19d374276b40fb8bbdee95aef7c7fa6b5316ec764510eb64b8dd0e2ed0d7e7f5"
+
[[package]]
name = "crc32fast"
version = "1.4.2"
@@ -429,12 +527,31 @@ dependencies = [
"crossbeam-utils",
]
+[[package]]
+name = "crossbeam-queue"
+version = "0.3.11"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "df0346b5d5e76ac2fe4e327c5fd1118d6be7c51dfb18f9b7922923f287471e35"
+dependencies = [
+ "crossbeam-utils",
+]
+
[[package]]
name = "crossbeam-utils"
version = "0.8.20"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "22ec99545bb0ed0ea7bb9b8e1e9122ea386ff8a48c0922e43f36d45ab09e0e80"
+[[package]]
+name = "crypto-common"
+version = "0.1.6"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "1bfb12502f3fc46cca1bb51ac28df9d618d813cdc3d2f25b9fe775a34af26bb3"
+dependencies = [
+ "generic-array",
+ "typenum",
+]
+
[[package]]
name = "darling"
version = "0.20.10"
@@ -456,7 +573,7 @@ dependencies = [
"proc-macro2",
"quote",
"strsim",
- "syn",
+ "syn 2.0.72",
]
[[package]]
@@ -467,7 +584,18 @@ checksum = "d336a2a514f6ccccaa3e09b02d41d35330c07ddf03a62165fcec10bb561c7806"
dependencies = [
"darling_core",
"quote",
- "syn",
+ "syn 2.0.72",
+]
+
+[[package]]
+name = "der"
+version = "0.7.9"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "f55bf8e7b65898637379c1b74eb1551107c8294ed26d855ceb9fd1a09cfc9bc0"
+dependencies = [
+ "const-oid",
+ "pem-rfc7468",
+ "zeroize",
]
[[package]]
@@ -480,12 +608,30 @@ dependencies = [
"serde",
]
+[[package]]
+name = "digest"
+version = "0.10.7"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "9ed9a281f7bc9b7576e61468ba615a66a5c8cfdff42420a70aa82701a3b1e292"
+dependencies = [
+ "block-buffer",
+ "const-oid",
+ "crypto-common",
+ "subtle",
+]
+
[[package]]
name = "dotenv"
version = "0.15.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "77c90badedccf4105eca100756a0b1289e191f6fcbdadd3cee1d2f614f97da8f"
+[[package]]
+name = "dotenvy"
+version = "0.15.7"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "1aaf95b3e5c8f23aa320147307562d361db0ae0d51242340f558153b4eb2439b"
+
[[package]]
name = "dyn-clone"
version = "1.0.17"
@@ -497,6 +643,9 @@ name = "either"
version = "1.13.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "60b1af1c220855b6ceac025d3f6ecdd2b7c4894bfe9cd9bda4fbb4bc7c0d4cf0"
+dependencies = [
+ "serde",
+]
[[package]]
name = "encode_unicode"
@@ -529,6 +678,33 @@ dependencies = [
"windows-sys 0.52.0",
]
+[[package]]
+name = "etcetera"
+version = "0.8.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "136d1b5283a1ab77bd9257427ffd09d8667ced0570b6f938942bc7568ed5b943"
+dependencies = [
+ "cfg-if",
+ "home",
+ "windows-sys 0.48.0",
+]
+
+[[package]]
+name = "event-listener"
+version = "2.5.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "0206175f82b8d6bf6652ff7d71a1e27fd2e4efde587fd368662814d6ec1d9ce0"
+
+[[package]]
+name = "fancy-regex"
+version = "0.11.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "b95f7c0680e4142284cf8b22c14a476e87d61b004a3a0861872b32ef7ead40a2"
+dependencies = [
+ "bit-set",
+ "regex",
+]
+
[[package]]
name = "fastrand"
version = "2.1.0"
@@ -545,6 +721,17 @@ dependencies = [
"miniz_oxide",
]
+[[package]]
+name = "flume"
+version = "0.11.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "55ac459de2512911e4b674ce33cf20befaba382d05b62b008afc1c8b57cbf181"
+dependencies = [
+ "futures-core",
+ "futures-sink",
+ "spin",
+]
+
[[package]]
name = "fnv"
version = "1.0.7"
@@ -575,6 +762,16 @@ dependencies = [
"percent-encoding",
]
+[[package]]
+name = "fraction"
+version = "0.13.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "3027ae1df8d41b4bed2241c8fdad4acc1e7af60c8e17743534b545e77182d678"
+dependencies = [
+ "lazy_static",
+ "num",
+]
+
[[package]]
name = "futures-channel"
version = "0.3.30"
@@ -582,6 +779,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "eac8f7d7865dcb88bd4373ab671c8cf4508703796caa2b1985a9ca867b3fcb78"
dependencies = [
"futures-core",
+ "futures-sink",
]
[[package]]
@@ -601,6 +799,17 @@ dependencies = [
"futures-util",
]
+[[package]]
+name = "futures-intrusive"
+version = "0.5.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "1d930c203dd0b6ff06e0201a4a2fe9149b43c684fd4420555b26d21b1a02956f"
+dependencies = [
+ "futures-core",
+ "lock_api",
+ "parking_lot",
+]
+
[[package]]
name = "futures-io"
version = "0.3.30"
@@ -615,7 +824,7 @@ checksum = "87750cf4b7a4c0625b1529e4c543c2182106e4dedc60a2a6455e00d212c489ac"
dependencies = [
"proc-macro2",
"quote",
- "syn",
+ "syn 2.0.72",
]
[[package]]
@@ -647,6 +856,16 @@ dependencies = [
"slab",
]
+[[package]]
+name = "generic-array"
+version = "0.14.7"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "85649ca51fd72272d7821adaf274ad91c288277713d9c18820d8499a7ff69e9a"
+dependencies = [
+ "typenum",
+ "version_check",
+]
+
[[package]]
name = "getrandom"
version = "0.2.15"
@@ -654,8 +873,10 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c4567c8db10ae91089c99af84c68c38da3ec2f087c3f82960bcdbf3656b6f4d7"
dependencies = [
"cfg-if",
+ "js-sys",
"libc",
"wasi",
+ "wasm-bindgen",
]
[[package]]
@@ -700,6 +921,28 @@ name = "hashbrown"
version = "0.14.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e5274423e17b7c9fc20b6e7e208532f9b19825d82dfd615708b70edd83df41f1"
+dependencies = [
+ "ahash",
+ "allocator-api2",
+]
+
+[[package]]
+name = "hashlink"
+version = "0.8.4"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "e8094feaf31ff591f651a2664fb9cfd92bba7a60ce3197265e9482ebe753c8f7"
+dependencies = [
+ "hashbrown 0.14.5",
+]
+
+[[package]]
+name = "heck"
+version = "0.4.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "95505c38b4572b2d910cecb0281560f54b440a19336cbbcb27bf6ce6adc6f5a8"
+dependencies = [
+ "unicode-segmentation",
+]
[[package]]
name = "heck"
@@ -719,6 +962,33 @@ version = "0.4.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7f24254aa9a54b5c858eaee2f5bccdb46aaf0e486a595ed5fd8f86ba55232a70"
+[[package]]
+name = "hkdf"
+version = "0.12.4"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "7b5f8eb2ad728638ea2c7d47a21db23b7b58a72ed6a38256b8a1849f15fbbdf7"
+dependencies = [
+ "hmac",
+]
+
+[[package]]
+name = "hmac"
+version = "0.12.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "6c49c37c09c17a53d937dfbb742eb3a961d65a994e6bcdcf37e7399d0cc8ab5e"
+dependencies = [
+ "digest",
+]
+
+[[package]]
+name = "home"
+version = "0.5.9"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "e3d1354bf6b7235cb4a0576c2619fd4ed18183f689b12b006a0ee7329eeff9a5"
+dependencies = [
+ "windows-sys 0.52.0",
+]
+
[[package]]
name = "http"
version = "0.2.12"
@@ -847,6 +1117,26 @@ dependencies = [
"unicode-normalization",
]
+[[package]]
+name = "include_dir"
+version = "0.7.4"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "923d117408f1e49d914f1a379a309cffe4f18c05cf4e3d12e613a15fc81bd0dd"
+dependencies = [
+ "glob",
+ "include_dir_macros",
+]
+
+[[package]]
+name = "include_dir_macros"
+version = "0.7.4"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "7cab85a7ed0bd5f0e76d93846e0147172bed2e2d3f859bcc33a8d9699cad1a75"
+dependencies = [
+ "proc-macro2",
+ "quote",
+]
+
[[package]]
name = "indexmap"
version = "1.9.3"
@@ -893,6 +1183,15 @@ version = "1.70.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7943c866cc5cd64cbc25b2e01621d07fa8eb2a1a23160ee81ce38704e97b8ecf"
+[[package]]
+name = "iso8601"
+version = "0.6.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "924e5d73ea28f59011fec52a0d12185d496a9b075d360657aed2a5707f701153"
+dependencies = [
+ "nom",
+]
+
[[package]]
name = "itertools"
version = "0.12.1"
@@ -951,11 +1250,44 @@ dependencies = [
"wasm-bindgen",
]
+[[package]]
+name = "jsonschema"
+version = "0.17.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "2a071f4f7efc9a9118dfb627a0a94ef247986e1ab8606a4c806ae2b3aa3b6978"
+dependencies = [
+ "ahash",
+ "anyhow",
+ "base64 0.21.7",
+ "bytecount",
+ "clap",
+ "fancy-regex",
+ "fraction",
+ "getrandom",
+ "iso8601",
+ "itoa",
+ "memchr",
+ "num-cmp",
+ "once_cell",
+ "parking_lot",
+ "percent-encoding",
+ "regex",
+ "reqwest",
+ "serde",
+ "serde_json",
+ "time",
+ "url",
+ "uuid",
+]
+
[[package]]
name = "lazy_static"
version = "1.5.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "bbd2bcb4c963f2ddae06a2efc7e9f3591312473c50c6685e1f298068316e66fe"
+dependencies = [
+ "spin",
+]
[[package]]
name = "libc"
@@ -973,6 +1305,23 @@ dependencies = [
"winapi",
]
+[[package]]
+name = "libm"
+version = "0.2.8"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "4ec2a862134d2a7d32d7983ddcdd1c4923530833c9f2ea1a44fc5fa473989058"
+
+[[package]]
+name = "libsqlite3-sys"
+version = "0.27.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "cf4e226dcd58b4be396f7bd3c20da8fdee2911400705297ba7d2d7cc2c30f716"
+dependencies = [
+ "cc",
+ "pkg-config",
+ "vcpkg",
+]
+
[[package]]
name = "linked-hash-map"
version = "0.5.6"
@@ -1016,6 +1365,16 @@ version = "0.7.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0e7465ac9959cc2b1404e8e2367b43684a6d13790fe23056cc8c6c5a6b7bcb94"
+[[package]]
+name = "md-5"
+version = "0.10.6"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "d89e7ee0cfbedfc4da3340218492196241d89eefb6dab27de5df917a6d2e78cf"
+dependencies = [
+ "cfg-if",
+ "digest",
+]
+
[[package]]
name = "memchr"
version = "2.7.4"
@@ -1038,6 +1397,12 @@ dependencies = [
"unicase",
]
+[[package]]
+name = "minimal-lexical"
+version = "0.2.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "68354c5c6bd36d73ff3feceb05efa59b6acb7626617f4962be322a825e61f79a"
+
[[package]]
name = "miniz_oxide"
version = "0.7.4"
@@ -1093,6 +1458,8 @@ dependencies = [
"jni",
"log",
"mime",
+ "ndc-calcite-schema",
+ "ndc-calcite-values",
"ndc-models",
"ndc-sdk",
"once_cell",
@@ -1122,8 +1489,9 @@ dependencies = [
"anyhow",
"build-data",
"clap",
+ "include_dir",
"insta",
- "schemars",
+ "ndc-calcite-schema",
"serde",
"serde_json",
"serde_yaml",
@@ -1133,21 +1501,67 @@ dependencies = [
]
[[package]]
-name = "ndc-models"
+name = "ndc-calcite-schema"
+version = "0.1.4"
+dependencies = [
+ "anyhow",
+ "clap",
+ "jni",
+ "jsonschema",
+ "ndc-calcite-values",
+ "ndc-models",
+ "ndc-sdk",
+ "once_cell",
+ "prometheus",
+ "schemars",
+ "serde",
+ "serde_json",
+ "smol_str",
+ "sqlx",
+ "thiserror",
+ "tokio",
+ "tracing",
+]
+
+[[package]]
+name = "ndc-calcite-values"
version = "0.1.4"
-source = "git+http://github.com/hasura/ndc-spec.git?tag=v0.1.4#20172e3b2552b78d16dbafcd047f559ced420309"
+dependencies = [
+ "anyhow",
+ "clap",
+ "jni",
+ "jsonschema",
+ "ndc-models",
+ "once_cell",
+ "prometheus",
+ "schemars",
+ "serde",
+ "serde_json",
+ "smol_str",
+ "sqlx",
+ "thiserror",
+ "tokio",
+ "tracing",
+]
+
+[[package]]
+name = "ndc-models"
+version = "0.1.5"
+source = "git+https://github.com/hasura/ndc-spec.git?tag=v0.1.5#78f52768bd02a8289194078a5abc2432c8e3a758"
dependencies = [
"indexmap 2.2.6",
+ "ref-cast",
"schemars",
"serde",
"serde_json",
"serde_with",
+ "smol_str",
]
[[package]]
name = "ndc-sdk"
-version = "0.1.4"
-source = "git+https://github.com/hasura/ndc-sdk-rs.git?tag=v0.1.4#29adcb5983c1237e8a5f4732d5230c2ba8ab75d3"
+version = "0.2.1"
+source = "git+https://github.com/hasura/ndc-sdk-rs.git?tag=v0.2.2#9120a826037cc16f8261c83663fef63452f4d5c6"
dependencies = [
"async-trait",
"axum",
@@ -1179,8 +1593,8 @@ dependencies = [
[[package]]
name = "ndc-test"
-version = "0.1.4"
-source = "git+http://github.com/hasura/ndc-spec.git?tag=v0.1.4#20172e3b2552b78d16dbafcd047f559ced420309"
+version = "0.1.5"
+source = "git+https://github.com/hasura/ndc-spec.git?tag=v0.1.5#78f52768bd02a8289194078a5abc2432c8e3a758"
dependencies = [
"async-trait",
"clap",
@@ -1192,11 +1606,22 @@ dependencies = [
"semver",
"serde",
"serde_json",
+ "smol_str",
"thiserror",
"tokio",
"url",
]
+[[package]]
+name = "nom"
+version = "7.1.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "d273983c5a657a70a3e8f2a01329822f3b8c8172b73826411a55751e404a0a4a"
+dependencies = [
+ "memchr",
+ "minimal-lexical",
+]
+
[[package]]
name = "nu-ansi-term"
version = "0.46.0"
@@ -1207,12 +1632,99 @@ dependencies = [
"winapi",
]
+[[package]]
+name = "num"
+version = "0.4.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "35bd024e8b2ff75562e5f34e7f4905839deb4b22955ef5e73d2fea1b9813cb23"
+dependencies = [
+ "num-bigint",
+ "num-complex",
+ "num-integer",
+ "num-iter",
+ "num-rational",
+ "num-traits",
+]
+
+[[package]]
+name = "num-bigint"
+version = "0.4.6"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "a5e44f723f1133c9deac646763579fdb3ac745e418f2a7af9cd0c431da1f20b9"
+dependencies = [
+ "num-integer",
+ "num-traits",
+]
+
+[[package]]
+name = "num-bigint-dig"
+version = "0.8.4"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "dc84195820f291c7697304f3cbdadd1cb7199c0efc917ff5eafd71225c136151"
+dependencies = [
+ "byteorder",
+ "lazy_static",
+ "libm",
+ "num-integer",
+ "num-iter",
+ "num-traits",
+ "rand",
+ "smallvec",
+ "zeroize",
+]
+
+[[package]]
+name = "num-cmp"
+version = "0.1.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "63335b2e2c34fae2fb0aa2cecfd9f0832a1e24b3b32ecec612c3426d46dc8aaa"
+
+[[package]]
+name = "num-complex"
+version = "0.4.6"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "73f88a1307638156682bada9d7604135552957b7818057dcef22705b4d509495"
+dependencies = [
+ "num-traits",
+]
+
[[package]]
name = "num-conv"
version = "0.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "51d515d32fb182ee37cda2ccdcb92950d6a3c2893aa280e540671c2cd0f3b1d9"
+[[package]]
+name = "num-integer"
+version = "0.1.46"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "7969661fd2958a5cb096e56c8e1ad0444ac2bbcd0061bd28660485a44879858f"
+dependencies = [
+ "num-traits",
+]
+
+[[package]]
+name = "num-iter"
+version = "0.1.45"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "1429034a0490724d0075ebb2bc9e875d6503c3cf69e235a8941aa757d83ef5bf"
+dependencies = [
+ "autocfg",
+ "num-integer",
+ "num-traits",
+]
+
+[[package]]
+name = "num-rational"
+version = "0.4.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "f83d14da390562dca69fc84082e73e548e1ad308d24accdedd2720017cb37824"
+dependencies = [
+ "num-bigint",
+ "num-integer",
+ "num-traits",
+]
+
[[package]]
name = "num-traits"
version = "0.2.19"
@@ -1220,6 +1732,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "071dfc062690e90b734c0b2273ce72ad0ffa95f0c74596bc250dcfd960262841"
dependencies = [
"autocfg",
+ "libm",
]
[[package]]
@@ -1260,7 +1773,7 @@ checksum = "a948666b637a0f465e8564c73e89d4dde00d72d4d473cc972f390fc3dcee7d9c"
dependencies = [
"proc-macro2",
"quote",
- "syn",
+ "syn 2.0.72",
]
[[package]]
@@ -1424,11 +1937,26 @@ checksum = "1e401f977ab385c9e4e3ab30627d6f26d00e2c73eef317493c4ec6d468726cf8"
dependencies = [
"cfg-if",
"libc",
- "redox_syscall",
+ "redox_syscall 0.5.3",
"smallvec",
"windows-targets 0.52.6",
]
+[[package]]
+name = "paste"
+version = "1.0.15"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "57c0d7b74b563b49d38dae00a0c37d4d6de9b432382b2892f0574ddcae73fd0a"
+
+[[package]]
+name = "pem-rfc7468"
+version = "0.7.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "88b39c9bfcfc231068454382784bb460aae594343fb030d46e9f50a645418412"
+dependencies = [
+ "base64ct",
+]
+
[[package]]
name = "percent-encoding"
version = "2.3.1"
@@ -1452,20 +1980,41 @@ checksum = "2f38a4412a78282e09a2cf38d195ea5420d15ba0602cb375210efbc877243965"
dependencies = [
"proc-macro2",
"quote",
- "syn",
+ "syn 2.0.72",
]
[[package]]
name = "pin-project-lite"
version = "0.2.14"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "bda66fc9667c18cb2758a2ac84d1167245054bcf85d5d1aaa6923f45801bdd02"
+checksum = "bda66fc9667c18cb2758a2ac84d1167245054bcf85d5d1aaa6923f45801bdd02"
+
+[[package]]
+name = "pin-utils"
+version = "0.1.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184"
+
+[[package]]
+name = "pkcs1"
+version = "0.7.5"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "c8ffb9f10fa047879315e6625af03c164b16962a5368d724ed16323b68ace47f"
+dependencies = [
+ "der",
+ "pkcs8",
+ "spki",
+]
[[package]]
-name = "pin-utils"
-version = "0.1.0"
+name = "pkcs8"
+version = "0.10.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184"
+checksum = "f950b2377845cebe5cf8b5165cb3cc1a5e0fa5cfa3e1f7f55707d8fd82e0a7b7"
+dependencies = [
+ "der",
+ "spki",
+]
[[package]]
name = "pkg-config"
@@ -1485,7 +2034,7 @@ version = "0.2.18"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "dee4364d9f3b902ef14fab8a1ddffb783a1cb6b4bba3bfc1fa3922732c7de97f"
dependencies = [
- "zerocopy",
+ "zerocopy 0.6.6",
]
[[package]]
@@ -1532,7 +2081,7 @@ dependencies = [
"itertools",
"proc-macro2",
"quote",
- "syn",
+ "syn 2.0.72",
]
[[package]]
@@ -1580,6 +2129,15 @@ dependencies = [
"getrandom",
]
+[[package]]
+name = "redox_syscall"
+version = "0.4.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "4722d768eff46b75989dd134e5c353f0d6296e5aaa3132e776cbdb56be7731aa"
+dependencies = [
+ "bitflags 1.3.2",
+]
+
[[package]]
name = "redox_syscall"
version = "0.5.3"
@@ -1589,6 +2147,26 @@ dependencies = [
"bitflags 2.6.0",
]
+[[package]]
+name = "ref-cast"
+version = "1.0.23"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "ccf0a6f84d5f1d581da8b41b47ec8600871962f2a528115b542b362d4b744931"
+dependencies = [
+ "ref-cast-impl",
+]
+
+[[package]]
+name = "ref-cast-impl"
+version = "1.0.23"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "bcc303e793d3734489387d205e9b186fac9c6cfacedd98cbb2e8a5943595f3e6"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "syn 2.0.72",
+]
+
[[package]]
name = "regex"
version = "1.10.5"
@@ -1692,6 +2270,26 @@ dependencies = [
"windows-sys 0.52.0",
]
+[[package]]
+name = "rsa"
+version = "0.9.6"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "5d0e5124fcb30e76a7e79bfee683a2746db83784b86289f6251b54b7950a0dfc"
+dependencies = [
+ "const-oid",
+ "digest",
+ "num-bigint-dig",
+ "num-integer",
+ "num-traits",
+ "pkcs1",
+ "pkcs8",
+ "rand_core",
+ "signature",
+ "spki",
+ "subtle",
+ "zeroize",
+]
+
[[package]]
name = "rustc-demangle"
version = "0.1.24"
@@ -1897,7 +2495,7 @@ dependencies = [
"proc-macro2",
"quote",
"serde_derive_internals",
- "syn",
+ "syn 2.0.72",
]
[[package]]
@@ -1962,7 +2560,7 @@ checksum = "e0cd7e117be63d3c3678776753929474f3b04a43a080c744d6b0ae2a8c28e222"
dependencies = [
"proc-macro2",
"quote",
- "syn",
+ "syn 2.0.72",
]
[[package]]
@@ -1973,7 +2571,7 @@ checksum = "18d26a20a969b9e3fdf2fc2d9f21eda6c40e2de84c9408bb5d3b05d499aae711"
dependencies = [
"proc-macro2",
"quote",
- "syn",
+ "syn 2.0.72",
]
[[package]]
@@ -2038,7 +2636,7 @@ dependencies = [
"darling",
"proc-macro2",
"quote",
- "syn",
+ "syn 2.0.72",
]
[[package]]
@@ -2054,6 +2652,28 @@ dependencies = [
"unsafe-libyaml",
]
+[[package]]
+name = "sha1"
+version = "0.10.6"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "e3bf829a2d51ab4a5ddf1352d8470c140cadc8301b2ae1789db023f01cedd6ba"
+dependencies = [
+ "cfg-if",
+ "cpufeatures",
+ "digest",
+]
+
+[[package]]
+name = "sha2"
+version = "0.10.8"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "793db75ad2bcafc3ffa7c68b215fee268f537982cd901d132f89c6343f3a3dc8"
+dependencies = [
+ "cfg-if",
+ "cpufeatures",
+ "digest",
+]
+
[[package]]
name = "sharded-slab"
version = "0.1.7"
@@ -2072,6 +2692,16 @@ dependencies = [
"libc",
]
+[[package]]
+name = "signature"
+version = "2.2.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "77549399552de45a898a580c1b41d445bf730df867cc44e6c0233bbc4b8329de"
+dependencies = [
+ "digest",
+ "rand_core",
+]
+
[[package]]
name = "similar"
version = "2.6.0"
@@ -2117,6 +2747,237 @@ name = "spin"
version = "0.9.8"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6980e8d7511241f8acf4aebddbb1ff938df5eebe98691418c4468d0b72a96a67"
+dependencies = [
+ "lock_api",
+]
+
+[[package]]
+name = "spki"
+version = "0.7.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "d91ed6c858b01f942cd56b37a94b3e0a1798290327d1236e4d9cf4eaca44d29d"
+dependencies = [
+ "base64ct",
+ "der",
+]
+
+[[package]]
+name = "sqlformat"
+version = "0.2.4"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "f895e3734318cc55f1fe66258926c9b910c124d47520339efecbb6c59cec7c1f"
+dependencies = [
+ "nom",
+ "unicode_categories",
+]
+
+[[package]]
+name = "sqlx"
+version = "0.7.4"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "c9a2ccff1a000a5a59cd33da541d9f2fdcd9e6e8229cc200565942bff36d0aaa"
+dependencies = [
+ "sqlx-core",
+ "sqlx-macros",
+ "sqlx-mysql",
+ "sqlx-postgres",
+ "sqlx-sqlite",
+]
+
+[[package]]
+name = "sqlx-core"
+version = "0.7.4"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "24ba59a9342a3d9bab6c56c118be528b27c9b60e490080e9711a04dccac83ef6"
+dependencies = [
+ "ahash",
+ "atoi",
+ "byteorder",
+ "bytes",
+ "crc",
+ "crossbeam-queue",
+ "either",
+ "event-listener",
+ "futures-channel",
+ "futures-core",
+ "futures-intrusive",
+ "futures-io",
+ "futures-util",
+ "hashlink",
+ "hex",
+ "indexmap 2.2.6",
+ "log",
+ "memchr",
+ "once_cell",
+ "paste",
+ "percent-encoding",
+ "rustls 0.21.12",
+ "rustls-pemfile 1.0.4",
+ "serde",
+ "serde_json",
+ "sha2",
+ "smallvec",
+ "sqlformat",
+ "thiserror",
+ "tokio",
+ "tokio-stream",
+ "tracing",
+ "url",
+ "webpki-roots",
+]
+
+[[package]]
+name = "sqlx-macros"
+version = "0.7.4"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "4ea40e2345eb2faa9e1e5e326db8c34711317d2b5e08d0d5741619048a803127"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "sqlx-core",
+ "sqlx-macros-core",
+ "syn 1.0.109",
+]
+
+[[package]]
+name = "sqlx-macros-core"
+version = "0.7.4"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "5833ef53aaa16d860e92123292f1f6a3d53c34ba8b1969f152ef1a7bb803f3c8"
+dependencies = [
+ "dotenvy",
+ "either",
+ "heck 0.4.1",
+ "hex",
+ "once_cell",
+ "proc-macro2",
+ "quote",
+ "serde",
+ "serde_json",
+ "sha2",
+ "sqlx-core",
+ "sqlx-mysql",
+ "sqlx-postgres",
+ "sqlx-sqlite",
+ "syn 1.0.109",
+ "tempfile",
+ "tokio",
+ "url",
+]
+
+[[package]]
+name = "sqlx-mysql"
+version = "0.7.4"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "1ed31390216d20e538e447a7a9b959e06ed9fc51c37b514b46eb758016ecd418"
+dependencies = [
+ "atoi",
+ "base64 0.21.7",
+ "bitflags 2.6.0",
+ "byteorder",
+ "bytes",
+ "crc",
+ "digest",
+ "dotenvy",
+ "either",
+ "futures-channel",
+ "futures-core",
+ "futures-io",
+ "futures-util",
+ "generic-array",
+ "hex",
+ "hkdf",
+ "hmac",
+ "itoa",
+ "log",
+ "md-5",
+ "memchr",
+ "once_cell",
+ "percent-encoding",
+ "rand",
+ "rsa",
+ "serde",
+ "sha1",
+ "sha2",
+ "smallvec",
+ "sqlx-core",
+ "stringprep",
+ "thiserror",
+ "tracing",
+ "whoami",
+]
+
+[[package]]
+name = "sqlx-postgres"
+version = "0.7.4"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "7c824eb80b894f926f89a0b9da0c7f435d27cdd35b8c655b114e58223918577e"
+dependencies = [
+ "atoi",
+ "base64 0.21.7",
+ "bitflags 2.6.0",
+ "byteorder",
+ "crc",
+ "dotenvy",
+ "etcetera",
+ "futures-channel",
+ "futures-core",
+ "futures-io",
+ "futures-util",
+ "hex",
+ "hkdf",
+ "hmac",
+ "home",
+ "itoa",
+ "log",
+ "md-5",
+ "memchr",
+ "once_cell",
+ "rand",
+ "serde",
+ "serde_json",
+ "sha2",
+ "smallvec",
+ "sqlx-core",
+ "stringprep",
+ "thiserror",
+ "tracing",
+ "whoami",
+]
+
+[[package]]
+name = "sqlx-sqlite"
+version = "0.7.4"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "b244ef0a8414da0bed4bb1910426e890b19e5e9bccc27ada6b797d05c55ae0aa"
+dependencies = [
+ "atoi",
+ "flume",
+ "futures-channel",
+ "futures-core",
+ "futures-executor",
+ "futures-intrusive",
+ "futures-util",
+ "libsqlite3-sys",
+ "log",
+ "percent-encoding",
+ "serde",
+ "sqlx-core",
+ "tracing",
+ "url",
+ "urlencoding",
+]
+
+[[package]]
+name = "stringprep"
+version = "0.1.5"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "7b4df3d392d81bd458a8a621b8bffbd2302a12ffe288a9d931670948749463b1"
+dependencies = [
+ "unicode-bidi",
+ "unicode-normalization",
+ "unicode-properties",
+]
[[package]]
name = "strsim"
@@ -2130,6 +2991,17 @@ version = "2.6.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "13c2bddecc57b384dee18652358fb23172facb8a2c51ccc10d74c157bdea3292"
+[[package]]
+name = "syn"
+version = "1.0.109"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "72b64191b275b66ffe2469e8af2c1cfe3bafa67b529ead792a6d0160888b4237"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "unicode-ident",
+]
+
[[package]]
name = "syn"
version = "2.0.72"
@@ -2197,7 +3069,7 @@ checksum = "a4558b58466b9ad7ca0f102865eccc95938dca1a74a856f2b57b6629050da261"
dependencies = [
"proc-macro2",
"quote",
- "syn",
+ "syn 2.0.72",
]
[[package]]
@@ -2292,7 +3164,7 @@ checksum = "693d596312e88961bc67d7f1f97af8a70227d9f90c31bba5806eec004978d752"
dependencies = [
"proc-macro2",
"quote",
- "syn",
+ "syn 2.0.72",
]
[[package]]
@@ -2444,7 +3316,7 @@ checksum = "34704c8d6ebcbc939824180af020566b01a7c01f80641264eba0999f6c2b6be7"
dependencies = [
"proc-macro2",
"quote",
- "syn",
+ "syn 2.0.72",
]
[[package]]
@@ -2538,9 +3410,15 @@ checksum = "1f718dfaf347dcb5b983bfc87608144b0bad87970aebcbea5ce44d2a30c08e63"
dependencies = [
"proc-macro2",
"quote",
- "syn",
+ "syn 2.0.72",
]
+[[package]]
+name = "typenum"
+version = "1.17.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "42ff0bf0c66b8238c6f3b578df37d0b7848e55df8577b3f74f92a69acceeb825"
+
[[package]]
name = "unicase"
version = "2.7.0"
@@ -2571,6 +3449,24 @@ dependencies = [
"tinyvec",
]
+[[package]]
+name = "unicode-properties"
+version = "0.1.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "52ea75f83c0137a9b98608359a5f1af8144876eb67bcb1ce837368e906a9f524"
+
+[[package]]
+name = "unicode-segmentation"
+version = "1.11.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "d4c87d22b6e3f4a18d4d40ef354e97c90fcb14dd91d7dc0aa9d8a1172ebf7202"
+
+[[package]]
+name = "unicode_categories"
+version = "0.1.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "39ec24b3121d976906ece63c9daad25b85969647682eee313cb5779fdd69e14e"
+
[[package]]
name = "unsafe-libyaml"
version = "0.2.11"
@@ -2606,6 +3502,12 @@ version = "0.2.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "06abde3611657adf66d383f00b093d7faecc7fa57071cce2578660c9f1010821"
+[[package]]
+name = "uuid"
+version = "1.10.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "81dfa00651efa65069b0b6b651f4aaa31ba9e3c3ce0137aaad053604ee7e0314"
+
[[package]]
name = "valuable"
version = "0.1.0"
@@ -2649,6 +3551,12 @@ version = "0.11.0+wasi-snapshot-preview1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423"
+[[package]]
+name = "wasite"
+version = "0.1.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "b8dad83b4f25e74f184f64c43b150b91efe7647395b42289f38e50566d82855b"
+
[[package]]
name = "wasm-bindgen"
version = "0.2.92"
@@ -2670,7 +3578,7 @@ dependencies = [
"once_cell",
"proc-macro2",
"quote",
- "syn",
+ "syn 2.0.72",
"wasm-bindgen-shared",
]
@@ -2704,7 +3612,7 @@ checksum = "e94f17b526d0a461a191c78ea52bbce64071ed5c04c9ffe424dcb38f74171bb7"
dependencies = [
"proc-macro2",
"quote",
- "syn",
+ "syn 2.0.72",
"wasm-bindgen-backend",
"wasm-bindgen-shared",
]
@@ -2748,6 +3656,22 @@ dependencies = [
"wasm-bindgen",
]
+[[package]]
+name = "webpki-roots"
+version = "0.25.4"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "5f20c57d8d7db6d3b86154206ae5d8fba62dd39573114de97c2cb0578251f8e1"
+
+[[package]]
+name = "whoami"
+version = "1.5.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "a44ab49fad634e88f55bf8f9bb3abd2f27d7204172a112c7c9987e01c1c94ea9"
+dependencies = [
+ "redox_syscall 0.4.1",
+ "wasite",
+]
+
[[package]]
name = "winapi"
version = "0.3.9"
@@ -3010,7 +3934,16 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "854e949ac82d619ee9a14c66a1b674ac730422372ccb759ce0c39cabcf2bf8e6"
dependencies = [
"byteorder",
- "zerocopy-derive",
+ "zerocopy-derive 0.6.6",
+]
+
+[[package]]
+name = "zerocopy"
+version = "0.7.35"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "1b9b4fd18abc82b8136838da5d50bae7bdea537c574d8dc1a34ed098d6c166f0"
+dependencies = [
+ "zerocopy-derive 0.7.35",
]
[[package]]
@@ -3021,7 +3954,18 @@ checksum = "125139de3f6b9d625c39e2efdd73d41bdac468ccd556556440e322be0e1bbd91"
dependencies = [
"proc-macro2",
"quote",
- "syn",
+ "syn 2.0.72",
+]
+
+[[package]]
+name = "zerocopy-derive"
+version = "0.7.35"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "fa4f8080344d4671fb4e831a13ad1e68092748387dfc4f55e356242fae12ce3e"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "syn 2.0.72",
]
[[package]]
diff --git a/Cargo.toml b/Cargo.toml
index aacd8cc..74ce7d3 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -22,15 +22,8 @@ must_use_candidate = { level = "allow" }
wildcard_imports = { level = "allow" }
[workspace.dependencies]
-indexmap = "2.2.6"
jni = { version = "0.21.1", features = ["invocation"] }
-ndc-models = { git = "http://github.com/hasura/ndc-spec.git", tag = "v0.1.4" }
-ndc-sdk = { git = "https://github.com/hasura/ndc-sdk-rs.git", tag = "v0.1.4" }
-async-trait = "0.1.79"
-axum = { version = "0.6.20", features = ["http2"] }
axum-extra = "0.8.0"
-bytes = "1.6.0"
-clap = { version = "4.5.4", features = ["derive", "env"] }
http = "0.2"
mime = "0.3.17"
opentelemetry = "0.22.0"
@@ -39,22 +32,46 @@ opentelemetry-otlp = { version = "0.15.0", features = ["reqwest-client", "gzip-t
opentelemetry-semantic-conventions = "0.14.0"
opentelemetry_sdk = { version = "0.22.1", features = ["rt-tokio"] }
opentelemetry-zipkin = "0.20.0"
-prometheus = "0.13.3"
-reqwest = "0.11.27"
-serde = { version = "1.0.197", features = ["derive"] }
-serde_json = { version = "1.0.115", features = ["raw_value"] }
-schemars = "0.8.1"
-thiserror = "1.0"
-tokio = { version = "1.36.0", features = ["fs", "macros", "rt-multi-thread", "signal"] }
tower-http = { version = "0.4.4", features = ["cors", "trace", "validate-request"] }
-tracing = "0.1.40"
tracing-opentelemetry = "0.23.0"
tracing-subscriber = { version = "0.3", default-features = false, features = ["ansi", "env-filter", "fmt", "json"] }
-url = "2.5.0"
dotenv = "0.15.0"
once_cell = "1.19.0"
-anyhow = "1.0.86"
-serde_yaml = "0.9"
+ndc-models = { git = "https://github.com/hasura/ndc-spec.git", tag = "v0.1.5" }
+ndc-sdk = { git = "https://github.com/hasura/ndc-sdk-rs.git", tag = "v0.2.2" }
+ndc-test = { git = "https://github.com/hasura/ndc-spec.git", tag = "v0.1.5" }
+
+anyhow = "1"
+async-trait = "0.1"
+axum = "0.6"
+axum-test-helper = "0.3"
+build-data = "0.2"
+bytes = "1"
+clap = "4"
+env_logger = "0.11"
+hyper = "0.14"
+indexmap = "2"
insta = "1"
+jsonschema = "0.17"
+log = "0.4.22"
+multimap = "0.9"
+nonempty = "0.10"
+percent-encoding = "2"
+prometheus = "0.13"
+ref-cast = "1"
+reqwest = "0.11"
+schemars = "0.8"
+serde = "1"
+serde_json = "1"
+serde_yaml = "0.9"
+similar-asserts = "1"
+smol_str = "0.1"
+sqlformat = "0.2"
+sqlx = "0.7"
tempfile = "3"
-build-data = "0.2"
\ No newline at end of file
+test-each = "0.2"
+thiserror = "1"
+tokio = "1"
+tracing = "0.1"
+url = "2"
+uuid = "1"
\ No newline at end of file
diff --git a/adapters/arrow/dev.local.configuration.json b/adapters/arrow/dev.local.configuration.json
index 84ce872..cafbf76 100644
--- a/adapters/arrow/dev.local.configuration.json
+++ b/adapters/arrow/dev.local.configuration.json
@@ -1,5 +1,5 @@
{
- "version": "4",
+ "version": "5",
"$schema": "schema.json",
"model_file_path": "./model.json",
"fixes": true
diff --git a/adapters/arrow/schema.json b/adapters/arrow/schema.json
index 4ee9e59..1346c1e 100644
--- a/adapters/arrow/schema.json
+++ b/adapters/arrow/schema.json
@@ -126,7 +126,7 @@
"Version": {
"type": "string",
"enum": [
- "4"
+ "5"
]
}
}
diff --git a/adapters/cassandra/dev.local.configuration.json b/adapters/cassandra/dev.local.configuration.json
index 0303258..7ebf972 100644
--- a/adapters/cassandra/dev.local.configuration.json
+++ b/adapters/cassandra/dev.local.configuration.json
@@ -1,5 +1,5 @@
{
- "version": "4",
+ "version": "5",
"$schema": "schema.json",
"model": {
"version": "1.0",
diff --git a/adapters/cassandra/root.crt b/adapters/cassandra/root.crt
new file mode 100644
index 0000000..ea92a08
--- /dev/null
+++ b/adapters/cassandra/root.crt
@@ -0,0 +1,24 @@
+-----BEGIN CERTIFICATE-----
+MIIEDzCCAvegAwIBAgIBADANBgkqhkiG9w0BAQUFADBoMQswCQYDVQQGEwJVUzEl
+MCMGA1UEChMcU3RhcmZpZWxkIFRlY2hub2xvZ2llcywgSW5jLjEyMDAGA1UECxMp
+U3RhcmZpZWxkIENsYXNzIDIgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkwHhcNMDQw
+NjI5MTczOTE2WhcNMzQwNjI5MTczOTE2WjBoMQswCQYDVQQGEwJVUzElMCMGA1UE
+ChMcU3RhcmZpZWxkIFRlY2hub2xvZ2llcywgSW5jLjEyMDAGA1UECxMpU3RhcmZp
+ZWxkIENsYXNzIDIgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkwggEgMA0GCSqGSIb3
+DQEBAQUAA4IBDQAwggEIAoIBAQC3Msj+6XGmBIWtDBFk385N78gDGIc/oav7PKaf
+8MOh2tTYbitTkPskpD6E8J7oX+zlJ0T1KKY/e97gKvDIr1MvnsoFAZMej2YcOadN
++lq2cwQlZut3f+dZxkqZJRRU6ybH838Z1TBwj6+wRir/resp7defqgSHo9T5iaU0
+X9tDkYI22WY8sbi5gv2cOj4QyDvvBmVmepsZGD3/cVE8MC5fvj13c7JdBmzDI1aa
+K4UmkhynArPkPw2vCHmCuDY96pzTNbO8acr1zJ3o/WSNF4Azbl5KXZnJHoe0nRrA
+1W4TNSNe35tfPe/W93bC6j67eA0cQmdrBNj41tpvi/JEoAGrAgEDo4HFMIHCMB0G
+A1UdDgQWBBS/X7fRzt0fhvRbVazc1xDCDqmI5zCBkgYDVR0jBIGKMIGHgBS/X7fR
+zt0fhvRbVazc1xDCDqmI56FspGowaDELMAkGA1UEBhMCVVMxJTAjBgNVBAoTHFN0
+YXJmaWVsZCBUZWNobm9sb2dpZXMsIEluYy4xMjAwBgNVBAsTKVN0YXJmaWVsZCBD
+bGFzcyAyIENlcnRpZmljYXRpb24gQXV0aG9yaXR5ggEAMAwGA1UdEwQFMAMBAf8w
+DQYJKoZIhvcNAQEFBQADggEBAAWdP4id0ckaVaGsafPzWdqbAYcaT1epoXkJKtv3
+L7IezMdeatiDh6GX70k1PncGQVhiv45YuApnP+yz3SFmH8lU+nLMPUxA2IGvd56D
+eruix/U0F47ZEUD0/CwqTRV/p2JdLiXTAAsgGh1o+Re49L2L7ShZ3U0WixeDyLJl
+xy16paq8U4Zt3VekyvggQQto8PT7dL5WXXp59fkdheMtlb71cZBDzI0fmgAKhynp
+VSJYACPq4xJDKVtHCN2MQWplBqjlIapBtJUhlbl90TSrE9atvNziPTnNvT51cKEY
+WQPJIrSPnNVeKtelttQKbfi3QBFGmh95DmK/D5fs4C8fF5Q=
+-----END CERTIFICATE-----
\ No newline at end of file
diff --git a/adapters/cassandra/schema.json b/adapters/cassandra/schema.json
index 4ee9e59..1346c1e 100644
--- a/adapters/cassandra/schema.json
+++ b/adapters/cassandra/schema.json
@@ -126,7 +126,7 @@
"Version": {
"type": "string",
"enum": [
- "4"
+ "5"
]
}
}
diff --git a/adapters/csv/configuration.json b/adapters/csv/configuration.json
index ce0536f..cef05dd 100644
--- a/adapters/csv/configuration.json
+++ b/adapters/csv/configuration.json
@@ -1,5 +1,5 @@
{
- "version": "4",
+ "version": "5",
"$schema": "schema.json",
"model": {
"version": "1.0",
diff --git a/adapters/csv/dev.local.configuration.json b/adapters/csv/dev.local.configuration.json
index 062e1a8..010bef2 100644
--- a/adapters/csv/dev.local.configuration.json
+++ b/adapters/csv/dev.local.configuration.json
@@ -1,5 +1,5 @@
{
- "version": "4",
+ "version": "5",
"$schema": "schema.json",
"model": {
"version": "1.0",
diff --git a/adapters/csv/schema.json b/adapters/csv/schema.json
index 95904f5..1346c1e 100644
--- a/adapters/csv/schema.json
+++ b/adapters/csv/schema.json
@@ -41,6 +41,9 @@
"jdbcUrl": {
"type": "string"
},
+ "sqlDialectFactory": {
+ "type": "string"
+ },
"jdbcCatalog": {
"type": "string"
},
@@ -123,7 +126,7 @@
"Version": {
"type": "string",
"enum": [
- "4"
+ "5"
]
}
}
diff --git a/adapters/db2/.env b/adapters/db2/.env
new file mode 100644
index 0000000..18cf2aa
--- /dev/null
+++ b/adapters/db2/.env
@@ -0,0 +1,6 @@
+JAR_DEPENDENCY_FOLDER=../../calcite-rs-jni/target/dependency
+CALCITE_JAR=../../calcite-rs-jni/target/calcite-rs-jni-1.0-SNAPSHOT.jar
+RUST_LOG=info
+OTEL_LOGS_EXPORTER=console
+OTEL_LOG_LEVEL=trace
+LOG4J_CONFIGURATION_FILE=../../calcite-rs-jni/target/classes/log4j2.xml
\ No newline at end of file
diff --git a/config-templates/.env.local b/adapters/db2/.env.local
similarity index 100%
rename from config-templates/.env.local
rename to adapters/db2/.env.local
diff --git a/adapters/db2/dev.local.configuration.json b/adapters/db2/dev.local.configuration.json
new file mode 100644
index 0000000..4c7d2d1
--- /dev/null
+++ b/adapters/db2/dev.local.configuration.json
@@ -0,0 +1,90 @@
+{
+ "version": "5",
+ "$schema": "schema.json",
+ "model": {
+ "version": "1.0",
+ "defaultSchema": "db2",
+ "schemas": [
+ {
+ "type": "jdbc",
+ "name": "db2",
+ "jdbcUser": "db2inst1",
+ "jdbcPassword": "mypassword",
+ "jdbcUrl": "jdbc:db2://192.168.86.233:50000/testdb"
+ }
+ ]
+ },
+ "model_file_path": "./model.json",
+ "fixes": true,
+ "metadata": {
+ "PROJECTS": {
+ "schema": "db2",
+ "name": "PROJECTS",
+ "columns": {
+ "PROJECTID": {
+ "name": "PROJECTID",
+ "scalarType": "INTEGER",
+ "nullable": false
+ },
+ "PROJECTNAME": {
+ "name": "PROJECTNAME",
+ "scalarType": "VARCHAR",
+ "nullable": true
+ },
+ "DEPARTMENTID": {
+ "name": "DEPARTMENTID",
+ "scalarType": "INTEGER",
+ "nullable": true
+ }
+ },
+ "primaryKeys": [],
+ "exportedKeys": []
+ },
+ "EMPLOYEES": {
+ "schema": "db2",
+ "name": "EMPLOYEES",
+ "columns": {
+ "FIRSTNAME": {
+ "name": "FIRSTNAME",
+ "scalarType": "VARCHAR",
+ "nullable": true
+ },
+ "LASTNAME": {
+ "name": "LASTNAME",
+ "scalarType": "VARCHAR",
+ "nullable": true
+ },
+ "EMPLOYEEID": {
+ "name": "EMPLOYEEID",
+ "scalarType": "INTEGER",
+ "nullable": false
+ },
+ "DEPARTMENTID": {
+ "name": "DEPARTMENTID",
+ "scalarType": "INTEGER",
+ "nullable": true
+ }
+ },
+ "primaryKeys": [],
+ "exportedKeys": []
+ },
+ "DEPARTMENTS": {
+ "schema": "db2",
+ "name": "DEPARTMENTS",
+ "columns": {
+ "DEPARTMENTNAME": {
+ "name": "DEPARTMENTNAME",
+ "scalarType": "VARCHAR",
+ "nullable": true
+ },
+ "DEPARTMENTID": {
+ "name": "DEPARTMENTID",
+ "scalarType": "INTEGER",
+ "nullable": false
+ }
+ },
+ "primaryKeys": [],
+ "exportedKeys": []
+ }
+ }
+}
\ No newline at end of file
diff --git a/config-templates/schema.json b/adapters/db2/schema.json
similarity index 99%
rename from config-templates/schema.json
rename to adapters/db2/schema.json
index 4ee9e59..1346c1e 100644
--- a/config-templates/schema.json
+++ b/adapters/db2/schema.json
@@ -126,7 +126,7 @@
"Version": {
"type": "string",
"enum": [
- "4"
+ "5"
]
}
}
diff --git a/adapters/file/configuration.json b/adapters/file/configuration.json
index 04d8e49..e54a3c9 100644
--- a/adapters/file/configuration.json
+++ b/adapters/file/configuration.json
@@ -1,5 +1,5 @@
{
- "version": "4",
+ "version": "5",
"$schema": "schema.json",
"model": {
"version": "1.0",
diff --git a/adapters/file/connector-metadata.yaml b/adapters/file/connector-metadata.yaml
deleted file mode 100644
index c153715..0000000
--- a/adapters/file/connector-metadata.yaml
+++ /dev/null
@@ -1,15 +0,0 @@
-packagingDefinition:
- type: PrebuiltDockerImage
- dockerImage: "kstott/file_connector:latest"
-supportedEnvironmentVariables:
- - name: DATA_FOLDER
- description: A local directory of *.csv and *.json files
-commands:
- update: ndc-calcite update
-cliPlugin:
- name: elasticsearch
- version: "v0.1.0"
-dockerComposeWatch:
- - path: ./
- target: /etc/ndc-calcite
- action: sync+restart
diff --git a/adapters/file/dev.local.configuration.json b/adapters/file/dev.local.configuration.json
index c45fa45..7e4a845 100644
--- a/adapters/file/dev.local.configuration.json
+++ b/adapters/file/dev.local.configuration.json
@@ -1,5 +1,5 @@
{
- "version": "4",
+ "version": "5",
"$schema": "schema.json",
"model": {
"version": "1.0",
@@ -10,7 +10,7 @@
"name": "sales",
"factory": "org.apache.calcite.adapter.file.FileSchemaFactory",
"operand": {
- "directory": "/Users/kennethstott/Documents/GitHub/ndc-calcite/adapters/file/resources/test/sales"
+ "directory": "/Users/kennethstott/Documents/GitHub/ndc-calcite/adapters/file/resources/test/bug"
}
}
]
@@ -18,48 +18,177 @@
"model_file_path": "./model.json",
"fixes": true,
"metadata": {
- "EMPS": {
+ "ARCHERS": {
"schema": "sales",
- "name": "EMPS",
+ "name": "ARCHERS",
"columns": {
- "CITY": {
- "name": "CITY",
+ "f": {
+ "name": "f",
"scalarType": "VARCHAR",
"nullable": true
},
- "JOINEDAT": {
- "name": "JOINEDAT",
- "scalarType": "DATE",
+ "d": {
+ "name": "d",
+ "scalarType": "LIST",
"nullable": true
},
- "MANAGER": {
- "name": "MANAGER",
- "scalarType": "BOOLEAN",
+ "c": {
+ "name": "c",
+ "scalarType": "VARCHAR",
+ "nullable": true
+ },
+ "e": {
+ "name": "e",
+ "scalarType": "VARCHAR",
+ "nullable": true
+ },
+ "b": {
+ "name": "b",
+ "scalarType": "VARCHAR",
+ "nullable": true
+ },
+ "object": {
+ "name": "object",
+ "scalarType": "VARCHAR",
+ "nullable": true
+ },
+ "id": {
+ "name": "id",
+ "scalarType": "INTEGER",
+ "nullable": true
+ },
+ "a": {
+ "name": "a",
+ "scalarType": "VARCHAR",
+ "nullable": true
+ },
+ "g": {
+ "name": "g",
+ "scalarType": "LIST",
+ "nullable": true
+ }
+ },
+ "primaryKeys": [],
+ "exportedKeys": []
+ },
+ "test": {
+ "schema": "sales",
+ "name": "test",
+ "columns": {
+ "id": {
+ "name": "id",
+ "scalarType": "INTEGER",
+ "nullable": true
+ },
+ "d": {
+ "name": "d",
+ "scalarType": "LIST",
+ "nullable": true
+ },
+ "b": {
+ "name": "b",
+ "scalarType": "VARCHAR",
+ "nullable": true
+ },
+ "object": {
+ "name": "object",
+ "scalarType": "VARCHAR",
"nullable": true
},
+ "f": {
+ "name": "f",
+ "scalarType": "VARCHAR",
+ "nullable": true
+ },
+ "c": {
+ "name": "c",
+ "scalarType": "VARCHAR",
+ "nullable": true
+ },
+ "g": {
+ "name": "g",
+ "scalarType": "LIST",
+ "nullable": true
+ },
+ "a": {
+ "name": "a",
+ "scalarType": "VARCHAR",
+ "nullable": true
+ },
+ "e": {
+ "name": "e",
+ "scalarType": "VARCHAR",
+ "nullable": true
+ }
+ },
+ "primaryKeys": [],
+ "exportedKeys": []
+ },
+ "LONG_EMPS": {
+ "schema": "sales",
+ "name": "LONG_EMPS",
+ "columns": {
"EMPID": {
"name": "EMPID",
"scalarType": "INTEGER",
"nullable": true
},
- "GENDER": {
- "name": "GENDER",
+ "CITY": {
+ "name": "CITY",
"scalarType": "VARCHAR",
"nullable": true
},
+ "SLACKER": {
+ "name": "SLACKER",
+ "scalarType": "BOOLEAN",
+ "nullable": true
+ },
+ "EMPNO": {
+ "name": "EMPNO",
+ "scalarType": "INTEGER",
+ "nullable": true
+ },
+ "DEPTNO": {
+ "name": "DEPTNO",
+ "scalarType": "INTEGER",
+ "nullable": true
+ },
"AGE": {
"name": "AGE",
"scalarType": "INTEGER",
"nullable": true
},
+ "GENDER": {
+ "name": "GENDER",
+ "scalarType": "VARCHAR",
+ "nullable": true
+ },
+ "MANAGER": {
+ "name": "MANAGER",
+ "scalarType": "BOOLEAN",
+ "nullable": true
+ },
+ "JOINEDAT": {
+ "name": "JOINEDAT",
+ "scalarType": "DATE",
+ "nullable": true
+ },
"NAME": {
"name": "NAME",
"scalarType": "VARCHAR",
"nullable": true
- },
- "DEPTNO": {
- "name": "DEPTNO",
- "scalarType": "INTEGER",
+ }
+ },
+ "primaryKeys": [],
+ "exportedKeys": []
+ },
+ "WACKY_COLUMN_NAMES": {
+ "schema": "sales",
+ "name": "WACKY_COLUMN_NAMES",
+ "columns": {
+ "CITY": {
+ "name": "CITY",
+ "scalarType": "VARCHAR",
"nullable": true
},
"SLACKER": {
@@ -71,41 +200,106 @@
"name": "EMPNO",
"scalarType": "INTEGER",
"nullable": true
+ },
+ "2gender": {
+ "name": "2gender",
+ "scalarType": "VARCHAR",
+ "nullable": true
+ },
+ "AGE": {
+ "name": "AGE",
+ "scalarType": "INTEGER",
+ "nullable": true
+ },
+ "naME": {
+ "name": "naME",
+ "scalarType": "VARCHAR",
+ "nullable": true
+ },
+ "EMPID": {
+ "name": "EMPID",
+ "scalarType": "INTEGER",
+ "nullable": true
+ },
+ "MANAGER": {
+ "name": "MANAGER",
+ "scalarType": "BOOLEAN",
+ "nullable": true
+ },
+ "DEPTNO": {
+ "name": "DEPTNO",
+ "scalarType": "VARCHAR",
+ "nullable": true
+ },
+ "joined at": {
+ "name": "joined at",
+ "scalarType": "DATE",
+ "nullable": true
}
},
"primaryKeys": [],
"exportedKeys": []
},
- "DEPTS": {
+ "configuration": {
"schema": "sales",
- "name": "DEPTS",
+ "name": "configuration",
"columns": {
- "NAME": {
- "name": "NAME",
+ "metadata": {
+ "name": "metadata",
+ "scalarType": "MAP",
+ "nullable": true
+ },
+ "fixes": {
+ "name": "fixes",
"scalarType": "VARCHAR",
"nullable": true
},
- "DEPTNO": {
- "name": "DEPTNO",
- "scalarType": "INTEGER",
+ "$schema": {
+ "name": "$schema",
+ "scalarType": "VARCHAR",
+ "nullable": true
+ },
+ "model": {
+ "name": "model",
+ "scalarType": "MAP",
+ "nullable": true
+ },
+ "model_file_path": {
+ "name": "model_file_path",
+ "scalarType": "VARCHAR",
+ "nullable": true
+ },
+ "version": {
+ "name": "version",
+ "scalarType": "VARCHAR",
"nullable": true
}
},
"primaryKeys": [],
"exportedKeys": []
},
- "SDEPTS": {
+ "DATES": {
"schema": "sales",
- "name": "SDEPTS",
+ "name": "DATES",
"columns": {
- "DEPTNO": {
- "name": "DEPTNO",
- "scalarType": "INTEGER",
+ "JOINTIMES": {
+ "name": "JOINTIMES",
+ "scalarType": "TIMESTAMP",
"nullable": true
},
- "NAME": {
- "name": "NAME",
- "scalarType": "VARCHAR",
+ "JOINEDAT": {
+ "name": "JOINEDAT",
+ "scalarType": "DATE",
+ "nullable": true
+ },
+ "JOINTIME": {
+ "name": "JOINTIME",
+ "scalarType": "TIME",
+ "nullable": true
+ },
+ "EMPNO": {
+ "name": "EMPNO",
+ "scalarType": "INTEGER",
"nullable": true
}
},
diff --git a/adapters/file/resources/test/bug/configuration.json b/adapters/file/resources/test/bug/configuration.json
index 03e8b00..f102c77 100644
--- a/adapters/file/resources/test/bug/configuration.json
+++ b/adapters/file/resources/test/bug/configuration.json
@@ -1,5 +1,5 @@
{
- "version": "4",
+ "version": "5",
"$schema": "schema.json",
"model": {
"version": "1.0",
diff --git a/adapters/file/schema.json b/adapters/file/schema.json
index 95904f5..1346c1e 100644
--- a/adapters/file/schema.json
+++ b/adapters/file/schema.json
@@ -41,6 +41,9 @@
"jdbcUrl": {
"type": "string"
},
+ "sqlDialectFactory": {
+ "type": "string"
+ },
"jdbcCatalog": {
"type": "string"
},
@@ -123,7 +126,7 @@
"Version": {
"type": "string",
"enum": [
- "4"
+ "5"
]
}
}
diff --git a/adapters/h2/dev.local.configuration.json b/adapters/h2/dev.local.configuration.json
new file mode 100644
index 0000000..4c7d2d1
--- /dev/null
+++ b/adapters/h2/dev.local.configuration.json
@@ -0,0 +1,90 @@
+{
+ "version": "5",
+ "$schema": "schema.json",
+ "model": {
+ "version": "1.0",
+ "defaultSchema": "db2",
+ "schemas": [
+ {
+ "type": "jdbc",
+ "name": "db2",
+ "jdbcUser": "db2inst1",
+ "jdbcPassword": "mypassword",
+ "jdbcUrl": "jdbc:db2://192.168.86.233:50000/testdb"
+ }
+ ]
+ },
+ "model_file_path": "./model.json",
+ "fixes": true,
+ "metadata": {
+ "PROJECTS": {
+ "schema": "db2",
+ "name": "PROJECTS",
+ "columns": {
+ "PROJECTID": {
+ "name": "PROJECTID",
+ "scalarType": "INTEGER",
+ "nullable": false
+ },
+ "PROJECTNAME": {
+ "name": "PROJECTNAME",
+ "scalarType": "VARCHAR",
+ "nullable": true
+ },
+ "DEPARTMENTID": {
+ "name": "DEPARTMENTID",
+ "scalarType": "INTEGER",
+ "nullable": true
+ }
+ },
+ "primaryKeys": [],
+ "exportedKeys": []
+ },
+ "EMPLOYEES": {
+ "schema": "db2",
+ "name": "EMPLOYEES",
+ "columns": {
+ "FIRSTNAME": {
+ "name": "FIRSTNAME",
+ "scalarType": "VARCHAR",
+ "nullable": true
+ },
+ "LASTNAME": {
+ "name": "LASTNAME",
+ "scalarType": "VARCHAR",
+ "nullable": true
+ },
+ "EMPLOYEEID": {
+ "name": "EMPLOYEEID",
+ "scalarType": "INTEGER",
+ "nullable": false
+ },
+ "DEPARTMENTID": {
+ "name": "DEPARTMENTID",
+ "scalarType": "INTEGER",
+ "nullable": true
+ }
+ },
+ "primaryKeys": [],
+ "exportedKeys": []
+ },
+ "DEPARTMENTS": {
+ "schema": "db2",
+ "name": "DEPARTMENTS",
+ "columns": {
+ "DEPARTMENTNAME": {
+ "name": "DEPARTMENTNAME",
+ "scalarType": "VARCHAR",
+ "nullable": true
+ },
+ "DEPARTMENTID": {
+ "name": "DEPARTMENTID",
+ "scalarType": "INTEGER",
+ "nullable": false
+ }
+ },
+ "primaryKeys": [],
+ "exportedKeys": []
+ }
+ }
+}
\ No newline at end of file
diff --git a/adapters/h2/docker-compose.yaml b/adapters/h2/docker-compose.yaml
new file mode 100644
index 0000000..0601dd9
--- /dev/null
+++ b/adapters/h2/docker-compose.yaml
@@ -0,0 +1,17 @@
+version: '3.8'
+
+services:
+ h2:
+ image: oscarfonts/h2:latest
+ container_name: h2-database
+ ports:
+ - "81:81"
+ - "1521:1521"
+ environment:
+ - H2_OPTIONS=-tcp -tcpAllowOthers -web -webAllowOthers -ifNotExists
+ volumes:
+ - h2-data:/opt/h2-data
+ - ./init.sql:/docker-entrypoint-initdb.d/init.sql
+
+volumes:
+ h2-data:
diff --git a/adapters/h2/schema.json b/adapters/h2/schema.json
new file mode 100644
index 0000000..1346c1e
--- /dev/null
+++ b/adapters/h2/schema.json
@@ -0,0 +1,133 @@
+{
+ "$schema": "http://json-schema.org/draft-07/schema#",
+ "title": "ParsedConfiguration",
+ "type": "object",
+ "required": [
+ "version"
+ ],
+ "properties": {
+ "version": {
+ "$ref": "#/definitions/Version"
+ },
+ "$schema": {
+ "type": "string"
+ },
+ "model": {
+ "type": "object",
+ "properties": {
+ "version": {
+ "type": "string"
+ },
+ "defaultSchema": {
+ "type": "string"
+ },
+ "schemas": {
+ "type": "array",
+ "items": {
+ "type": "object",
+ "properties": {
+ "type": {
+ "type": "string"
+ },
+ "name": {
+ "type": "string"
+ },
+ "jdbcUser": {
+ "type": "string"
+ },
+ "jdbcPassword": {
+ "type": "string"
+ },
+ "jdbcUrl": {
+ "type": "string"
+ },
+ "sqlDialectFactory": {
+ "type": "string"
+ },
+ "jdbcCatalog": {
+ "type": "string"
+ },
+ "jdbcSchema": {},
+ "factory": {
+ "type": "string"
+ },
+ "operand": {
+ "type": "object",
+ "properties": {
+ "directory": {
+ "type": "string"
+ },
+ "host": {
+ "type": "string"
+ },
+ "port": {
+ "type": "number"
+ },
+ "database": {
+ "type": "string"
+ },
+ "password": {
+ "type": "string"
+ }
+ }
+ },
+ "tables": {
+ "type": "array",
+ "items": {
+ "type": "object",
+ "properties": {
+ "name": {
+ "type": "string"
+ },
+ "factory": {
+ "type": "string"
+ },
+ "operand": {
+ "type": "object",
+ "properties": {
+ "dataFormat": {
+ "type": "string"
+ },
+ "fields": {
+ "type": "array",
+ "items": {
+ "type": "object",
+ "properties": {
+ "name": {
+ "type": "string"
+ },
+ "type": {
+ "type": "string"
+ },
+ "mapping": {}
+ },
+ "required": [
+ "name",
+ "type",
+ "mapping"
+ ]
+ }
+ },
+ "keyDelimiter": {
+ "type": "string"
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ },
+ "definitions": {
+ "Version": {
+ "type": "string",
+ "enum": [
+ "5"
+ ]
+ }
+ }
+}
\ No newline at end of file
diff --git a/adapters/hive/dev.local.configuration.json b/adapters/hive/dev.local.configuration.json
index 0c129c6..e25b8a8 100644
--- a/adapters/hive/dev.local.configuration.json
+++ b/adapters/hive/dev.local.configuration.json
@@ -1,5 +1,5 @@
{
- "version": "4",
+ "version": "5",
"$schema": "schema.json",
"model": {
"version": "1.0",
diff --git a/adapters/hive/schema.json b/adapters/hive/schema.json
new file mode 100644
index 0000000..1346c1e
--- /dev/null
+++ b/adapters/hive/schema.json
@@ -0,0 +1,133 @@
+{
+ "$schema": "http://json-schema.org/draft-07/schema#",
+ "title": "ParsedConfiguration",
+ "type": "object",
+ "required": [
+ "version"
+ ],
+ "properties": {
+ "version": {
+ "$ref": "#/definitions/Version"
+ },
+ "$schema": {
+ "type": "string"
+ },
+ "model": {
+ "type": "object",
+ "properties": {
+ "version": {
+ "type": "string"
+ },
+ "defaultSchema": {
+ "type": "string"
+ },
+ "schemas": {
+ "type": "array",
+ "items": {
+ "type": "object",
+ "properties": {
+ "type": {
+ "type": "string"
+ },
+ "name": {
+ "type": "string"
+ },
+ "jdbcUser": {
+ "type": "string"
+ },
+ "jdbcPassword": {
+ "type": "string"
+ },
+ "jdbcUrl": {
+ "type": "string"
+ },
+ "sqlDialectFactory": {
+ "type": "string"
+ },
+ "jdbcCatalog": {
+ "type": "string"
+ },
+ "jdbcSchema": {},
+ "factory": {
+ "type": "string"
+ },
+ "operand": {
+ "type": "object",
+ "properties": {
+ "directory": {
+ "type": "string"
+ },
+ "host": {
+ "type": "string"
+ },
+ "port": {
+ "type": "number"
+ },
+ "database": {
+ "type": "string"
+ },
+ "password": {
+ "type": "string"
+ }
+ }
+ },
+ "tables": {
+ "type": "array",
+ "items": {
+ "type": "object",
+ "properties": {
+ "name": {
+ "type": "string"
+ },
+ "factory": {
+ "type": "string"
+ },
+ "operand": {
+ "type": "object",
+ "properties": {
+ "dataFormat": {
+ "type": "string"
+ },
+ "fields": {
+ "type": "array",
+ "items": {
+ "type": "object",
+ "properties": {
+ "name": {
+ "type": "string"
+ },
+ "type": {
+ "type": "string"
+ },
+ "mapping": {}
+ },
+ "required": [
+ "name",
+ "type",
+ "mapping"
+ ]
+ }
+ },
+ "keyDelimiter": {
+ "type": "string"
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ },
+ "definitions": {
+ "Version": {
+ "type": "string",
+ "enum": [
+ "5"
+ ]
+ }
+ }
+}
\ No newline at end of file
diff --git a/adapters/jdbc/configuration.json b/adapters/jdbc/configuration.json
index a7a0451..459e4ac 100644
--- a/adapters/jdbc/configuration.json
+++ b/adapters/jdbc/configuration.json
@@ -1,5 +1,5 @@
{
- "version": "4",
+ "version": "5",
"$schema": "schema.json",
"fixes": true,
"model_file": "./model"
diff --git a/adapters/jdbc/dev.local.configuration.json b/adapters/jdbc/dev.local.configuration.json
index a3429c6..025eade 100644
--- a/adapters/jdbc/dev.local.configuration.json
+++ b/adapters/jdbc/dev.local.configuration.json
@@ -1,5 +1,5 @@
{
- "version": "4",
+ "version": "5",
"$schema": "schema.json",
"model": {
"version": "1.0",
diff --git a/adapters/jdbc/schema.json b/adapters/jdbc/schema.json
index 4ee9e59..1346c1e 100644
--- a/adapters/jdbc/schema.json
+++ b/adapters/jdbc/schema.json
@@ -126,7 +126,7 @@
"Version": {
"type": "string",
"enum": [
- "4"
+ "5"
]
}
}
diff --git a/adapters/kafka/dev.local.configuration.json b/adapters/kafka/dev.local.configuration.json
index b0ca42a..45c1cbb 100644
--- a/adapters/kafka/dev.local.configuration.json
+++ b/adapters/kafka/dev.local.configuration.json
@@ -1,5 +1,5 @@
{
- "version": "4",
+ "version": "5",
"$schema": "schema.json",
"model_file_path": "./model.json",
"fixes": true
diff --git a/adapters/kafka/schema.json b/adapters/kafka/schema.json
index 95904f5..1346c1e 100644
--- a/adapters/kafka/schema.json
+++ b/adapters/kafka/schema.json
@@ -41,6 +41,9 @@
"jdbcUrl": {
"type": "string"
},
+ "sqlDialectFactory": {
+ "type": "string"
+ },
"jdbcCatalog": {
"type": "string"
},
@@ -123,7 +126,7 @@
"Version": {
"type": "string",
"enum": [
- "4"
+ "5"
]
}
}
diff --git a/adapters/redis/schema.json b/adapters/redis/schema.json
new file mode 100644
index 0000000..1346c1e
--- /dev/null
+++ b/adapters/redis/schema.json
@@ -0,0 +1,133 @@
+{
+ "$schema": "http://json-schema.org/draft-07/schema#",
+ "title": "ParsedConfiguration",
+ "type": "object",
+ "required": [
+ "version"
+ ],
+ "properties": {
+ "version": {
+ "$ref": "#/definitions/Version"
+ },
+ "$schema": {
+ "type": "string"
+ },
+ "model": {
+ "type": "object",
+ "properties": {
+ "version": {
+ "type": "string"
+ },
+ "defaultSchema": {
+ "type": "string"
+ },
+ "schemas": {
+ "type": "array",
+ "items": {
+ "type": "object",
+ "properties": {
+ "type": {
+ "type": "string"
+ },
+ "name": {
+ "type": "string"
+ },
+ "jdbcUser": {
+ "type": "string"
+ },
+ "jdbcPassword": {
+ "type": "string"
+ },
+ "jdbcUrl": {
+ "type": "string"
+ },
+ "sqlDialectFactory": {
+ "type": "string"
+ },
+ "jdbcCatalog": {
+ "type": "string"
+ },
+ "jdbcSchema": {},
+ "factory": {
+ "type": "string"
+ },
+ "operand": {
+ "type": "object",
+ "properties": {
+ "directory": {
+ "type": "string"
+ },
+ "host": {
+ "type": "string"
+ },
+ "port": {
+ "type": "number"
+ },
+ "database": {
+ "type": "string"
+ },
+ "password": {
+ "type": "string"
+ }
+ }
+ },
+ "tables": {
+ "type": "array",
+ "items": {
+ "type": "object",
+ "properties": {
+ "name": {
+ "type": "string"
+ },
+ "factory": {
+ "type": "string"
+ },
+ "operand": {
+ "type": "object",
+ "properties": {
+ "dataFormat": {
+ "type": "string"
+ },
+ "fields": {
+ "type": "array",
+ "items": {
+ "type": "object",
+ "properties": {
+ "name": {
+ "type": "string"
+ },
+ "type": {
+ "type": "string"
+ },
+ "mapping": {}
+ },
+ "required": [
+ "name",
+ "type",
+ "mapping"
+ ]
+ }
+ },
+ "keyDelimiter": {
+ "type": "string"
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ },
+ "definitions": {
+ "Version": {
+ "type": "string",
+ "enum": [
+ "5"
+ ]
+ }
+ }
+}
\ No newline at end of file
diff --git a/adapters/sybase/.env b/adapters/sybase/.env
new file mode 100644
index 0000000..18cf2aa
--- /dev/null
+++ b/adapters/sybase/.env
@@ -0,0 +1,6 @@
+JAR_DEPENDENCY_FOLDER=../../calcite-rs-jni/target/dependency
+CALCITE_JAR=../../calcite-rs-jni/target/calcite-rs-jni-1.0-SNAPSHOT.jar
+RUST_LOG=info
+OTEL_LOGS_EXPORTER=console
+OTEL_LOG_LEVEL=trace
+LOG4J_CONFIGURATION_FILE=../../calcite-rs-jni/target/classes/log4j2.xml
\ No newline at end of file
diff --git a/adapters/sybase/Dockerfile b/adapters/sybase/Dockerfile
new file mode 100644
index 0000000..70d02a5
--- /dev/null
+++ b/adapters/sybase/Dockerfile
@@ -0,0 +1,4 @@
+
+FROM datagrip/sybase:latest
+
+# Add any additional setup or dependencies here
diff --git a/adapters/sybase/custom-entrypoint.sh b/adapters/sybase/custom-entrypoint.sh
new file mode 100755
index 0000000..df2dd5a
--- /dev/null
+++ b/adapters/sybase/custom-entrypoint.sh
@@ -0,0 +1,15 @@
+#!/bin/bash
+# Source Sybase environment setup script
+source /opt/sybase/SYBASE.sh
+
+# Start Sybase
+/opt/sybase/ASE-16_0/bin/dataserver -d/opt/sybase/data/master.dat &
+
+# Wait for Sybase to start
+sleep 30
+
+# Create the database
+isql -U sa -P $SYBASE_PASSWORD -Q "CREATE DATABASE your_database;"
+
+# Keep the container running
+tail -f /dev/null
diff --git a/adapters/sybase/dev.local.configuration.json b/adapters/sybase/dev.local.configuration.json
new file mode 100644
index 0000000..4c7d2d1
--- /dev/null
+++ b/adapters/sybase/dev.local.configuration.json
@@ -0,0 +1,90 @@
+{
+ "version": "5",
+ "$schema": "schema.json",
+ "model": {
+ "version": "1.0",
+ "defaultSchema": "db2",
+ "schemas": [
+ {
+ "type": "jdbc",
+ "name": "db2",
+ "jdbcUser": "db2inst1",
+ "jdbcPassword": "mypassword",
+ "jdbcUrl": "jdbc:db2://192.168.86.233:50000/testdb"
+ }
+ ]
+ },
+ "model_file_path": "./model.json",
+ "fixes": true,
+ "metadata": {
+ "PROJECTS": {
+ "schema": "db2",
+ "name": "PROJECTS",
+ "columns": {
+ "PROJECTID": {
+ "name": "PROJECTID",
+ "scalarType": "INTEGER",
+ "nullable": false
+ },
+ "PROJECTNAME": {
+ "name": "PROJECTNAME",
+ "scalarType": "VARCHAR",
+ "nullable": true
+ },
+ "DEPARTMENTID": {
+ "name": "DEPARTMENTID",
+ "scalarType": "INTEGER",
+ "nullable": true
+ }
+ },
+ "primaryKeys": [],
+ "exportedKeys": []
+ },
+ "EMPLOYEES": {
+ "schema": "db2",
+ "name": "EMPLOYEES",
+ "columns": {
+ "FIRSTNAME": {
+ "name": "FIRSTNAME",
+ "scalarType": "VARCHAR",
+ "nullable": true
+ },
+ "LASTNAME": {
+ "name": "LASTNAME",
+ "scalarType": "VARCHAR",
+ "nullable": true
+ },
+ "EMPLOYEEID": {
+ "name": "EMPLOYEEID",
+ "scalarType": "INTEGER",
+ "nullable": false
+ },
+ "DEPARTMENTID": {
+ "name": "DEPARTMENTID",
+ "scalarType": "INTEGER",
+ "nullable": true
+ }
+ },
+ "primaryKeys": [],
+ "exportedKeys": []
+ },
+ "DEPARTMENTS": {
+ "schema": "db2",
+ "name": "DEPARTMENTS",
+ "columns": {
+ "DEPARTMENTNAME": {
+ "name": "DEPARTMENTNAME",
+ "scalarType": "VARCHAR",
+ "nullable": true
+ },
+ "DEPARTMENTID": {
+ "name": "DEPARTMENTID",
+ "scalarType": "INTEGER",
+ "nullable": false
+ }
+ },
+ "primaryKeys": [],
+ "exportedKeys": []
+ }
+ }
+}
\ No newline at end of file
diff --git a/adapters/sybase/docker-compose.yaml b/adapters/sybase/docker-compose.yaml
new file mode 100644
index 0000000..1c44911
--- /dev/null
+++ b/adapters/sybase/docker-compose.yaml
@@ -0,0 +1,20 @@
+version: '3.8'
+
+services:
+ sybase:
+ image: datagrip/sybase
+ container_name: sybase
+ ports:
+ - "5001:5000"
+ environment:
+ - SYBASE_USER=sa
+ - SYBASE_PASSWORD=your_password
+ - LD_LIBRARY_PATH=/opt/sybase/ASE-16_0/lib:/opt/sybase/OCS-16_0/lib:$LD_LIBRARY_PATH
+ volumes:
+ - sybase-data:/var/lib/sybase
+ - ./init-scripts:/docker-entrypoint-initdb.d
+ - ./custom-entrypoint.sh:/custom-entrypoint.sh
+ entrypoint: ["/bin/bash", "/custom-entrypoint.sh"]
+
+volumes:
+ sybase-data:
diff --git a/adapters/sybase/init-scripts/create-database.sql b/adapters/sybase/init-scripts/create-database.sql
new file mode 100644
index 0000000..3a2a689
--- /dev/null
+++ b/adapters/sybase/init-scripts/create-database.sql
@@ -0,0 +1,2 @@
+CREATE DATABASE test;
+GO
diff --git a/adapters/sybase/model.json b/adapters/sybase/model.json
new file mode 100644
index 0000000..1329176
--- /dev/null
+++ b/adapters/sybase/model.json
@@ -0,0 +1,13 @@
+{
+ "version": "1.0",
+ "defaultSchema": "db2",
+ "schemas": [
+ {
+ "name": "db2",
+ "type": "jdbc",
+ "jdbcUrl": "jdbc:db2://192.168.86.233:50000/testdb",
+ "jdbcUser": "db2inst1",
+ "jdbcPassword": "mypassword"
+ }
+ ]
+}
diff --git a/adapters/sybase/schema.json b/adapters/sybase/schema.json
new file mode 100644
index 0000000..1346c1e
--- /dev/null
+++ b/adapters/sybase/schema.json
@@ -0,0 +1,133 @@
+{
+ "$schema": "http://json-schema.org/draft-07/schema#",
+ "title": "ParsedConfiguration",
+ "type": "object",
+ "required": [
+ "version"
+ ],
+ "properties": {
+ "version": {
+ "$ref": "#/definitions/Version"
+ },
+ "$schema": {
+ "type": "string"
+ },
+ "model": {
+ "type": "object",
+ "properties": {
+ "version": {
+ "type": "string"
+ },
+ "defaultSchema": {
+ "type": "string"
+ },
+ "schemas": {
+ "type": "array",
+ "items": {
+ "type": "object",
+ "properties": {
+ "type": {
+ "type": "string"
+ },
+ "name": {
+ "type": "string"
+ },
+ "jdbcUser": {
+ "type": "string"
+ },
+ "jdbcPassword": {
+ "type": "string"
+ },
+ "jdbcUrl": {
+ "type": "string"
+ },
+ "sqlDialectFactory": {
+ "type": "string"
+ },
+ "jdbcCatalog": {
+ "type": "string"
+ },
+ "jdbcSchema": {},
+ "factory": {
+ "type": "string"
+ },
+ "operand": {
+ "type": "object",
+ "properties": {
+ "directory": {
+ "type": "string"
+ },
+ "host": {
+ "type": "string"
+ },
+ "port": {
+ "type": "number"
+ },
+ "database": {
+ "type": "string"
+ },
+ "password": {
+ "type": "string"
+ }
+ }
+ },
+ "tables": {
+ "type": "array",
+ "items": {
+ "type": "object",
+ "properties": {
+ "name": {
+ "type": "string"
+ },
+ "factory": {
+ "type": "string"
+ },
+ "operand": {
+ "type": "object",
+ "properties": {
+ "dataFormat": {
+ "type": "string"
+ },
+ "fields": {
+ "type": "array",
+ "items": {
+ "type": "object",
+ "properties": {
+ "name": {
+ "type": "string"
+ },
+ "type": {
+ "type": "string"
+ },
+ "mapping": {}
+ },
+ "required": [
+ "name",
+ "type",
+ "mapping"
+ ]
+ }
+ },
+ "keyDelimiter": {
+ "type": "string"
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ },
+ "definitions": {
+ "Version": {
+ "type": "string",
+ "enum": [
+ "5"
+ ]
+ }
+ }
+}
\ No newline at end of file
diff --git a/adapters/trino/.env b/adapters/trino/.env
new file mode 100644
index 0000000..18cf2aa
--- /dev/null
+++ b/adapters/trino/.env
@@ -0,0 +1,6 @@
+JAR_DEPENDENCY_FOLDER=../../calcite-rs-jni/target/dependency
+CALCITE_JAR=../../calcite-rs-jni/target/calcite-rs-jni-1.0-SNAPSHOT.jar
+RUST_LOG=info
+OTEL_LOGS_EXPORTER=console
+OTEL_LOG_LEVEL=trace
+LOG4J_CONFIGURATION_FILE=../../calcite-rs-jni/target/classes/log4j2.xml
\ No newline at end of file
diff --git a/adapters/trino/.env.local b/adapters/trino/.env.local
new file mode 100644
index 0000000..afdaddc
--- /dev/null
+++ b/adapters/trino/.env.local
@@ -0,0 +1,4 @@
+RUST_LOG=info
+OTEL_LOGS_EXPORTER=console
+OTEL_LOG_LEVEL=trace
+OTEL_EXPORTER_OTLP_ENDPOINT=http://local.hasura.dev:4317
diff --git a/adapters/trino/config/config.properties b/adapters/trino/config/config.properties
new file mode 100644
index 0000000..0dd1818
--- /dev/null
+++ b/adapters/trino/config/config.properties
@@ -0,0 +1,11 @@
+http-server.authentication.type=PASSWORD
+internal-communication.shared-secret=TBf+WfgyRXCQN+8bevQTA5LOvfFRIsO4W/l6J06bUvo=
+coordinator=true
+node-scheduler.include-coordinator=true
+http-server.http.port=8080
+discovery.uri=http://localhost:8080
+http-server.authentication.allow-insecure-over-http=true
+http-server.https.enabled=true
+http-server.https.port=8443
+http-server.https.keystore.path=/etc/trino/trino-keystore.jks
+http-server.https.keystore.key=testtest
diff --git a/adapters/trino/config/jvm.config b/adapters/trino/config/jvm.config
new file mode 100644
index 0000000..b027857
--- /dev/null
+++ b/adapters/trino/config/jvm.config
@@ -0,0 +1,8 @@
+-Xmx16G
+-XX:+UseG1GC
+-XX:G1HeapRegionSize=32M
+-XX:+UseGCOverheadLimit
+-XX:+ExplicitGCInvokesConcurrent
+-XX:+HeapDumpOnOutOfMemoryError
+-XX:OnOutOfMemoryError=kill -9 %p
+-XX:+ExitOnOutOfMemoryError
diff --git a/adapters/trino/config/node.properties b/adapters/trino/config/node.properties
new file mode 100644
index 0000000..0d1d3f4
--- /dev/null
+++ b/adapters/trino/config/node.properties
@@ -0,0 +1,3 @@
+node.environment=production
+node.id=unique-node-id
+node.data-dir=/var/trino/data
diff --git a/adapters/trino/config/password-authenticator.properties b/adapters/trino/config/password-authenticator.properties
new file mode 100644
index 0000000..9c76ffa
--- /dev/null
+++ b/adapters/trino/config/password-authenticator.properties
@@ -0,0 +1,2 @@
+password-authenticator.name=file
+file.password-file=/etc/trino/password.db
diff --git a/adapters/trino/config/password.db b/adapters/trino/config/password.db
new file mode 100644
index 0000000..ca0f12f
--- /dev/null
+++ b/adapters/trino/config/password.db
@@ -0,0 +1 @@
+trino:trino
diff --git a/adapters/trino/dev.local.configuration.json b/adapters/trino/dev.local.configuration.json
new file mode 100644
index 0000000..4c7d2d1
--- /dev/null
+++ b/adapters/trino/dev.local.configuration.json
@@ -0,0 +1,90 @@
+{
+ "version": "5",
+ "$schema": "schema.json",
+ "model": {
+ "version": "1.0",
+ "defaultSchema": "db2",
+ "schemas": [
+ {
+ "type": "jdbc",
+ "name": "db2",
+ "jdbcUser": "db2inst1",
+ "jdbcPassword": "mypassword",
+ "jdbcUrl": "jdbc:db2://192.168.86.233:50000/testdb"
+ }
+ ]
+ },
+ "model_file_path": "./model.json",
+ "fixes": true,
+ "metadata": {
+ "PROJECTS": {
+ "schema": "db2",
+ "name": "PROJECTS",
+ "columns": {
+ "PROJECTID": {
+ "name": "PROJECTID",
+ "scalarType": "INTEGER",
+ "nullable": false
+ },
+ "PROJECTNAME": {
+ "name": "PROJECTNAME",
+ "scalarType": "VARCHAR",
+ "nullable": true
+ },
+ "DEPARTMENTID": {
+ "name": "DEPARTMENTID",
+ "scalarType": "INTEGER",
+ "nullable": true
+ }
+ },
+ "primaryKeys": [],
+ "exportedKeys": []
+ },
+ "EMPLOYEES": {
+ "schema": "db2",
+ "name": "EMPLOYEES",
+ "columns": {
+ "FIRSTNAME": {
+ "name": "FIRSTNAME",
+ "scalarType": "VARCHAR",
+ "nullable": true
+ },
+ "LASTNAME": {
+ "name": "LASTNAME",
+ "scalarType": "VARCHAR",
+ "nullable": true
+ },
+ "EMPLOYEEID": {
+ "name": "EMPLOYEEID",
+ "scalarType": "INTEGER",
+ "nullable": false
+ },
+ "DEPARTMENTID": {
+ "name": "DEPARTMENTID",
+ "scalarType": "INTEGER",
+ "nullable": true
+ }
+ },
+ "primaryKeys": [],
+ "exportedKeys": []
+ },
+ "DEPARTMENTS": {
+ "schema": "db2",
+ "name": "DEPARTMENTS",
+ "columns": {
+ "DEPARTMENTNAME": {
+ "name": "DEPARTMENTNAME",
+ "scalarType": "VARCHAR",
+ "nullable": true
+ },
+ "DEPARTMENTID": {
+ "name": "DEPARTMENTID",
+ "scalarType": "INTEGER",
+ "nullable": false
+ }
+ },
+ "primaryKeys": [],
+ "exportedKeys": []
+ }
+ }
+}
\ No newline at end of file
diff --git a/adapters/trino/docker-compose.yaml b/adapters/trino/docker-compose.yaml
new file mode 100644
index 0000000..477443c
--- /dev/null
+++ b/adapters/trino/docker-compose.yaml
@@ -0,0 +1,31 @@
+version: '3.8'
+
+services:
+ trino:
+ image: trinodb/trino:latest
+ ports:
+ - "8080:8080"
+ environment:
+ - JAVA_TOOL_OPTIONS=-Duser.timezone=UTC
+ depends_on:
+ - postgres
+ volumes:
+ - trino_catalog:/etc/trino/catalog
+ - ./config:/etc/trino
+ - ./var/trino:/var/trino
+ command: /usr/lib/trino/bin/run-trino
+
+ postgres:
+ image: postgres:latest
+ environment:
+ POSTGRES_USER: trino
+ POSTGRES_PASSWORD: trino
+ POSTGRES_DB: postgres
+ ports:
+ - "5432:5432"
+ volumes:
+ - postgres_data:/var/lib/postgresql/data
+
+volumes:
+ trino_catalog:
+ postgres_data:
diff --git a/adapters/trino/init.sql b/adapters/trino/init.sql
new file mode 100644
index 0000000..e176ccb
--- /dev/null
+++ b/adapters/trino/init.sql
@@ -0,0 +1,6 @@
+CREATE SCHEMA IF NOT EXISTS TEST;
+CREATE TABLE IF NOT EXISTS TEST.USERS (
+ ID INT PRIMARY KEY,
+ NAME VARCHAR(255)
+);
+INSERT INTO TEST.USERS (ID, NAME) VALUES (1, 'Alice'), (2, 'Bob');
diff --git a/adapters/trino/model.json b/adapters/trino/model.json
new file mode 100644
index 0000000..5a56810
--- /dev/null
+++ b/adapters/trino/model.json
@@ -0,0 +1,15 @@
+{
+ "version": "1.0",
+ "defaultSchema": "TEST",
+ "schemas": [
+ {
+ "name": "TEST",
+ "type": "jdbc",
+ "jdbcDriver": "org.h2.Driver",
+ "jdbcUrl": "jdbc:h2:tcp://localhost:1521/test",
+ "jdbcSchema": "PUBLIC",
+ "jdbcUser": "sa",
+ "jdbcPassword": ""
+ }
+ ]
+}
diff --git a/adapters/trino/schema.json b/adapters/trino/schema.json
new file mode 100644
index 0000000..1346c1e
--- /dev/null
+++ b/adapters/trino/schema.json
@@ -0,0 +1,133 @@
+{
+ "$schema": "http://json-schema.org/draft-07/schema#",
+ "title": "ParsedConfiguration",
+ "type": "object",
+ "required": [
+ "version"
+ ],
+ "properties": {
+ "version": {
+ "$ref": "#/definitions/Version"
+ },
+ "$schema": {
+ "type": "string"
+ },
+ "model": {
+ "type": "object",
+ "properties": {
+ "version": {
+ "type": "string"
+ },
+ "defaultSchema": {
+ "type": "string"
+ },
+ "schemas": {
+ "type": "array",
+ "items": {
+ "type": "object",
+ "properties": {
+ "type": {
+ "type": "string"
+ },
+ "name": {
+ "type": "string"
+ },
+ "jdbcUser": {
+ "type": "string"
+ },
+ "jdbcPassword": {
+ "type": "string"
+ },
+ "jdbcUrl": {
+ "type": "string"
+ },
+ "sqlDialectFactory": {
+ "type": "string"
+ },
+ "jdbcCatalog": {
+ "type": "string"
+ },
+ "jdbcSchema": {},
+ "factory": {
+ "type": "string"
+ },
+ "operand": {
+ "type": "object",
+ "properties": {
+ "directory": {
+ "type": "string"
+ },
+ "host": {
+ "type": "string"
+ },
+ "port": {
+ "type": "number"
+ },
+ "database": {
+ "type": "string"
+ },
+ "password": {
+ "type": "string"
+ }
+ }
+ },
+ "tables": {
+ "type": "array",
+ "items": {
+ "type": "object",
+ "properties": {
+ "name": {
+ "type": "string"
+ },
+ "factory": {
+ "type": "string"
+ },
+ "operand": {
+ "type": "object",
+ "properties": {
+ "dataFormat": {
+ "type": "string"
+ },
+ "fields": {
+ "type": "array",
+ "items": {
+ "type": "object",
+ "properties": {
+ "name": {
+ "type": "string"
+ },
+ "type": {
+ "type": "string"
+ },
+ "mapping": {}
+ },
+ "required": [
+ "name",
+ "type",
+ "mapping"
+ ]
+ }
+ },
+ "keyDelimiter": {
+ "type": "string"
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ },
+ "definitions": {
+ "Version": {
+ "type": "string",
+ "enum": [
+ "5"
+ ]
+ }
+ }
+}
\ No newline at end of file
diff --git a/adapters/trino/trino_catalog/postgres.properties b/adapters/trino/trino_catalog/postgres.properties
new file mode 100644
index 0000000..a0a088c
--- /dev/null
+++ b/adapters/trino/trino_catalog/postgres.properties
@@ -0,0 +1,4 @@
+connector.name=postgresql
+connection-url=jdbc:postgresql://postgres:5432/postgres
+connection-user=trino
+connection-password=trino
diff --git a/build.sh b/build.sh
index 6e55f48..2518908 100755
--- a/build.sh
+++ b/build.sh
@@ -4,8 +4,8 @@ release_info=$(curl -L \
-H "X-GitHub-Api-Version: 2022-11-28" \
https://api.github.com/repos/hasura/ndc-calcite/releases/latest)
TAG=$(echo "$release_info" | grep 'tag_name' | awk -F':' '{print $2}' | tr -d ' "",')
-tar -czvf connector-definition.tgz connector-definition
docker build . --platform linux/arm64,linux/amd64 -t kstott/meta_connector:latest
+docker buildx build --platform linux/arm64,linux/amd64 --output type=oci,dest=./image.tar .
docker tag kstott/meta_connector:latest kstott/meta_connector:"$TAG"
docker push kstott/meta_connector:latest
docker push kstott/meta_connector:"$TAG"
diff --git a/calcite-rs-jni/calcite b/calcite-rs-jni/calcite
index 208afa6..1abb606 160000
--- a/calcite-rs-jni/calcite
+++ b/calcite-rs-jni/calcite
@@ -1 +1 @@
-Subproject commit 208afa6244338de9ebad251f6a9484d2385a0d06
+Subproject commit 1abb60601523203d56f947c735262fbe2045032e
diff --git a/calcite-rs-jni/pom.xml b/calcite-rs-jni/pom.xml
index 2345c9e..6d11eec 100644
--- a/calcite-rs-jni/pom.xml
+++ b/calcite-rs-jni/pom.xml
@@ -272,6 +272,11 @@
trino-jdbc
453
+
+ com.teradata.jdbc
+ terajdbc
+ 20.00.00.24
+
com.microsoft.sqlserver
mssql-jdbc
diff --git a/calcite-rs-jni/src/main/java/org/kenstott/CalciteQuery.java b/calcite-rs-jni/src/main/java/org/kenstott/CalciteQuery.java
index 574c6ab..68cd50f 100644
--- a/calcite-rs-jni/src/main/java/org/kenstott/CalciteQuery.java
+++ b/calcite-rs-jni/src/main/java/org/kenstott/CalciteQuery.java
@@ -241,7 +241,9 @@ private Map getTableColumnInfo(TableMetadata table) {
entry("VARCHAR(65536) NOT NULL", "VARCHAR"),
entry("VARCHAR NOT NULL", "VARCHAR"),
entry("JavaType(class java.util.ArrayList)", "LIST"),
+ entry("JavaType(class org.apache.calcite.adapter.file.ComparableArrayList)", "LIST"),
entry("JavaType(class java.util.LinkedHashMap)", "MAP"),
+ entry("JavaType(class org.apache.calcite.adapter.file.ComparableLinkedHashMap)", "MAP"),
entry("JavaType(class java.lang.String)", "VARCHAR"),
entry("JavaType(class java.lang.Integer)", "INTEGER"),
entry("INTEGER NOT NULL", "INTEGER"),
diff --git a/calcite-rs-jni/src/main/java/org/kenstott/Main.java b/calcite-rs-jni/src/main/java/org/kenstott/Main.java
index 84ced05..8a23586 100644
--- a/calcite-rs-jni/src/main/java/org/kenstott/Main.java
+++ b/calcite-rs-jni/src/main/java/org/kenstott/Main.java
@@ -15,7 +15,7 @@
public class Main {
public static void main(String[] args) {
- String modelPath = "../adapters/h2/model.json";
+ String modelPath = "../adapters/file/model.json";
String username = "";
String password = "";
Connection calciteConnection = null;
@@ -34,7 +34,7 @@ public static void main(String[] args) {
// """);
// System.out.println(zz);
String z1 = query.queryModels("""
- SELECT "ID" FROM "TEST"."PROJECTS"
+ SELECT COUNT("a") AS "a_count", COUNT(DISTINCT "a") AS "a_distinct_count", COUNT("b") AS "b_count", COUNT(DISTINCT "b") AS "b_distinct_count", COUNT("c") AS "c_count", COUNT(DISTINCT "c") AS "c_distinct_count", COUNT("d") AS "d_count", COUNT(DISTINCT "d") AS "d_distinct_count", COUNT("e") AS "e_count", COUNT(DISTINCT "e") AS "e_distinct_count", COUNT("f") AS "f_count", COUNT(DISTINCT "f") AS "f_distinct_count", COUNT("g") AS "g_count", COUNT(DISTINCT "g") AS "g_distinct_count", COUNT("id") AS "id_count", COUNT(DISTINCT "id") AS "id_distinct_count", COUNT("object") AS "object_count", COUNT(DISTINCT "object") AS "object_distinct_count" FROM "sales"."ARCHERS" LIMIT 10
"""
);
System.out.println(z1);
diff --git a/config-templates/configuration.json b/config-templates/configuration.json
deleted file mode 100644
index f56d2ab..0000000
--- a/config-templates/configuration.json
+++ /dev/null
@@ -1,6 +0,0 @@
-{
- "version": "4",
- "$schema": "schema.json",
- "model_file_path": "/etc/connector/models/model.json",
- "fixes": true
-}
diff --git a/config-templates/docker-compose.file.meta.yaml b/config-templates/docker-compose.file.meta.yaml
deleted file mode 100644
index 6e830ae..0000000
--- a/config-templates/docker-compose.file.meta.yaml
+++ /dev/null
@@ -1,23 +0,0 @@
-services:
- meta_connector:
- build:
- context: .
- dockerfile_inline: |-
- FROM docker.io/kstott/meta_connector:latest
- develop:
- watch:
- - path: ./
- action: sync+restart
- target: /etc/connector
- env_file:
- - .env.local
- extra_hosts:
- - local.hasura.dev=host-gateway
- ports:
- - mode: ingress
- target: 8080
- published: ${HASURA_CONNECTOR_PORT:-8080}
- protocol: tcp
- volumes:
- - .:/etc/connector
- - ${MODEL_FILE:-./models/model.json}:/etc/connector/models/model.json
diff --git a/connector-definition.tgz b/connector-definition.tgz
deleted file mode 100644
index e66d18c..0000000
Binary files a/connector-definition.tgz and /dev/null differ
diff --git a/connector-definition/connector-metadata.yaml b/connector-definition/connector-metadata.yaml
deleted file mode 100644
index 4d394f0..0000000
--- a/connector-definition/connector-metadata.yaml
+++ /dev/null
@@ -1,15 +0,0 @@
-packagingDefinition:
- type: PrebuiltDockerImage
- dockerImage: "docker.io/kstott/meta_connector:latest"
-supportedEnvironmentVariables:
- - name: MODEL_FILE
- description: The location of the calcite model file defaults to /etc/connector/models/model.json
-commands:
- update: hasura-calcite update
-cliPlugin:
- name: ndc-calcite-cli
- version: "v0.1.0"
-dockerComposeWatch:
- - path: ./
- target: /etc/connector
- action: sync+restart
diff --git a/crates/calcite-schema/Cargo.toml b/crates/calcite-schema/Cargo.toml
new file mode 100644
index 0000000..35a825c
--- /dev/null
+++ b/crates/calcite-schema/Cargo.toml
@@ -0,0 +1,31 @@
+[package]
+name = "ndc-calcite-schema"
+version.workspace = true
+edition.workspace = true
+license.workspace = true
+
+[lints]
+workspace = true
+
+[dependencies]
+ndc-calcite-values = { path = "../values"}
+ndc-models = { workspace = true }
+ndc-sdk = { workspace = true }
+jni = { workspace = true }
+
+anyhow = { workspace = true }
+# We only use clap for the derive feature.
+clap = { workspace = true, features = ["derive", "env"] }
+prometheus = {workspace = true }
+schemars = { workspace = true, features = ["smol_str", "preserve_order"] }
+serde = { workspace = true }
+serde_json = { workspace = true, features = ["raw_value"] }
+smol_str = { workspace = true }
+sqlx = { workspace = true, features = ["json", "postgres", "runtime-tokio-rustls"] }
+thiserror = { workspace = true }
+tokio = { workspace = true, features = ["full"] }
+tracing = { workspace = true }
+once_cell = { workspace = true}
+
+[dev-dependencies]
+jsonschema = { workspace = true }
diff --git a/crates/connectors/ndc-calcite/src/aggregates.rs b/crates/calcite-schema/src/aggregates.rs
similarity index 79%
rename from crates/connectors/ndc-calcite/src/aggregates.rs
rename to crates/calcite-schema/src/aggregates.rs
index 758baea..84d13c5 100644
--- a/crates/connectors/ndc-calcite/src/aggregates.rs
+++ b/crates/calcite-schema/src/aggregates.rs
@@ -14,7 +14,7 @@
use std::collections::BTreeMap;
-use ndc_models::{AggregateFunctionDefinition, Type};
+use ndc_models::{AggregateFunctionDefinition, AggregateFunctionName, Type};
/// Generates numeric aggregate functions for a given underlying type.
///
@@ -28,13 +28,13 @@ use ndc_models::{AggregateFunctionDefinition, Type};
#[tracing::instrument]
pub fn numeric_aggregates(
underlying_type: &str,
-) -> BTreeMap {
- let aggregate_functions: BTreeMap =
+) -> BTreeMap {
+ let aggregate_functions: BTreeMap =
["sum", "max", "avg", "min"]
.iter()
.map(|function| {
(
- function.to_string(),
+ AggregateFunctionName::from(function.to_string()),
aggregate_function_definition(underlying_type),
)
})
diff --git a/crates/connectors/ndc-calcite/src/configuration.rs b/crates/calcite-schema/src/calcite.rs
similarity index 82%
rename from crates/connectors/ndc-calcite/src/configuration.rs
rename to crates/calcite-schema/src/calcite.rs
index b92d29a..2a1d514 100644
--- a/crates/connectors/ndc-calcite/src/configuration.rs
+++ b/crates/calcite-schema/src/calcite.rs
@@ -9,12 +9,14 @@
extern crate serde_json;
use std::collections::HashMap;
+use ndc_models::{FieldName};
+use schemars::JsonSchema;
use serde::{Deserialize, Serialize};
use serde_json::Value;
/// The type of the schema.
// ANCHOR: Schema
-#[derive(Serialize, Deserialize, Clone, Debug)]
+#[derive(PartialEq, Eq, JsonSchema, Serialize, Deserialize, Clone, Debug)]
pub struct Schema {
#[serde(skip_serializing_if = "Option::is_none")]
#[serde(rename = "type")]
@@ -60,7 +62,7 @@ pub struct Schema {
/// Represents a lattice in the schema. A lattice (in Calcite)
/// refers to aggregates.
-#[derive(Serialize, Deserialize, Clone, Debug)]
+#[derive(Eq, PartialEq, JsonSchema, Serialize, Deserialize, Clone, Debug)]
pub struct Lattice {
#[serde(skip_serializing_if = "Option::is_none")]
pub name: Option,
@@ -83,21 +85,21 @@ pub struct Lattice {
pub tiles: Option>,
}
-#[derive(Serialize, Deserialize, Clone, Debug)]
+#[derive(Eq, PartialEq, JsonSchema, Serialize, Deserialize, Clone, Debug)]
pub struct Tile {
#[serde(skip_serializing_if = "Option::is_none")]
pub dimensions: Option,
#[serde(skip_serializing_if = "Option::is_none")]
pub measures: Option>
}
-#[derive(Serialize, Deserialize, Clone, Debug)]
+#[derive(Eq, PartialEq, JsonSchema, Serialize, Deserialize, Clone, Debug)]
pub struct Measure {
#[serde(skip_serializing_if = "Option::is_none")]
pub agg: Option,
#[serde(skip_serializing_if = "Option::is_none")]
pub args: Option
}
-#[derive(Serialize, Deserialize, Clone, Debug)]
+#[derive(Eq, PartialEq, JsonSchema, Serialize, Deserialize, Clone, Debug)]
pub struct Materialization {
#[serde(skip_serializing_if = "Option::is_none")]
pub view: Option,
@@ -107,14 +109,14 @@ pub struct Materialization {
pub sql: Option
}
-#[derive(Serialize, Deserialize, Clone, Debug)]
+#[derive(Eq, PartialEq, JsonSchema, Serialize, Deserialize, Clone, Debug)]
pub struct Column {
#[serde(rename = "type")]
pub r#type: String,
pub name: String,
}
-#[derive(Serialize, Deserialize, Clone, Debug)]
+#[derive(Eq, PartialEq, JsonSchema, Serialize, Deserialize, Clone, Debug)]
pub struct Type {
#[serde(rename = "type")]
pub r#type: String,
@@ -130,7 +132,7 @@ pub struct Type {
/// - `name` - The name of the table. It is an optional field.
/// - `factory` - The factory of the table. It is an optional field.
/// - `operand` - The operand of the table. It is an optional field.
-#[derive(Serialize, Deserialize, Clone, Debug)]
+#[derive(Eq, PartialEq, JsonSchema, Serialize, Deserialize, Clone, Debug)]
pub struct Table {
pub name: Option,
#[serde(skip_serializing_if = "Option::is_none")]
@@ -153,7 +155,7 @@ pub struct Table {
}
/// Represents a function.
-#[derive(Serialize, Deserialize, Clone, Debug)]
+#[derive(Eq, PartialEq, JsonSchema, Serialize, Deserialize, Clone, Debug)]
pub struct Function {
pub name: Option,
#[serde(skip_serializing_if = "Option::is_none")]
@@ -167,7 +169,7 @@ pub struct Function {
}
/// Represents the operand used in the schema.
-#[derive(Serialize, Deserialize, Clone, Debug)]
+#[derive(Eq, PartialEq, JsonSchema, Serialize, Deserialize, Clone, Debug)]
pub struct Operand {
#[serde(skip_serializing_if = "Option::is_none")]
pub directory: Option,
@@ -206,7 +208,7 @@ pub struct Operand {
/// Represents a model. This is explained in greater detail
/// in the Apache Calcite docs.
-#[derive(Serialize, Deserialize, Clone, Debug)]
+#[derive(JsonSchema, Serialize, Deserialize, Clone, Debug, PartialEq, Eq)]
pub struct Model {
/// Calcite version
pub version: String,
@@ -223,38 +225,8 @@ pub struct Model {
pub types: Option>
}
-/// Represents the configuration for the Calcite engine.
-#[derive(Serialize, Deserialize, Clone, Debug)]
-pub struct CalciteConfiguration {
- /// Hasura NDC version
- pub version: String,
- /// JSON Schema file that defines a valid configuration
- #[serde(rename = "$schema")]
- pub _schema: String,
- /// The Calcite Model - somewhat dependent on type of calcite adapter being used.
- /// Better documentation can be found [here](https://calcite.apache.org/docs/model.html).
- pub model: Option,
- /// Used internally
- pub model_file_path: Option,
- #[serde(skip_serializing_if = "Option::is_none")]
- /// Certain fixes that will solve for missing field values, for non-existing fields.
- /// It's expensive and probably not necessary, but required to pass the NDC
- /// tests. You can set the value to false in order to improve performance.
- pub fixes: Option,
- #[serde(skip_serializing_if = "Option::is_none")]
- #[serde(rename = "supportJsonObject")]
- pub supports_json_object: Option,
- #[serde(skip_serializing_if = "Option::is_none")]
- /// Many common JDBC jars are included by default. Some are not you can
- /// create a directory with additional required JARS and point to that
- /// directory here.
- pub jars: Option,
- #[serde(skip_serializing_if = "Option::is_none")]
- pub metadata: Option>
-}
-
/// Represents an exported key between two tables in a database.
-#[derive(Serialize, Deserialize, Clone, Debug)]
+#[derive(JsonSchema, Serialize, Deserialize, Clone, Debug, Eq, PartialEq)]
pub struct ExportedKey {
#[serde(skip_serializing_if = "Option::is_none")]
#[serde(rename = "pkTableCatalog")]
@@ -295,7 +267,7 @@ pub struct ExportedKey {
/// - `columns` - A `HashMap` containing the columns of the table.
/// - `primary_keys` - An optional `Vec` of primary key column names.
/// - `exported_keys` - An optional `Vec` of exported keys to other tables.
-#[derive(Serialize, Deserialize, Clone, Debug)]
+#[derive(JsonSchema, Serialize, Deserialize, Clone, Debug, PartialEq, Eq)]
pub struct TableMetadata {
#[serde(skip_serializing_if = "Option::is_none")]
pub catalog: Option,
@@ -304,7 +276,7 @@ pub struct TableMetadata {
pub name: String,
#[serde(skip_serializing_if = "Option::is_none")]
pub description: Option,
- pub columns: HashMap,
+ pub columns: HashMap,
#[serde(skip_serializing_if = "Option::is_none")]
#[serde(rename = "primaryKeys")]
pub primary_keys: Option>,
@@ -314,7 +286,7 @@ pub struct TableMetadata {
}
/// Represents the metadata of a column in a database table.
-#[derive(Serialize, Deserialize, Clone, Debug)]
+#[derive(PartialEq, Eq, JsonSchema, Serialize, Deserialize, Clone, Debug)]
pub struct ColumnMetadata {
pub name: String,
#[serde(skip_serializing_if = "Option::is_none")]
diff --git a/crates/connectors/ndc-calcite/src/collections.rs b/crates/calcite-schema/src/collections.rs
similarity index 70%
rename from crates/connectors/ndc-calcite/src/collections.rs
rename to crates/calcite-schema/src/collections.rs
index 9e2c18e..f8b8578 100644
--- a/crates/connectors/ndc-calcite/src/collections.rs
+++ b/crates/calcite-schema/src/collections.rs
@@ -5,10 +5,10 @@
use std::collections::{BTreeMap, HashMap};
use std::error::Error;
-use ndc_models::{CollectionInfo, ForeignKeyConstraint, ObjectField, ObjectType, ScalarType, SchemaResponse, Type, UniquenessConstraint};
+use ndc_models::{CollectionInfo, CollectionName, FieldName, ForeignKeyConstraint, ObjectField, ObjectType, ObjectTypeName, ScalarType, ScalarTypeName, SchemaResponse, Type, TypeName, UniquenessConstraint};
use ndc_models::Type::{Named, Nullable};
-use crate::configuration::{ColumnMetadata, TableMetadata};
+use crate::calcite::{ColumnMetadata, TableMetadata};
/// Extracts information from data models and scalar types to generate object types and collection information.
///
@@ -28,26 +28,27 @@ use crate::configuration::{ColumnMetadata, TableMetadata};
/// An inner Result can also be returned, which contains an error indicating an issue with the input data.
// ANCHOR: collections
pub fn collections(
- data_models: &HashMap,
- scalar_types: &BTreeMap,
-) -> Result<(BTreeMap, Vec), Result>, > {
- let mut object_types: BTreeMap = BTreeMap::new();
+ data_models: &HashMap,
+ scalar_types: &BTreeMap,
+) -> Result<(BTreeMap, Vec), Result>, > {
+ let mut object_types: BTreeMap = BTreeMap::new();
let mut collection_infos: Vec = Vec::new();
for (table, table_metadata) in data_models {
let fields = build_fields(&table_metadata.columns);
- if !scalar_types.contains_key(&table_metadata.name) {
- object_types.insert(table.clone(), ObjectType {
+ let tbl_name = ScalarTypeName::new(table_metadata.name.clone().into());
+ if !scalar_types.contains_key(&tbl_name) {
+ object_types.insert(ObjectTypeName::new(table.to_string().into()), ObjectType {
description: table_metadata.description.clone(),
fields,
}, );
let uniqueness_constraints = build_uniqueness_constraints(&table_metadata);
let foreign_keys = build_foreign_keys(&table_metadata, data_models);
collection_infos.push(CollectionInfo {
- name: table_metadata.name.clone(),
+ name: CollectionName::new(table_metadata.name.clone().parse().unwrap()),
description: Some(format!("A collection of {}", table)),
- collection_type: table_metadata.name.clone(),
+ collection_type: ObjectTypeName::new(TypeName::from(table_metadata.name.clone())),
arguments: BTreeMap::new(),
foreign_keys,
uniqueness_constraints,
@@ -66,16 +67,16 @@ pub fn collections(
}
#[tracing::instrument]
-fn build_fields(column_metadata: &HashMap) -> BTreeMap {
+fn build_fields(column_metadata: &HashMap) -> BTreeMap {
column_metadata.iter().map(|(column_name, column_metadata)| {
- let scalar_type = column_metadata.scalar_type.clone();
+ let scalar_type = TypeName::from(column_metadata.scalar_type.clone());
let nullable = column_metadata.nullable.clone();
let final_type: Type = if nullable {
Nullable { underlying_type: Box::new(Named { name: scalar_type }) }
} else {
Named { name: scalar_type }
};
- (column_name.into(),
+ (column_name.clone(),
ObjectField {
description: column_metadata.description.clone(),
r#type: final_type,
@@ -87,12 +88,12 @@ fn build_fields(column_metadata: &HashMap) -> BTreeMap BTreeMap {
let mut uc = BTreeMap::new();
uc.insert("PK".into(), UniquenessConstraint {
- unique_columns: tb_metadata.primary_keys.clone().unwrap()
+ unique_columns: tb_metadata.primary_keys.clone().unwrap().iter().map(|s| FieldName::new(s.clone().parse().unwrap())).collect()
});
uc
}
-fn build_foreign_keys(tb_metadata: &TableMetadata, data_models: &HashMap) -> BTreeMap {
+fn build_foreign_keys(tb_metadata: &TableMetadata, data_models: &HashMap) -> BTreeMap {
let mut constraints: BTreeMap = Default::default();
for (_, foreign_table_metadata) in data_models {
for ft in foreign_table_metadata.clone().exported_keys.unwrap_or_default() {
@@ -102,13 +103,13 @@ fn build_foreign_keys(tb_metadata: &TableMetadata, data_models: &HashMap {
let mut constraint = ForeignKeyConstraint {
column_mapping: Default::default(),
- foreign_collection: pk_table_name.clone()
+ foreign_collection: CollectionName::from(pk_table_name.clone())
};
- constraint.column_mapping.insert(ft.fk_column_name, ft.pk_column_name);
+ constraint.column_mapping.insert(FieldName::from(ft.fk_column_name), FieldName::from(ft.pk_column_name));
constraints.insert(pk_table_name.clone(), constraint);
}
Some(value) => {
- value.column_mapping.insert(ft.fk_column_name, ft.pk_column_name);
+ value.column_mapping.insert(FieldName::from(ft.fk_column_name), FieldName::from(ft.pk_column_name));
}
}
}
diff --git a/crates/connectors/ndc-calcite/src/comparators.rs b/crates/calcite-schema/src/comparators.rs
similarity index 82%
rename from crates/connectors/ndc-calcite/src/comparators.rs
rename to crates/calcite-schema/src/comparators.rs
index 8b7041e..373188f 100644
--- a/crates/connectors/ndc-calcite/src/comparators.rs
+++ b/crates/calcite-schema/src/comparators.rs
@@ -4,7 +4,7 @@
//!
use std::collections::BTreeMap;
-use ndc_models::{ComparisonOperatorDefinition, Type};
+use ndc_models::{ComparisonOperatorDefinition, ComparisonOperatorName, Type, TypeName};
/// Generate string comparison operators based on the underlying type.
///
@@ -25,8 +25,8 @@ use ndc_models::{ComparisonOperatorDefinition, Type};
// ANCHOR: string_comparators
#[tracing::instrument]
pub fn string_comparators(
- numeric_comparison_operators: &BTreeMap,
-) -> BTreeMap {
+ numeric_comparison_operators: &BTreeMap,
+) -> BTreeMap {
let mut string_comparison_operators = numeric_comparison_operators.clone();
string_comparison_operators.insert(
"_like".into(),
@@ -82,7 +82,7 @@ pub fn string_comparators(
/// ```
// ANCHOR: numeric_comparators
#[tracing::instrument]
-pub fn numeric_comparators(underlying: String) -> BTreeMap {
+pub fn numeric_comparators(underlying: String) -> BTreeMap {
let numeric_comparison_operators = BTreeMap::from_iter([
("_eq".into(), ComparisonOperatorDefinition::Equal),
("_in".into(), ComparisonOperatorDefinition::In),
@@ -90,7 +90,7 @@ pub fn numeric_comparators(underlying: String) -> BTreeMap BTreeMap BTreeMap BTreeMap RootSchema {
+ SchemaSettings::openapi3()
+ .into_generator()
+ .into_root_schema_for::()
+}
pub const DEFAULT_CONNECTION_URI_VARIABLE: &str = "CONNECTION_URI";
@@ -19,7 +26,7 @@ pub const DEFAULT_CONNECTION_URI_VARIABLE: &str = "CONNECTION_URI";
/// Introducing a breaking configuration format change involves adding a new case to this type.
///
/// 'ParsedConfiguration' is used to support serialization and deserialization of an NDC
-/// configuration. It retains all the salient information that constitutes an instance of an NDC
+/// configuration. It retains all the salient information that constitues an instance of an NDC
/// deployment, such that 'c = parse_configuration(dir) => { write_parsed_configuration(c, dir2) ;
/// assert(c == parse_configuration(dir2))}'.
///
@@ -27,20 +34,18 @@ pub const DEFAULT_CONNECTION_URI_VARIABLE: &str = "CONNECTION_URI";
/// 'ParsedConfiguration' as well.
#[derive(Clone, PartialEq, Eq, Debug)]
pub enum ParsedConfiguration {
- Version1
-}
-
-#[derive(Debug, Copy, Clone)]
-pub enum VersionTag {
- Version1
+ Version5(version5::ParsedConfiguration),
}
+type Configuration = ParsedConfiguration;
impl ParsedConfiguration {
pub fn initial() -> Self {
- ParsedConfiguration::Version1
+ ParsedConfiguration::Version5(version5::ParsedConfiguration::empty())
}
pub fn version(&self) -> VersionTag {
- VersionTag::Version1
+ match self {
+ ParsedConfiguration::Version5(_) => VersionTag::Version5,
+ }
}
}
@@ -53,23 +58,30 @@ impl ParsedConfiguration {
///
/// Separating 'ParsedConfiguration' and 'Configuration' simplifies the main query translation
/// logic by placing the responsibility of dealing with configuration format evolution in
-/// 'ParsedConfiguration.
+/// 'ParsedConfiguration'.
///
-#[derive(Debug)]
-pub struct Configuration {
- fake: String
-}
+
+
pub async fn introspect(
input: ParsedConfiguration,
+ _context_path: &PathBuf,
environment: impl Environment,
) -> anyhow::Result {
- Ok(ParsedConfiguration::Version1)
+ match input {
+ ParsedConfiguration::Version5(config) => Ok(ParsedConfiguration::Version5(
+ version5::introspect(config, environment).await?,
+ )),
+ }
}
pub async fn parse_configuration(
configuration_dir: impl AsRef + Send,
) -> Result {
- Ok(ParsedConfiguration::Version1)
+ // Try parsing each supported version in turn
+ match version5::parse_configuration(configuration_dir.as_ref()).await {
+ Err(v5_err) => Err(v5_err),
+ Ok(config) => Ok(ParsedConfiguration::Version5(config)),
+ }
}
/// Turn a 'ParsedConfiguration' into a 'Configuration', such that it may be used in main
@@ -79,9 +91,11 @@ pub async fn parse_configuration(
/// into the runtime configuration.
pub fn make_runtime_configuration(
parsed_config: ParsedConfiguration,
- environment: impl Environment,
+ _environment: impl Environment,
) -> Result {
- Ok(Configuration{fake: "".to_string()})
+ match parsed_config {
+ ParsedConfiguration::Version5(c) => Ok(ParsedConfiguration::Version5(c)),
+ }
}
/// Write out a parsed configuration to a directory.
@@ -89,13 +103,17 @@ pub async fn write_parsed_configuration(
parsed_config: ParsedConfiguration,
out_dir: impl AsRef,
) -> Result<(), WriteParsedConfigurationError> {
- Ok(())
+ match parsed_config {
+ ParsedConfiguration::Version5(c) => version5::write_parsed_configuration(c, out_dir).await,
+ }
}
/// Produce an equivalent version of a parsed configuration in the latest supported version.
///
/// This is part of the configuration crate API to enable users to upgrade their configurations
-/// mechanically, using the ndc-calcite cli, when new versions are released..
+/// mechanically, using the ndc-postgres cli, when new versions are released.
pub fn upgrade_to_latest_version(parsed_config: ParsedConfiguration) -> ParsedConfiguration {
- ParsedConfiguration::Version1
+ match parsed_config {
+ ParsedConfiguration::Version5(_) => parsed_config,
+ }
}
diff --git a/crates/cli/src/error.rs b/crates/calcite-schema/src/error.rs
similarity index 100%
rename from crates/cli/src/error.rs
rename to crates/calcite-schema/src/error.rs
diff --git a/crates/connectors/ndc-calcite/src/jvm.rs b/crates/calcite-schema/src/jvm.rs
similarity index 95%
rename from crates/connectors/ndc-calcite/src/jvm.rs
rename to crates/calcite-schema/src/jvm.rs
index 3d44c4d..0ce5558 100644
--- a/crates/connectors/ndc-calcite/src/jvm.rs
+++ b/crates/calcite-schema/src/jvm.rs
@@ -9,11 +9,10 @@ use std::sync::Mutex;
use jni::{InitArgsBuilder, JavaVM, JNIVersion};
use once_cell::sync::OnceCell;
use tracing::{event, Level};
-
-use crate::configuration::CalciteConfiguration;
+use crate::configuration::ParsedConfiguration;
static JVM: OnceCell> = OnceCell::new();
-static CONFIG: OnceCell> = OnceCell::new();
+static CONFIG: OnceCell> = OnceCell::new();
/// Returns a reference to the global JVM instance.
///
@@ -67,7 +66,11 @@ pub fn get_jvm() -> &'static Mutex {
/// ```
// ANCHOR: init_jvm
#[tracing::instrument]
-pub fn init_jvm(calcite_configuration: &CalciteConfiguration) {
+pub fn init_jvm(calcite_configuration: &ParsedConfiguration) {
+ let configuration = match calcite_configuration {
+ ParsedConfiguration::Version5(c) => c
+ };
+
let state_inited = env::var("STATE_INITED").unwrap_or("false".to_string());
if state_inited == "false" {
let folder_path = env::var("JAR_DEPENDENCY_FOLDER").unwrap_or("/calcite-rs-jni/target/dependency".into());
@@ -88,7 +91,7 @@ pub fn init_jvm(calcite_configuration: &CalciteConfiguration) {
}
}
}
- match &calcite_configuration.jars {
+ match &configuration.jars {
Some(jars) => {
if let Ok(entries) = fs::read_dir(jars) {
for entry in entries {
diff --git a/crates/calcite-schema/src/lib.rs b/crates/calcite-schema/src/lib.rs
new file mode 100644
index 0000000..ab167ca
--- /dev/null
+++ b/crates/calcite-schema/src/lib.rs
@@ -0,0 +1,18 @@
+pub mod schema;
+pub mod scalars;
+pub mod aggregates;
+pub mod collections;
+
+pub mod comparators;
+pub mod models;
+
+pub mod version5;
+pub mod calcite;
+pub mod environment;
+pub mod error;
+pub mod jvm;
+
+pub mod configuration;
+pub mod version;
+mod metrics;
+mod test;
\ No newline at end of file
diff --git a/crates/calcite-schema/src/metrics.rs b/crates/calcite-schema/src/metrics.rs
new file mode 100644
index 0000000..72353f7
--- /dev/null
+++ b/crates/calcite-schema/src/metrics.rs
@@ -0,0 +1,70 @@
+//! Metrics setup and update for our connector.
+
+use prometheus::{IntGauge, Registry};
+
+use crate::version::VersionTag;
+
+/// The collection of configuration-related metrics exposed through the `/metrics` endpoint.
+#[derive(Debug, Clone)]
+pub struct Metrics {
+ configuration_version_3: IntGauge,
+ configuration_version_4: IntGauge,
+ configuration_version_5: IntGauge,
+}
+
+impl Metrics {
+ /// Set up counters and gauges used to produce Prometheus metrics
+ pub fn initialize(metrics_registry: &mut Registry) -> Result {
+ let configuration_version_3 = add_int_gauge_metric(
+ metrics_registry,
+ "ndc_postgres_configuration_version_3",
+ "Get whether configuration version 3 is used",
+ )?;
+
+ let configuration_version_4 = add_int_gauge_metric(
+ metrics_registry,
+ "ndc_postgres_configuration_version_4",
+ "Get whether configuration version 4 is used",
+ )?;
+
+ let configuration_version_5 = add_int_gauge_metric(
+ metrics_registry,
+ "ndc_postgres_configuration_version_5",
+ "Get whether configuration version 5 is used",
+ )?;
+
+ Ok(Self {
+ configuration_version_3,
+ configuration_version_4,
+ configuration_version_5,
+ })
+ }
+
+ /// Set the configuration version used by this connector instance.
+ pub fn set_configuration_version(&self, version: VersionTag) {
+ match version {
+ VersionTag::Version3 => self.configuration_version_3.set(1),
+ VersionTag::Version4 => self.configuration_version_4.set(1),
+ VersionTag::Version5 => self.configuration_version_5.set(1),
+ }
+ }
+}
+
+/// Create a new int gauge metric and register it with the provided Prometheus Registry
+fn add_int_gauge_metric(
+ metrics_registry: &mut Registry,
+ metric_name: &str,
+ metric_description: &str,
+) -> Result {
+ let int_gauge = IntGauge::with_opts(prometheus::Opts::new(metric_name, metric_description))?;
+ register_collector(metrics_registry, int_gauge)
+}
+
+/// Register a new collector with the registry, and returns it for later use.
+fn register_collector(
+ metrics_registry: &mut Registry,
+ collector: Collector,
+) -> Result {
+ metrics_registry.register(Box::new(collector.clone()))?;
+ Ok(collector)
+}
diff --git a/crates/calcite-schema/src/models.rs b/crates/calcite-schema/src/models.rs
new file mode 100644
index 0000000..b5f7556
--- /dev/null
+++ b/crates/calcite-schema/src/models.rs
@@ -0,0 +1,39 @@
+use jni::objects::{GlobalRef, JObject, JString, JValueGen};
+use std::collections::HashMap;
+use jni::objects::JValueGen::Object;
+use ndc_models::CollectionName;
+use crate::calcite::TableMetadata;
+use tracing::{event, Level};
+use crate::jvm::get_jvm;
+
+/// Retrieves models from Calcite.
+///
+/// # Arguments
+///
+/// * `calcite_ref` - A reference to the Calcite instance.
+///
+/// # Return
+///
+/// A `HashMap` containing the retrieved models. The outer `HashMap` maps model names
+/// to inner `HashMap`s, where each inner `HashMap` represents a model with its properties.
+#[tracing::instrument]
+pub fn get_models(calcite_ref: GlobalRef) -> HashMap {
+ let jvm = get_jvm().lock().unwrap();
+ let env = jvm.attach_current_thread().unwrap();
+ let calcite_query = env.new_local_ref(calcite_ref).unwrap();
+ let mut env = jvm.attach_current_thread_as_daemon().unwrap();
+ let args: &[JValueGen<&JObject<'_>>] = &[];
+ let method_signature = "()Ljava/lang/String;";
+ let result = env.call_method(calcite_query, "getModels", method_signature, args);
+ let map= match result.unwrap() {
+ Object(obj) => {
+ let j_string = JString::from(obj);
+ let json_string: String = env.get_string(&j_string).unwrap().into();
+ let map: HashMap = serde_json::from_str(&json_string).unwrap();
+ map
+ }
+ _ => todo!(),
+ };
+ event!(Level::INFO, "Retrieved models from Calcite");
+ return map;
+}
diff --git a/crates/connectors/ndc-calcite/src/scalars.rs b/crates/calcite-schema/src/scalars.rs
similarity index 97%
rename from crates/connectors/ndc-calcite/src/scalars.rs
rename to crates/calcite-schema/src/scalars.rs
index 65aaabf..e7e94df 100644
--- a/crates/connectors/ndc-calcite/src/scalars.rs
+++ b/crates/calcite-schema/src/scalars.rs
@@ -4,7 +4,7 @@
//!
use std::collections::BTreeMap;
-use ndc_models::{ComparisonOperatorDefinition, ScalarType, TypeRepresentation};
+use ndc_models::{ComparisonOperatorDefinition, ScalarType, ScalarTypeName, TypeRepresentation};
use crate::{aggregates, comparators};
@@ -68,7 +68,7 @@ use crate::{aggregates, comparators};
/// ```
// ANCHOR: scalars
#[tracing::instrument]
-pub fn scalars() -> BTreeMap {
+pub fn scalars() -> BTreeMap {
let string_comparison_operators =
comparators::string_comparators(&comparators::numeric_comparators("VARCHAR".into()));
let scalar_types = BTreeMap::from_iter([
diff --git a/crates/connectors/ndc-calcite/src/schema.rs b/crates/calcite-schema/src/schema.rs
similarity index 86%
rename from crates/connectors/ndc-calcite/src/schema.rs
rename to crates/calcite-schema/src/schema.rs
index 5a465af..21bc69e 100644
--- a/crates/connectors/ndc-calcite/src/schema.rs
+++ b/crates/calcite-schema/src/schema.rs
@@ -3,6 +3,7 @@
//! Introspects Calcite metadata and generates a new schema. Updates
//! the config file with the new schema.
//!
+
use std::error::Error;
use std::fs::File;
use std::io::Write;
@@ -10,12 +11,14 @@ use std::path::Path;
use jni::objects::GlobalRef;
use ndc_models as models;
-use ndc_models::SchemaResponse;
+use ndc_models::{SchemaResponse};
use tracing::{event, Level};
-use crate::{calcite, collections, scalars};
-use crate::configuration::CalciteConfiguration;
-use crate::connector::calcite::{CONFIG_FILE_NAME, DEV_CONFIG_FILE_NAME, is_running_in_container};
+use ndc_calcite_values::is_running_in_container::is_running_in_container;
+use ndc_calcite_values::values::{CONFIG_FILE_NAME, DEV_CONFIG_FILE_NAME};
+use crate::version5::ParsedConfiguration;
+use crate::models::get_models;
+use crate::{collections, scalars};
/// Get the schema information from the given `calcite_ref`.
///
@@ -61,15 +64,14 @@ use crate::connector::calcite::{CONFIG_FILE_NAME, DEV_CONFIG_FILE_NAME, is_runni
/// ```
// ANCHOR: get_schema
#[tracing::instrument]
-pub fn get_schema(configuration: &CalciteConfiguration, calcite_ref: GlobalRef) -> Result> {
+pub fn get_schema(configuration: &ParsedConfiguration, calcite_ref: GlobalRef) -> Result> {
event!(Level::INFO, "in get_schema");
- let data_models = calcite::get_models(calcite_ref);
+ let data_models = get_models(calcite_ref);
let scalar_types = scalars::scalars();
let (object_types, collections) = match collections::collections(&data_models, &scalar_types) {
Ok(value) => value,
Err(value) => return value,
- };
- let procedures = vec![];
+ }; let procedures = vec![];
let functions: Vec = vec![];
let schema = SchemaResponse {
scalar_types,
diff --git a/crates/calcite-schema/src/test.rs b/crates/calcite-schema/src/test.rs
new file mode 100644
index 0000000..6d05cbb
--- /dev/null
+++ b/crates/calcite-schema/src/test.rs
@@ -0,0 +1,48 @@
+#[cfg(test)]
+pub mod common {
+ use std::fmt::Write;
+ use std::path::{Path, PathBuf};
+
+ /// Find the project root via the crate root provided by `cargo test`,
+ /// and get our single static configuration file.
+ /// This depends on the convention that all our crates live in `/crates/`
+ /// and will break in the unlikely case that we change this
+ pub fn get_path_from_project_root(ndc_metadata_path: impl AsRef) -> PathBuf {
+ let mut d = PathBuf::from(env!("CARGO_MANIFEST_DIR"));
+ d.push("../../");
+ d.push(ndc_metadata_path);
+
+ d
+ }
+ /// Checks that a given value conforms to the schema generated by `schemars`.
+ ///
+ /// Panics with a human-readable error if the value does not conform, or if the
+ /// schema could not be compiled.
+ pub fn check_value_conforms_to_schema(value: &serde_json::Value) {
+ let schema_json = serde_json::to_value(schemars::schema_for!(T))
+ .expect("the schema could not be converted to JSON");
+ let schema = jsonschema::JSONSchema::options()
+ .with_draft(jsonschema::Draft::Draft7)
+ .compile(&schema_json)
+ .expect("the schema could not be compiled");
+
+ let result = schema.validate(value);
+
+ match result {
+ Ok(()) => (),
+ Err(errors) => {
+ panic!(
+ "The configuration does not conform to the schema.\n{}",
+ errors.fold(String::new(), |mut str, error| {
+ let _ = write!(
+ str,
+ "{}\ninstance path: {}\nschema path: {}\n\n",
+ error, error.instance_path, error.schema_path
+ );
+ str
+ })
+ )
+ }
+ }
+ }
+}
diff --git a/crates/calcite-schema/src/version.rs b/crates/calcite-schema/src/version.rs
new file mode 100644
index 0000000..e908a80
--- /dev/null
+++ b/crates/calcite-schema/src/version.rs
@@ -0,0 +1,23 @@
+#[derive(Debug, Copy, Clone)]
+pub enum VersionTag {
+ Version3,
+ Version4,
+ Version5,
+}
+
+/// Emit deprecation warning text if the version is deprecated.
+pub fn deprecated_config_warning(version: VersionTag) -> Option {
+ match version {
+ VersionTag::Version3 => Some(
+ "Warning: ndc-postgres configuration version '3' is deprecated.
+Consider upgrading to the latest version:
+https://hasura.io/docs/3.0/connectors/postgresql/configuration-reference/#upgrading-the-configuration-format-version".to_string()
+ ),
+ VersionTag::Version4 => Some(
+ "Warning: ndc-postgres configuration version '4' is deprecated.
+Consider upgrading to the latest version:
+https://hasura.io/docs/3.0/connectors/postgresql/configuration-reference/#upgrading-the-configuration-format-version".to_string()
+ ),
+ VersionTag::Version5 => None,
+ }
+}
diff --git a/crates/calcite-schema/src/version5.rs b/crates/calcite-schema/src/version5.rs
new file mode 100644
index 0000000..e7ba1aa
--- /dev/null
+++ b/crates/calcite-schema/src/version5.rs
@@ -0,0 +1,198 @@
+//! Internal Configuration and state for our connector.
+
+use std::collections::{HashMap};
+use std::path::Path;
+use jni::JNIEnv;
+use jni::objects::{GlobalRef, JObject, JValueGen, JValueOwned};
+use jni::objects::JValueGen::Object;
+use ndc_models::CollectionName;
+use ndc_sdk::connector::InitializationError;
+
+use schemars::JsonSchema;
+use serde::{Deserialize, Serialize};
+use tokio::fs;
+use tracing::{event, Level};
+use ndc_calcite_values::values::{CONFIGURATION_FILENAME, CONFIGURATION_JSONSCHEMA_FILENAME};
+
+use crate::calcite::{Model, TableMetadata};
+use crate::environment::Environment;
+use crate::error::{ParseConfigurationError, WriteParsedConfigurationError};
+use crate::jvm::{get_jvm, init_jvm};
+use crate::models::get_models;
+
+/// Initial configuration, just enough to connect to a database and elaborate a full
+/// 'Configuration'.
+#[derive(Clone, PartialEq, Eq, Debug, Deserialize, Serialize, JsonSchema)]
+pub struct ParsedConfiguration {
+ /// Hasura NDC version
+ pub version: Version,
+ /// JSON Schema file that defines a valid configuration
+ #[serde(rename = "$schema")]
+ pub _schema: Option,
+ /// The Calcite Model - somewhat dependent on type of calcite adapter being used.
+ /// Better documentation can be found [here](https://calcite.apache.org/docs/model.html).
+ #[serde(skip_serializing_if = "Option::is_none")]
+ pub model: Option,
+ /// Used internally
+ pub model_file_path: Option,
+ #[serde(skip_serializing_if = "Option::is_none")]
+ /// Certain fixes that will solve for missing field values, for non-existing fields.
+ /// It's expensive and probably not necessary, but required to pass the NDC
+ /// tests. You can set the value to false in order to improve performance.
+ pub fixes: Option,
+ #[serde(skip_serializing_if = "Option::is_none")]
+ #[serde(rename = "supportJsonObject")]
+ pub supports_json_object: Option,
+ #[serde(skip_serializing_if = "Option::is_none")]
+ /// Many common JDBC jars are included by default. Some are not you can
+ /// create a directory with additional required JARS and point to that
+ /// directory here.
+ pub jars: Option,
+ #[serde(skip_serializing_if = "Option::is_none")]
+ pub metadata: Option>
+}
+
+#[derive(Clone, PartialEq, Eq, Debug, Deserialize, Serialize, JsonSchema)]
+pub enum Version {
+ #[serde(rename = "5")]
+ This,
+}
+
+impl ParsedConfiguration {
+ pub fn empty() -> Self {
+ Self {
+ version: Version::This,
+ _schema: Some(CONFIGURATION_JSONSCHEMA_FILENAME.to_string()),
+ model: None,
+ model_file_path: Some("./models/model.json".to_string()),
+ fixes: Some(true),
+ supports_json_object: None,
+ jars: None,
+ metadata: None,
+ }
+ }
+}
+
+pub fn create_calcite_connection<'a>(
+ configuration: &ParsedConfiguration,
+ calcite_query: &JObject<'a>,
+ env: &'a mut JNIEnv<'a>,
+) -> Result, InitializationError> {
+ let calcite_model = configuration.clone().model_file_path.unwrap_or_default();
+ let arg0: JObject = env.new_string(calcite_model).unwrap().into();
+ let args: &[JValueGen<&JObject<'_>>] = &[Object(&arg0)];
+ let method_signature = "(Ljava/lang/String;)Ljava/sql/Connection;";
+ let result = env.call_method(
+ calcite_query,
+ "createCalciteConnection",
+ method_signature,
+ args,
+ );
+
+ match result {
+ Ok(val) => {
+ event!(Level::INFO, "Connected to Calcite");
+ Ok(val)
+ }
+ Err(e) => {
+ event!(Level::ERROR, "Error while connecting to Calcite: {:?}", e);
+ Err(InitializationError::Other(Box::new(e)))
+ }
+ }
+}
+pub fn create_calcite_query_engine<'a>(configuration: &ParsedConfiguration, env: &'a mut JNIEnv<'a>) -> JObject<'a> {
+ let class = env.find_class("org/kenstott/CalciteQuery").unwrap();
+ let instance = env.new_object(class, "()V", &[]).unwrap();
+ let _ = create_calcite_connection(configuration, &instance, env);
+ event!(Level::INFO, "Instantiated Calcite Query Engine");
+ return instance;
+}
+pub async fn introspect(
+ args: ParsedConfiguration,
+ _environment: impl Environment,
+) -> anyhow::Result {
+ init_jvm(&crate::configuration::ParsedConfiguration::Version5(args.clone()));
+ let calcite_ref: GlobalRef;
+ {
+ let java_vm = get_jvm().lock().unwrap();
+ let mut env = java_vm.attach_current_thread_as_daemon().unwrap();
+ let calcite = create_calcite_query_engine(&args, &mut env);
+ let env = java_vm.attach_current_thread_as_daemon().unwrap();
+ calcite_ref = env.new_global_ref(calcite).unwrap();
+ }
+ let metadata = get_models(calcite_ref);
+ let introspected = ParsedConfiguration {
+ version: Version::This,
+ _schema: args._schema,
+ model: args.model,
+ model_file_path: args.model_file_path,
+ fixes: args.fixes,
+ supports_json_object: args.supports_json_object,
+ jars: args.jars,
+ metadata: Some(metadata),
+ };
+ Ok(introspected)
+}
+
+/// Parse the configuration format from a directory.
+pub async fn parse_configuration(
+ configuration_dir: impl AsRef,
+) -> Result {
+ let configuration_file = configuration_dir.as_ref().join(CONFIGURATION_FILENAME);
+
+ let configuration_file_contents =
+ fs::read_to_string(&configuration_file)
+ .await
+ .map_err(|err| {
+ ParseConfigurationError::IoErrorButStringified(format!(
+ "{}: {}",
+ &configuration_file.display(),
+ err
+ ))
+ })?;
+
+ let parsed_config: ParsedConfiguration = serde_json::from_str(&configuration_file_contents)
+ .map_err(|error| ParseConfigurationError::ParseError {
+ file_path: configuration_file.clone(),
+ line: error.line(),
+ column: error.column(),
+ message: error.to_string(),
+ })?;
+
+ Ok(parsed_config)
+}
+
+/// Write the parsed configuration into a directory on disk.
+pub async fn write_parsed_configuration(
+ parsed_config: ParsedConfiguration,
+ out_dir: impl AsRef,
+) -> Result<(), WriteParsedConfigurationError> {
+ let configuration_file = out_dir.as_ref().to_owned().join(CONFIGURATION_FILENAME);
+ fs::create_dir_all(out_dir.as_ref()).await?;
+
+ // create the configuration file
+ fs::write(
+ configuration_file,
+ serde_json::to_string_pretty(&parsed_config)
+ .map_err(|e| WriteParsedConfigurationError::IoError(e.into()))?
+ + "\n",
+ )
+ .await?;
+
+ // create the jsonschema file
+ let configuration_jsonschema_file_path = out_dir
+ .as_ref()
+ .to_owned()
+ .join(CONFIGURATION_JSONSCHEMA_FILENAME);
+
+ let output = schemars::schema_for!(ParsedConfiguration);
+ fs::write(
+ &configuration_jsonschema_file_path,
+ serde_json::to_string_pretty(&output)
+ .map_err(|e| WriteParsedConfigurationError::IoError(e.into()))?
+ + "\n",
+ )
+ .await?;
+
+ Ok(())
+}
diff --git a/crates/cli/Cargo.toml b/crates/cli/Cargo.toml
index 7e71e3b..cbe1278 100644
--- a/crates/cli/Cargo.toml
+++ b/crates/cli/Cargo.toml
@@ -8,14 +8,16 @@ license.workspace = true
workspace = true
[dependencies]
+ndc-calcite-schema = { path = "../calcite-schema"}
+
anyhow = { workspace = true }
clap = { workspace = true, features = ["derive", "env"] }
serde = { workspace = true, features = ["derive"] }
serde_json = { workspace = true }
serde_yaml = { workspace = true }
-schemars = { workspace = true }
thiserror = { workspace = true }
tokio = { workspace = true, features = ["full"] }
+include_dir = { version = "0.7.4", features = ["default", "glob"] }
[build-dependencies]
build-data = { workspace = true }
diff --git a/crates/cli/assets/.ddnignore b/crates/cli/assets/.ddnignore
new file mode 100644
index 0000000..ed72dd1
--- /dev/null
+++ b/crates/cli/assets/.ddnignore
@@ -0,0 +1,2 @@
+.env*
+compose.yaml
diff --git a/config-templates/data/arrow/albums.arrow b/crates/cli/assets/data/arrow/albums.arrow
similarity index 100%
rename from config-templates/data/arrow/albums.arrow
rename to crates/cli/assets/data/arrow/albums.arrow
diff --git a/config-templates/data/arrow/artists.arrow b/crates/cli/assets/data/arrow/artists.arrow
similarity index 100%
rename from config-templates/data/arrow/artists.arrow
rename to crates/cli/assets/data/arrow/artists.arrow
diff --git a/config-templates/data/arrow/customers.arrow b/crates/cli/assets/data/arrow/customers.arrow
similarity index 100%
rename from config-templates/data/arrow/customers.arrow
rename to crates/cli/assets/data/arrow/customers.arrow
diff --git a/config-templates/data/arrow/employees.arrow b/crates/cli/assets/data/arrow/employees.arrow
similarity index 100%
rename from config-templates/data/arrow/employees.arrow
rename to crates/cli/assets/data/arrow/employees.arrow
diff --git a/config-templates/data/arrow/genres.arrow b/crates/cli/assets/data/arrow/genres.arrow
similarity index 100%
rename from config-templates/data/arrow/genres.arrow
rename to crates/cli/assets/data/arrow/genres.arrow
diff --git a/config-templates/data/arrow/invoice_items.arrow b/crates/cli/assets/data/arrow/invoice_items.arrow
similarity index 100%
rename from config-templates/data/arrow/invoice_items.arrow
rename to crates/cli/assets/data/arrow/invoice_items.arrow
diff --git a/config-templates/data/arrow/invoices.arrow b/crates/cli/assets/data/arrow/invoices.arrow
similarity index 100%
rename from config-templates/data/arrow/invoices.arrow
rename to crates/cli/assets/data/arrow/invoices.arrow
diff --git a/config-templates/data/arrow/media_types.arrow b/crates/cli/assets/data/arrow/media_types.arrow
similarity index 100%
rename from config-templates/data/arrow/media_types.arrow
rename to crates/cli/assets/data/arrow/media_types.arrow
diff --git a/config-templates/data/arrow/playlist_track.arrow b/crates/cli/assets/data/arrow/playlist_track.arrow
similarity index 100%
rename from config-templates/data/arrow/playlist_track.arrow
rename to crates/cli/assets/data/arrow/playlist_track.arrow
diff --git a/config-templates/data/arrow/playlists.arrow b/crates/cli/assets/data/arrow/playlists.arrow
similarity index 100%
rename from config-templates/data/arrow/playlists.arrow
rename to crates/cli/assets/data/arrow/playlists.arrow
diff --git a/config-templates/data/arrow/tracks.arrow b/crates/cli/assets/data/arrow/tracks.arrow
similarity index 100%
rename from config-templates/data/arrow/tracks.arrow
rename to crates/cli/assets/data/arrow/tracks.arrow
diff --git a/config-templates/data/chinook.db b/crates/cli/assets/data/chinook.db
similarity index 100%
rename from config-templates/data/chinook.db
rename to crates/cli/assets/data/chinook.db
diff --git a/config-templates/data/files/ARCHERS.json b/crates/cli/assets/data/files/ARCHERS.json
similarity index 100%
rename from config-templates/data/files/ARCHERS.json
rename to crates/cli/assets/data/files/ARCHERS.json
diff --git a/config-templates/data/files/DATES.csv b/crates/cli/assets/data/files/DATES.csv
similarity index 100%
rename from config-templates/data/files/DATES.csv
rename to crates/cli/assets/data/files/DATES.csv
diff --git a/config-templates/data/files/DEPTS.csv b/crates/cli/assets/data/files/DEPTS.csv
similarity index 100%
rename from config-templates/data/files/DEPTS.csv
rename to crates/cli/assets/data/files/DEPTS.csv
diff --git a/config-templates/data/files/EMPS.csv.gz b/crates/cli/assets/data/files/EMPS.csv.gz
similarity index 100%
rename from config-templates/data/files/EMPS.csv.gz
rename to crates/cli/assets/data/files/EMPS.csv.gz
diff --git a/config-templates/data/files/LONG_EMPS.csv b/crates/cli/assets/data/files/LONG_EMPS.csv
similarity index 100%
rename from config-templates/data/files/LONG_EMPS.csv
rename to crates/cli/assets/data/files/LONG_EMPS.csv
diff --git a/config-templates/data/files/SDEPTS.csv b/crates/cli/assets/data/files/SDEPTS.csv
similarity index 100%
rename from config-templates/data/files/SDEPTS.csv
rename to crates/cli/assets/data/files/SDEPTS.csv
diff --git a/config-templates/data/files/WACKY_COLUMN_NAMES.csv b/crates/cli/assets/data/files/WACKY_COLUMN_NAMES.csv
similarity index 100%
rename from config-templates/data/files/WACKY_COLUMN_NAMES.csv
rename to crates/cli/assets/data/files/WACKY_COLUMN_NAMES.csv
diff --git a/config-templates/models/model.arrow.json b/crates/cli/assets/models/model.arrow.json
similarity index 86%
rename from config-templates/models/model.arrow.json
rename to crates/cli/assets/models/model.arrow.json
index 7669e3a..539ed61 100644
--- a/config-templates/models/model.arrow.json
+++ b/crates/cli/assets/models/model.arrow.json
@@ -7,7 +7,7 @@
"type": "custom",
"factory": "org.apache.calcite.adapter.arrow.ArrowSchemaFactory",
"operand": {
- "directory": "data/arrow"
+ "directory": "./data/arrow"
}
}
]
diff --git a/crates/cli/assets/models/model.cassandra.json b/crates/cli/assets/models/model.cassandra.json
new file mode 100644
index 0000000..ea9778a
--- /dev/null
+++ b/crates/cli/assets/models/model.cassandra.json
@@ -0,0 +1,21 @@
+{
+ "version": "1.0",
+ "defaultSchema": "cassandra",
+ "schemas": [
+ {
+ "name": "cassandra",
+ "type": "custom",
+ "factory": "org.apache.calcite.adapter.cassandra.CassandraSchemaFactory",
+ "operand": {
+ "host": "",
+ "keyspace": "",
+ "username": "",
+ "password": ">",
+ "port": 9142,
+ "ssl": true,
+ "dc": "",
+ "pathToRootCert": ""
+ }
+ }
+ ]
+}
diff --git a/config-templates/models/model.files.json b/crates/cli/assets/models/model.files.json
similarity index 82%
rename from config-templates/models/model.files.json
rename to crates/cli/assets/models/model.files.json
index fc21294..59bb732 100644
--- a/config-templates/models/model.files.json
+++ b/crates/cli/assets/models/model.files.json
@@ -7,7 +7,7 @@
"type": "custom",
"factory": "org.apache.calcite.adapter.file.FileSchemaFactory",
"operand": {
- "directory": "/etc/connector/data/files"
+ "directory": "./data/files"
}
}
]
diff --git a/crates/cli/assets/models/model.h2.json b/crates/cli/assets/models/model.h2.json
new file mode 100644
index 0000000..5a56810
--- /dev/null
+++ b/crates/cli/assets/models/model.h2.json
@@ -0,0 +1,15 @@
+{
+ "version": "1.0",
+ "defaultSchema": "TEST",
+ "schemas": [
+ {
+ "name": "TEST",
+ "type": "jdbc",
+ "jdbcDriver": "org.h2.Driver",
+ "jdbcUrl": "jdbc:h2:tcp://localhost:1521/test",
+ "jdbcSchema": "PUBLIC",
+ "jdbcUser": "sa",
+ "jdbcPassword": ""
+ }
+ ]
+}
diff --git a/crates/cli/assets/models/model.hive.json b/crates/cli/assets/models/model.hive.json
new file mode 100644
index 0000000..e3febb2
--- /dev/null
+++ b/crates/cli/assets/models/model.hive.json
@@ -0,0 +1,12 @@
+{
+ "version": "1.0",
+ "defaultSchema": "hive",
+ "schemas": [
+ {
+ "name": "hive",
+ "type": "jdbc",
+ "jdbcUrl": "jdbc:hive2://192.168.86.233:10000",
+ "jdbcSchema": "default"
+ }
+ ]
+}
diff --git a/config-templates/models/model.json b/crates/cli/assets/models/model.json
similarity index 77%
rename from config-templates/models/model.json
rename to crates/cli/assets/models/model.json
index eb15a89..d567945 100644
--- a/config-templates/models/model.json
+++ b/crates/cli/assets/models/model.json
@@ -6,7 +6,7 @@
"name": "default",
"type": "jdbc",
"sqlDialectFactory": "org.kenstott.SQLiteSqlDialectFactory",
- "jdbcUrl": "jdbc:sqlite:/etc/connector/data/chinook.db"
+ "jdbcUrl": "jdbc:sqlite:./data/chinook.db"
}
]
}
\ No newline at end of file
diff --git a/config-templates/models/model.pg.json b/crates/cli/assets/models/model.pg.json
similarity index 100%
rename from config-templates/models/model.pg.json
rename to crates/cli/assets/models/model.pg.json
diff --git a/crates/cli/assets/models/model.sqlite.json b/crates/cli/assets/models/model.sqlite.json
new file mode 100644
index 0000000..d567945
--- /dev/null
+++ b/crates/cli/assets/models/model.sqlite.json
@@ -0,0 +1,12 @@
+{
+ "version": "1.0",
+ "defaultSchema": "default",
+ "schemas": [
+ {
+ "name": "default",
+ "type": "jdbc",
+ "sqlDialectFactory": "org.kenstott.SQLiteSqlDialectFactory",
+ "jdbcUrl": "jdbc:sqlite:./data/chinook.db"
+ }
+ ]
+ }
\ No newline at end of file
diff --git a/crates/cli/readme.md b/crates/cli/readme.md
index e0196a4..088cb95 100644
--- a/crates/cli/readme.md
+++ b/crates/cli/readme.md
@@ -1,6 +1,6 @@
-# ndc-postgres-cli
+# ndc-calcite-cli
-ndc-postgres-cli is used to configure a deployment of ndc-postgres.
+ndc-calcite-cli is used to configure a deployment of ndc-calcite.
It is intended to be automatically downloaded and invoked via the Hasura CLI, as a plugin.
## Create a configuration
@@ -10,13 +10,13 @@ Create a configuration in a new directory using the following commands:
1. Initialize a configuration:
```sh
- CONNECTION_URI='' cargo run --bin ndc-postgres-cli -- --context='' initialize
+ CONNECTION_URI='' cargo run --bin ndc-calcite-cli -- --context='' initialize
```
2. Update the configuration by introspecting the database:
```sh
- CONNECTION_URI='' cargo run --bin ndc-postgres-cli -- --context='' update
+ CONNECTION_URI='' cargo run --bin ndc-calcite-cli -- --context='' update
```
## Upgrade a configuration
@@ -24,18 +24,18 @@ Create a configuration in a new directory using the following commands:
An older configuration version (e.g. "v3") can be upgraded to a newer one using the `upgrade` command.
```sh
-cargo run --bin ndc-postgres-cli -- upgrade --dir-from --dir-to
+cargo run --bin ndc-calcite-cli -- upgrade --dir-from --dir-to
```
## Native Operations
-Native Operations can be listed, added, and deleted using ndc-postgres-cli:
+Native Operations can be listed, added, and deleted using ndc-calcite-cli:
```sh
-$ CONNECTION_URI='' cargo run --bin ndc-postgres-cli -- --context='' native-operation --help
+$ CONNECTION_URI='' cargo run --bin ndc-calcite-cli -- --context='' native-operation --help
Commands on Native Operations
-Usage: hasura-ndc-postgres native-operation
+Usage: hasura-ndc-calcite native-operation
Commands:
list List the existing Native Operations
diff --git a/crates/cli/src/lib.rs b/crates/cli/src/lib.rs
index c9bd816..752609d 100644
--- a/crates/cli/src/lib.rs
+++ b/crates/cli/src/lib.rs
@@ -3,19 +3,17 @@
//! The CLI can do a few things. This provides a central point where those things are routed and
//! then done, making it easier to test this crate deterministically.
-pub mod metadata;
-pub mod environment;
-pub mod configuration;
-pub mod error;
-
-
-use std::{env, io};
-use std::path::{Path, PathBuf};
+use std::path::PathBuf;
use clap::Subcommand;
+use include_dir::{DirEntry, include_dir};
+use include_dir::Dir;
use tokio::fs;
-use crate::environment::Environment;
+use ndc_calcite_schema::configuration::{introspect, parse_configuration, ParsedConfiguration, upgrade_to_latest_version, write_parsed_configuration};
+use ndc_calcite_schema::environment::Environment;
+
+mod metadata;
const UPDATE_ATTEMPTS: u8 = 3;
@@ -32,7 +30,7 @@ pub enum Command {
/// Initialize a configuration in the current (empty) directory.
Initialize {
#[arg(long)]
- /// Whether to create the hasura ndc-calcite metadata.
+ /// Whether to create the hasura connector metadata.
with_metadata: bool,
},
/// Update the configuration by introspecting the database, using the configuration options.
@@ -43,7 +41,7 @@ pub enum Command {
dir_from: PathBuf,
#[arg(long)]
dir_to: PathBuf,
- }
+ },
}
/// The set of errors that can go wrong _in addition to_ generic I/O or parsing errors.
@@ -63,41 +61,17 @@ pub async fn run(command: Command, context: Context) -> anyhow
Ok(())
}
-fn copy_files(input_dir: &str, output_dir: &str) -> io::Result<()> {
- let input_path = Path::new(input_dir);
- let output_path = Path::new(output_dir);
-
- if !output_path.exists() {
- std::fs::create_dir_all(&output_path)?;
- }
+const MODELS_DIR: Dir = include_dir!("$CARGO_MANIFEST_DIR/assets");
- if input_path.is_dir() {
- for entry in std::fs::read_dir(input_path)? {
- let entry = entry?;
- let entry_path = entry.path();
- let output_file_path = output_path.join(entry_path.file_name().unwrap());
- if entry_path.is_dir() {
- copy_files(entry_path.to_str().unwrap(), output_file_path.to_str().unwrap())?;
- } else if entry_path.is_file() {
- std::fs::copy(entry_path, output_file_path)?;
- }
- }
- }
- Ok(())
-}
-
-fn is_running_in_container() -> bool {
- Path::new("/.dockerenv").exists() || env::var("KUBERNETES_SERVICE_HOST").is_ok()
-}
-
-/// Initialize an empty directory with an empty ndc-calcite configuration.
+/// Initialize an empty directory with an empty connector configuration.
///
/// An empty configuration contains default settings and options, and is expected to be filled with
/// information such as the database connection string by the user, and later on metadata
/// information via introspection.
///
-/// Optionally, this can also create the ndc-calcite metadata, which is used by the Hasura CLI to
+/// Optionally, this can also create the connector metadata, which is used by the Hasura CLI to
/// automatically work with this CLI as a plugin.
+
async fn initialize(with_metadata: bool, context: Context) -> anyhow::Result<()> {
// refuse to initialize the directory unless it is empty
let mut items_in_dir = fs::read_dir(&context.context_path).await?;
@@ -105,51 +79,56 @@ async fn initialize(with_metadata: bool, context: Context) ->
Err(Error::DirectoryIsNotEmpty)?;
}
- let config_path = if is_running_in_container() {
- Path::new("/config-templates")
- } else {
- Path::new("../config-templates")
- };
- let context_path_str = context.context_path.to_str().ok_or(anyhow::anyhow!("Failed to convert PathBuf to &str"))?;
- let config_path_str = config_path.to_str().ok_or(anyhow::anyhow!("Failed to convert PathBuf to &str"))?;
- let _ = copy_files(config_path_str, context_path_str);
-
- configuration::write_parsed_configuration(
- configuration::ParsedConfiguration::initial(),
+ write_parsed_configuration(
+ ParsedConfiguration::initial(),
&context.context_path,
)
- .await?;
+ .await?;
+
+ for entry in MODELS_DIR.find("**/*").unwrap() {
+ match entry {
+ DirEntry::Dir(dir) => {
+ let path = dir.path();
+ fs::create_dir(&context.context_path.join(path)).await?
+ }
+ DirEntry::File(file) => {
+ let path = file.path();
+ let contents = file.contents();
+ std::fs::write(&context.context_path.join(path), contents).expect("Unable to write file");
+ }
+ }
+ }
// if requested, create the metadata
if with_metadata {
- let metadata_dir = context.context_path.join(".hasura-ndc-calcite");
+ let metadata_dir = context.context_path.join(".hasura-connector");
fs::create_dir(&metadata_dir).await?;
- let metadata_file = metadata_dir.join("ndc-calcite-metadata.yaml");
+ let metadata_file = metadata_dir.join("connector-metadata.yaml");
let metadata = metadata::ConnectorMetadataDefinition {
packaging_definition: metadata::PackagingDefinition::PrebuiltDockerImage(
metadata::PrebuiltDockerImagePackaging {
docker_image: format!(
- "docker.io/kstott/meta-connector:{}",
+ "docker.io/kstott/meta_connector:{}",
context.release_version.unwrap_or("latest")
),
},
),
supported_environment_variables: vec![metadata::EnvironmentVariableDefinition {
name: "MODEL_FILE".to_string(),
- description: "The Calcite connection model".to_string(),
- default_value: Some("/etc/connection/models/model.json".to_string()),
+ description: "The calcite connection mode file path".to_string(),
+ default_value: Some("./models/model.json".to_string()),
}],
commands: metadata::Commands {
update: Some("hasura-ndc-calcite update".to_string()),
watch: None,
},
cli_plugin: Some(metadata::CliPluginDefinition {
- name: "ndc-calcite".to_string(),
+ name: "ndc-calcite-cli".to_string(),
version: context.release_version.unwrap_or("latest").to_string(),
}),
docker_compose_watch: vec![metadata::DockerComposeWatchItem {
path: "./".to_string(),
- target: Some(".".to_string()),
+ target: Some("/etc/connector".to_string()),
action: metadata::DockerComposeWatchAction::SyncAndRestart,
ignore: vec![],
}],
@@ -163,26 +142,26 @@ async fn initialize(with_metadata: bool, context: Context) ->
/// Update the configuration in the current directory by introspecting the database.
///
-/// This expects a configuration with a valid connection URI.
+/// This expects a configuration with a valid model.json.
async fn update(context: Context) -> anyhow::Result<()> {
// It is possible to change the file in the middle of introspection.
// We want to detect this scenario and retry, or fail if we are unable to.
// We do that with a few attempts.
for _attempt in 1..=UPDATE_ATTEMPTS {
let existing_configuration =
- configuration::parse_configuration(&context.context_path).await?;
+ parse_configuration(&context.context_path).await?;
let output =
- configuration::introspect(existing_configuration.clone(), &context.environment).await?;
+ introspect(existing_configuration.clone(), &context.context_path, &context.environment).await?;
// Check that the input file did not change since we started introspecting,
let input_again_before_write =
- configuration::parse_configuration(&context.context_path).await?;
+ parse_configuration(&context.context_path).await?;
// and skip this attempt if it has.
if input_again_before_write == existing_configuration {
// In order to be sure to capture default values absent in the initial input we have to
// always write out the updated configuration.
- configuration::write_parsed_configuration(output, &context.context_path).await?;
+ write_parsed_configuration(output, &context.context_path).await?;
return Ok(());
}
@@ -199,9 +178,9 @@ async fn update(context: Context) -> anyhow::Result<()> {
/// out to a different directory.
///
async fn upgrade(dir_from: PathBuf, dir_to: PathBuf) -> anyhow::Result<()> {
- let old_configuration = configuration::parse_configuration(dir_from).await?;
- let upgraded_configuration = configuration::upgrade_to_latest_version(old_configuration);
- configuration::write_parsed_configuration(upgraded_configuration, dir_to).await?;
+ let old_configuration = parse_configuration(dir_from).await?;
+ let upgraded_configuration = upgrade_to_latest_version(old_configuration);
+ write_parsed_configuration(upgraded_configuration, dir_to).await?;
eprintln!("Upgrade completed successfully. You may need to also run 'update'.");
diff --git a/crates/cli/src/main.rs b/crates/cli/src/main.rs
index 2de652f..2792676 100644
--- a/crates/cli/src/main.rs
+++ b/crates/cli/src/main.rs
@@ -8,9 +8,9 @@ use std::path::PathBuf;
use std::process::ExitCode;
use clap::Parser;
-use ndc_calcite_cli::{Command, Context, run, environment::ProcessEnvironment};
-
+use ndc_calcite_cli::*;
+use ndc_calcite_schema as configuration;
/// The release version specified at build time.
///
@@ -54,7 +54,7 @@ async fn try_main() -> anyhow::Result<()> {
};
let context = Context {
context_path,
- environment: ProcessEnvironment,
+ environment: configuration::environment::ProcessEnvironment,
release_version: RELEASE_VERSION,
};
run(args.subcommand, context).await?;
diff --git a/crates/cli/src/metadata.rs b/crates/cli/src/metadata.rs
index edc7965..74d2c8d 100644
--- a/crates/cli/src/metadata.rs
+++ b/crates/cli/src/metadata.rs
@@ -1,6 +1,6 @@
-//! Structures that represent the ndc-calcite metadata definition.
+//! Structures that represent the connector metadata definition.
//!
-//! See .
+//! See https://github.com/hasura/ndc-hub/blob/main/rfcs/0001-packaging.md#connector-definition.
use serde::{Deserialize, Serialize};
diff --git a/crates/cli/tests/initialize_tests.rs b/crates/cli/tests/initialize_tests.rs
index 821e410..045d50b 100644
--- a/crates/cli/tests/initialize_tests.rs
+++ b/crates/cli/tests/initialize_tests.rs
@@ -3,8 +3,8 @@ mod common;
use tokio::fs;
use ndc_calcite_cli::*;
-use ndc_calcite_cli::configuration as configuration;
-use ndc_calcite_cli::configuration::ParsedConfiguration;
+use ndc_calcite_configuration as configuration;
+use ndc_calcite_configuration::ParsedConfiguration;
#[tokio::test]
async fn test_initialize_directory() -> anyhow::Result<()> {
@@ -35,8 +35,8 @@ async fn test_initialize_directory() -> anyhow::Result<()> {
let metadata_file_path = dir
.path()
- .join(".hasura-ndc-calcite")
- .join("ndc-calcite-metadata.yaml");
+ .join(".hasura-connector")
+ .join("connector-metadata.yaml");
assert!(!metadata_file_path.exists());
Ok(())
@@ -133,8 +133,8 @@ async fn test_initialize_directory_with_metadata() -> anyhow::Result<()> {
let metadata_file_path = dir
.path()
- .join(".hasura-ndc-calcite")
- .join("ndc-calcite-metadata.yaml");
+ .join(".hasura-connector")
+ .join("connector-metadata.yaml");
assert!(metadata_file_path.exists());
let contents = fs::read_to_string(metadata_file_path).await?;
common::assert_ends_with_newline(&contents);
@@ -170,8 +170,8 @@ async fn test_initialize_directory_with_metadata_and_release_version() -> anyhow
let metadata_file_path = dir
.path()
- .join(".hasura-ndc-calcite")
- .join("ndc-calcite-metadata.yaml");
+ .join(".hasura-connector")
+ .join("connector-metadata.yaml");
assert!(metadata_file_path.exists());
let contents = fs::read_to_string(metadata_file_path).await?;
common::assert_ends_with_newline(&contents);
diff --git a/crates/cli/tests/snapshots/initialize_tests__initialize_directory_with_metadata.snap b/crates/cli/tests/snapshots/initialize_tests__initialize_directory_with_metadata.snap
index e6642f9..cb28435 100644
--- a/crates/cli/tests/snapshots/initialize_tests__initialize_directory_with_metadata.snap
+++ b/crates/cli/tests/snapshots/initialize_tests__initialize_directory_with_metadata.snap
@@ -4,15 +4,15 @@ expression: contents
---
packagingDefinition:
type: PrebuiltDockerImage
- dockerImage: ghcr.io/hasura/ndc-postgres:latest
+ dockerImage: docker.io/hasura/ndc-calcite:latest
supportedEnvironmentVariables:
-- name: CONNECTION_URI
- description: The PostgreSQL connection URI
- defaultValue: postgresql://read_only_user:readonlyuser@35.236.11.122:5432/v3-docs-sample-app
+- name: MODEL_FILE
+ description: The Calcite model file path
+ defaultValue: ./models/model.json
commands:
- update: hasura-ndc-postgres update
+ update: hasura-ndc-calcite update
cliPlugin:
- name: ndc-postgres
+ name: ndc-calcite
version: latest
dockerComposeWatch:
- path: ./
diff --git a/crates/cli/tests/snapshots/initialize_tests__initialize_directory_with_metadata_and_release_version.snap b/crates/cli/tests/snapshots/initialize_tests__initialize_directory_with_metadata_and_release_version.snap
index 2940634..57f3c92 100644
--- a/crates/cli/tests/snapshots/initialize_tests__initialize_directory_with_metadata_and_release_version.snap
+++ b/crates/cli/tests/snapshots/initialize_tests__initialize_directory_with_metadata_and_release_version.snap
@@ -4,15 +4,15 @@ expression: contents
---
packagingDefinition:
type: PrebuiltDockerImage
- dockerImage: ghcr.io/hasura/ndc-postgres:v1.2.3
+ dockerImage: ghcr.io/hasura/ndc-calcite:v1.2.3
supportedEnvironmentVariables:
- name: CONNECTION_URI
- description: The PostgreSQL connection URI
- defaultValue: postgresql://read_only_user:readonlyuser@35.236.11.122:5432/v3-docs-sample-app
+ description: The calciteQL connection URI
+ defaultValue: calciteql://read_only_user:readonlyuser@35.236.11.122:5432/v3-docs-sample-app
commands:
- update: hasura-ndc-postgres update
+ update: hasura-ndc-calcite update
cliPlugin:
- name: ndc-postgres
+ name: ndc-calcite
version: v1.2.3
dockerComposeWatch:
- path: ./
diff --git a/crates/connectors/ndc-calcite/Cargo.toml b/crates/connectors/ndc-calcite/Cargo.toml
index cc80c6f..0c3ab07 100644
--- a/crates/connectors/ndc-calcite/Cargo.toml
+++ b/crates/connectors/ndc-calcite/Cargo.toml
@@ -22,38 +22,40 @@ native-tls = ["reqwest/native-tls"]
rustls = ["reqwest/rustls"]
[dependencies]
-indexmap = "2.2.6"
-jni = { version = "0.21.1", features = ["invocation"] }
-ndc-models = { git = "http://github.com/hasura/ndc-spec.git", tag = "v0.1.4" }
-ndc-sdk = { git = "https://github.com/hasura/ndc-sdk-rs.git", tag = "v0.1.4" }
-async-trait = "0.1.79"
-axum = { version = "0.6.20", features = ["http2"] }
-axum-extra = "0.8.0"
-bytes = "1.6.0"
-clap = { version = "4.5.4", features = ["derive", "env"] }
-http = "0.2"
-mime = "0.3.17"
-opentelemetry = "0.22.0"
-opentelemetry-http = "0.11.0"
-opentelemetry-otlp = { version = "0.15.0", features = ["reqwest-client", "gzip-tonic", "tls", "tls-roots", "http-proto"] }
-opentelemetry-semantic-conventions = "0.14.0"
-opentelemetry_sdk = { version = "0.22.1", features = ["rt-tokio"] }
-opentelemetry-zipkin = "0.20.0"
-prometheus = "0.13.3"
-reqwest = "0.11.27"
-serde = { version = "1.0.197", features = ["derive"] }
-serde_json = { version = "1.0.115", features = ["raw_value"] }
-thiserror = "1.0"
-tokio = { version = "1.36.0", features = ["fs", "macros", "rt-multi-thread", "signal"] }
-tower-http = { version = "0.4.4", features = ["cors", "trace", "validate-request"] }
-tracing = "0.1.40"
-tracing-opentelemetry = "0.23.0"
-tracing-subscriber = { version = "0.3", default-features = false, features = ["ansi", "env-filter", "fmt", "json"] }
-url = "2.5.0"
-dotenv = "0.15.0"
-once_cell = "1.19.0"
-anyhow = "1.0.86"
-log = "0.4.22"
+ndc-calcite-schema = { path = "../../calcite-schema" }
+ndc-calcite-values = { path = "../../values"}
+indexmap = {workspace = true}
+jni = { workspace = true }
+ndc-models = { workspace = true }
+ndc-sdk = { workspace = true }
+async-trait = { workspace = true}
+axum = { workspace = true, features = ["http2"] }
+axum-extra = {workspace = true}
+bytes = {workspace = true}
+clap = { workspace = true, features = ["derive", "env"] }
+http = { workspace = true }
+mime = {workspace = true}
+opentelemetry = {workspace = true}
+opentelemetry-http = {workspace = true}
+opentelemetry-otlp = { workspace = true, features = ["reqwest-client", "gzip-tonic", "tls", "tls-roots", "http-proto"] }
+opentelemetry-semantic-conventions = {workspace = true}
+opentelemetry_sdk = { workspace = true, features = ["rt-tokio"] }
+opentelemetry-zipkin = {workspace = true}
+prometheus = {workspace = true}
+reqwest = {workspace = true}
+serde = { workspace = true, features = ["derive"] }
+serde_json = { workspace = true, features = ["raw_value"] }
+thiserror = {workspace = true}
+tokio = { workspace = true, features = ["fs", "macros", "rt-multi-thread", "signal"] }
+tower-http = { workspace = true, features = ["cors", "trace", "validate-request"] }
+tracing = {workspace = true}
+tracing-opentelemetry = { workspace = true }
+tracing-subscriber = {workspace = true, default-features = false, features = ["ansi", "env-filter", "fmt", "json"] }
+url = {workspace = true}
+dotenv = {workspace = true}
+once_cell = {workspace = true}
+anyhow = {workspace = true}
+log = {workspace = true}
[dev-dependencies]
-axum-test-helper = "0.3.0"
\ No newline at end of file
+axum-test-helper = {workspace = true}
\ No newline at end of file
diff --git a/crates/connectors/ndc-calcite/src/calcite.rs b/crates/connectors/ndc-calcite/src/calcite.rs
index 547bbaf..c543033 100644
--- a/crates/connectors/ndc-calcite/src/calcite.rs
+++ b/crates/connectors/ndc-calcite/src/calcite.rs
@@ -3,53 +3,22 @@
//! Takes a Calcite query, passes it to Calcite Query Engine
//! and then transforms it into a Vec.
//!
-use std::collections::HashMap;
use std::fmt;
use indexmap::IndexMap;
use jni::JNIEnv;
-use jni::objects::{GlobalRef, JObject, JString, JValueGen, JValueOwned};
+use jni::objects::{GlobalRef, JObject, JString, JValueGen};
use jni::objects::JValueGen::Object;
use ndc_models as models;
-use ndc_models::RowFieldValue;
-use ndc_sdk::connector::{InitializationError, QueryError};
-use serde_json::{Value};
+use ndc_models::{FieldName, RowFieldValue};
+use ndc_sdk::connector::{QueryError};
+use serde_json::Value;
use tracing::{event, Level};
+use ndc_calcite_schema::version5::ParsedConfiguration;
+use ndc_calcite_schema::jvm::get_jvm;
+use ndc_calcite_schema::version5::create_calcite_connection;
-use crate::configuration::CalciteConfiguration;
-use crate::jvm::get_jvm;
-use crate::configuration::TableMetadata;
-
-pub type Row = IndexMap;
-
-#[tracing::instrument]
-fn create_calcite_connection<'a>(
- configuration: &CalciteConfiguration,
- calcite_query: &JObject<'a>,
- env: &'a mut JNIEnv<'a>,
-) -> Result, InitializationError> {
- let calcite_model = configuration.clone().model_file_path.unwrap_or_default();
- let arg0: JObject = env.new_string(calcite_model).unwrap().into();
- let args: &[JValueGen<&JObject<'_>>] = &[Object(&arg0)];
- let method_signature = "(Ljava/lang/String;)Ljava/sql/Connection;";
- let result = env.call_method(
- calcite_query,
- "createCalciteConnection",
- method_signature,
- args,
- );
-
- match result {
- Ok(val) => {
- event!(Level::INFO, "Connected to Calcite");
- Ok(val)
- }
- Err(e) => {
- event!(Level::ERROR, "Error while connecting to Calcite: {:?}", e);
- Err(InitializationError::Other(Box::new(e)))
- }
- }
-}
+pub type Row = IndexMap;
/// Creates a Calcite query engine.
///
@@ -72,11 +41,10 @@ fn create_calcite_connection<'a>(
/// use jni::JNIEnv;
/// use jni::objects::JObject;
/// use tracing::Level;
-///
-/// # fn create_calcite_connection(configuration: &CalciteConfiguration, instance: &JObject, env: &mut JNIEnv) { unimplemented!() }
+/// use ndc_calcite_schema::version5::{create_calcite_connection, ParsedConfiguration};
///
/// #[tracing::instrument]
-/// pub fn create_calcite_query_engine<'a>(configuration: &CalciteConfiguration, env: &'a mut JNIEnv<'a>) -> JObject<'a> {
+/// pub fn create_calcite_query_engine<'a>(configuration: &ParsedConfiguration, env: &'a mut JNIEnv<'a>) -> JObject<'a> {
/// let class = env.find_class("org/kenstott/CalciteQuery").unwrap();
/// let instance = env.new_object(class, "()V", &[]).unwrap();
/// let _ = create_calcite_connection(configuration, &instance, env);
@@ -85,7 +53,7 @@ fn create_calcite_connection<'a>(
/// }
/// ```
#[tracing::instrument]
-pub fn create_calcite_query_engine<'a>(configuration: &CalciteConfiguration, env: &'a mut JNIEnv<'a>) -> JObject<'a> {
+pub fn create_calcite_query_engine<'a>(configuration: &ParsedConfiguration, env: &'a mut JNIEnv<'a>) -> JObject<'a> {
let class = env.find_class("org/kenstott/CalciteQuery").unwrap();
let instance = env.new_object(class, "()V", &[]).unwrap();
let _ = create_calcite_connection(configuration, &instance, env);
@@ -93,38 +61,6 @@ pub fn create_calcite_query_engine<'a>(configuration: &CalciteConfiguration, env
return instance;
}
-/// Retrieves models from Calcite.
-///
-/// # Arguments
-///
-/// * `calcite_ref` - A reference to the Calcite instance.
-///
-/// # Return
-///
-/// A `HashMap` containing the retrieved models. The outer `HashMap` maps model names
-/// to inner `HashMap`s, where each inner `HashMap` represents a model with its properties.
-#[tracing::instrument]
-pub fn get_models(calcite_ref: GlobalRef) -> HashMap {
- let jvm = get_jvm().lock().unwrap();
- let env = jvm.attach_current_thread().unwrap();
- let calcite_query = env.new_local_ref(calcite_ref).unwrap();
- let mut env = jvm.attach_current_thread_as_daemon().unwrap();
- let args: &[JValueGen<&JObject<'_>>] = &[];
- let method_signature = "()Ljava/lang/String;";
- let result = env.call_method(calcite_query, "getModels", method_signature, args);
- let map= match result.unwrap() {
- Object(obj) => {
- let j_string = JString::from(obj);
- let json_string: String = env.get_string(&j_string).unwrap().into();
- let map: HashMap = serde_json::from_str(&json_string).unwrap();
- map
- }
- _ => todo!(),
- };
- event!(Level::INFO, "Retrieved models from Calcite");
- return map;
-}
-
fn parse_to_row(data: Vec) -> Vec {
let mut rows: Vec = Vec::new();
for item in data {
@@ -181,7 +117,7 @@ fn parse_to_row(data: Vec) -> Vec {
// ANCHOR: calcite_query
#[tracing::instrument]
pub fn calcite_query(
- config: &CalciteConfiguration,
+ config: &ParsedConfiguration,
calcite_reference: GlobalRef,
sql_query: &str,
query_metadata: &models::Query,
@@ -208,7 +144,7 @@ pub fn calcite_query(
Ok(rows) => rows,
Err(_) => {
println!("{:?}", json_string);
- return Err(QueryError::Other(Box::new(CalciteError{message: String::from("Invalid response from Calcite.")})))
+ return Err(QueryError::Other(Box::new(CalciteError{message: String::from("Invalid response from Calcite.")}), serde_json::from_str(&json_string).unwrap_or_default()))
}
};
let rows = parse_to_row(json_rows);
@@ -220,7 +156,7 @@ pub fn calcite_query(
log_event(Level::INFO, &format!("Completed Query. Retrieved {} rows. Result: {}", rows.len().to_string(), serde_json::to_string(&rows).unwrap()));
Ok(rows)
},
- _ => Err(QueryError::Other(Box::new(CalciteError{message: String::from("Invalid response from Calcite.")})))
+ _ => Err(QueryError::Other(Box::new(CalciteError{message: String::from("Invalid response from Calcite.")}), Value::Null))
}
}
@@ -238,7 +174,7 @@ fn fix_rows(rows: Vec, query_metadata: &models::Query) -> Vec {
let fields = query_metadata.clone().fields.unwrap_or_default();
let aggregates = query_metadata.clone().aggregates.unwrap_or_default();
let max_keys = fields.len() + aggregates.len();
- let mut key_sample: Vec = vec![];
+ let mut key_sample: Vec = vec![];
for (key, _) in fields {
key_sample.push(key);
@@ -252,7 +188,7 @@ fn fix_rows(rows: Vec, query_metadata: &models::Query) -> Vec {
if max_keys > row.len() {
for key in &key_sample {
if !row.contains_key(key) {
- row.insert(key.into(), RowFieldValue(Value::Null));
+ row.insert(key.clone(), RowFieldValue(Value::Null));
}
}
}
diff --git a/crates/connectors/ndc-calcite/src/connector/calcite.rs b/crates/connectors/ndc-calcite/src/connector/calcite.rs
index 603ca6a..0d10cd8 100644
--- a/crates/connectors/ndc-calcite/src/connector/calcite.rs
+++ b/crates/connectors/ndc-calcite/src/connector/calcite.rs
@@ -4,31 +4,34 @@
//! the request to the underlying code and providing the result.
//!
use std::collections::BTreeMap;
-use std::{env, fs};
+use std::{fs};
use std::path::Path;
use log::{info, error};
use async_trait::async_trait;
use dotenv;
use jni::objects::GlobalRef;
-use ndc_models::{Argument, ExplainResponse, RelationshipArgument};
+use ndc_models as models;
+use ndc_models::{ArgumentName, Capabilities, CollectionName, Relationship, RelationshipName, VariableName};
use ndc_sdk::connector::{
Connector, ConnectorSetup, ExplainError, FetchMetricsError, HealthError, InitializationError,
MutationError, ParseError, QueryError, SchemaError,
};
use ndc_sdk::json_response::JsonResponse;
-use ndc_sdk::models;
+use serde_json::Value;
use tracing::info_span;
use tracing::Instrument;
-use crate::{calcite, jvm, query, schema};
use crate::capabilities::calcite_capabilities;
-use crate::configuration::{CalciteConfiguration, Model};
-use crate::jvm::init_jvm;
+use ndc_calcite_schema::jvm::{get_jvm, init_jvm};
+use ndc_calcite_schema::calcite::Model;
+use ndc_calcite_schema::models::get_models;
+use ndc_calcite_schema::schema::get_schema as retrieve_schema;
+use ndc_calcite_schema::version5::ParsedConfiguration;
+use ndc_calcite_values::is_running_in_container::is_running_in_container;
+use ndc_calcite_values::values::{CONFIG_FILE_NAME, DEV_CONFIG_FILE_NAME};
+use crate::{calcite, query};
use crate::query::QueryParams;
-pub const CONFIG_FILE_NAME: &str = "configuration.json";
-pub const DEV_CONFIG_FILE_NAME: &str = "dev.local.configuration.json";
-
#[derive(Clone, Default, Debug)]
pub struct Calcite {}
@@ -37,39 +40,14 @@ pub struct CalciteState {
pub calcite_ref: GlobalRef,
}
-/// Checks if the code is running inside a container.
-///
-/// This function checks for the existence of the `/.dockerenv` file in the filesystem,
-/// which is commonly used to indicate that the code is running inside a Docker container.
-///
-/// # Examples
-///
-/// ```
-/// use std::path::Path;
-///
-/// fn is_running_in_container() -> bool {
-/// Path::new("/.dockerenv").exists()
-/// }
-///
-/// assert_eq!(is_running_in_container(), false);
-/// ```
-///
-/// # Returns
-///
-/// Returns `true` if the code is running inside a container, `false` otherwise.
-#[tracing::instrument]
-pub fn is_running_in_container() -> bool {
- Path::new("/.dockerenv").exists() || env::var("KUBERNETES_SERVICE_HOST").is_ok()
-}
-
#[tracing::instrument]
fn execute_query_with_variables(
- config: &CalciteConfiguration,
- coll: &str,
- args: &BTreeMap,
- coll_rel: &BTreeMap,
+ config: &ParsedConfiguration,
+ coll: &CollectionName,
+ args: &BTreeMap,
+ coll_rel: &BTreeMap,
query: &models::Query,
- vars: &BTreeMap,
+ vars: &BTreeMap,
state: &CalciteState,
explain: &bool
) -> Result {
@@ -99,7 +77,7 @@ impl ConnectorSetup for Calcite {
match fs::read_to_string(file_path) {
Ok(file_content) => {
println!("Configuration file content: {:?}", file_content);
- let mut json_object: CalciteConfiguration = serde_json::from_str(&file_content)
+ let mut json_object: ParsedConfiguration = serde_json::from_str(&file_content)
.map_err(|err| ParseError::Other(Box::from(err.to_string())))?;
match json_object.model_file_path {
None => {
@@ -123,7 +101,7 @@ impl ConnectorSetup for Calcite {
match json_object.metadata {
None => {
let state = init_state(&json_object).expect("TODO: panic message");
- json_object.metadata = Some(calcite::get_models(state.calcite_ref));
+ json_object.metadata = Some(get_models(state.calcite_ref));
println!("metadata: {:?}", serde_json::to_string_pretty(&json_object.metadata));
}
Some(_) => {}
@@ -146,7 +124,7 @@ impl ConnectorSetup for Calcite {
#[async_trait]
impl Connector for Calcite {
- type Configuration = CalciteConfiguration;
+ type Configuration = ParsedConfiguration;
type State = CalciteState;
fn fetch_metrics(
@@ -163,8 +141,8 @@ impl Connector for Calcite {
Ok(())
}
- async fn get_capabilities() -> JsonResponse {
- calcite_capabilities().into()
+ async fn get_capabilities() -> Capabilities {
+ calcite_capabilities().capabilities
}
async fn get_schema(
@@ -179,17 +157,17 @@ impl Connector for Calcite {
let calcite;
let calcite_ref;
{
- let java_vm = jvm::get_jvm().lock().unwrap();
+ let java_vm = get_jvm().lock().unwrap();
let mut env = java_vm.attach_current_thread_as_daemon().unwrap();
calcite = calcite::create_calcite_query_engine(configuration, &mut env);
let env = java_vm.attach_current_thread_as_daemon().unwrap();
calcite_ref = env.new_global_ref(calcite).unwrap();
}
- let schema = schema::get_schema(configuration, calcite_ref.clone());
+ let schema = retrieve_schema(configuration, calcite_ref.clone());
match schema {
- Ok(schema) => Ok(schema.into()),
- Err(e) => Err(SchemaError::Other(e.to_string().into())),
+ Ok(schema) => Ok(JsonResponse::from(schema)),
+ Err(e) => Err(SchemaError::Other(e.to_string().into(), Value::Null)),
}
}
@@ -200,8 +178,8 @@ impl Connector for Calcite {
) -> Result, ExplainError> {
let variable_sets = request.variables.unwrap_or(vec![BTreeMap::new()]);
let mut map: BTreeMap = BTreeMap::new();
- let input_map: BTreeMap = request.arguments.clone();
- let relationship_arguments : BTreeMap =
+ let input_map: BTreeMap = request.arguments.clone();
+ let relationship_arguments : BTreeMap =
input_map.iter()
.map(|(key, value)|
(key.clone(), convert_to_relationship_argument(value))
@@ -217,12 +195,12 @@ impl Connector for Calcite {
variables,
&state,
&true
- ).map_err(|error| ExplainError::Other(Box::new(error)))?;
+ ).map_err(|error| ExplainError::Other(Box::new(error), Value::Null))?;
match row_set.aggregates {
None => {}
Some(map_index) => {
let map_btree: BTreeMap = map_index.iter()
- .map(|(key, value)| (key.clone(), value.to_string()))
+ .map(|(key, value)| (key.clone().to_string(), value.to_string()))
.collect();
map.extend(map_btree);
}
@@ -232,14 +210,14 @@ impl Connector for Calcite {
Some(r) => {
for map_index in r {
let map_btree: BTreeMap = map_index.iter()
- .map(|(key, value)| (key.clone(), value.0.to_string()))
+ .map(|(key, value)| (key.clone().to_string(), value.0.to_string()))
.collect();
map.extend(map_btree);
}
}
}
}
- let explain_response = ExplainResponse {
+ let explain_response = models::ExplainResponse {
details: map,
};
Ok(JsonResponse::from(explain_response))
@@ -269,8 +247,8 @@ impl Connector for Calcite {
// println!("{:?}", serde_json::to_string_pretty(&request));
let variable_sets = request.variables.unwrap_or(vec![BTreeMap::new()]);
let mut row_sets = vec![];
- let input_map: BTreeMap = request.arguments.clone();
- let relationship_arguments : BTreeMap =
+ let input_map: BTreeMap = request.arguments.clone();
+ let relationship_arguments : BTreeMap =
input_map.iter()
.map(|(key, value)|
// Assuming we have a function `convert_to_relationship_argument`
@@ -308,19 +286,19 @@ impl Connector for Calcite {
}
}
-fn convert_to_relationship_argument(p0: &Argument) -> RelationshipArgument {
+fn convert_to_relationship_argument(p0: &models::Argument) -> models::RelationshipArgument {
match p0 {
- Argument::Variable { name } => RelationshipArgument::Variable { name: name.to_string() },
- Argument::Literal { value } => RelationshipArgument::Literal { value: value.clone() }
+ models::Argument::Variable { name } => models::RelationshipArgument::Variable { name: name.clone() },
+ models::Argument::Literal { value } => models::RelationshipArgument::Literal { value: value.clone() }
}
}
fn init_state(
- configuration: &CalciteConfiguration,
+ configuration: &ParsedConfiguration,
) -> Result {
dotenv::dotenv().ok();
- init_jvm(configuration);
- let java_vm = jvm::get_jvm().lock().unwrap();
+ init_jvm(&ndc_calcite_schema::configuration::ParsedConfiguration::Version5(configuration.clone()));
+ let java_vm = get_jvm().lock().unwrap();
let calcite;
let calcite_ref;
{
diff --git a/crates/connectors/ndc-calcite/src/lib.rs b/crates/connectors/ndc-calcite/src/lib.rs
index 29b6fcf..4f7ce0c 100644
--- a/crates/connectors/ndc-calcite/src/lib.rs
+++ b/crates/connectors/ndc-calcite/src/lib.rs
@@ -70,18 +70,12 @@
//! - Path'ed where-predicates (you can only use the root in List arguments)
//! - Nested objects are not supported
-pub mod aggregates;
pub mod calcite;
pub mod capabilities;
-pub mod collections;
-pub mod comparators;
-pub mod jvm;
-pub mod scalars;
-pub mod schema;
pub mod sql;
-pub mod configuration;
pub mod query;
pub mod connector {
pub mod calcite;
}
+
diff --git a/crates/connectors/ndc-calcite/src/query.rs b/crates/connectors/ndc-calcite/src/query.rs
index 0bff453..bb7a933 100644
--- a/crates/connectors/ndc-calcite/src/query.rs
+++ b/crates/connectors/ndc-calcite/src/query.rs
@@ -8,13 +8,13 @@
use std::collections::BTreeMap;
use indexmap::IndexMap;
-use ndc_models::{ComparisonTarget, ComparisonValue, Expression, Field, Query, Relationship, RelationshipArgument, RelationshipType, RowFieldValue};
+use ndc_models::{ArgumentName, CollectionName, ComparisonOperatorName, ComparisonTarget, ComparisonValue, Expression, Field, FieldName, Query, Relationship, RelationshipArgument, RelationshipName, RelationshipType, RowFieldValue, VariableName};
use ndc_sdk::connector::QueryError;
use ndc_sdk::models;
use serde_json::{Number, Value};
use crate::calcite::{calcite_query, Row};
-use crate::configuration::CalciteConfiguration;
+use ndc_calcite_schema::version5::ParsedConfiguration;
use crate::connector::calcite::CalciteState;
use crate::sql;
@@ -29,12 +29,12 @@ use crate::sql;
/// `'a` - A lifetime parameter specifying the lifetime of the query parameters.
#[derive(Clone, Copy)]
pub struct QueryParams<'a> {
- pub config: &'a CalciteConfiguration,
- pub coll: &'a str,
- pub coll_rel: &'a BTreeMap,
- pub args: &'a BTreeMap,
- pub query: &'a models::Query,
- pub vars: &'a BTreeMap,
+ pub config: &'a ParsedConfiguration,
+ pub coll: &'a CollectionName,
+ pub coll_rel: &'a BTreeMap,
+ pub args: &'a BTreeMap,
+ pub query: &'a Query,
+ pub vars: &'a BTreeMap,
pub state: &'a CalciteState,
pub explain: &'a bool
}
@@ -45,7 +45,7 @@ pub struct QueryParams<'a> {
/// These components include the argument values, the SELECT clause, the ORDER BY clause,
/// the pagination settings, the aggregates, the predicates, the final aggregates, and the join clause.
pub struct QueryComponents {
- pub argument_values: BTreeMap,
+ pub argument_values: BTreeMap,
pub select: Option,
pub order_by: Option,
pub pagination: Option,
@@ -87,7 +87,7 @@ pub fn orchestrate_query(
) -> Result {
let components = sql::parse_query(¶ms.config, params.coll, params.coll_rel, params.args, params.query, params.vars)?;
let mut rows: Option> = process_rows(params, &components)?;
- let aggregates: Option> = process_aggregates(params, &components)?;
+ let aggregates: Option> = process_aggregates(params, &components)?;
let fields = params.query.clone().fields.unwrap_or_default();
for (field_name, field) in &fields {
match &rows {
@@ -134,12 +134,12 @@ fn generate_value_from_rows(rows: &Vec, sub_relationship: &Relationship) ->
Ok(value)
}
-fn parse_relationship(sub_relationship: &Relationship) -> Result<(Vec<&String>, Vec<&String>, RelationshipType), QueryError> {
- let pks: Vec<&String> = sub_relationship.column_mapping.values().collect();
+fn parse_relationship(sub_relationship: &Relationship) -> Result<(Vec<&FieldName>, Vec<&FieldName>, RelationshipType), QueryError> {
+ let pks: Vec<&FieldName> = sub_relationship.column_mapping.values().collect();
if pks.len() > 1 {
- return Err(QueryError::Other(Box::from("Cannot create a sub-query based on a composite key")));
+ return Err(QueryError::Other(Box::from("Cannot create a sub-query based on a composite key"), Value::Null));
}
- let fks: Vec<&String> = sub_relationship.column_mapping.keys().collect();
+ let fks: Vec<&FieldName> = sub_relationship.column_mapping.keys().collect();
let relationship_type = sub_relationship.relationship_type.clone();
Ok((pks, fks, relationship_type))
}
@@ -168,7 +168,7 @@ fn process_rows(params: QueryParams, query_components: &QueryComponents) -> Resu
}
-fn process_aggregates(params: QueryParams, query_components: &QueryComponents) -> Result