From b9c3d883d9c30e34884b05eda06e8dd8cc2e468a Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 9 Jun 2026 02:03:49 +0000 Subject: [PATCH 1/5] chore(deps): bump datafusion from 53.1.0 to 54.0.0 Bumps [datafusion](https://github.com/apache/datafusion) from 53.1.0 to 54.0.0. - [Changelog](https://github.com/apache/datafusion/blob/main/CHANGELOG.md) - [Commits](https://github.com/apache/datafusion/compare/53.1.0...54.0.0) --- updated-dependencies: - dependency-name: datafusion dependency-version: 54.0.0 dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] --- Cargo.lock | 1352 +++++++++++++++++++++++++++++++++++++--------------- Cargo.toml | 2 +- 2 files changed, 956 insertions(+), 398 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 2c5fd77..3422a73 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -143,35 +143,6 @@ version = "1.0.101" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5f0e0fee31ef5ed1ba1316088939cea399010ed7731dba877ed44aeb407a75ea" -[[package]] -name = "apache-avro" -version = "0.21.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "36fa98bc79671c7981272d91a8753a928ff6a1cd8e4f20a44c45bd5d313840bf" -dependencies = [ - "bigdecimal", - "bon", - "bzip2", - "crc32fast", - "digest", - "liblzma", - "log", - "miniz_oxide", - "num-bigint", - "quad-rand", - "rand 0.9.2", - "regex-lite", - "serde", - "serde_bytes", - "serde_json", - "snap", - "strum", - "strum_macros", - "thiserror 2.0.17", - "uuid", - "zstd", -] - [[package]] name = "approx" version = "0.5.1" @@ -210,9 +181,9 @@ checksum = "7c02d123df017efcdfbd739ef81735b36c5ba83ec3c59c80a9d7ecc718f92e50" [[package]] name = "arrow" -version = "58.1.0" +version = "58.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d441fdda254b65f3e9025910eb2c2066b6295d9c8ed409522b8d2ace1ff8574c" +checksum = "378530e55cd479eda3c14eb345310799717e6f76d0c332041e8487022166b471" dependencies = [ "arrow-arith", "arrow-array", @@ -231,9 +202,9 @@ dependencies = [ [[package]] name = "arrow-arith" -version = "58.1.0" +version = "58.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ced5406f8b720cc0bc3aa9cf5758f93e8593cda5490677aa194e4b4b383f9a59" +checksum = "a0ab212d2c1886e802f51c5212d78ebbcbb0bec980fff9dadc1eb8d45cd0b738" dependencies = [ "arrow-array", "arrow-buffer", @@ -245,9 +216,9 @@ dependencies = [ [[package]] name = "arrow-array" -version = "58.1.0" +version = "58.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "772bd34cacdda8baec9418d80d23d0fb4d50ef0735685bd45158b83dfeb6e62d" +checksum = "cfd33d3e92f207444098c75b42de99d329562be0cf686b307b097cc52b4e999e" dependencies = [ "ahash 0.8.12", "arrow-buffer", @@ -256,17 +227,41 @@ dependencies = [ "chrono", "chrono-tz", "half", - "hashbrown 0.16.1", + "hashbrown 0.17.1", "num-complex", "num-integer", "num-traits", ] +[[package]] +name = "arrow-avro" +version = "58.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "049230728cd6e093088c8d231b4beede184e35cad7777c1505c0d5a8571f4376" +dependencies = [ + "arrow-array", + "arrow-buffer", + "arrow-schema", + "bytes", + "bzip2", + "crc", + "flate2", + "indexmap", + "liblzma", + "rand 0.9.2", + "serde", + "serde_json", + "snap", + "strum_macros", + "uuid", + "zstd", +] + [[package]] name = "arrow-buffer" -version = "58.1.0" +version = "58.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "898f4cf1e9598fdb77f356fdf2134feedfd0ee8d5a4e0a5f573e7d0aec16baa4" +checksum = "0c6cd424c2693bcdbc150d843dc9d4d137dd2de4782ce6df491ad11a3a0416c0" dependencies = [ "bytes", "half", @@ -276,9 +271,9 @@ dependencies = [ [[package]] name = "arrow-cast" -version = "58.1.0" +version = "58.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b0127816c96533d20fc938729f48c52d3e48f99717e7a0b5ade77d742510736d" +checksum = "4c5aefb56a2c02e9e2b30746241058b85f8983f0fcff2ba0c6d09006e1cded7f" dependencies = [ "arrow-array", "arrow-buffer", @@ -298,9 +293,9 @@ dependencies = [ [[package]] name = "arrow-csv" -version = "58.1.0" +version = "58.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ca025bd0f38eeecb57c2153c0123b960494138e6a957bbda10da2b25415209fe" +checksum = "e94e8cf7e517657a52b91ea1263acf38c4ca62a84655d72458a3359b12ab97de" dependencies = [ "arrow-array", "arrow-cast", @@ -313,9 +308,9 @@ dependencies = [ [[package]] name = "arrow-data" -version = "58.1.0" +version = "58.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "42d10beeab2b1c3bb0b53a00f7c944a178b622173a5c7bcabc3cb45d90238df4" +checksum = "3c88210023a2bfee1896af366309a3028fc3bcbd6515fa29a7990ee1baa08ee0" dependencies = [ "arrow-buffer", "arrow-schema", @@ -326,9 +321,9 @@ dependencies = [ [[package]] name = "arrow-ipc" -version = "58.1.0" +version = "58.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "609a441080e338147a84e8e6904b6da482cefb957c5cdc0f3398872f69a315d0" +checksum = "238438f0834483703d88896db6fe5a7138b2230debc31b34c0336c2996e3c64f" dependencies = [ "arrow-array", "arrow-buffer", @@ -342,15 +337,16 @@ dependencies = [ [[package]] name = "arrow-json" -version = "58.1.0" +version = "58.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6ead0914e4861a531be48fe05858265cf854a4880b9ed12618b1d08cba9bebc8" +checksum = "205ca2119e6d679d5c133c6f30e68f027738d95ed948cf77677ea69c7800036b" dependencies = [ "arrow-array", "arrow-buffer", "arrow-cast", - "arrow-data", + "arrow-ord", "arrow-schema", + "arrow-select", "chrono", "half", "indexmap", @@ -366,9 +362,9 @@ dependencies = [ [[package]] name = "arrow-ord" -version = "58.1.0" +version = "58.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "763a7ba279b20b52dad300e68cfc37c17efa65e68623169076855b3a9e941ca5" +checksum = "1bffd8fd2579286a5d63bac898159873e5094a79009940bcb42bbfce4f19f1d0" dependencies = [ "arrow-array", "arrow-buffer", @@ -386,7 +382,7 @@ dependencies = [ "async-trait", "bytes", "chrono", - "datafusion", + "datafusion 54.0.0", "futures", "geo-postgis", "geo-traits", @@ -402,9 +398,9 @@ dependencies = [ [[package]] name = "arrow-row" -version = "58.1.0" +version = "58.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e14fe367802f16d7668163ff647830258e6e0aeea9a4d79aaedf273af3bdcd3e" +checksum = "bab5994731204603c73ba69267616c50f80780774c6bb0476f1f830625115e0c" dependencies = [ "arrow-array", "arrow-buffer", @@ -425,9 +421,9 @@ dependencies = [ [[package]] name = "arrow-select" -version = "58.1.0" +version = "58.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "78694888660a9e8ac949853db393af2a8b8fc82c19ce333132dfa2e72cc1a7fe" +checksum = "8cd065c54172ac787cf3f2f8d4107e0d3fdc26edba76fdf4f4cc170258942222" dependencies = [ "ahash 0.8.12", "arrow-array", @@ -439,9 +435,9 @@ dependencies = [ [[package]] name = "arrow-string" -version = "58.1.0" +version = "58.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "61e04a01f8bb73ce54437514c5fd3ee2aa3e8abe4c777ee5cc55853b1652f79e" +checksum = "29dd7cda3ab9692f43a2e4acc444d760cc17b12bb6d8232ddf64e9bab7c06b42" dependencies = [ "arrow-array", "arrow-buffer", @@ -525,7 +521,6 @@ dependencies = [ "num-bigint", "num-integer", "num-traits", - "serde", ] [[package]] @@ -558,7 +553,7 @@ version = "0.10.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "46502ad458c9a52b69d4d4d32775c788b7a1b85e8bc9d482d92250fc0e3f8efe" dependencies = [ - "digest", + "digest 0.10.7", ] [[package]] @@ -584,28 +579,12 @@ dependencies = [ ] [[package]] -name = "bon" -version = "3.8.2" +name = "block-buffer" +version = "0.12.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "234655ec178edd82b891e262ea7cf71f6584bcd09eff94db786be23f1821825c" +checksum = "cdd35008169921d80bc60d3d0ab416eecb028c4cd653352907921d95084790be" dependencies = [ - "bon-macros", - "rustversion", -] - -[[package]] -name = "bon-macros" -version = "3.8.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "89ec27229c38ed0eb3c0feee3d2c1d6a4379ae44f418a29a658890e062d8f365" -dependencies = [ - "darling", - "ident_case", - "prettyplease", - "proc-macro2", - "quote", - "rustversion", - "syn 2.0.117", + "hybrid-array", ] [[package]] @@ -871,6 +850,12 @@ version = "0.9.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c2459377285ad874054d797f3ccebf984978aa39129f6eafde5cdc8315b612f8" +[[package]] +name = "const-oid" +version = "0.10.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a6ef517f0926dd24a1582492c791b6a4818a4d94e789a334894aa15b0d12f55c" + [[package]] name = "const-random" version = "0.1.18" @@ -921,6 +906,21 @@ dependencies = [ "libc", ] +[[package]] +name = "crc" +version = "3.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5eb8a2a1cd12ab0d987a5d5e825195d372001a4094a0376319d5a0ad71c1ba0d" +dependencies = [ + "crc-catalog", +] + +[[package]] +name = "crc-catalog" +version = "2.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "217698eaf96b4a3f0bc4f3662aaa55bdf913cd54d7204591faa790070c6d0853" + [[package]] name = "crc32fast" version = "1.5.0" @@ -1006,6 +1006,15 @@ dependencies = [ "typenum", ] +[[package]] +name = "crypto-common" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ce6e4c961d6cd6c9a86db418387425e8bdeaf05b3c8bc1411e6dca4c252f1453" +dependencies = [ + "hybrid-array", +] + [[package]] name = "csv" version = "1.4.0" @@ -1027,41 +1036,6 @@ dependencies = [ "memchr", ] -[[package]] -name = "darling" -version = "0.21.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9cdf337090841a411e2a7f3deb9187445851f91b309c0c0a29e05f74a00a48c0" -dependencies = [ - "darling_core", - "darling_macro", -] - -[[package]] -name = "darling_core" -version = "0.21.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1247195ecd7e3c85f83c8d2a366e4210d588e802133e1e355180a9870b517ea4" -dependencies = [ - "fnv", - "ident_case", - "proc-macro2", - "quote", - "strsim", - "syn 2.0.117", -] - -[[package]] -name = "darling_macro" -version = "0.21.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d38308df82d1080de0afee5d069fa14b0326a88c14f15c5ccda35b4a6c414c81" -dependencies = [ - "darling_core", - "quote", - "syn 2.0.117", -] - [[package]] name = "dashmap" version = "6.1.0" @@ -1086,44 +1060,88 @@ dependencies = [ "arrow-schema", "async-trait", "bytes", + "chrono", + "datafusion-catalog 53.1.0", + "datafusion-catalog-listing 53.1.0", + "datafusion-common 53.1.0", + "datafusion-common-runtime 53.1.0", + "datafusion-datasource 53.1.0", + "datafusion-datasource-arrow 53.1.0", + "datafusion-datasource-csv 53.1.0", + "datafusion-datasource-json 53.1.0", + "datafusion-execution 53.1.0", + "datafusion-expr 53.1.0", + "datafusion-expr-common 53.1.0", + "datafusion-functions 53.1.0", + "datafusion-functions-aggregate 53.1.0", + "datafusion-functions-table 53.1.0", + "datafusion-functions-window 53.1.0", + "datafusion-optimizer 53.1.0", + "datafusion-physical-expr 53.1.0", + "datafusion-physical-expr-adapter 53.1.0", + "datafusion-physical-expr-common 53.1.0", + "datafusion-physical-optimizer 53.1.0", + "datafusion-physical-plan 53.1.0", + "datafusion-session 53.1.0", + "futures", + "itertools 0.14.0", + "log", + "object_store", + "parking_lot", + "rand 0.9.2", + "regex", + "tempfile", + "tokio", + "url", + "uuid", +] + +[[package]] +name = "datafusion" +version = "54.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "997a31e15872606a49478e670c58302094c97cb96abb0a7d60720f8e92170040" +dependencies = [ + "arrow", + "arrow-schema", + "async-trait", "bzip2", "chrono", - "datafusion-catalog", - "datafusion-catalog-listing", - "datafusion-common", - "datafusion-common-runtime", - "datafusion-datasource", - "datafusion-datasource-arrow", + "datafusion-catalog 54.0.0", + "datafusion-catalog-listing 54.0.0", + "datafusion-common 54.0.0", + "datafusion-common-runtime 54.0.0", + "datafusion-datasource 54.0.0", + "datafusion-datasource-arrow 54.0.0", "datafusion-datasource-avro", - "datafusion-datasource-csv", - "datafusion-datasource-json", + "datafusion-datasource-csv 54.0.0", + "datafusion-datasource-json 54.0.0", "datafusion-datasource-parquet", - "datafusion-execution", - "datafusion-expr", - "datafusion-expr-common", - "datafusion-functions", - "datafusion-functions-aggregate", + "datafusion-execution 54.0.0", + "datafusion-expr 54.0.0", + "datafusion-expr-common 54.0.0", + "datafusion-functions 54.0.0", + "datafusion-functions-aggregate 54.0.0", "datafusion-functions-nested", - "datafusion-functions-table", - "datafusion-functions-window", - "datafusion-optimizer", - "datafusion-physical-expr", - "datafusion-physical-expr-adapter", - "datafusion-physical-expr-common", - "datafusion-physical-optimizer", - "datafusion-physical-plan", - "datafusion-session", + "datafusion-functions-table 54.0.0", + "datafusion-functions-window 54.0.0", + "datafusion-optimizer 54.0.0", + "datafusion-physical-expr 54.0.0", + "datafusion-physical-expr-adapter 54.0.0", + "datafusion-physical-expr-common 54.0.0", + "datafusion-physical-optimizer 54.0.0", + "datafusion-physical-plan 54.0.0", + "datafusion-session 54.0.0", "datafusion-sql", "flate2", "futures", + "indexmap", "itertools 0.14.0", "liblzma", "log", "object_store", "parking_lot", "parquet", - "rand 0.9.2", - "regex", "sqlparser", "tempfile", "tokio", @@ -1141,14 +1159,39 @@ dependencies = [ "arrow", "async-trait", "dashmap", - "datafusion-common", - "datafusion-common-runtime", - "datafusion-datasource", - "datafusion-execution", - "datafusion-expr", - "datafusion-physical-expr", - "datafusion-physical-plan", - "datafusion-session", + "datafusion-common 53.1.0", + "datafusion-common-runtime 53.1.0", + "datafusion-datasource 53.1.0", + "datafusion-execution 53.1.0", + "datafusion-expr 53.1.0", + "datafusion-physical-expr 53.1.0", + "datafusion-physical-plan 53.1.0", + "datafusion-session 53.1.0", + "futures", + "itertools 0.14.0", + "log", + "object_store", + "parking_lot", + "tokio", +] + +[[package]] +name = "datafusion-catalog" +version = "54.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f7dd61161508f8f5fa1107774ea687bd753c22d83a32eebf963549f89de14139" +dependencies = [ + "arrow", + "async-trait", + "dashmap", + "datafusion-common 54.0.0", + "datafusion-common-runtime 54.0.0", + "datafusion-datasource 54.0.0", + "datafusion-execution 54.0.0", + "datafusion-expr 54.0.0", + "datafusion-physical-expr 54.0.0", + "datafusion-physical-plan 54.0.0", + "datafusion-session 54.0.0", "futures", "itertools 0.14.0", "log", @@ -1165,15 +1208,38 @@ checksum = "17e112307715d6a7a331111a4c2330ff54bc237183511c319e3708a4cff431fb" dependencies = [ "arrow", "async-trait", - "datafusion-catalog", - "datafusion-common", - "datafusion-datasource", - "datafusion-execution", - "datafusion-expr", - "datafusion-physical-expr", - "datafusion-physical-expr-adapter", - "datafusion-physical-expr-common", - "datafusion-physical-plan", + "datafusion-catalog 53.1.0", + "datafusion-common 53.1.0", + "datafusion-datasource 53.1.0", + "datafusion-execution 53.1.0", + "datafusion-expr 53.1.0", + "datafusion-physical-expr 53.1.0", + "datafusion-physical-expr-adapter 53.1.0", + "datafusion-physical-expr-common 53.1.0", + "datafusion-physical-plan 53.1.0", + "futures", + "itertools 0.14.0", + "log", + "object_store", +] + +[[package]] +name = "datafusion-catalog-listing" +version = "54.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "897c70f871277f9ce99aa38347be0d679bbe3e617156c4d2a8378cec8a2a0891" +dependencies = [ + "arrow", + "async-trait", + "datafusion-catalog 54.0.0", + "datafusion-common 54.0.0", + "datafusion-datasource 54.0.0", + "datafusion-execution 54.0.0", + "datafusion-expr 54.0.0", + "datafusion-physical-expr 54.0.0", + "datafusion-physical-expr-adapter 54.0.0", + "datafusion-physical-expr-common 54.0.0", + "datafusion-physical-plan 54.0.0", "futures", "itertools 0.14.0", "log", @@ -1187,7 +1253,6 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d72a11ca44a95e1081870d3abb80c717496e8a7acb467a1d3e932bb636af5cc2" dependencies = [ "ahash 0.8.12", - "apache-avro", "arrow", "arrow-ipc", "chrono", @@ -1198,11 +1263,34 @@ dependencies = [ "libc", "log", "object_store", - "parquet", "paste", + "tokio", + "web-time", +] + +[[package]] +name = "datafusion-common" +version = "54.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "121c9ded5d87d9172319e006f2afdb9928d72dbacd6a90a458d8acb1e3b43a65" +dependencies = [ + "arrow", + "arrow-ipc", + "arrow-schema", + "chrono", + "foldhash 0.2.0", + "half", + "hashbrown 0.17.1", + "indexmap", + "itertools 0.14.0", + "libc", + "log", + "object_store", + "parquet", "recursive", "sqlparser", "tokio", + "uuid", "web-time", ] @@ -1217,11 +1305,51 @@ dependencies = [ "tokio", ] +[[package]] +name = "datafusion-common-runtime" +version = "54.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "981b9dae74f78ee3d9f714fb49b01919eab975461b56149510c3ba9ea11287d1" +dependencies = [ + "futures", + "log", + "tokio", +] + [[package]] name = "datafusion-datasource" version = "53.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e9fb386e1691355355a96419978a0022b7947b44d4a24a6ea99f00b6b485cbb6" +dependencies = [ + "arrow", + "async-trait", + "bytes", + "chrono", + "datafusion-common 53.1.0", + "datafusion-common-runtime 53.1.0", + "datafusion-execution 53.1.0", + "datafusion-expr 53.1.0", + "datafusion-physical-expr 53.1.0", + "datafusion-physical-expr-adapter 53.1.0", + "datafusion-physical-expr-common 53.1.0", + "datafusion-physical-plan 53.1.0", + "datafusion-session 53.1.0", + "futures", + "glob", + "itertools 0.14.0", + "log", + "object_store", + "rand 0.9.2", + "tokio", + "url", +] + +[[package]] +name = "datafusion-datasource" +version = "54.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ffd7d295b2ec7c00d8a56562f41ed41062cf0af75549ed891c12a0a09eddfefe" dependencies = [ "arrow", "async-compression", @@ -1229,15 +1357,15 @@ dependencies = [ "bytes", "bzip2", "chrono", - "datafusion-common", - "datafusion-common-runtime", - "datafusion-execution", - "datafusion-expr", - "datafusion-physical-expr", - "datafusion-physical-expr-adapter", - "datafusion-physical-expr-common", - "datafusion-physical-plan", - "datafusion-session", + "datafusion-common 54.0.0", + "datafusion-common-runtime 54.0.0", + "datafusion-execution 54.0.0", + "datafusion-expr 54.0.0", + "datafusion-physical-expr 54.0.0", + "datafusion-physical-expr-adapter 54.0.0", + "datafusion-physical-expr-common 54.0.0", + "datafusion-physical-plan 54.0.0", + "datafusion-session 54.0.0", "flate2", "futures", "glob", @@ -1245,6 +1373,7 @@ dependencies = [ "liblzma", "log", "object_store", + "parking_lot", "rand 0.9.2", "tokio", "tokio-util", @@ -1262,14 +1391,38 @@ dependencies = [ "arrow-ipc", "async-trait", "bytes", - "datafusion-common", - "datafusion-common-runtime", - "datafusion-datasource", - "datafusion-execution", - "datafusion-expr", - "datafusion-physical-expr-common", - "datafusion-physical-plan", - "datafusion-session", + "datafusion-common 53.1.0", + "datafusion-common-runtime 53.1.0", + "datafusion-datasource 53.1.0", + "datafusion-execution 53.1.0", + "datafusion-expr 53.1.0", + "datafusion-physical-expr-common 53.1.0", + "datafusion-physical-plan 53.1.0", + "datafusion-session 53.1.0", + "futures", + "itertools 0.14.0", + "object_store", + "tokio", +] + +[[package]] +name = "datafusion-datasource-arrow" +version = "54.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "552b0b3f342f7ec41b3fbd70f6339dc82a30cfd0349e7f280e7852528085349f" +dependencies = [ + "arrow", + "arrow-ipc", + "async-trait", + "bytes", + "datafusion-common 54.0.0", + "datafusion-common-runtime 54.0.0", + "datafusion-datasource 54.0.0", + "datafusion-execution 54.0.0", + "datafusion-expr 54.0.0", + "datafusion-physical-expr-common 54.0.0", + "datafusion-physical-plan 54.0.0", + "datafusion-session 54.0.0", "futures", "itertools 0.14.0", "object_store", @@ -1278,21 +1431,20 @@ dependencies = [ [[package]] name = "datafusion-datasource-avro" -version = "53.1.0" +version = "54.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a579c3bd290c66ea4b269493e75e8a3ed42c9c895a651f10210a29538aee50c4" +checksum = "fb517d08967d536284ce70afb5fe8583133779249f2d7b90587d339741a7f195" dependencies = [ - "apache-avro", "arrow", + "arrow-avro", "async-trait", "bytes", - "datafusion-common", - "datafusion-datasource", - "datafusion-physical-expr-common", - "datafusion-physical-plan", - "datafusion-session", + "datafusion-common 54.0.0", + "datafusion-datasource 54.0.0", + "datafusion-physical-expr-adapter 54.0.0", + "datafusion-physical-plan 54.0.0", + "datafusion-session 54.0.0", "futures", - "num-traits", "object_store", ] @@ -1305,14 +1457,37 @@ dependencies = [ "arrow", "async-trait", "bytes", - "datafusion-common", - "datafusion-common-runtime", - "datafusion-datasource", - "datafusion-execution", - "datafusion-expr", - "datafusion-physical-expr-common", - "datafusion-physical-plan", - "datafusion-session", + "datafusion-common 53.1.0", + "datafusion-common-runtime 53.1.0", + "datafusion-datasource 53.1.0", + "datafusion-execution 53.1.0", + "datafusion-expr 53.1.0", + "datafusion-physical-expr-common 53.1.0", + "datafusion-physical-plan 53.1.0", + "datafusion-session 53.1.0", + "futures", + "object_store", + "regex", + "tokio", +] + +[[package]] +name = "datafusion-datasource-csv" +version = "54.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "68850aa426b897e879c8b87e512ea8124f1d0a2869a4e51808ddaaddf1bc0ada" +dependencies = [ + "arrow", + "async-trait", + "bytes", + "datafusion-common 54.0.0", + "datafusion-common-runtime 54.0.0", + "datafusion-datasource 54.0.0", + "datafusion-execution 54.0.0", + "datafusion-expr 54.0.0", + "datafusion-physical-expr-common 54.0.0", + "datafusion-physical-plan 54.0.0", + "datafusion-session 54.0.0", "futures", "object_store", "regex", @@ -1328,14 +1503,14 @@ dependencies = [ "arrow", "async-trait", "bytes", - "datafusion-common", - "datafusion-common-runtime", - "datafusion-datasource", - "datafusion-execution", - "datafusion-expr", - "datafusion-physical-expr-common", - "datafusion-physical-plan", - "datafusion-session", + "datafusion-common 53.1.0", + "datafusion-common-runtime 53.1.0", + "datafusion-datasource 53.1.0", + "datafusion-execution 53.1.0", + "datafusion-expr 53.1.0", + "datafusion-physical-expr-common 53.1.0", + "datafusion-physical-plan 53.1.0", + "datafusion-session 53.1.0", "futures", "object_store", "serde_json", @@ -1343,27 +1518,51 @@ dependencies = [ "tokio-stream", ] +[[package]] +name = "datafusion-datasource-json" +version = "54.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "402f93242ae08ef99139ee2c528a49d087efe88d5c7b2c3ff5480855a40ce54f" +dependencies = [ + "arrow", + "async-trait", + "bytes", + "datafusion-common 54.0.0", + "datafusion-common-runtime 54.0.0", + "datafusion-datasource 54.0.0", + "datafusion-execution 54.0.0", + "datafusion-expr 54.0.0", + "datafusion-physical-expr-common 54.0.0", + "datafusion-physical-plan 54.0.0", + "datafusion-session 54.0.0", + "futures", + "object_store", + "tokio", + "tokio-stream", +] + [[package]] name = "datafusion-datasource-parquet" -version = "53.1.0" +version = "54.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "32a8e0365e0e08e8ff94d912f0ababcf9065a1a304018ba90b1fc83c855b4997" +checksum = "ffd2499c1bee0eeccf6a57156105700eeeb17bc701899ac719183c4e74231450" dependencies = [ "arrow", "async-trait", "bytes", - "datafusion-common", - "datafusion-common-runtime", - "datafusion-datasource", - "datafusion-execution", - "datafusion-expr", - "datafusion-functions-aggregate-common", - "datafusion-physical-expr", - "datafusion-physical-expr-adapter", - "datafusion-physical-expr-common", - "datafusion-physical-plan", - "datafusion-pruning", - "datafusion-session", + "datafusion-common 54.0.0", + "datafusion-common-runtime 54.0.0", + "datafusion-datasource 54.0.0", + "datafusion-execution 54.0.0", + "datafusion-expr 54.0.0", + "datafusion-functions 54.0.0", + "datafusion-functions-aggregate-common 54.0.0", + "datafusion-physical-expr 54.0.0", + "datafusion-physical-expr-adapter 54.0.0", + "datafusion-physical-expr-common 54.0.0", + "datafusion-physical-plan 54.0.0", + "datafusion-pruning 54.0.0", + "datafusion-session 54.0.0", "futures", "itertools 0.14.0", "log", @@ -1379,6 +1578,12 @@ version = "53.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8de6ac0df1662b9148ad3c987978b32cbec7c772f199b1d53520c8fa764a87ee" +[[package]] +name = "datafusion-doc" +version = "54.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cb9e7e5d11130c48c8bd4e80c79a9772dd28ce6dc330baca9246205d245b9e2e" + [[package]] name = "datafusion-execution" version = "53.1.0" @@ -1390,9 +1595,31 @@ dependencies = [ "async-trait", "chrono", "dashmap", - "datafusion-common", - "datafusion-expr", - "datafusion-physical-expr-common", + "datafusion-common 53.1.0", + "datafusion-expr 53.1.0", + "datafusion-physical-expr-common 53.1.0", + "futures", + "log", + "object_store", + "parking_lot", + "rand 0.9.2", + "tempfile", + "url", +] + +[[package]] +name = "datafusion-execution" +version = "54.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "37a8643ab852eb68864e1b72ae789e8066282dce48eea6347ffb0aee33d1ccc0" +dependencies = [ + "arrow", + "arrow-buffer", + "async-trait", + "dashmap", + "datafusion-common 54.0.0", + "datafusion-expr 54.0.0", + "datafusion-physical-expr-common 54.0.0", "futures", "log", "object_store", @@ -1411,38 +1638,99 @@ dependencies = [ "arrow", "async-trait", "chrono", - "datafusion-common", - "datafusion-doc", - "datafusion-expr-common", - "datafusion-functions-aggregate-common", - "datafusion-functions-window-common", - "datafusion-physical-expr-common", + "datafusion-common 53.1.0", + "datafusion-doc 53.1.0", + "datafusion-expr-common 53.1.0", + "datafusion-functions-aggregate-common 53.1.0", + "datafusion-functions-window-common 53.1.0", + "datafusion-physical-expr-common 53.1.0", "indexmap", "itertools 0.14.0", "paste", + "serde_json", +] + +[[package]] +name = "datafusion-expr" +version = "54.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6932f4d71eed9c8d9341476a2b845aadfabde5495d08dbcd8fc23881f49fa7a0" +dependencies = [ + "arrow", + "arrow-schema", + "async-trait", + "chrono", + "datafusion-common 54.0.0", + "datafusion-doc 54.0.0", + "datafusion-expr-common 54.0.0", + "datafusion-functions-aggregate-common 54.0.0", + "datafusion-functions-window-common 54.0.0", + "datafusion-physical-expr-common 54.0.0", + "indexmap", + "itertools 0.14.0", "recursive", "serde_json", "sqlparser", ] [[package]] -name = "datafusion-expr-common" +name = "datafusion-expr-common" +version = "53.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7d7c3adf3db8bf61e92eb90cb659c8e8b734593a8f7c8e12a843c7ddba24b87e" +dependencies = [ + "arrow", + "datafusion-common 53.1.0", + "indexmap", + "itertools 0.14.0", + "paste", +] + +[[package]] +name = "datafusion-expr-common" +version = "54.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0225491839a31b1f7d2cb8092c2d50792e2fe1c1724e4e6d08e011f5feaf4ed2" +dependencies = [ + "arrow", + "datafusion-common 54.0.0", + "indexmap", + "itertools 0.14.0", +] + +[[package]] +name = "datafusion-functions" version = "53.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7d7c3adf3db8bf61e92eb90cb659c8e8b734593a8f7c8e12a843c7ddba24b87e" +checksum = "f28aa4e10384e782774b10e72aca4d93ef7b31aa653095d9d4536b0a3dbc51b6" dependencies = [ "arrow", - "datafusion-common", - "indexmap", + "arrow-buffer", + "base64", + "chrono", + "chrono-tz", + "datafusion-common 53.1.0", + "datafusion-doc 53.1.0", + "datafusion-execution 53.1.0", + "datafusion-expr 53.1.0", + "datafusion-expr-common 53.1.0", + "datafusion-macros 53.1.0", + "hex", "itertools 0.14.0", - "paste", + "log", + "memchr", + "num-traits", + "rand 0.9.2", + "regex", + "unicode-segmentation", + "uuid", ] [[package]] name = "datafusion-functions" -version = "53.1.0" +version = "54.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f28aa4e10384e782774b10e72aca4d93ef7b31aa653095d9d4536b0a3dbc51b6" +checksum = "14872c47bfc3d21e53ec82f57074e6987a15941c1e2f43cde4ac6ae2746634e3" dependencies = [ "arrow", "arrow-buffer", @@ -1451,22 +1739,22 @@ dependencies = [ "blake3", "chrono", "chrono-tz", - "datafusion-common", - "datafusion-doc", - "datafusion-execution", - "datafusion-expr", - "datafusion-expr-common", - "datafusion-macros", + "datafusion-common 54.0.0", + "datafusion-doc 54.0.0", + "datafusion-execution 54.0.0", + "datafusion-expr 54.0.0", + "datafusion-expr-common 54.0.0", + "datafusion-macros 54.0.0", + "datafusion-physical-expr-common 54.0.0", "hex", "itertools 0.14.0", "log", - "md-5", + "md-5 0.11.0", "memchr", "num-traits", "rand 0.9.2", "regex", - "sha2", - "unicode-segmentation", + "sha2 0.11.0", "uuid", ] @@ -1478,20 +1766,41 @@ checksum = "00aa6217e56098ba84e0a338176fe52f0a84cca398021512c6c8c5eff806d0ad" dependencies = [ "ahash 0.8.12", "arrow", - "datafusion-common", - "datafusion-doc", - "datafusion-execution", - "datafusion-expr", - "datafusion-functions-aggregate-common", - "datafusion-macros", - "datafusion-physical-expr", - "datafusion-physical-expr-common", + "datafusion-common 53.1.0", + "datafusion-doc 53.1.0", + "datafusion-execution 53.1.0", + "datafusion-expr 53.1.0", + "datafusion-functions-aggregate-common 53.1.0", + "datafusion-macros 53.1.0", + "datafusion-physical-expr 53.1.0", + "datafusion-physical-expr-common 53.1.0", "half", "log", "num-traits", "paste", ] +[[package]] +name = "datafusion-functions-aggregate" +version = "54.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "75a2ca14e1b609be21e657e2d3130b2f446456b08393b377bb721a33952d2e09" +dependencies = [ + "arrow", + "datafusion-common 54.0.0", + "datafusion-doc 54.0.0", + "datafusion-execution 54.0.0", + "datafusion-expr 54.0.0", + "datafusion-functions-aggregate-common 54.0.0", + "datafusion-macros 54.0.0", + "datafusion-physical-expr 54.0.0", + "datafusion-physical-expr-common 54.0.0", + "foldhash 0.2.0", + "half", + "log", + "num-traits", +] + [[package]] name = "datafusion-functions-aggregate-common" version = "53.1.0" @@ -1500,34 +1809,46 @@ checksum = "b511250349407db7c43832ab2de63f5557b19a20dfd236b39ca2c04468b50d47" dependencies = [ "ahash 0.8.12", "arrow", - "datafusion-common", - "datafusion-expr-common", - "datafusion-physical-expr-common", + "datafusion-common 53.1.0", + "datafusion-expr-common 53.1.0", + "datafusion-physical-expr-common 53.1.0", +] + +[[package]] +name = "datafusion-functions-aggregate-common" +version = "54.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1ece74ba09092d2ef9c9b54a38445450aea292a1f8b04faf531936b723a24b3c" +dependencies = [ + "arrow", + "datafusion-common 54.0.0", + "datafusion-expr-common 54.0.0", + "datafusion-physical-expr-common 54.0.0", ] [[package]] name = "datafusion-functions-nested" -version = "53.1.0" +version = "54.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ef13a858e20d50f0a9bb5e96e7ac82b4e7597f247515bccca4fdd2992df0212a" +checksum = "3f3e3f9ee8ca59bf70518802107de6f1b88a9509efdc629fadc5de9d6b2d5ef5" dependencies = [ "arrow", "arrow-ord", - "datafusion-common", - "datafusion-doc", - "datafusion-execution", - "datafusion-expr", - "datafusion-expr-common", - "datafusion-functions", - "datafusion-functions-aggregate", - "datafusion-functions-aggregate-common", - "datafusion-macros", - "datafusion-physical-expr-common", - "hashbrown 0.16.1", + "datafusion-common 54.0.0", + "datafusion-doc 54.0.0", + "datafusion-execution 54.0.0", + "datafusion-expr 54.0.0", + "datafusion-expr-common 54.0.0", + "datafusion-functions 54.0.0", + "datafusion-functions-aggregate 54.0.0", + "datafusion-functions-aggregate-common 54.0.0", + "datafusion-macros 54.0.0", + "datafusion-physical-expr-common 54.0.0", + "hashbrown 0.17.1", "itertools 0.14.0", "itoa", "log", - "paste", + "memchr", ] [[package]] @@ -1538,14 +1859,30 @@ checksum = "72b40d3f5bbb3905f9ccb1ce9485a9595c77b69758a7c24d3ba79e334ff51e7e" dependencies = [ "arrow", "async-trait", - "datafusion-catalog", - "datafusion-common", - "datafusion-expr", - "datafusion-physical-plan", + "datafusion-catalog 53.1.0", + "datafusion-common 53.1.0", + "datafusion-expr 53.1.0", + "datafusion-physical-plan 53.1.0", "parking_lot", "paste", ] +[[package]] +name = "datafusion-functions-table" +version = "54.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "89161dffc22cf2b50f9f4b1bee83b5221d3b4ed7c2e37fd7aa2b22a5297b3a26" +dependencies = [ + "arrow", + "async-trait", + "datafusion-catalog 54.0.0", + "datafusion-common 54.0.0", + "datafusion-expr 54.0.0", + "datafusion-physical-expr 54.0.0", + "datafusion-physical-plan 54.0.0", + "parking_lot", +] + [[package]] name = "datafusion-functions-window" version = "53.1.0" @@ -1553,25 +1890,52 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d4e88ec9d57c9b685d02f58bfee7be62d72610430ddcedb82a08e5d9925dbfb6" dependencies = [ "arrow", - "datafusion-common", - "datafusion-doc", - "datafusion-expr", - "datafusion-functions-window-common", - "datafusion-macros", - "datafusion-physical-expr", - "datafusion-physical-expr-common", + "datafusion-common 53.1.0", + "datafusion-doc 53.1.0", + "datafusion-expr 53.1.0", + "datafusion-functions-window-common 53.1.0", + "datafusion-macros 53.1.0", + "datafusion-physical-expr 53.1.0", + "datafusion-physical-expr-common 53.1.0", "log", "paste", ] +[[package]] +name = "datafusion-functions-window" +version = "54.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d7339345b226b3874037708bf5023ba1c2de705128f8457a095aae5ae9cb9c78" +dependencies = [ + "arrow", + "datafusion-common 54.0.0", + "datafusion-doc 54.0.0", + "datafusion-expr 54.0.0", + "datafusion-functions-window-common 54.0.0", + "datafusion-macros 54.0.0", + "datafusion-physical-expr 54.0.0", + "datafusion-physical-expr-common 54.0.0", + "log", +] + [[package]] name = "datafusion-functions-window-common" version = "53.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8307bb93519b1a91913723a1130cfafeee3f72200d870d88e91a6fc5470ede5c" dependencies = [ - "datafusion-common", - "datafusion-physical-expr-common", + "datafusion-common 53.1.0", + "datafusion-physical-expr-common 53.1.0", +] + +[[package]] +name = "datafusion-functions-window-common" +version = "54.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fa84836dc2392df6f43d6a29d37fb56a8ebdc8b3f4e10ae8dc15861fd20278fb" +dependencies = [ + "datafusion-common 54.0.0", + "datafusion-physical-expr-common 54.0.0", ] [[package]] @@ -1580,7 +1944,18 @@ version = "53.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2e367e6a71051d0ebdd29b2f85d12059b38b1d1f172c6906e80016da662226bd" dependencies = [ - "datafusion-doc", + "datafusion-doc 53.1.0", + "quote", + "syn 2.0.117", +] + +[[package]] +name = "datafusion-macros" +version = "54.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "587164e03ad68732aa9e7bfe5686e3f25970d4c64fd4bd80790749840892dae5" +dependencies = [ + "datafusion-doc 54.0.0", "quote", "syn 2.0.117", ] @@ -1593,10 +1968,29 @@ checksum = "e929015451a67f77d9d8b727b2bf3a40c4445fdef6cdc53281d7d97c76888ace" dependencies = [ "arrow", "chrono", - "datafusion-common", - "datafusion-expr", - "datafusion-expr-common", - "datafusion-physical-expr", + "datafusion-common 53.1.0", + "datafusion-expr 53.1.0", + "datafusion-expr-common 53.1.0", + "datafusion-physical-expr 53.1.0", + "indexmap", + "itertools 0.14.0", + "log", + "regex", + "regex-syntax", +] + +[[package]] +name = "datafusion-optimizer" +version = "54.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "77f20e8cf9e8654d92f4c16b24c487353ee5bf153ffc12d5772cd399ab8cd281" +dependencies = [ + "arrow", + "chrono", + "datafusion-common 54.0.0", + "datafusion-expr 54.0.0", + "datafusion-expr-common 54.0.0", + "datafusion-physical-expr 54.0.0", "indexmap", "itertools 0.14.0", "log", @@ -1612,7 +2006,7 @@ dependencies = [ "arrow-pg", "async-trait", "criterion", - "datafusion", + "datafusion 54.0.0", "env_logger", "futures", "log", @@ -1628,11 +2022,11 @@ checksum = "4b1e68aba7a4b350401cfdf25a3d6f989ad898a7410164afe9ca52080244cb59" dependencies = [ "ahash 0.8.12", "arrow", - "datafusion-common", - "datafusion-expr", - "datafusion-expr-common", - "datafusion-functions-aggregate-common", - "datafusion-physical-expr-common", + "datafusion-common 53.1.0", + "datafusion-expr 53.1.0", + "datafusion-expr-common 53.1.0", + "datafusion-functions-aggregate-common 53.1.0", + "datafusion-physical-expr-common 53.1.0", "half", "hashbrown 0.16.1", "indexmap", @@ -1640,6 +2034,27 @@ dependencies = [ "parking_lot", "paste", "petgraph", + "tokio", +] + +[[package]] +name = "datafusion-physical-expr" +version = "54.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f015a4a82f6f7ff7e1d8d4bf3870a936752fa38b17705dfcc14adef95aa8922c" +dependencies = [ + "arrow", + "datafusion-common 54.0.0", + "datafusion-expr 54.0.0", + "datafusion-expr-common 54.0.0", + "datafusion-functions-aggregate-common 54.0.0", + "datafusion-physical-expr-common 54.0.0", + "half", + "hashbrown 0.17.1", + "indexmap", + "itertools 0.14.0", + "parking_lot", + "petgraph", "recursive", "tokio", ] @@ -1651,11 +2066,26 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ea22315f33cf2e0adc104e8ec42e285f6ed93998d565c65e82fec6a9ee9f9db4" dependencies = [ "arrow", - "datafusion-common", - "datafusion-expr", - "datafusion-functions", - "datafusion-physical-expr", - "datafusion-physical-expr-common", + "datafusion-common 53.1.0", + "datafusion-expr 53.1.0", + "datafusion-functions 53.1.0", + "datafusion-physical-expr 53.1.0", + "datafusion-physical-expr-common 53.1.0", + "itertools 0.14.0", +] + +[[package]] +name = "datafusion-physical-expr-adapter" +version = "54.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "51e6ffff8acdfe54e0ea15ccf38115c4a9184433b0439f42907637928d00a235" +dependencies = [ + "arrow", + "datafusion-common 54.0.0", + "datafusion-expr 54.0.0", + "datafusion-functions 54.0.0", + "datafusion-physical-expr 54.0.0", + "datafusion-physical-expr-common 54.0.0", "itertools 0.14.0", ] @@ -1668,14 +2098,31 @@ dependencies = [ "ahash 0.8.12", "arrow", "chrono", - "datafusion-common", - "datafusion-expr-common", + "datafusion-common 53.1.0", + "datafusion-expr-common 53.1.0", "hashbrown 0.16.1", "indexmap", "itertools 0.14.0", "parking_lot", ] +[[package]] +name = "datafusion-physical-expr-common" +version = "54.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7967a3e171c6a4bf09474b3f7a14f1a3db13ed1714ba12156f33fcce2bba54e8" +dependencies = [ + "arrow", + "chrono", + "datafusion-common 54.0.0", + "datafusion-expr-common 54.0.0", + "hashbrown 0.17.1", + "indexmap", + "itertools 0.14.0", + "parking_lot", + "pin-project", +] + [[package]] name = "datafusion-physical-optimizer" version = "53.1.0" @@ -1683,14 +2130,32 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7cb13397809a425918f608dfe8653f332015a3e330004ab191b4404187238b95" dependencies = [ "arrow", - "datafusion-common", - "datafusion-execution", - "datafusion-expr", - "datafusion-expr-common", - "datafusion-physical-expr", - "datafusion-physical-expr-common", - "datafusion-physical-plan", - "datafusion-pruning", + "datafusion-common 53.1.0", + "datafusion-execution 53.1.0", + "datafusion-expr 53.1.0", + "datafusion-expr-common 53.1.0", + "datafusion-physical-expr 53.1.0", + "datafusion-physical-expr-common 53.1.0", + "datafusion-physical-plan 53.1.0", + "datafusion-pruning 53.1.0", + "itertools 0.14.0", +] + +[[package]] +name = "datafusion-physical-optimizer" +version = "54.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "59ff803e2a96054cb6d83f35f9e60fd4f42eac515e1932bd1b2dbc91d5fcbf36" +dependencies = [ + "arrow", + "datafusion-common 54.0.0", + "datafusion-execution 54.0.0", + "datafusion-expr 54.0.0", + "datafusion-expr-common 54.0.0", + "datafusion-physical-expr 54.0.0", + "datafusion-physical-expr-common 54.0.0", + "datafusion-physical-plan 54.0.0", + "datafusion-pruning 54.0.0", "itertools 0.14.0", "recursive", ] @@ -1706,15 +2171,15 @@ dependencies = [ "arrow-ord", "arrow-schema", "async-trait", - "datafusion-common", - "datafusion-common-runtime", - "datafusion-execution", - "datafusion-expr", - "datafusion-functions", - "datafusion-functions-aggregate-common", - "datafusion-functions-window-common", - "datafusion-physical-expr", - "datafusion-physical-expr-common", + "datafusion-common 53.1.0", + "datafusion-common-runtime 53.1.0", + "datafusion-execution 53.1.0", + "datafusion-expr 53.1.0", + "datafusion-functions 53.1.0", + "datafusion-functions-aggregate-common 53.1.0", + "datafusion-functions-window-common 53.1.0", + "datafusion-physical-expr 53.1.0", + "datafusion-physical-expr-common 53.1.0", "futures", "half", "hashbrown 0.16.1", @@ -1727,6 +2192,39 @@ dependencies = [ "tokio", ] +[[package]] +name = "datafusion-physical-plan" +version = "54.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "776ee54d47d15bdb126452f9ca17b03761e3b004682914beaedd3f86eb507fbc" +dependencies = [ + "arrow", + "arrow-data", + "arrow-ipc", + "arrow-ord", + "arrow-schema", + "async-trait", + "datafusion-common 54.0.0", + "datafusion-common-runtime 54.0.0", + "datafusion-execution 54.0.0", + "datafusion-expr 54.0.0", + "datafusion-functions 54.0.0", + "datafusion-functions-aggregate-common 54.0.0", + "datafusion-functions-window-common 54.0.0", + "datafusion-physical-expr 54.0.0", + "datafusion-physical-expr-common 54.0.0", + "futures", + "half", + "hashbrown 0.17.1", + "indexmap", + "itertools 0.14.0", + "log", + "num-traits", + "parking_lot", + "pin-project-lite", + "tokio", +] + [[package]] name = "datafusion-postgres" version = "0.17.0" @@ -1735,7 +2233,7 @@ dependencies = [ "async-trait", "bytes", "chrono", - "datafusion", + "datafusion 54.0.0", "datafusion-pg-catalog", "env_logger", "futures", @@ -1755,7 +2253,7 @@ dependencies = [ name = "datafusion-postgres-cli" version = "0.17.0" dependencies = [ - "datafusion", + "datafusion 54.0.0", "datafusion-postgres", "env_logger", "log", @@ -1770,16 +2268,32 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ac8c76860e355616555081cab5968cec1af7a80701ff374510860bcd567e365a" dependencies = [ "arrow", - "datafusion-common", - "datafusion-datasource", - "datafusion-expr-common", - "datafusion-physical-expr", - "datafusion-physical-expr-common", - "datafusion-physical-plan", + "datafusion-common 53.1.0", + "datafusion-datasource 53.1.0", + "datafusion-expr-common 53.1.0", + "datafusion-physical-expr 53.1.0", + "datafusion-physical-expr-common 53.1.0", + "datafusion-physical-plan 53.1.0", "itertools 0.14.0", "log", ] +[[package]] +name = "datafusion-pruning" +version = "54.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d5fb9e5774660aa69c3ba93c610f175f75b65cb8c3776edb3626de8f3a4f4ee3" +dependencies = [ + "arrow", + "datafusion-common 54.0.0", + "datafusion-datasource 54.0.0", + "datafusion-expr-common 54.0.0", + "datafusion-physical-expr 54.0.0", + "datafusion-physical-expr-common 54.0.0", + "datafusion-physical-plan 54.0.0", + "log", +] + [[package]] name = "datafusion-session" version = "53.1.0" @@ -1787,24 +2301,38 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5412111aa48e2424ba926112e192f7a6b7e4ccb450145d25ce5ede9f19dc491e" dependencies = [ "async-trait", - "datafusion-common", - "datafusion-execution", - "datafusion-expr", - "datafusion-physical-plan", + "datafusion-common 53.1.0", + "datafusion-execution 53.1.0", + "datafusion-expr 53.1.0", + "datafusion-physical-plan 53.1.0", + "parking_lot", +] + +[[package]] +name = "datafusion-session" +version = "54.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "15ce715fa2a61f4623cc234bcc14a3ef6a91f189128d5b14b468a6a17cdfc417" +dependencies = [ + "async-trait", + "datafusion-common 54.0.0", + "datafusion-execution 54.0.0", + "datafusion-expr 54.0.0", + "datafusion-physical-plan 54.0.0", "parking_lot", ] [[package]] name = "datafusion-sql" -version = "53.1.0" +version = "54.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fa0d133ddf8b9b3b872acac900157f783e7b879fe9a6bccf389abebbfac45ec1" +checksum = "6094ad36a3ed6d7ac87b20b479b2d0b118250f66cf997603829fdc65b44a7099" dependencies = [ "arrow", "bigdecimal", "chrono", - "datafusion-common", - "datafusion-expr", + "datafusion-common 54.0.0", + "datafusion-expr 54.0.0", "datafusion-functions-nested", "indexmap", "log", @@ -1819,7 +2347,7 @@ version = "0.7.10" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e7c1832837b905bbfb5101e07cc24c8deddf52f93225eee6ead5f4d63d53ddcb" dependencies = [ - "const-oid", + "const-oid 0.9.6", "zeroize", ] @@ -1840,11 +2368,22 @@ version = "0.10.7" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9ed9a281f7bc9b7576e61468ba615a66a5c8cfdff42420a70aa82701a3b1e292" dependencies = [ - "block-buffer", - "crypto-common", + "block-buffer 0.10.4", + "crypto-common 0.1.7", "subtle", ] +[[package]] +name = "digest" +version = "0.11.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f1dd6dbb5841937940781866fa1281a1ff7bd3bf827091440879f9994983d5c2" +dependencies = [ + "block-buffer 0.12.0", + "const-oid 0.10.2", + "crypto-common 0.2.2", +] + [[package]] name = "displaydoc" version = "0.2.5" @@ -1908,7 +2447,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "39cab71617ae0d63f51a36d69f866391735b51691dbda63cf6f96d042b63efeb" dependencies = [ "libc", - "windows-sys 0.59.0", + "windows-sys 0.61.2", ] [[package]] @@ -1962,12 +2501,6 @@ version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8bf7cc16383c4b8d58b9905a8509f02926ce3058053c056376248d958c9df1e8" -[[package]] -name = "fnv" -version = "1.0.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1" - [[package]] name = "foldhash" version = "0.1.5" @@ -2205,7 +2738,7 @@ dependencies = [ "arrow-arith", "arrow-array", "arrow-schema", - "datafusion", + "datafusion 53.1.0", "geo", "geo-traits", "geoarrow-array", @@ -2348,6 +2881,17 @@ dependencies = [ "foldhash 0.2.0", ] +[[package]] +name = "hashbrown" +version = "0.17.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ed5909b6e89a2db4456e54cd5f673791d7eca6732202bbf2a9cc504fe2f9b84a" +dependencies = [ + "allocator-api2", + "equivalent", + "foldhash 0.2.0", +] + [[package]] name = "heapless" version = "0.8.0" @@ -2385,7 +2929,7 @@ version = "0.12.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6c49c37c09c17a53d937dfbb742eb3a961d65a994e6bcdcf37e7399d0cc8ab5e" dependencies = [ - "digest", + "digest 0.10.7", ] [[package]] @@ -2404,6 +2948,15 @@ version = "2.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "135b12329e5e3ce057a9f972339ea52bc954fe1e9358ef27f95e89716fbc5424" +[[package]] +name = "hybrid-array" +version = "0.4.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9155a582abd142abc056962c29e3ce5ff2ad5469f4246b537ed42c5deba857da" +dependencies = [ + "typenum", +] + [[package]] name = "i_float" version = "1.15.0" @@ -2558,12 +3111,6 @@ version = "2.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3d3067d79b975e8844ca9eb072e16b31c3c1c36928edf9c6789548c524d0d954" -[[package]] -name = "ident_case" -version = "1.0.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b9e0384b61958566e926dc50660321d12159025e767c18e043daf26b70104c39" - [[package]] name = "idna" version = "1.1.0" @@ -2587,12 +3134,12 @@ dependencies = [ [[package]] name = "indexmap" -version = "2.13.0" +version = "2.14.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7714e70437a7dc3ac8eb7e6f8df75fd8eb422675fc7678aff7364301092b1017" +checksum = "d466e9454f08e4a911e14806c24e16fba1b4c121d1ea474396f396069cf949d9" dependencies = [ "equivalent", - "hashbrown 0.16.1", + "hashbrown 0.17.1", "serde", "serde_core", ] @@ -2786,9 +3333,9 @@ checksum = "2c4a545a15244c7d945065b5d392b2d2d7f21526fba56ce51467b06ed445e8f7" [[package]] name = "libc" -version = "0.2.183" +version = "0.2.186" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b5b646652bf6661599e1da8901b3b9522896f01e736bad5f723fe7a3a27f899d" +checksum = "68ab91017fe16c622486840e4c83c9a37afeff978bd239b5293d61ece587de66" [[package]] name = "liblzma" @@ -2859,7 +3406,17 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d89e7ee0cfbedfc4da3340218492196241d89eefb6dab27de5df917a6d2e78cf" dependencies = [ "cfg-if", - "digest", + "digest 0.10.7", +] + +[[package]] +name = "md-5" +version = "0.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "69b6441f590336821bb897fb28fc622898ccceb1d6cea3fde5ea86b090c4de98" +dependencies = [ + "cfg-if", + "digest 0.11.3", ] [[package]] @@ -2903,7 +3460,6 @@ checksum = "a5e44f723f1133c9deac646763579fdb3ac745e418f2a7af9cd0c431da1f20b9" dependencies = [ "num-integer", "num-traits", - "serde", ] [[package]] @@ -3053,9 +3609,9 @@ dependencies = [ [[package]] name = "parquet" -version = "58.1.0" +version = "58.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7d3f9f2205199603564127932b89695f52b62322f541d0fc7179d57c2e1c9877" +checksum = "5dafa7d01085b62a47dd0c1829550a0a36710ea9c4fe358a05a85477cec8a908" dependencies = [ "ahash 0.8.12", "arrow-array", @@ -3071,7 +3627,7 @@ dependencies = [ "flate2", "futures", "half", - "hashbrown 0.16.1", + "hashbrown 0.17.1", "lz4_flex", "num-bigint", "num-integer", @@ -3184,6 +3740,26 @@ dependencies = [ "siphasher", ] +[[package]] +name = "pin-project" +version = "1.1.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2466b2336ed02bcdca6b294417127b90ec92038d1d5c4fbeac971a922e0e0924" +dependencies = [ + "pin-project-internal", +] + +[[package]] +name = "pin-project-internal" +version = "1.1.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c96395f0a926bc13b1c17622aaddda1ecb55d49c8f1bf9777e4d877800a43f8b" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.117", +] + [[package]] name = "pin-project-lite" version = "0.2.16" @@ -3261,10 +3837,10 @@ dependencies = [ "bytes", "fallible-iterator", "hmac", - "md-5", + "md-5 0.10.6", "memchr", "rand 0.9.2", - "sha2", + "sha2 0.10.9", "stringprep", ] @@ -3406,12 +3982,6 @@ dependencies = [ "syn 1.0.109", ] -[[package]] -name = "quad-rand" -version = "0.2.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5a651516ddc9168ebd67b24afd085a718be02f8858fe406591b013d101ce2f40" - [[package]] name = "quote" version = "1.0.45" @@ -3699,7 +4269,7 @@ dependencies = [ "errno", "libc", "linux-raw-sys", - "windows-sys 0.59.0", + "windows-sys 0.61.2", ] [[package]] @@ -3801,16 +4371,6 @@ dependencies = [ "serde_derive", ] -[[package]] -name = "serde_bytes" -version = "0.11.19" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a5d440709e79d88e51ac01c4b72fc6cb7314017bb7da9eeff678aa94c10e3ea8" -dependencies = [ - "serde", - "serde_core", -] - [[package]] name = "serde_core" version = "1.0.228" @@ -3852,7 +4412,18 @@ checksum = "a7507d819769d01a365ab707794a4084392c824f54a7a6a7862f8c3d0892b283" dependencies = [ "cfg-if", "cpufeatures 0.2.17", - "digest", + "digest 0.10.7", +] + +[[package]] +name = "sha2" +version = "0.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "446ba717509524cb3f22f17ecc096f10f4822d76ab5c0b9822c5f9c284e825f4" +dependencies = [ + "cfg-if", + "cpufeatures 0.3.0", + "digest 0.11.3", ] [[package]] @@ -3960,9 +4531,9 @@ dependencies = [ [[package]] name = "sqlparser" -version = "0.61.0" +version = "0.62.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dbf5ea8d4d7c808e1af1cbabebca9a2abe603bcefc22294c5b95018d53200cb7" +checksum = "13c6d1b651dc4edf07eead2a0c6c78016ce971bc2c10da5266861b13f25e7cec" dependencies = [ "log", "recursive", @@ -4010,12 +4581,6 @@ dependencies = [ "unicode-properties", ] -[[package]] -name = "strsim" -version = "0.11.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7da8b5736845d9f2fcb837ea5d9e2628564b3b043a70948a3f0b778838c5fb4f" - [[package]] name = "structopt" version = "0.3.26" @@ -4040,17 +4605,11 @@ dependencies = [ "syn 1.0.109", ] -[[package]] -name = "strum" -version = "0.27.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "af23d6f6c1a224baef9d3f61e287d2761385a5b88fdab4eb4c6f11aeb54c4bcf" - [[package]] name = "strum_macros" -version = "0.27.2" +version = "0.28.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7695ce3845ea4b33927c055a39dc438a45b059f7c1b3d91d38d10355fb8cbca7" +checksum = "ab85eea0270ee17587ed4156089e10b9e6880ee688791d45a905f5b1ca36f664" dependencies = [ "heck 0.5.0", "proc-macro2", @@ -4113,7 +4672,7 @@ dependencies = [ "getrandom 0.3.4", "once_cell", "rustix", - "windows-sys 0.59.0", + "windows-sys 0.61.2", ] [[package]] @@ -4352,9 +4911,9 @@ checksum = "9ea3136b675547379c4bd395ca6b938e5ad3c3d20fad76e7fe85f9e0d011419c" [[package]] name = "typenum" -version = "1.19.0" +version = "1.20.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "562d481066bde0658276a35467c4af00bdc6ee726305698a55b86e61d7ad82bb" +checksum = "b6f5e870be6c3b371b77fe0ee0bafb859fa4964b4404c27de1d380043c4dda20" [[package]] name = "unicode-bidi" @@ -4445,7 +5004,6 @@ checksum = "5ac8b6f42ead25368cf5b098aeb3dc8a1a2c05a3eee8a9a1a68c640edbfc79d9" dependencies = [ "getrandom 0.4.1", "js-sys", - "serde_core", "wasm-bindgen", ] @@ -4624,7 +5182,7 @@ version = "0.1.11" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c2a7b1c03c876122aa43f3020e6c3c3ee5c05081c9a00739faf7503aeba10d22" dependencies = [ - "windows-sys 0.59.0", + "windows-sys 0.61.2", ] [[package]] diff --git a/Cargo.toml b/Cargo.toml index 4b095d4..7c8fbd9 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -17,7 +17,7 @@ arrow = "58" arrow-schema = "58" bytes = "1.11.1" chrono = { version = "0.4", features = ["std"] } -datafusion = { version = "53" } +datafusion = { version = "54" } futures = "0.3" pgwire = { version = "0.40", default-features = false } postgres-types = "0.2" From 71794c454a6a10b5e0c63e13b6e75860a79bad5a Mon Sep 17 00:00:00 2001 From: Ning Sun Date: Tue, 9 Jun 2026 20:07:55 -0700 Subject: [PATCH 2/5] fix: update for datafusion 54 api changes --- datafusion-pg-catalog/src/pg_catalog.rs | 8 ------- .../src/pg_catalog/format_type.rs | 4 ---- .../src/pg_catalog/has_privilege_udf.rs | 4 ---- .../src/pg_catalog/pg_get_expr_udf.rs | 4 ---- .../src/pg_catalog/quote_ident_udf.rs | 4 ---- datafusion-postgres/src/hooks/permissions.rs | 1 + datafusion-postgres/src/hooks/set_show.rs | 21 ++++++++++++++++--- datafusion-postgres/src/planner.rs | 2 +- 8 files changed, 20 insertions(+), 28 deletions(-) diff --git a/datafusion-pg-catalog/src/pg_catalog.rs b/datafusion-pg-catalog/src/pg_catalog.rs index 6749f30..f4ec2e7 100644 --- a/datafusion-pg-catalog/src/pg_catalog.rs +++ b/datafusion-pg-catalog/src/pg_catalog.rs @@ -206,10 +206,6 @@ pub struct PgCatalogSchemaProvider { #[async_trait] impl SchemaProvider for PgCatalogSchemaProvider { - fn as_any(&self) -> &dyn std::any::Any { - self - } - fn table_names(&self) -> Vec { PG_CATALOG_TABLES.iter().map(ToString::to_string).collect() } @@ -1369,10 +1365,6 @@ pub fn create_pg_get_constraintdef() -> ScalarUDF { } impl ScalarUDFImpl for GetConstraintDefUDF { - fn as_any(&self) -> &dyn std::any::Any { - self - } - fn name(&self) -> &str { "pg_get_constraintdef" } diff --git a/datafusion-pg-catalog/src/pg_catalog/format_type.rs b/datafusion-pg-catalog/src/pg_catalog/format_type.rs index 24da102..78319d2 100644 --- a/datafusion-pg-catalog/src/pg_catalog/format_type.rs +++ b/datafusion-pg-catalog/src/pg_catalog/format_type.rs @@ -267,10 +267,6 @@ impl ScalarUDFImpl for FormatTypeUDF { fn invoke_with_args(&self, args: ScalarFunctionArgs) -> Result { format_type_impl(&args.args) } - - fn as_any(&self) -> &dyn std::any::Any { - self - } } pub fn create_format_type_udf() -> ScalarUDF { diff --git a/datafusion-pg-catalog/src/pg_catalog/has_privilege_udf.rs b/datafusion-pg-catalog/src/pg_catalog/has_privilege_udf.rs index 0e17c62..b505f47 100644 --- a/datafusion-pg-catalog/src/pg_catalog/has_privilege_udf.rs +++ b/datafusion-pg-catalog/src/pg_catalog/has_privilege_udf.rs @@ -60,10 +60,6 @@ impl ScalarUDFImpl for PgHasPrivilegeUDF { Ok(ColumnarValue::Array(array)) } - - fn as_any(&self) -> &dyn std::any::Any { - self - } } pub fn create_has_privilege_udf(name: &str) -> ScalarUDF { diff --git a/datafusion-pg-catalog/src/pg_catalog/pg_get_expr_udf.rs b/datafusion-pg-catalog/src/pg_catalog/pg_get_expr_udf.rs index 7750536..510d38f 100644 --- a/datafusion-pg-catalog/src/pg_catalog/pg_get_expr_udf.rs +++ b/datafusion-pg-catalog/src/pg_catalog/pg_get_expr_udf.rs @@ -65,10 +65,6 @@ impl ScalarUDFImpl for PgGetExprUDF { Ok(ColumnarValue::Array(array)) } - - fn as_any(&self) -> &dyn std::any::Any { - self - } } pub fn create_pg_get_expr_udf() -> ScalarUDF { diff --git a/datafusion-pg-catalog/src/pg_catalog/quote_ident_udf.rs b/datafusion-pg-catalog/src/pg_catalog/quote_ident_udf.rs index f189e1b..1eeefde 100644 --- a/datafusion-pg-catalog/src/pg_catalog/quote_ident_udf.rs +++ b/datafusion-pg-catalog/src/pg_catalog/quote_ident_udf.rs @@ -81,10 +81,6 @@ impl Default for ParseIdentUDF { } impl ScalarUDFImpl for ParseIdentUDF { - fn as_any(&self) -> &dyn std::any::Any { - self - } - fn signature(&self) -> &Signature { &self.signature } diff --git a/datafusion-postgres/src/hooks/permissions.rs b/datafusion-postgres/src/hooks/permissions.rs index 42f7594..8d5172d 100644 --- a/datafusion-postgres/src/hooks/permissions.rs +++ b/datafusion-postgres/src/hooks/permissions.rs @@ -82,6 +82,7 @@ impl PermissionsHook { Statement::Set { .. } | Statement::ShowVariable { .. } | Statement::ShowStatus { .. } + | Statement::ShowCatalogs { .. } | Statement::StartTransaction { .. } | Statement::Commit { .. } | Statement::Rollback { .. } diff --git a/datafusion-postgres/src/hooks/set_show.rs b/datafusion-postgres/src/hooks/set_show.rs index 91fd36d..82abe2d 100644 --- a/datafusion-postgres/src/hooks/set_show.rs +++ b/datafusion-postgres/src/hooks/set_show.rs @@ -37,7 +37,9 @@ impl QueryHook for SetShowHook { Statement::Set { .. } => { try_respond_set_statements(client, statement, session_context).await } - Statement::ShowVariable { .. } | Statement::ShowStatus { .. } => { + Statement::ShowVariable { .. } + | Statement::ShowStatus { .. } + | Statement::ShowCatalogs { .. } => { try_respond_show_statements(client, statement, session_context).await } _ => None, @@ -64,7 +66,9 @@ impl QueryHook for SetShowHook { .map_err(|e| PgWireError::ApiError(Box::new(e))); Some(result) } - Statement::ShowVariable { .. } | Statement::ShowStatus { .. } => { + Statement::ShowVariable { .. } + | Statement::ShowStatus { .. } + | Statement::ShowCatalogs { .. } => { let show_schema = Arc::new(Schema::new(vec![Field::new("show", DataType::Utf8, false)])); let result = show_schema @@ -94,7 +98,9 @@ impl QueryHook for SetShowHook { Statement::Set { .. } => { try_respond_set_statements(client, statement, session_context).await } - Statement::ShowVariable { .. } | Statement::ShowStatus { .. } => { + Statement::ShowVariable { .. } + | Statement::ShowStatus { .. } + | Statement::ShowCatalogs { .. } => { try_respond_show_statements(client, statement, session_context).await } _ => None, @@ -279,6 +285,13 @@ async fn try_respond_show_statements( statement: &Statement, session_context: &SessionContext, ) -> Option> { + // Handle SHOW CATALOGS separately since it's its own variant in sqlparser 0.62+ + if let Statement::ShowCatalogs { .. } = statement { + let catalogs = session_context.catalog_names(); + let value = catalogs.join(", "); + return Some(mock_show_response("Catalogs", &value).map(Response::Query)); + } + let Statement::ShowVariable { variable } = statement else { return None; }; @@ -596,6 +609,8 @@ mod tests { let show_response = try_respond_show_statements(&client, &statement, &session_context).await; + dbg!(query); + dbg!(&show_response); let Some(Ok(Response::Query(show_response))) = show_response else { panic!("unexpected show response"); }; diff --git a/datafusion-postgres/src/planner.rs b/datafusion-postgres/src/planner.rs index 290015e..002e872 100644 --- a/datafusion-postgres/src/planner.rs +++ b/datafusion-postgres/src/planner.rs @@ -16,7 +16,7 @@ fn extract_placeholder_cast_types(plan: &LogicalPlan) -> Result Date: Wed, 24 Jun 2026 16:45:19 +0800 Subject: [PATCH 3/5] feat: arrow_upper/array_lower UDFs for datafusion 54 (#362) * chore(deps): bump rust_decimal from 1.42.0 to 1.42.1 (#354) Bumps [rust_decimal](https://github.com/paupino/rust-decimal) from 1.42.0 to 1.42.1. - [Release notes](https://github.com/paupino/rust-decimal/releases) - [Changelog](https://github.com/paupino/rust-decimal/blob/master/CHANGELOG.md) - [Commits](https://github.com/paupino/rust-decimal/compare/1.42.0...1.42.1) --- updated-dependencies: - dependency-name: rust_decimal dependency-version: 1.42.1 dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> * chore(deps): bump getset from 0.1.6 to 0.1.7 (#353) Bumps [getset](https://github.com/jbaublitz/getset) from 0.1.6 to 0.1.7. - [Release notes](https://github.com/jbaublitz/getset/releases) - [Commits](https://github.com/jbaublitz/getset/compare/v0.1.6...v0.1.7) --- updated-dependencies: - dependency-name: getset dependency-version: 0.1.7 dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> * chore(deps): bump postgres-types from 0.2.13 to 0.2.14 (#356) Bumps [postgres-types](https://github.com/rust-postgres/rust-postgres) from 0.2.13 to 0.2.14. - [Release notes](https://github.com/rust-postgres/rust-postgres/releases) - [Commits](https://github.com/rust-postgres/rust-postgres/compare/postgres-types-v0.2.13...postgres-types-v0.2.14) --- updated-dependencies: - dependency-name: postgres-types dependency-version: 0.2.14 dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> * feat: update regclass cast to subquery * feat: add array_upper/array_lower UDFs DataFusion ships `array_length` but not `array_upper`/`array_lower`, so Postgres client queries using them only "worked" via hardcoded blacklist token substitution -- any non-byte-matching variant failed at planning with `Invalid function 'array_upper'`. Implement both as scalar UDFs (`array_bounds_udf.rs`) with Postgres semantics: * arrow lists are always 1-based, so array_lower(arr,1) -> 1 and array_upper(arr,1) -> array_length(arr,1) * NULL for null array, out-of-range dim, or empty array * accepts List/LargeList/FixedSizeList + Int32/Int64 dims, returns Int32 Register them in `setup_pg_catalog`. The dbeaver startup test went from FAILED -> PASS (18/19 queries now run for real). The two dbeaver queries that still can't run are blacklisted: one needs dynamic `generate_series` bounds (DF only takes literal Int64), the other needs Postgres regnamespace/oid-alias string resolution. Neither is fixable by adding the UDF; both get type-compatible NULL stubs. Includes unit + end-to-end integration tests. * feat: rewrite regclass/regnamespace/regtype/regproc casts to oid lookups These are all Postgres `oid` (int4) alias types: casting a *name* to one yields the matching catalog oid. DataFusion has no such types, so a bare `'trigger'::regtype` was stripped to the string `'trigger'` and then crashed an oid comparison with "Cannot cast string 'trigger' to Int32". Generalize the existing regclass-only rewrite rule into `RewriteRegCastToSubquery`, with a registry of name->oid lookup queries: * regclass -> pg_class.oid (schema-qualified relation name) * regnamespace -> pg_namespace.oid (schema name) * regtype -> pg_type.oid (schema-qualified type name) * regproc -> pg_proc.oid (schema-qualified function name) Direction guard: only the *forward* direction (name -> oid) is rewritten, detected by a string-literal or `$1` placeholder operand. The *reverse* direction (`::regtype`, e.g. `prorettype::regtype::text` for display, or the left side of `prorettype::regtype != 'trigger'::regtype`) has a column operand and is left untouched; it is stripped to the bare oid column by RemoveUnsupportedTypes, which is correct since the column already is an oid. `regclass` is re-added to the unsupported-types set so its reverse direction is stripped too (it was removed earlier for the forward case, now handled by the rewrite). Results -- client startup tests, base branch -> this branch: * pgcli : FAILED -> PASS (the `'trigger'::regtype` crash is fixed) * dbeaver: PASS (already green from the array_upper work) * psql : 3 failures -> 1 failure; the two regclass/regtype-related queries now pass. The remaining failure is a DataFusion internal "ScalarSubqueryExpr evaluated before the subquery was executed" bug in `IN (subquery UNION ALL VALUES(...))`, which is blacklisted here as it can't be fixed at the SQL-rewrite layer. The full workspace test suite is green. * chore(deps): bump log from 0.4.32 to 0.4.33 (#361) Bumps [log](https://github.com/rust-lang/log) from 0.4.32 to 0.4.33. - [Release notes](https://github.com/rust-lang/log/releases) - [Changelog](https://github.com/rust-lang/log/blob/master/CHANGELOG.md) - [Commits](https://github.com/rust-lang/log/compare/0.4.32...0.4.33) --- updated-dependencies: - dependency-name: log dependency-version: 0.4.33 dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> * fix: ordered_param_types and add unit test (#357) * fix ordered_param_types and add unit test Refactor sorting of parameter types to sort numerically based on placeholder keys. Add unit test to verify correct sorting of parameter types. * fix cargo fmt * chore(deps): bump pgwire from 0.40.1 to 0.40.3 (#359) Bumps [pgwire](https://github.com/sunng87/pgwire) from 0.40.1 to 0.40.3. - [Release notes](https://github.com/sunng87/pgwire/releases) - [Changelog](https://github.com/sunng87/pgwire/blob/master/CHANGELOG.md) - [Commits](https://github.com/sunng87/pgwire/compare/v0.40.1...v0.40.3) --- updated-dependencies: - dependency-name: pgwire dependency-version: 0.40.3 dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> * refactor: replace 2 blacklists with proper rewrite rules The previous commit added 3 BLACKLIST_SQL_MAPPING entries to keep client startup tests green. Two of them can be replaced with general, correct rewrite rules; only the one that genuinely needs schema awareness remains. 1. dbeaver type lookup (REMOVED): `generate_series(1, array_upper(current_schemas(false), 1))` failed because our array_upper UDF returns Int32 (correct Postgres int4) but DataFusion's generate_series wants Int64. Postgres implicitly coerces int4->int8 here; DF does not. New rule `CastArrayBoundsForGenerateSeries` wraps array_upper/array_lower args of generate_series in ::bigint, the way Postgres would. 2. psql foreign-key \d lookup (REMOVED): `VALUES ('16417'::pg_catalog.regclass)` broke DF's subquery decorrelator because the regclass rewrite embedded a (SELECT ...) inside VALUES. Fix it at the source: a *numeric* string operand like '16417' should resolve directly to that oid (Postgres behavior), not do a name lookup. RewriteRegCastToSubquery now emits a literal oid for numeric operands, which both is more correct and avoids the nested subquery. 3. dbeaver relation-size lookup (KEPT): `WHERE c.relnamespace='public'` compares an oid column to a bare string, needing Postgres' implicit string->oid coercion. The explicit `'public'::regnamespace` form is already handled, but detecting that a bare string needs coercing requires knowing the column is an oid column -- schema awareness the AST-rewrite layer lacks. Hardcoding pg_catalog column names would risk regressing user tables with same-named columns, so this single entry stays, with an accurate comment. Net: BLACKLIST_SQL_MAPPING goes from +3 (previous commit) to +1 vs the base branch, and that one is the genuinely hard case. Full test suite + clippy are green. * chore: format * chore(deps): bump bytes from 1.11.1 to 1.12.0 (#360) Bumps [bytes](https://github.com/tokio-rs/bytes) from 1.11.1 to 1.12.0. - [Release notes](https://github.com/tokio-rs/bytes/releases) - [Changelog](https://github.com/tokio-rs/bytes/blob/master/CHANGELOG.md) - [Commits](https://github.com/tokio-rs/bytes/compare/v1.11.1...v1.12.0) --- updated-dependencies: - dependency-name: bytes dependency-version: 1.12.0 dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> * feat: oid coercion analyzer rule (#363) * feat: postgres-correct oid/string comparison via Field metadata + analyzer rule Postgres catalog columns like pg_class.relnamespace or pg_attribute.atttypid are object identifiers stored as Int32, but clients compare them against string literals (WHERE relnamespace = 'public', WHERE atttypid = '23') and expect Postgres name/numeric oid resolution. DataFusion has no notion of "oid": it coerces Int32_col = Utf8('public') to CAST(col AS Utf8) = 'public', silently returning zero rows for name strings. This implements the design as a standalone feature: 1. oid_field.rs -- annotate oid/oid-alias columns via Arrow Field metadata (key "pg.oid_alias" -> kind: oid/regclass/regnamespace/regtype/regproc). The metadata survives into the logical plan schema, readable via ExprSchema::metadata(). pg_namespace/pg_class/pg_attribute oid columns are annotated. 2. oid_coercion_rule.rs -- an AnalyzerRule (OidStringCoercion) that rewrites oid-alias column comparisons against string literals using Postgres semantics: - numeric string -> literal Int32 oid (e.g. '16417' -> 16417) - name string -> scalar subquery SELECT oid FROM WHERE = $s (regnamespace->pg_namespace, regclass->pg_class, regproc->pg_proc) The rule is order-independent (handles both the pre-coercion `col = 'x'` form and the post-coercion `CAST(col AS Utf8) = 'x'` form) and supports =, <>, and IN (...). Name resolution works in the sync analyzer because PgCatalogSchemaProvider can build a table provider synchronously (dynamic tables defer data fetch to execution via a streaming source). The rule captures an OidLookupProvider handle to build the lookup subquery plans; data materializes lazily at execution. 3. Registered in setup_pg_catalog. Verified end-to-end: relnamespace = '' and relnamespace = '' return the same rows as the int-oid baseline (which previously returned empty). 29 lib tests + full workspace green. * feat: stamp oid-alias metadata into pg_catalog feather exports The oid-coercion analyzer rule relies on Arrow field metadata (`pg.oid_alias=`) to know which Int32 columns are object identifiers. Previously only the handful of dynamic tables (pg_namespace, pg_class, pg_attribute) were annotated by hand. The ~50 static tables loaded from the embedded feather files (pg_type, pg_proc, pg_aggregate, pg_operator, ...) had no metadata, so string-vs-oid comparisons on them silently returned zero rows. This moves the annotation to the source of truth: the export scripts that read the real schema from PostgreSQL. export_pg_catalog_arrow.sh (embedded exporter): - Map every oid-alias type (oid, regproc, regprocedure, regoper, regoperator, regclass, regtype, regnamespace, regrole, regconfig, regdictionary, regcollation) to int32 (the raw oid), not string. - reg* columns are cast with ::oid at SELECT time so Postgres returns the integer, not its display (name) form. - Attach field metadata `pg.oid_alias=` to those columns. Arrow IPC round-trips this metadata faithfully (verified pyarrow -> feather -> arrow-rs). pg_to_arrow.py (generic exporter): same treatment, detecting oid-alias columns from pg_type at runtime. Regenerated all 65 feather files. 251 oid-alias columns are now annotated (216 oid, 35 regproc); the 21 reg* columns previously stored as string (e.g. pg_type.typinput, pg_aggregate.aggfnoid) are now int32 + metadata. The dynamic tables (pg_namespace/pg_class/pg_attribute) keep their hand-annotated oid_field() calls since they build schemas at runtime; the feather metadata covers everything else transparently. Added end-to-end test feather_metadata_reaches_rule_for_static_tables: pg_type.typinput (regproc, annotated solely via the feather file) resolves a proc-name string via pg_proc name->oid lookup, matching the int-oid baseline. 60 tests pass. * chore: format and cleanup * refactor: remove RewriteRegclassCastToSubquery, rely on oid-coercion rule The oid-coercion analyzer rule + Field metadata (added in be40d6b/0300310) now handle `'name'::regclass::oid` casts in comparison predicates natively at the logical-plan layer, making the SQL-rewrite rule redundant for that purpose. Remove it. To support this, fix RemoveUnsupportedTypes to peel nested casts to a fixed point. Previously the visitor replaced an `Expr::Cast` with its inner expression in a single pass and never re-visited the replacement, so `'x'::regclass::oid` became `'x'::regclass` (the residual REGCLASS then being rejected by DataFusion as an unsupported SQL type at plan time). Looping to a fixed point fully unwinds it to `'x'`, which the oid-coercion rule resolves against any oid-alias column it is compared with. Net: -162 lines. The `'x'::regclass::oid` pattern in comparisons (the only shape exercised by client queries -- pgadbc, psql) is now covered by: 1. RemoveUnsupportedTypes -> peels to bare 'x' 2. OidStringCoercion rule -> resolves 'x' via pg_namespace/pg_class/pg_proc Trade-off: schema-qualified names in casts (e.g. `oid = 'pg_catalog.pg_type'::regclass::oid`) no longer split into schema+name. The old rule attempted this via parse_ident()+current_schema(), but that path was never verified to resolve correctly and relies on UDFs DataFusion may not support. Bare-oid columns never supported name resolution in either approach by design (no names-for-oid table). All 59 remaining tests pass (the removed rule's own test was deleted). Added regression assertions to test_remove_unsupported_types pinning the full-peel behavior. * refactor: unify oid-alias type names, rename RemoveUnsupportedTypes Two cleanups to the oid machinery: 1. Single source of truth. The list of oid-alias type names previously lived in two places that could drift: * RemoveUnsupportedTypes had a hardcoded set of 6 names to strip (regclass, regproc, regtype, regtype[], regnamespace, oid) * oid_field::kind had 5 named constants for metadata annotation Both must enumerate the same Postgres oid-alias family, so consolidate them into one constant `oid_field::OID_ALIAS_TYPE_NAMES`, now covering the full pg_catalog oid-alias set (oid, regproc, regprocedure, regoper, regoperator, regclass, regtype, regnamespace, regrole, regconfig, regdictionary, regcollation) -- matching what the feather export scripts stamp as metadata. RemoveOidTypeCast derives its strip set from it, generating the bare / `pg_catalog.`-qualified / array spellings. Net effect: cast types like `::regrole` that DF rejects are now stripped too (previously would error); no client query regressed (over-stripping is harmless since these casts can only ever resolve to oid behavior). 2. Rename RemoveUnsupportedTypes -> RemoveOidTypeCast. The old name was a misnomer inherited from when the rule was generic; it now exists for one specific purpose: stripping oid-alias cast type names so they survive DataFusion's sql_to_plan (which has no notion of oid types) and reach the oid-coercion analyzer rule at the logical-plan layer. Visitor renamed accordingly. oid_field()'s debug_assert now validates against OID_ALIAS_TYPE_NAMES instead of a separate match. Added regression assertions: newly-covered `::regrole` and the array variant `::regtype[]` (the latter used by pgcli's `proallargtypes::regtype[]`). 59 tests pass. * chore: format * fix: resolve master merge for DataFusion 54 (oid-cast + analyzer rule) Merging master's oid-coercion work (PR #363) into the DF54 branch broke compilation and the dbeaver e2e test. Two distinct problems, both rooted in the DF53->DF54 upgrade: 1. DataFusion 54 API: Cast/TryCast lost `data_type` in favor of `field: FieldRef`. Updated the oid-coercion-rule tests; the production code already used `Cast { expr, .. }`. 2. Type-coercion direction change: DF53 coerced `Int32 = Utf8` leniently (column -> string, returning empty); DF54 coerces the other way (string -> Int32) and ERRORS on non-numeric names. Master removed the SQL-layer RewriteRegCastToSubquery relying on DF53's leniency, but on DF54 that removal makes explicit `'name'::regclass` casts (stripped to bare strings by RemoveOidTypeCast) hit the broken coercion path. Restore RewriteRegCastToSubquery (run before RemoveOidTypeCast) so explicit forward oid-alias casts resolve to an oid (literal for numeric strings, name-lookup subquery otherwise) in ANY position -- projection, join ON, filter. This is complementary to master's oid-coercion analyzer rule, which handles the implicit `oid_col = 'name'` case via Field metadata. Also: - Extend the oid-coercion analyzer rule to rewrite LogicalPlan::Join filters (not just Filter), and to peek through CAST('str' AS int) so it stays order-independent under DF54's appended-after-TypeCoercion ordering. - Remove stale RewriteRegCastToSubquery tests left mis-merged, then re-add them against the restored rule; refresh the now-inaccurate parser.rs blacklist comment. - Drop redundant PostgreSqlDialect/Parser imports from the test module (now at crate top level). 70 tests pass (38 lib + 32 integration), no new clippy warnings. * refactor: replace both oid SQL rewrite rules with a metadata-aware TypePlanner Eliminates RewriteRegCastToSubquery and RemoveOidTypeCast (two SQL/AST-layer rewrite rules, ~570 lines) in favor of a single, metadata-aware mechanism that resolves oid-alias casts and comparisons at the analyzer layer -- the architectural goal of pushing oid resolution off the AST layer entirely. Key insight: DataFusion 54 exposes a TypePlanner extension point consulted *before* the default type conversion that rejects `regclass`/`regtype`/etc. Registering a TypePlanner that maps each oid-alias type name to an int4 Field carrying `pg.oid_alias` metadata means DF accepts the casts (no more "Unsupported SQL type") AND the kind survives into the logical plan inside the resulting Expr::Cast.field. The oid-coercion analyzer rule then reads that metadata to resolve names -> oids. Changes: * oid_type_planner.rs (new): PgOidTypePlanner maps regclass/regproc/regtype/ regnamespace/oid (+ pg_catalog.-prefixed) to int4 Field with kind metadata. Registered via SessionStateBuilder in setup_pg_catalog. * oid_coercion_rule.rs: PlanRewriter now uses map_expressions (covers every plan node -- projections, filters, join ON filters -- not just Filter/Join). Added a Cast/TryCast arm that reads the cast's OWN field metadata (not just the column's), so oid-column casts like `classoid = 'pg_namespace'::regclass` resolve even though classoid is bare `oid`-kind. Added regtype -> pg_type name resolution. Added kind_from_field + immediate_str_literal helpers. * rules.rs: deleted RewriteRegCastToSubquery, RemoveOidTypeCast, and their 4 test functions. * parser.rs: dropped both rules from the registration list + their imports. * oid_field.rs: refreshed OID_ALIAS_TYPE_NAMES doc (set is now consumed by the TypePlanner, not a strip rule). Net: -387 lines, 69 tests pass (was 70; the 4 deleted SQL-rewrite tests are superseded by analyzer-rule + type-planner tests), zero new clippy warnings. This completes the goal of removing all SQL-level oid-cast rewriting: both the cast-stripping (RemoveOidTypeCast) and the cast-rebuilding (RewriteRegCastToSubquery) are gone, leaving resolution entirely to the metadata-aware analyzer rule. * refactor: drop the dbeaver relation-size blacklist entry The oid-coercion analyzer rule (added with the TypePlanner work) now resolves `c.relnamespace = 'public'` -- a bare string compared against an oid-alias Int32 column -- to the namespace oid via a pg_namespace lookup, the way Postgres does. That was the sole reason this query was blacklisted (the rest of it -- pg_total_relation_size / pg_relation_size -- already worked), so the NULL-fallback entry is no longer needed: the real query executes directly. 6 of 7 blacklist entries remain. Each is blocked by an unrelated, non-oid DataFusion limitation, verified by probing the exact original SQL through the full pipeline: - pgcli FK columns: unnest() of a subquery result - pgcli types: correlated scalar subqueries - psql \d policies: `array(SELECT ...)` constructor unsupported - statistics: `any(stxkind)` -> array_has type mismatch - publications: duplicate NULL projection names - grafana search_path: missing current_setting() UDF 69 tests pass (dbeaver sends the un-blacklisted query and succeeds). --------- Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Co-authored-by: Cemre Mengu --- Cargo.lock | 123 ++-- .../export_pg_catalog_arrow.sh | 73 +- .../pg_aggregate.feather | Bin 16898 -> 11338 bytes .../pg_catalog_arrow_exports/pg_am.feather | Bin 1354 -> 1538 bytes .../pg_catalog_arrow_exports/pg_amop.feather | Bin 14506 -> 15306 bytes .../pg_amproc.feather | Bin 12530 -> 8842 bytes .../pg_attrdef.feather | Bin 594 -> 878 bytes .../pg_attribute.feather | Bin 68602 -> 68970 bytes .../pg_auth_members.feather | Bin 1618 -> 2114 bytes .../pg_authid.feather | Bin 3234 -> 3394 bytes .../pg_catalog_arrow_exports/pg_cast.feather | Bin 5914 -> 6394 bytes .../pg_catalog_arrow_exports/pg_class.feather | Bin 27506 -> 28610 bytes .../pg_collation.feather | Bin 29818 -> 30186 bytes .../pg_constraint.feather | Bin 12138 -> 12938 bytes .../pg_conversion.feather | Bin 5946 -> 5394 bytes .../pg_database.feather | Bin 4330 -> 4714 bytes .../pg_db_role_setting.feather | Bin 546 -> 798 bytes .../pg_default_acl.feather | Bin 734 -> 1118 bytes .../pg_depend.feather | Bin 18466 -> 18962 bytes .../pg_description.feather | Bin 80106 -> 80394 bytes .../pg_catalog_arrow_exports/pg_enum.feather | Bin 626 -> 910 bytes .../pg_event_trigger.feather | Bin 914 -> 1294 bytes .../pg_extension.feather | Bin 2002 -> 2370 bytes .../pg_foreign_data_wrapper.feather | Bin 946 -> 1426 bytes .../pg_foreign_server.feather | Bin 1006 -> 1378 bytes .../pg_foreign_table.feather | Bin 546 -> 798 bytes .../pg_catalog_arrow_exports/pg_index.feather | Bin 9610 -> 9898 bytes .../pg_inherits.feather | Bin 654 -> 930 bytes .../pg_init_privs.feather | Bin 4338 -> 4626 bytes .../pg_language.feather | Bin 2178 -> 2754 bytes .../pg_largeobject.feather | Bin 498 -> 674 bytes .../pg_largeobject_metadata.feather | Bin 530 -> 782 bytes .../pg_namespace.feather | Bin 1338 -> 1610 bytes .../pg_opclass.feather | Bin 5746 -> 6546 bytes .../pg_operator.feather | Bin 36658 -> 26554 bytes .../pg_opfamily.feather | Bin 3434 -> 3914 bytes .../pg_parameter_acl.feather | Bin 510 -> 674 bytes .../pg_partitioned_table.feather | Bin 1058 -> 1330 bytes .../pg_policy.feather | Bin 1010 -> 1282 bytes .../pg_catalog_arrow_exports/pg_proc.feather | Bin 194802 -> 182026 bytes .../pg_publication.feather | Bin 1086 -> 1358 bytes .../pg_publication_namespace.feather | Bin 498 -> 850 bytes .../pg_publication_rel.feather | Bin 718 -> 1070 bytes .../pg_catalog_arrow_exports/pg_range.feather | Bin 1978 -> 2586 bytes .../pg_replication_origin.feather | Bin 398 -> 558 bytes .../pg_rewrite.feather | Bin 251050 -> 251322 bytes .../pg_seclabel.feather | Bin 718 -> 994 bytes .../pg_sequence.feather | Bin 1074 -> 1358 bytes .../pg_shdepend.feather | Bin 942 -> 1534 bytes .../pg_shdescription.feather | Bin 1050 -> 1338 bytes .../pg_shseclabel.feather | Bin 606 -> 882 bytes .../pg_statistic.feather | Bin 90938 -> 92154 bytes .../pg_statistic_ext.feather | Bin 1154 -> 1646 bytes .../pg_statistic_ext_data.feather | Bin 834 -> 1006 bytes .../pg_subscription.feather | Bin 2046 -> 2430 bytes .../pg_subscription_rel.feather | Bin 638 -> 914 bytes .../pg_tablespace.feather | Bin 1426 -> 1698 bytes .../pg_transform.feather | Bin 702 -> 1298 bytes .../pg_trigger.feather | Bin 2174 -> 2974 bytes .../pg_ts_config.feather | Bin 1762 -> 2226 bytes .../pg_ts_config_map.feather | Bin 1690 -> 1962 bytes .../pg_ts_dict.feather | Bin 2562 -> 3042 bytes .../pg_ts_parser.feather | Bin 2074 -> 2714 bytes .../pg_ts_template.feather | Bin 1602 -> 1922 bytes .../pg_catalog_arrow_exports/pg_type.feather | Bin 56026 -> 36226 bytes .../pg_user_mapping.feather | Bin 642 -> 994 bytes datafusion-pg-catalog/pg_to_arrow.py | 48 +- datafusion-pg-catalog/src/pg_catalog.rs | 50 +- .../src/pg_catalog/array_bounds_udf.rs | 345 +++++++++ .../src/pg_catalog/oid_coercion_rule.rs | 652 ++++++++++++++++++ .../src/pg_catalog/oid_field.rs | 105 +++ .../src/pg_catalog/oid_type_planner.rs | 154 +++++ .../src/pg_catalog/pg_attribute.rs | 11 +- .../src/pg_catalog/pg_class.rs | 14 +- .../src/pg_catalog/pg_namespace.rs | 8 +- datafusion-pg-catalog/src/sql/parser.rs | 6 +- datafusion-pg-catalog/src/sql/rules.rs | 332 ++------- datafusion-postgres/src/handlers.rs | 29 +- datafusion-postgres/tests/array_bounds.rs | 38 + tests/probe_blacklist_removal.rs | 58 ++ 80 files changed, 1662 insertions(+), 384 deletions(-) create mode 100644 datafusion-pg-catalog/src/pg_catalog/array_bounds_udf.rs create mode 100644 datafusion-pg-catalog/src/pg_catalog/oid_coercion_rule.rs create mode 100644 datafusion-pg-catalog/src/pg_catalog/oid_field.rs create mode 100644 datafusion-pg-catalog/src/pg_catalog/oid_type_planner.rs create mode 100644 datafusion-postgres/tests/array_bounds.rs create mode 100644 tests/probe_blacklist_removal.rs diff --git a/Cargo.lock b/Cargo.lock index 3422a73..f8a3951 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -580,9 +580,9 @@ dependencies = [ [[package]] name = "block-buffer" -version = "0.12.0" +version = "0.12.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cdd35008169921d80bc60d3d0ab416eecb028c4cd653352907921d95084790be" +checksum = "d2f6c7dbe95a6ed67ad9f18e57daf93a2f034c524b99fd2b76d18fdfeb6660aa" dependencies = [ "hybrid-array", ] @@ -667,9 +667,9 @@ checksum = "1fd0f2584146f6f2ef48085050886acf353beff7305ebd1ae69500e27c67f64b" [[package]] name = "bytes" -version = "1.11.1" +version = "1.12.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1e748733b7cbc798e1434b6ac524f0c1ff2ab456fe201501e6497c8417a4fc33" +checksum = "8ae3f5d315924270530207e2a68396c3cc547f6dca3fbdca317cfb1a51edb593" [[package]] name = "bzip2" @@ -717,7 +717,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6f8d983286843e49675a4b7a2d174efe136dc93a18d69130dd18198a6c167601" dependencies = [ "cfg-if", - "cpufeatures 0.3.0", + "cpufeatures", "rand_core 0.10.0", ] @@ -807,6 +807,12 @@ version = "0.7.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a1d728cc89cf3aee9ff92b05e62b19ee65a02b5702cff7d5a377e32c6ae29d8d" +[[package]] +name = "cmov" +version = "0.5.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0c9ea0ac24bc397ab3c98583a3c9ba74fa56b09a4449bbe172b9b1ddb016027a" + [[package]] name = "colorchoice" version = "1.0.4" @@ -888,15 +894,6 @@ version = "0.8.7" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "773648b94d0e5d620f64f280777445740e61fe701025087ec8b57f45c791888b" -[[package]] -name = "cpufeatures" -version = "0.2.17" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "59ed5838eebb26a2bb2e58f6d5b5316989ae9d08bab10e0e6d103e656d1b0280" -dependencies = [ - "libc", -] - [[package]] name = "cpufeatures" version = "0.3.0" @@ -1036,6 +1033,15 @@ dependencies = [ "memchr", ] +[[package]] +name = "ctutils" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7d5515a3834141de9eafb9717ad39eea8247b5674e6066c404e8c4b365d2a29e" +dependencies = [ + "cmov", +] + [[package]] name = "dashmap" version = "6.1.0" @@ -1749,12 +1755,12 @@ dependencies = [ "hex", "itertools 0.14.0", "log", - "md-5 0.11.0", + "md-5", "memchr", "num-traits", "rand 0.9.2", "regex", - "sha2 0.11.0", + "sha2", "uuid", ] @@ -2379,9 +2385,10 @@ version = "0.11.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f1dd6dbb5841937940781866fa1281a1ff7bd3bf827091440879f9994983d5c2" dependencies = [ - "block-buffer 0.12.0", + "block-buffer 0.12.1", "const-oid 0.10.2", "crypto-common 0.2.2", + "ctutils", ] [[package]] @@ -2807,11 +2814,10 @@ dependencies = [ [[package]] name = "getset" -version = "0.1.6" +version = "0.1.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9cf0fc11e47561d47397154977bc219f4cf809b2974facc3ccb3b89e2436f912" +checksum = "6cf442baaabe4213ce7d1239afc26c039180b6456da2cededa316ae2c8a77a77" dependencies = [ - "proc-macro-error2", "proc-macro2", "quote", "syn 2.0.117", @@ -2925,11 +2931,11 @@ checksum = "7f24254aa9a54b5c858eaee2f5bccdb46aaf0e486a595ed5fd8f86ba55232a70" [[package]] name = "hmac" -version = "0.12.1" +version = "0.13.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6c49c37c09c17a53d937dfbb742eb3a961d65a994e6bcdcf37e7399d0cc8ab5e" +checksum = "6303bc9732ae41b04cb554b844a762b4115a61bfaa81e3e83050991eeb56863f" dependencies = [ - "digest 0.10.7", + "digest 0.11.3", ] [[package]] @@ -3386,9 +3392,9 @@ dependencies = [ [[package]] name = "log" -version = "0.4.32" +version = "0.4.33" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "953f07c43838f8e6f9758cab68bf5bed85465e7587ebe0b823f1bcd81978ad3a" +checksum = "0ceec5bc11778974d1bcb055b18002eba7f4b3518b6a0081b3af5f21666da9ad" [[package]] name = "lz4_flex" @@ -3399,16 +3405,6 @@ dependencies = [ "twox-hash", ] -[[package]] -name = "md-5" -version = "0.10.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d89e7ee0cfbedfc4da3340218492196241d89eefb6dab27de5df917a6d2e78cf" -dependencies = [ - "cfg-if", - "digest 0.10.7", -] - [[package]] name = "md-5" version = "0.11.0" @@ -3690,9 +3686,9 @@ dependencies = [ [[package]] name = "pgwire" -version = "0.40.1" +version = "0.40.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f690fba3b77370e278b606b75c6857d3f33f3e570781a75ef7516e76e44c0b19" +checksum = "bdc5af11aa35ec1e23f56699dfd96f70f02822bdac5bddeabfb53795af4cc477" dependencies = [ "async-trait", "base64", @@ -3828,27 +3824,27 @@ dependencies = [ [[package]] name = "postgres-protocol" -version = "0.6.9" +version = "0.6.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fbef655056b916eb868048276cfd5d6a7dea4f81560dfd047f97c8c6fe3fcfd4" +checksum = "08808e3c483c46e999108051c78334f473d5adb59d78bb80a1268c7e6aa6c514" dependencies = [ "base64", "byteorder", "bytes", "fallible-iterator", "hmac", - "md-5 0.10.6", + "md-5", "memchr", - "rand 0.9.2", - "sha2 0.10.9", + "rand 0.10.0", + "sha2", "stringprep", ] [[package]] name = "postgres-types" -version = "0.2.13" +version = "0.2.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8dc729a129e682e8d24170cd30ae1aa01b336b096cbb56df6d534ffec133d186" +checksum = "851ca9db4932932d69f3ea811b1abe63087a0f740a47692619dd40d4899b68be" dependencies = [ "array-init", "bytes", @@ -3921,28 +3917,6 @@ dependencies = [ "version_check", ] -[[package]] -name = "proc-macro-error-attr2" -version = "2.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "96de42df36bb9bba5542fe9f1a054b8cc87e172759a1868aa05c1f3acc89dfc5" -dependencies = [ - "proc-macro2", - "quote", -] - -[[package]] -name = "proc-macro-error2" -version = "2.0.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "11ec05c52be0a07b08061f7dd003e7d7092e0472bc731b4af7bb1ef876109802" -dependencies = [ - "proc-macro-error-attr2", - "proc-macro2", - "quote", - "syn 2.0.117", -] - [[package]] name = "proc-macro2" version = "1.0.105" @@ -4234,9 +4208,9 @@ dependencies = [ [[package]] name = "rust_decimal" -version = "1.42.0" +version = "1.42.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0c5108e3d4d903e21aac27f12ba5377b6b34f9f44b325e4894c7924169d06995" +checksum = "be2a24f50780bc85f09cc6ac299bdf1424302742d77221106859c9d8b102126a" dependencies = [ "arrayvec", "borsh", @@ -4404,17 +4378,6 @@ dependencies = [ "zmij", ] -[[package]] -name = "sha2" -version = "0.10.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a7507d819769d01a365ab707794a4084392c824f54a7a6a7862f8c3d0892b283" -dependencies = [ - "cfg-if", - "cpufeatures 0.2.17", - "digest 0.10.7", -] - [[package]] name = "sha2" version = "0.11.0" @@ -4422,7 +4385,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "446ba717509524cb3f22f17ecc096f10f4822d76ab5c0b9822c5f9c284e825f4" dependencies = [ "cfg-if", - "cpufeatures 0.3.0", + "cpufeatures", "digest 0.11.3", ] diff --git a/datafusion-pg-catalog/export_pg_catalog_arrow.sh b/datafusion-pg-catalog/export_pg_catalog_arrow.sh index 89ba075..2573377 100755 --- a/datafusion-pg-catalog/export_pg_catalog_arrow.sh +++ b/datafusion-pg-catalog/export_pg_catalog_arrow.sh @@ -160,7 +160,13 @@ import json import numpy as np def pg_type_to_arrow_type(pg_type, is_nullable=True): - """Map PostgreSQL types to Arrow types""" + """Map PostgreSQL types to Arrow types + + Every oid-alias type (oid, regproc, regtype, regclass, regnamespace, ...) + is stored as int32: the underlying object identifier. This lets the + `datafusion-pg-catalog` oid-coercion analyzer rule resolve name/numeric + string comparisons uniformly across all such columns. + """ type_mapping = { 'bigint': pa.int64(), 'integer': pa.int32(), @@ -173,10 +179,20 @@ def pg_type_to_arrow_type(pg_type, is_nullable=True): 'character varying': pa.string(), 'character': pa.string(), 'name': pa.string(), - 'oid': pa.int32(), # OIDs are signed - 'regproc': pa.string(), - 'regtype': pa.string(), - 'regclass': pa.string(), + # --- oid-alias family: all stored as int32 (the raw oid) --- + 'oid': pa.int32(), + 'regproc': pa.int32(), + 'regprocedure': pa.int32(), + 'regoper': pa.int32(), + 'regoperator': pa.int32(), + 'regclass': pa.int32(), + 'regtype': pa.int32(), + 'regnamespace': pa.int32(), + 'regrole': pa.int32(), + 'regconfig': pa.int32(), + 'regdictionary': pa.int32(), + 'regcollation': pa.int32(), + # --- end oid-alias family --- 'timestamp': pa.timestamp('us'), 'timestamp without time zone': pa.timestamp('us'), 'timestamp with time zone': pa.timestamp('us', tz='UTC'), @@ -207,6 +223,30 @@ def pg_type_to_arrow_type(pg_type, is_nullable=True): arrow_type = type_mapping.get(pg_type, pa.string()) return arrow_type +# PostgreSQL types that are object-identifier aliases. For these we stamp Arrow +# field metadata `pg.oid_alias=` so the catalog's oid-coercion analyzer +# rule can resolve name/numeric string comparisons the way Postgres does. +OID_ALIAS_TYPES = { + 'oid', + 'regproc', 'regprocedure', + 'regoper', 'regoperator', + 'regclass', 'regtype', + 'regnamespace', 'regrole', + 'regconfig', 'regdictionary', 'regcollation', +} + +# reg* aliases need an explicit `::oid` cast at SELECT time because Postgres +# returns their display (name) form, not the integer, on a plain SELECT. +REG_OID_TYPES = OID_ALIAS_TYPES - {'oid'} + + +def select_expr(col_name, data_type): + """Build a SELECT column expression, casting reg* columns to oid.""" + quoted = '"' + col_name.replace('"', '""') + '"' + if data_type in REG_OID_TYPES: + return f'{quoted}::oid AS {quoted}' + return quoted + def convert_value(value, arrow_type): """Convert PostgreSQL value to Arrow-compatible value""" if value is None: @@ -325,7 +365,9 @@ def export_table_to_arrow(conn, schema_name, table_name, output_dir): print(f"{'Column Name':<30} {'Type':<20} {'Nullable':<10} {'Description':<40}") print("-" * 100) - # Build Arrow schema + # Build Arrow schema. For oid-alias columns we attach field metadata + # so the Rust catalog's oid-coercion analyzer rule can resolve string + # comparisons against them. arrow_fields = [] for col_name, data_type, is_nullable, default, comment in columns: nullable = "YES" if is_nullable == 'YES' else "NO" @@ -334,13 +376,26 @@ def export_table_to_arrow(conn, schema_name, table_name, output_dir): # Create Arrow field arrow_type = pg_type_to_arrow_type(data_type, is_nullable == 'YES') - field = pa.field(col_name, arrow_type, nullable=(is_nullable == 'YES')) + metadata = {} + if data_type in OID_ALIAS_TYPES: + metadata['pg.oid_alias'] = data_type + print(f"{'':>62} -> annotated pg.oid_alias={data_type}") + field = pa.field( + col_name, arrow_type, + nullable=(is_nullable == 'YES'), + metadata=metadata, + ) arrow_fields.append(field) arrow_schema = pa.schema(arrow_fields) - # Fetch all data - cur.execute(f"SELECT * FROM {schema_name}.{table_name}") + # Fetch all data. reg* oid-alias columns are cast to oid at SELECT time + # so they are returned as integers (matching their stored Arrow type). + select_cols = ", ".join( + select_expr(name, dtype) + for (name, dtype, _, _, _) in columns + ) + cur.execute(f'SELECT {select_cols} FROM {schema_name}."{table_name}"') # Process data in batches to handle large tables batch_size = 10000 diff --git a/datafusion-pg-catalog/pg_catalog_arrow_exports/pg_aggregate.feather b/datafusion-pg-catalog/pg_catalog_arrow_exports/pg_aggregate.feather index 68de2ee4fa7099544dccecfeb2f86491f28f609f..bb42c29f2445985239c8cae079acedb2aa777515 100644 GIT binary patch literal 11338 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 literal 16898 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 literal 1354 zcmd^9Jx>Bb5FO+Y)H7nDh8Q)($`XS{8l%L*%9v27ogDEZmjGVi8oP_Xz{J>7T3A^5 zODrh;54I-w-ZG09KMHGy%+ANn&b*zSrCO^UpKgi_LAjJjUP#m8%A{l@2Mv^RU<<4q zR!3KAB7JZjTmsXMkq08fJO%YZAe)HSj;=#riah^;|Z8|D0dH@!~HyC_WE-o@3SUy zv=mj>eK2Es2#KS^(0MRhz6>72wu||Y(!n(Z+gAvWzdT*gHA7`(&z>qY$g@W zI>rezrib}g!5d&+)h_rDTmu`jiq_kM^DWDY=aJWF`Cj{6XS@+j$pI0}$QEiZNf|H} zr3@s~@1LpG>UyD@~56n0U3?T}{d8gz%adEs!GsXGQ gtRp4oj)!G(7AtT8)m0|n0sa5wzoLZmSIvLu2N&FwQUCw| diff --git a/datafusion-pg-catalog/pg_catalog_arrow_exports/pg_amop.feather b/datafusion-pg-catalog/pg_catalog_arrow_exports/pg_amop.feather index 60279084bf348826c364293a71b20c03b49c8473..06b054802f90f2792f790aeb81c9cad9421f0012 100644 GIT binary patch delta 1545 zcmZ2gc&ePwF(}AC+>n9cKM-7Cp2%lZZ@|pJu!4z!!2*a+FfuUo0I>%UKVV>BC;?&? zAZGjf|38po5&;q+K+FNeGC&Lhd_bI-n_p0zUsRHon46hX$-n^A4%Wv2)F%LC1Fd1m z&rD(90n!EOdO&7;VoqkFS}~B%@Z%5I0!9TOy9mj$03aV^nZ(4k;(;(zGYFdsHZ%cZ z5TgRnfLln0`T+SLLq#S&6t;sIdWJ|tk02R(;s0bNM!m^AOfr*g7!?$4{y{te^6@qZ z8#TlxS29Y&eX#+kf6<=W_rP2nPc@*ifKZj0!-4fkB8t0xZG~P7VSL zB0v!^0DBGQ2#`lW0G4z>o&+Ty4j{<_BtZ^^cvcpn2rYeq9I@G&N!5hu0rTV}GriID k4#}FM=^Z7hNdS`x2n><*Zi6?ygEI(vruzZRMUc`T0GEm+2LJ#7 delta 695 zcmX?AzN(PVF(}AC+>n9cKM*)DP2@AuxWmZ6Fa?MsfLI2IA22X5tO4Q*Aa(#^79fuJ z_y7Oo2aF;U8${|ufNY=;qXLka0AVu;0NFA?3{ndMTtJ+dn_rNdT9T2U!objhq~{2d z9tog2m>zbhp8SF$h8;-izd+cmAUhNo7$&b~RAf;Bx*q5r4FLrp11Qc2l8k`}icB_O z5)p`iN&s~*Oo2$qXy&A*m6TK#qyohlCLk#|17Rb)F`1EBobw1w#pIKW^1{g8V+QKa y&rI2TnpxF^DS&D6Cv&~gU}Rt*A{dRZ1S10n0}l|h12GsdDgdbrCI$vbS_J@|fVPbQ diff --git a/datafusion-pg-catalog/pg_catalog_arrow_exports/pg_amproc.feather b/datafusion-pg-catalog/pg_catalog_arrow_exports/pg_amproc.feather index 94fac528327e81fdf984e27276c7ddb48b13b2b2..67a59d7c5ab3f896d9586f3e42238a42685e7890 100644 GIT binary patch delta 2648 zcmeH}+iw(A7{I@?Guz#6XFJ>7mM*lgOR2D2q(xB+A}k16h>^lpt)`K-AQZ(=iyBPO zC9w~L09_c=Mg_|y1foXd*3xoQykLUHSVZ(etB6z+V{H}s0`)h$Ht=8~e*lyG&i9?~ zdd`{I+3BfXJ1cYg{P}YqnIO{7b;_|Z^R{@QL!?QGM4(kfR)Y>{SNr=Bj%~?vA;ONdyJn_P3&+X9q&PpTTI5{90yxDlRbf2i9L>YQkC?2HsDP_0p1Z%2n%pd4&z*hqY*+F z!!R7?P~z^eB-Uf!2*aXsk{w2H&BPVzl3vHJ?6ia4w_=PhqT19F32YWsQ;XhWgjH+_ z$}~f^U*Z(5KukX%HKPfC&}m3)49c1+6?>lg`Z9?%Ah8EtsFH%;JQF3B$PoE?l~`{h zSI}s`PYQBEsiESlka8UAwmrU;CjPHdgOov%817^aL6nPF=A7@w& z&%!gX0!C1^5Jo`+M#GOJ`~>IW0{j9O;cxH+i)D-voG3kGTUh8>XoWJ;)={n$X2Tp< zhkYLQCemJqH{uL$LbG?3)}6KmZ7aM5+h9FxD0K8rKqg=#bWr9Dd<|#e8`ww5{cr#d z!XapZRyYi8+0s9x9pwldg=26WHplsazXGqqYtRIn_;cvVwb1UOUkOZt$?!*(NH_cm zJ|VeakG#Ar7q13 zBI-0_uTW2g5)l#e6ei|TL{v9xY15~f6{5xm{82H=#4I7w7gc&Fi$Nkz^8}$KPP0z3 zLPIJ<4>d+rb|^2(>+qazuEv^g>)p<)8RU*&0wDwl0uqIQj0VIZ0U3z`0fsk7)9G}QmQHu*uJDqv zqlg@Vany_>;sboGpzaPH5fmS&M@G~EHIB%jj;@Y6EV>Be1BHS8R$%7rS^tAg&gXV@ zb@jcse)n0)+VRK3IW^O!)y*0va)zG`>b9KW6DpO+UqxgK;urxFCr+O^!;2@Eq}RD~ zyoiNxOKU0_aj$cKMf#IlM|+?CrM)=dy>h=a`|PoHkNd#v=%GqVr=PpRJ#*_%t{B$0 zq;&oNx?=B7t~jPj^ebm>+cDg0kV7)o(6L*Wstp|<>hjWq6`VTvlSQR-shm%;_~mvw zN{up=-BDw7@0enk9kY$ic_#yBFJ9Q^>}xvs{i3*58+ zjK+B!6Gj<@iCBO}EX69U#|CW1Hav&@_yk8`67^j4!=<n4{#JG zVQG;bI1g303NsNy8?M7|a5o;t@9{F;#ourYn(*bI82#`wOu#%tGSa|78?MJX+<`6F zj#tr%&u|Q-H-eH_L~1R1HNS+xIP4n|`d7Q(@e z_#Ga^P8`5z_#VM*+8RS~873o+6I&8)cyo!%;65YFt48av>LLE`5uNxmzJy|Z?v6nig~^B@jn!C>hw&mlz~7NoN?*Zcn1*I7$NEy*|9%d3 zVlVy^r%>FR2w(zYxB>U#8N7wV2$a!BP>J!FfhH`*D%^?3@f`N!AdW!#h!kNUs{3S^ zxj0ygTkr^8!}~Z2voB*7127DiV-AvN$6eTtx9|m|AG0HVhFUB@0_|9jP1ugt@jkxE zkl5u+rx=TQSb_D}jHj>%@8KhSi|qbX2%~U0rXvgoH)9jF;bk1a5u8N!c{CjcV+>{> z)95DHh#lC6&*2%s#i&3vrl1~+a2-0Z6}zwxpWp=i18Eiv!xfl~#aNFm*o}iYg~CC! zf8`){HHcs(Hscxm317o|K23%(n2IP?U@h*!qj(N);WK;-?_e^=KwOF`Scnu>;MaHn zPY!YZ3tqyzID#J#9L9`>i%^TXNaGefikEN*Cy_l|q%SVU zFEASsEXQqlbU5w*0tc_66aV`8=bLl8;`u?^x84b-QsL#1me%?hd#O{}i7svn$73zw zrf9uWpG?LJWlC$LIh-mKSW7hRgolVfPtJ2zFg?|Yl`ZykF)fDt6^siB zkk;)Hv}>l(G?N@#l_+3AK@j#Gb@VL%HWZtl~q}s4{$Lr^Re1$7pIv zIKDvHjEUBka3tK&km@azYPX8nnrLf@recx7?g@sMJ&(~?@9<3YxVnV2LIQ8A>p55w zjX24krgyI~t=@5>%jTHW(qApvL(Hj8BHR*P)K%>Zc)Izes7lK6yU&5fr-uARe4E97 zk4|unq1z1me90O^tCe_^q~wNBYnc2}iKN>O{^!N_qc$$__(w^wK}f{Xqi4Y*J^@0f(5?oO}Efjmh==Ikm3;QpYG|AQukeUFDb0*CB@+S zsKeq+7cHhP!;7WDP3(I`_lqU!-4D!4@qBL>wW3W^vc>_`xht=Xbu`kk|R$40_O@zz4s`0*C4XM?{AXqHf+m$&; z+;~(qb|w^&fm^W9^?IMWI4d^%Kh$&p^@Vo6=jXKt?>J za?EOqrJYb~l6DG3l8H3$q6w!^ZmUl&3$-O;$wZErTjmO4GO`85)CVH$aYaokoB9bq&8lz66xm>*0dK8<+X0h*K#P${YW~x0@GQl-6 zG`{?_WK%W!A9DWS`0_SMMq;T*Ji1hZp8jGlmx0DOF|QTx+uow4q-Fh}JO!eER32_+ zm3Z=GNJF$h%+-pfux#zg7nQ4-k5(jG9qOLGQ;Z)i-|s}{i+P7=CMsr(ZenG`$mELm zI?;62Ux}{qs=3;Vh?fa8D&AZMhWPTtoGo59*K=9^tgJc0&{DJAFq$ujl_y3_yxqiX z7As!@O`=8_-s47arFb`q`jtDA>Dk&lNQ@i1vRd7h)lK4iQuU1``uH;UGhR~Rh|?5H zBosrLhaD@W%sd(Cq+;$i-M2F2q~pH@lHHxQ)*vwY$jyGlKw^cREO+$ei-56^slzGj`WID=#=``rwjMzkU zplOb?f@M-2kA@o?#Ryx9(Zw|p{08NXG0iSxwEze`k}*rYr`@WRu+SLZ5E)NK+^ zOz01OiY*d*u_(H`-PZM@zf&?VqqxRiBIDHxFJaP0%@byQie;)LmS_nt3ng14u|#7s zUpBBDgjgTixM%Cn+DDvbdU$x8Qy)(zTPC|*C@@KMfdnUtE|i?Bc%1Rd4!w%%SE-DrbzoRV8HExYuINNL7b&aJ(&N?txergVB_DcK4`nP7AI;j; z&E0P`yIs$UiP25;EW@55?j5i&YF*+so}qh*-6WQJPke8>i?Gi&^#e*5E8m8$aNS0@ zG7?-kIZdF&h6Lb}`_A2p3$zBC0kfNI0qH>6%rN;)I6n(MsEfV9Ft^#+TEpSg) zfz})1pDe~G<-15xq-Tc;-Y513mj2u6W$VSrzDevl8Lgj_t_o+U@uO!m*w&Rn_6~Pk z*rS!LCwI@eTG{u@wRWRb=k+P`3B#^6YE+Zx{bGEkeFT8cV`^=mR)&2-S=RGn%wTHK zKaGMt)stZGng8w6RP2Np_HjnZ9CfX}O51bQ6dfa!s#A`3v!BqD z>C1P;5|MaYn)$3S+bWX4c5M|)aHqC>W~LcoaR|{@hrSk&06F-^4Pp#S znvV@oL}H53DZ>W172RUG6}2WB*7Pjj6WWbLVZe<#6Js%R z!m-E77st}kmR4u^_hNshI`yG}>T9vTP~&wk3O}qSeeJ1Fwj~-utat8`clK+Ej!fCe hye;bNu6*;k*Mk)uub1`v|L~{$!oZ8%)7k%0{0|4JRZ9Q> diff --git a/datafusion-pg-catalog/pg_catalog_arrow_exports/pg_attrdef.feather b/datafusion-pg-catalog/pg_catalog_arrow_exports/pg_attrdef.feather index 0c5d9e23770b85b1f698c360f4e10e84dcd3c866..73d238c7ed6b7ded40ec5871b639258ecef6e346 100644 GIT binary patch literal 878 zcmeH`K}rKb5JmsQNhU}mgUlie7de685d!XoAm~m;Mr0r+q6i+q6LTpzl}D zY+Si>_}>aO}#)je6Q*Jl?e(ieCuq*}(ll4hD}4g*DrFT6QxIjm;VC-#h;#)drqhXI9w4}DX?zgd5MsBSpw5m|AhuWGrcM)+cAm?tM?%<28UpVG9^GO3g$K0K{ zQDJTOaI@()jA>MiJdk@=j=DF@~kD*uXrf(l{(K*1X(8Dd3EYcx8xx(0O!%iUT zUqXFqePh&j?Rlw*Fz%uXAk+EtZ$9Pv@@a-o@;nA-?_PG9P$5dfBSCld<3ib GpM3)+He6i* literal 594 zcmd^7K?=e!5S(b*1nD6M4<0<^3xXf$3xr-gS1MT03Zg&p0Y1QI_yB*TvzrKBe1QYm zZYHzS&62ulR_g`uB7y+|1QS#!QNS}JjO8BOc}AO~WWb$k$F!`88>bXr4dxj%RIm+V1-fkF1a60;bxl)9ypQ8}xtQ uy^X0over}Q;k1U7i43%p`)F-Nzfx5}9c2RIBeRiNeDIHRihMh@zNI(zTt|-p diff --git a/datafusion-pg-catalog/pg_catalog_arrow_exports/pg_attribute.feather b/datafusion-pg-catalog/pg_catalog_arrow_exports/pg_attribute.feather index 118e1224932e482c3a1a8e231fdfce55353259ae..9513a7aee1961df6c24c37a138955d822b426c4f 100644 GIT binary patch delta 1459 zcmeHHJ!n%=6h7zX-S=Kn6J8`Vp^CiNVxWckLx(!FR4DjE#afDr2(}bm(BA-7+|ea|#YlqR>Iap@NGw=K0;12pJqYbnJoezVDuU{@%HVyDiSQ zXHMqS)YOH`$B81y757Qz#Q8N%Q~|aeqPM_9U=k<*pA$rHfCXRzC;(p-Q4LrErhyRn z&hQ16WW(jt>SaTEJRVf_hMe=bUo{$X*W)9q?~lCjc(geFJBo;i11#@bT;;&00UtOh zzdSxLf`Eh~s0I^jYB>s^Tk|()AHKKe20^dSR_15#U`uQ5u%SJZqR*xDW=E#iCaX$% zxEV!tsro#i%b+CdmOceNCSTy9-+^9}bQ0R1ppRrE32lge)hx}+Vv++rf&Herm>AFt zU^!Dwl=KSNnEZgb`vJ7lG^46phEg1)929TMf8I2oxLanRO9wW6y9;%>pF+9gZI%54 zN7k+CUWaPfEIYmFl@7nM*>HM`A3HQxks01`KPN$KKMN+S^C$nc^9(F@($29~Bo1Y{ zi+ju~m6gX`oH^>oe?qjM3UPEVzKno!(8Lnwo&jy;uIl_*o7-NQkJZ6yPj*s+wfD)3 z?cu`VgHn*k*v0X_v}@yS2N#3f HdZqsYiR@<8 delta 1042 zcmeH{J!=$E6o${abMH=Oc4mmOWR^f+Ai09sT>V)9MAO28On8g zN#*g{K*OQj4mdYwP~Yu_nli&3=OX(SX%6X@JyE$?LwagEaJxva-H5|u9-@0(b>Ph*SHpRAG9yT9VZg+siX3TrG+K2S$fR YLZ3$^^SS!}D*XFbA#C7t@BIY+0sz!SbpQYW diff --git a/datafusion-pg-catalog/pg_catalog_arrow_exports/pg_auth_members.feather b/datafusion-pg-catalog/pg_catalog_arrow_exports/pg_auth_members.feather index c9682618afda19e9a57b9e1632b2633109531576..019b8be182a1ed46d79b295dd222914038974a8a 100644 GIT binary patch literal 2114 zcmeHJJ#W)c6uoZT#6qTuPzDbSRzWHYsVXrr(j7!qA;H!L)oLv@aph)UjH>>Cs=t7N zfsuhB14Cz~{EW`DGjPs*zV4F=Z5Jel-ssx*>)ns%^PaN4x%v9-n#eEE=LM0jknTw= zZCR8E5-13v3$zH&uzHGgsA0_{5J|vapnm{A(KiKU<+#2lXgF~3*tIHdtko#_~xi#AG z53}L>ti%>WX5Lh1ySYZ<@&+l^oO(6hK=E{3FJ0Y8%RQ74Z zZ@T$s4ZrE;r<+)BHRArYPArhZ`W{i@^*Ljy`9~gojdj$jiZyg$OLwm6Y+(%B%TyxQCy5*IS0PL zbJ03UD^i4afHf}gi183;13Q2NJbz3k=n9NkN#@X*m{&pnH0t%ksEc*j+XFxuZ50Eq zr>y{Cw;jacmwpWGZbn~&M)f>rv(*W^X>@Y@iS+E61)iszS;ObJh@0Jh6idr$a#hUn zTS+_evHAr)HH9rgL$@=5F1kh z^_4%K;?-CFdWu(H`Qa3=KJSq>vR&G$ulzV=>_C0xImdDba;AMj9V q1yg;#tx?n>zZo@v?n9cKM*J|PvkRVZD3+xu$j!rwVJi#-~azDlQ(i{^RfV03=9m6 z3P57dWL-vW)(=3DHk1%i z$>fXN>a16QtP4Of@yQWP0+S~&$xkk3lCNiDU;&!Vz#zmR!N38e*%^3%qyU2mPy`H^ zM1WKT5QAg|z(NcR%s@InGlhW>NQ2aK07(`g2~z_y6Q%|vUy!Z`R34w0lbKiyzRJx*A91dPcYuyZO4A*n+JG62QP`V3?fC!9O{LGepP)$WZ}ekUv0v hG+>^5ic@Ox3r>-d8BLkwMdfBF(}AC+>n9cKM-7Cn#gCwn!&`tpfTB(Yc*@azyJSZCjaHq=8XWd7#J8B z6@bK)$-0c%tS5jXM<&NIYP0qPhc$6j=@yO~i2>>mT0b&*)1_5Ru&d*F? z;9%eZVs;<~14ac9wON<>Cu_Z#L7qoSVOp_SRgO`riC1KCl50_Vx~;8BQCP7@iJ_xU zl&eRsYo2y+Rhqw(N2O7?w?}1iQm%iZV|b-@a#e77s)>oMRiuZ7lW#_ga7~l diff --git a/datafusion-pg-catalog/pg_catalog_arrow_exports/pg_cast.feather b/datafusion-pg-catalog/pg_catalog_arrow_exports/pg_cast.feather index 9edd1049634a78c2f4c4f38474bb5782f5adfdc0..7c480aeaa75f755a7984a612bcc63fa074faaf30 100644 GIT binary patch delta 951 zcmbQG_sfvaF(}AC+>n9cKM+(fP2@9@yurx85CFta7#J8TfY=3yS%CP;#7K3PBS2-7 z0~p08c5906`}hApP@G8wNCW^e2M|k4b`%q@2kHiE*#cA{0A(`+>HN$T1|A??kgf-0 z#wX@vCKdy^3~L}JF)9GrYCs!+6soB}0TAE<;^f5Ql9I%t^wbgt2ADlEKs`wISmCrt z1Y$U&0??p7B#R<|e2DXP84=EJK{XbqsT>S^K;7(M6MzOWDgX%v1|bFsun0TY%K{7{ zKoKwidktnI$k`wO3m%}COu!mAfFujh0Fbkg{D#XBlj|8pH_u>vAS`48)Sv>ypg02s fPzTfGE>Wq;D?~*`qZXbrhg#HfEns3`faFyGMaZb_ delta 467 zcmexmI7^SuF(}AC+>n9cKM-^h@St%*0g?hh2nGn7AbbX9Af2C?0#wTb#Oz=_Kp{p2Ai=P?mFcmtkOh#X j0mL9L0DZ|kaz?D<-cRx diff --git a/datafusion-pg-catalog/pg_catalog_arrow_exports/pg_class.feather b/datafusion-pg-catalog/pg_catalog_arrow_exports/pg_class.feather index 41faca496fa58b3371d6d87e9630667733a1ae56..20ab6e1e8586d4ad0818af90ce3ca39346d63056 100644 GIT binary patch delta 2781 zcmeHJPe>GD6o0e3&aPI&WD9GVHhEZZ5F?48i&zMGkTMDD(7%P9{iAEjCg?$04;>;R zl6UD+Ab9W)vCyT1gmm(#AQfR&um_3gARhK#PQP!a(aEHi&ilb{=J$R3=J(#b_x9~> zyp`U3l9aRk{THvCBr>u3YNwTsBYFk&06`$< zCCUQ#fLK9(1M1o!+p#4oW3{77r_vMa!Qg{GGy)H>_k` zM~M>4i57VR6?$Ca_Jl6afi9HzMj~9Z0{V@=#6q0%sZBn_D&Bgnw3DgJ*o#aZSjil9S$ws*RkWQ@ zo+cYFIiciWQAsGPF4X}f9qxZ`1)ix1WgOLBQ5Kkpbo{OG-L{gX!S1z7wHJGlHqmTi zq2on^MTT*Ad}ROhk=e7m=3Gu%MB#UbjsvlTLpT{3zip(&-f`4`XDWFab?ewpZ6569 zh=&J5+nJxLP9Y7mHd{>t&4>q20QqTvBN>b2c zD@ht3A3DNp9AtG!$;eh85Y=N~h$Q>1GO4I;J$6`@=c^#%Q{hJ}r*A|IVrT?#_2KH+ z{HwQweE_}!FI)Yg>z-S+d@foYuv8tet{h=O2u7Zp#VX&b+72j*{(C464KzxR82zh8cNzvTUQ z>Cb1$xVpT2>-Id6i{rdjHx{0?1<`YG4Vd7IO4I}ekN`&tQ5$T4C18TCkEjJ|AO&VX zSB4MNzzq-r-z1_}paQM{9UKtR4yb}8QT^S#toQilT1-y#I4WJ#3q9A(0&eLcE=i_n zps|GzIl}H*P;}7T@A0;83ccD?IrF%jt7M4w;73l$f;r+tIm(yhpqO*;pbl=1iMx<@ z9DWM93Ay3$8#yl8kb4d<=3?SER=H-ja# zFqUM(yoNW*zkGgU$K&nxStzq2FmPRcz;PueE<+{d{*-teUCfoVuXmjzFK)w z!fT=nC_P*x3#Ks99;G|G9f|QseyUN!_2+{pbtwU)Q~TT=&=%0icaH2eyJ_!K5^z H$=~2F-(K|s diff --git a/datafusion-pg-catalog/pg_catalog_arrow_exports/pg_collation.feather b/datafusion-pg-catalog/pg_catalog_arrow_exports/pg_collation.feather index bfd5b372956b56c1d924c6ce4bf9486dbe5885a4..3ccbda6ca7a09bf86996c44edb290a52fc7c0f4f 100644 GIT binary patch delta 973 zcmezMg7MXBMn1=&ApdYf28RDY(7`;B&xrR069dBnAXWh4Et4M>dNVGVtXrhdcwusE zkv8j}fB*kqnOG=3S%6W1N#pzsY*VdV&{# zl0P8AtO7t`mC207!jl_{d1P4_K#+mq6-1Uv1jr5mVh$jdn7pu9JdhE{0;zZaQ~}Zp zVlxAAer5^-50EZM*8?)+6LT^Xi-BB*8%Wj%0qq3}flUnoGC-!vOm<|F4uF~J15`nb zsV)$c7!`mf2r!6%O=1VzF975-Fia{@t7ikdje$XkK>|fy1SkRqV0T0SnILz7bb$cO zFCZ6z{KEkxS%4%=4I%%6)N?SfGjM=300E=I=DSRr^OQ`0Y!x5|=?9rT17r~pC_w3g f?8(~-*wRK+F!rV8EyVqBc)u-kc|70c2?a hF-Qy0mkbY>CPx)XO)e;s7-GIRC&~9efUydRZvfJlmbCx? diff --git a/datafusion-pg-catalog/pg_catalog_arrow_exports/pg_constraint.feather b/datafusion-pg-catalog/pg_catalog_arrow_exports/pg_constraint.feather index 5572bd9a75022b5057962569112063af467bd8b4..e66024a68314712bc0a5f51e849b84944817b7cf 100644 GIT binary patch delta 1870 zcmeHIJxmlq6n-%rk!I$2RGzh#(5=;Z*~syVJd<6+ zOe`aM5WEK8Eaa^!GHx{ZWx=;l`?2IABTV|rH%E{b9Cu-!X!N4W=Gbi#$VRcl&o4k2!)66 z2zt@{qxD@I>k=~3XkAR0V%CF>tRLD=;7dx@Y8&fhvy;{z#er+Bb1fhvjn?6WDc1U( zi)Nt8czPMWZ(dgWKvP@_19b?r#wXzre+pI3#BJ&Ox`WZyi7f)?+r7vq=7s5&iaBJY zQ8Ak^36E#gAR9(6kE!e{D_(`DkKCBsj$cL(^JTP8 LgfW{a`Gx)lMDf9M delta 963 zcmeH`J4?e*6vuDU-1Gs4D76G1wS!bh-y-6oAaoEc_&{(G@zp^QTcJaB5JwRO%UL=& z_yI(OIylsCAjP3LId&)_ir^w9jsKXzeg(k`zr)Gzo_mwr!#&PEFDsMt^D~Pn#w?5? zFDb*ipEFjM7%PKqFa|uJ?qcj5Y=9{E5KCKY;@MZJrVG{5XM(?cS=Iu*M}ssic)4a+ z)*+q-eEIBdF3%WC8}u60#k@gRLRc&t^eBwV4=B4g=pd%c%(N^6ld-V!0gDxaijXv^ zmJHB|sLCs-STae8>+%`W6O$(5VY!O*)})pgmYYZ$CbkIBb<{%{mq&SmvbPE$Xe~_j z(?G(jsI6a}v2}p_lB%TJ^r54h2~{b!=^IBkB(>wRO*bjUBfJmCsL?7P;#0`dbjl;+ zMPvnl58(C>X#nT>Gu(*lxt+pZKFcmpbMDlMc3lWaWb)pQvSS6?)ai}~=`H1UNtm6J zd#DoYbfX_Ex4A)<++ES!vx8kD5QD&ekpPZ3?MHg39P$4**gldF!XIt0?*cc}xwqeb ChFZV? diff --git a/datafusion-pg-catalog/pg_catalog_arrow_exports/pg_conversion.feather b/datafusion-pg-catalog/pg_catalog_arrow_exports/pg_conversion.feather index 7118783f6971cd938debb9ecc22f805a13541064..329c82acc0c619bf81b67aaae7b54cb6b79e59e4 100644 GIT binary patch delta 1689 zcmeIz-)~D{7{Kx8oK|~gUDr-G)s`J4LK6$FcHzc_#Dzq&2<~K=S{kfNNhCyi>$Z+R z!G(Kw;$nY*_-%g86hj$P3}fv0KBsL`iv;(3lFxhIbKYOiIp^)^<-T*7@Q#6jJ^Qzc zxJ1n?hqrCsZHibpYlx&!5s?e%hac+~T$e*2LSdJWB};xTYeP@H!HiMQ!h+T{f*2}{ zj1~(+!kk`zi~icKW3|1Q8}`~m)JKQ=3i(3^2ao0lk8>*i`rL+1{YqmUF9DJAd|UZy zEWEv?$LvCRCQ~}ma%HA5rZu-Xb7^Rv_oaG{#%C_ zSG@4v#sR82T!(2i??zM7JF+PKl+8YWyJPKdk&M-?v+=}i3Jp?r=L{!crp;=|$(RYF z-`Q#Q8c`=_PAAUjdc>Hn*%D)+OQ(F}?asweXX!9~+{tTXdL1`#6Sr_1cW@WuxQF|A zfQNX52|UImo}hxKc!uYg!VA2_D^&3sZ!nFwC5m^L!F$y30Uz-Rv-pfJ_=-7v!*|T% z2Yy1LJQbMm!H;DKAh`G#mo4rFi>qzXBkUV0?FgX*VRRybD7vr$F?3s!t!?U|wi0oy zLIO#ouo`R73ma>Z#=59Dl~}f5irE$I|!1W;evydG&vzU($^mX8-^I delta 1966 zcmdVb?Q2_A9KiA4IrrwFZI&iY(xgqgc2OpTttM$#b9)3^OtZjir*Cwt?P4$rF8)aQT zFLl#;R)xJIH?=rncWSp*0zu#FH-#4|TZ1}2Xx7K)lc2ci?-CEWkH31lao$E<435RZ zA=-N2s`nwJddN6q&8;n`5!d3k5=N)mW9>4!RhxC#xSWV;nvh1;HI8NbRHO^5mul4P z`iDo&?^~>hD_ph5VlPY_o3Iso@F2!8g&EA@6wcraEZ|36!c`cncczPD0vYVa19%+c zcnZ&B7H{ITlB%4g@Fl*(5`Mu|m|CO_x1b+8aR84Xj|yh+GTy-3_z0h40YBg(e#JF7 zSPUPc*oYMFHmV}`QW(Nx$fJbk@FHHpNzCJ8e1-)qVHqoM^6&)_M-tm{01x93N|?bM zPT@VA!#7x}l3m6%GxxD5l?g<<3{g=3h-NxX|s@il(JGOokp6zRZ5q_GWqF^oK( z!EwBU^Qc}V`#Y^w%=mqgksUMkid>QLVj(k?Ef=#Bg&hCQq5_gEl!_j4w#z()>B3|x zy(JY9BP0`4G6MrqNs%99EaFUvxm#3JltYXj86dt_6!BK^ZkNqECdRy|Ui)X+FMXUZ zBHlZsDJD%*GE4PvC6~=j-XqTIVmX=LIhgdz$TG)7vTf zRc*g-YzZ;ZA85@ZyjFF;aHD*zJpII2DwFKns;x^c8>%H1B9qy2Cll$a52b!hBfL5_ zdvO0|q{;;Un~RyPqRtxPug|AT933)vw3vT%bc|(Po1_Zys++hzsdI-2Rf>3R(&~ fkOT_g1ojt3zrf_ zf1qWXpoI$yf}j>5ZTbN^oj0Rl(4rsUgLCJ+_wJl`?&HohB8`|gnNF{+PY{_H*Gkzt zIp$G_?qwna2mr4VQ57fwOMnX07*VC1Ta=7u`6|KA$}c*rayOfGd^Aln#aCF|skKbA z)a1`>IJ#ZP=d&lfL61EQbxEznX;|NSx7-7TCwMt20E=tk(kvw2@N->b}pHh}> zB^HK)k2FikWfkqioQR*x(Nm{ogQ%YZzY;X8Si>@s0To8XYhrY6P*@VTs3Izeog7hG zC+DwQ7Wpc3DVXV=h(Z#VXw1#oz?yQ{&d!$ O=$LkA)zM4#Pw5*kCpp3Tc&qDI^%Mv@o78rm?hl;0@o*&cN{4cD6mPmkNcojTxdC@oq(_DAxH>FUVRqj;q|!xx^jlw#(WYb9YL`;&x?^ z=oP&ddM3qNuCJOXiAV%U8LqoIng5F8Reo|qc?3FSWkOW}VL${(*L-e;vV~5QA3;9O zG%V~eu>x9*`PohJoAG4@Wtj)PoWBpkrU;NO`fNqDG;ey+ocwxgfY~?`wnGk|dLvVo z!A1shpkBZTDjn=nl7^rG=qE&QbML$)y*X4_s5cIWh`6ps`9b;r*24L}TL`;`VO;b;@5JkTegH5tRRzyLOf)hmI2y}FjP^6S$69}?|Fp4Qsq|6C87k46WW=WHZ zhAw0M@yuxU|Jhx8GMhaVqO@%hP1*JKAU1p`pwOV$UGCnR&3nBf&i#@0%s_f&Tu;E%EH*0uYd)IwQjFR92>VfbjuIt!RhNlk-=OfKVIO$G9ul!CspyKBGb3)S}dP%zFjs7C;;%jWv4Czb) v`srlOnr~_~rwf_n9cKM?$2n8;_u*fY`5Tkryq%fP_EBmg8NfS6_CLSfxK5J5%- xpnw2_2m=R@W@q35^FRuL0IWd;$Y7bQ$S6L!fKg;}2crkI&E(=>WMF`}8~`zvCkp@o diff --git a/datafusion-pg-catalog/pg_catalog_arrow_exports/pg_default_acl.feather b/datafusion-pg-catalog/pg_catalog_arrow_exports/pg_default_acl.feather index adaf3988faa1e5299a3c888dc3d6d911bc08260f..270fca5ca32f8c1a74a0a0f3380f51da2cd0b5b7 100644 GIT binary patch literal 1118 zcmeH{!AiqG5QhKMw2cxqNDe*pP^4$UM<{p~il8@%ZInth!S*6}^z1YF5I%r+{q)a9|N;Obl2^JE?_`*vV<8~DD(k7DL`97g1 zJ}bR}h1oZ(aU0{KZFE^)7mJD)`<1**x#JC;A#3@=+9^3PYO;%lwe{8Q=CLX9V}GQ> zz}L%(ouO8x@tW+TVcmUkSFW34QHqisckKMZ-Xd17mR?13bA)+WRI6f5Sb4yYCfF}u zxGwOGYlNEESp}|#x}w02=lPdBiT1!7Iwnxjgh4t0-&nd6%89u6e!Ch%-=uCI#vOW= zve(c#%dzw9a%}$lUK3XRtRdVF(!D<^JsXgf;u(ga+IgGZ^~<9F_vLTimnr{|ng3Tl E0qlsC{{R30 literal 734 zcmeH_Jx;?w5QU$K^8+%%MamQ|asebRkP{%K2_+_Wq(n{}ku$&GEFa*{43Fx4^kF{leoo><$FZ zuH4p#eYvc44!KFe*=NLy|I2C&yw|qjqK}A^YwYz7y#smIANk#}Mh}g4U6GrCp>qf& m1xuI-GzXrUyQ)=YTGr#=`Yrdr-+$|O#XFw)yZ!+Vg>csZ diff --git a/datafusion-pg-catalog/pg_catalog_arrow_exports/pg_depend.feather b/datafusion-pg-catalog/pg_catalog_arrow_exports/pg_depend.feather index 72f9f1a7b68a51d8658dacb985a583bc60d24c1c..3ded85996632d2ab956fde744c30c3b5a6ac13e0 100644 GIT binary patch delta 973 zcmZ29fpO9lMn1=&ApdYf28RDYu!CtLpOLHp69YpJBLhPS5Z_>6V8{Vt6Ch>*;tLaF zwVD3>o48MG;sOChhJXM60|glsfJ7aH%_IV32LLe#5KBxvD;@|m1+29Is6YV9W(Lyv znJElBK)N7Z56Fy9%*jkF267oPkPLl>&Ctn=jN(QxQ*RJy>VloE0SGdb4iU55I zw1-gvNKAsT!LAMg@cVS~5+p;M%{)N0Xf|&?%UJCqWC1in1BgLU h2QvNy)8r^OsmTRy5~Hy^FtHp)%~*Z_%&Cz43jm&xvIGDC delta 467 zcmbOlgYMn1=&ApdYf28RDYaDZ_lpOI_?BLjm75Z_^7U|0ggIY4Xz#4JF3W%5FI zZ6=2Qlh3)U34HnY|36TSQ2|Jp0JTqEz$h{C4v&BakPQ@KQ~(kg5OI;oEgk{_F-Q_~ zAQCD@6OaTiK-f$IK%Ejm46+ggSb;b{DJwGtNFVq=`Iv{AxB`#~lV%69lXDV_i!)Ou ruV)h7e1fUMMG53&6{sShZx}9s2qe10X>yvo+|c(e*9)M>Ah8GlsuF&* diff --git a/datafusion-pg-catalog/pg_catalog_arrow_exports/pg_description.feather b/datafusion-pg-catalog/pg_catalog_arrow_exports/pg_description.feather index 6e0c91eedf7b02fa3459b02afa99d948b27ef4d5..2fb3fa96d293c3004f0b43e00fa9e8df0ec9da7b 100644 GIT binary patch delta 670 zcmaF$k)`Vk3$J5Pkbk%#1H*qH*f5dTSdfE}fuVtcfx!caS%CP$#6bOtFJvb6$kYn} z)c{2p6@Ww^gv}%ZWJdro2M|jDF$jRz$vKI|#rc^jAU@DUuu%;_JpxcRGmr*J^8o3B zbUh$5J~1aVu^7k&>gNMucCa}>E~5gFU|c0>%24Uz>p z2n5)GI6o;1>;#YlKo)TTNfsapQb(Lacz|kQ4q<0tQ~+vZXx3%iuFJ^SY$j*{6;M_l^= delta 293 zcmeDB!t&}P3$J5Pkbk%#1H*qHP?*STEVzS#fuR71Er6H>h%+Vz>a)xM%1*yw!KfnJ z17rb385MxU83>z60LYdBVwUN$mW<+@2VhF3AGBbUX9cNbnZD4HQCN_Jfro*EfgOm! zfKj1&FXQ&TjEv1@f+j!_6_83GW&~n`>46rE($fnp7)5C5BsmNx0qynxIsg(b03%OC AKmY&$ diff --git a/datafusion-pg-catalog/pg_catalog_arrow_exports/pg_enum.feather b/datafusion-pg-catalog/pg_catalog_arrow_exports/pg_enum.feather index 0844d53a1715b4743cedfa7389c57bab9deae486..365496a9d0792b17b7dcc3703d979cb269384518 100644 GIT binary patch literal 910 zcmeH`Jx;?w5QX0oCoyP27IHyB;er~8Bc!84N&_7-iiIK>966z&Pt9340Egg4@Xf4I zghW9{!$>nbKbiMtXPw!6esz5zeITzvDr9n?sENkP@sN-aizvrtgEdcz^lUjVy&}DX zgF7~yYRGYDA8j6=9@_e@X+58Lf1%Rxrp{0d{2E#Rng0%h9HQ30?)pvFFPfhDa&+R= zpqIqER}$Z#HtC7icHEoi)p9|Ok)3->kMY<&MrcRX?zy@@$GxrFWxXZ@>j<4XCSj;B z(lPkP@-=x$#^u`#X`efM<4(Jb@TQIaZie{74C&pB)i5Hvw5>!UR0O)9$0EvbgloUvTpb!f7U>r(Hc7i)6RIGrdb8P?F zIlq3j*{rt<;7tn-$RHabMT`MFBbtktgPEs~IOKeIX=ZA^%Nsp_Vx^P;96PsDcW@M`;d>YEbMBK!WQxt$L=^JmL* zfpLb3X-{mMtlJeoGy3FK?Dph&B-X={3v?W({j4|TJgG{V>3*a_S`>fvsQSM*V9vL- HvbXjDH`PsX diff --git a/datafusion-pg-catalog/pg_catalog_arrow_exports/pg_event_trigger.feather b/datafusion-pg-catalog/pg_catalog_arrow_exports/pg_event_trigger.feather index 7ac630b035418fc2db07fc231df78a025c72d421..f809a78519fda147a84917f00ee5af46c6ac42df 100644 GIT binary patch literal 1294 zcmeH{F;2r!42GSOwh_t@p$;7wGBY4?11d2hfx5tkg8HZ`l{BJJSvUa4VdMl%42&H( z3*q};@+OuJjCJK#`^EO}-?1{8POomx%o?QXnPnz9wA2RHw*(7`Vtm6(IOFa#8{&ON zX0PZ4y2Y>1b997eoC$S?K0E7bM}1+8(HNDej@#6AF<;yFPt$Bsu6*1vMu<}{#JRG# zU%DCn(DO$d+Y{a;st#pKy1Eam#ms2W*Lf#i_^Nq;>Y2Dz^Ha>bV!0^Rxc1i8jdJW0 zaQO2W*BHW3{}S2sw0bVxll*{_ld}uXxUC)KlfxLo?;N@ z`*&{L9LnO+kvH(UW=C*P<&Zt%#*629i>asLAPKV)zjhZ=>a-iN3(thC1T57=qMSnl oWzE*(q`bKS5h9O9e>7|V`MdL1p3G*CPdCzm*gL6^#g%gP)sv?pT*g|gJUMH#G+^~WPY!;m zKfnvP1J|G+dvpe|yJ)pt&-NIC3|N>>*wuBpeA9??3<0kqZ$y!Jb{2S{D(CC4kf!kN z8}7v!&FAfEq1%Sz#`M=6eplNjLwoyPg;z?gJ3XIGeR7_*C+tF1Th9-??=#$X#;V)| z=CLRFWAmH4$sfg8x@WuOtIgrzdDylu;l?DkGq0kzIezyetB8u`oavZ)^3b^d_o(Pg P^5iev;}`$XB>sy>-yw&Y diff --git a/datafusion-pg-catalog/pg_catalog_arrow_exports/pg_extension.feather b/datafusion-pg-catalog/pg_catalog_arrow_exports/pg_extension.feather index 0801e5d54deb4338d20e66aa738230ea12bf73c3..f7c8f6845bb3d45221681374611ee36687966086 100644 GIT binary patch literal 2370 zcmeHJzi-n}5Wcjj8^A&l$`Anp3w2#)eDAC`%u|dwVXFS7KMi;_ zkc%+^wFD1r<@7FQkY_@OQBj!OSaZm7UC(HjNeyDGG&OUup^oRs7$q}Ugmd@U?q8-i zOi0R$;9b6L>zhVz8QnJO#AT0HxWcH*u76k2yX-Uap`v%$>p3$0b)zRn+eVw#2)FN) z8v`4c-M&|`FZbI*>bX_I{LpXO{VTo4sZzh^^*ayR+naA87Tx<^AgIljm>yz5EyrKM z8Ph{7rulR@f0YOQFXHPf)Z8&qX7@e+71xn^y%ry0q3Yk%#Ve)YjQK$kbcvtOF(}AC+>n9cKM?$2oXBUyJAsjbApnRafcVZtUwfu2|0ecXu?YYb@cf^6 zPEF7T$g%)p1_lN;0U)6;xt3j?CkH5!0TE@I{D4h-vOgoQYzjnxQ30rI0aOyCMFxmj zCa+}_=bM3~;tJ4svB?WK_?TIMvVR$+^qAm^ff_)78Hn>UQy4fHcz~E4h{1qS0Yq)y q%e0$W&;rQP0Ady(26};kV{#{(^yCF>5`)QS<|O${fr)_u5>WtboOBTY diff --git a/datafusion-pg-catalog/pg_catalog_arrow_exports/pg_foreign_data_wrapper.feather b/datafusion-pg-catalog/pg_catalog_arrow_exports/pg_foreign_data_wrapper.feather index 22d7d31001a906f95a0c102cf67b27126c6b4f37..27c292c346d35a247c9e63f4ae22da5d006384d6 100644 GIT binary patch literal 1426 zcmeHHF;2rk5FCfZSjdHiTu@N>1xP$05(OPrgao2Nr#OHmV@D7XN-EyN6DTPtc>o0k zH4gx0*0!)n5lV_|ber3|-JQMJm4~Cz!O<@8MS17}5hNQ3;bVY+JBrt*4O#(pztO-t zt%xzt9*}aq(VlVbnHTWFoD3c)=XP_(Kg)TR&8z7wugYuSiGC4c=JlCVNKsSAVyw?w z#=3E#O7sKnKZS!{Om)bmDupLeHu~SVBG25cy3!d-wYWRRsW#%F#u29Yo0mfQ!AXtB z24xz(*Wmb4s;7oi2z znx@ugSs&yd5KI0PFQMX7)O*7SIYT~gLt4r&CNu}yD|aiaIbO~2f1Be+en*G)E&c`p Cdd#T+ literal 946 zcmeH`F;2rk5JkU(<3z}X3kr%9J_1M-X(Q1irJ!7uR~e}@zB*f?iHj#uDZ`+dLJHGQ`wL0zR2cndhKQ#H&Hv8QB=&#b_~y4zNo zgS!YlG_oEweyB4R>K~x2z3@~vzmRI;C`6x&ULT%G%)SJbnbq|%=Xx+O#{<4)gYcNo$-j8zVXzS_#|LRWi<<}(LCN`311Pas=#RK d7>}_Zbh6t2dkva}Zz$FIFWu`K|JWk@t6xxwjW+-Q diff --git a/datafusion-pg-catalog/pg_catalog_arrow_exports/pg_foreign_server.feather b/datafusion-pg-catalog/pg_catalog_arrow_exports/pg_foreign_server.feather index c04a3c3393ddcf4e60de0bbc5cb317a04398bf23..47a44ac3d6bd6661c6a7bc3cf778f9b6680eb778 100644 GIT binary patch literal 1378 zcmeHHu}Z^G6g{bJ8YDxI3=R(Y0zq(a?dBj@x+pFhY?MGvLlRot{0s*NM+Zkg!qLGG zaP$krNj>Mi1cDWGa_TMj_1@&>+jH$F(?#Df2x@+d^Ym?x>M~C_w|>Cehh|47xdgg3G%;GvP}K?SW!x-`H|rm;0)n(C+{DzTWX$ IIxyeXFS~ZkJpcdz literal 1006 zcmeH`Jx;?w5QU$?u_NTd1qB5~u7E^AL6Z|8rJ*IlMv4?{%eE5eI0j`7z)>hU03`)y zz^R)BD;^Oi|8nD+$%4K$-Oo=9%vcjU6z1U3|<8idTbjO`D zT=+B74!^=r@fd#~E`{PCSc6?&ui*#gCBXd> zb5ph*L8WtWxeno(D0LO&V||`am?QN$`unC-&%MUw(4O%QaU++TVk;FM6V1Tv0({8H zdSrEOtFmRO$KZ~yLqB>ma;cWLB|Wsybg?@0tq#vG%(oAwUKL<7JauA#>LqQ_NzS)|T_j{&g39aytG=-QRhebN9|a0g7;-od5s; diff --git a/datafusion-pg-catalog/pg_catalog_arrow_exports/pg_foreign_table.feather b/datafusion-pg-catalog/pg_catalog_arrow_exports/pg_foreign_table.feather index 30e9080f7998e62e712353a3e664e5e5dc994685..14fb3ecf45fd20613cb7f5c86a93388d38d65330 100644 GIT binary patch literal 798 zcmeH`v2MaZ5JcC(U=y8?6}h0G;0uuW1UkA%G@*zTA;m_P5JtvAloZr_TmC3{vnEZd zH0iR|tai_LGjn&k#cK8ZGB^7q&XHMWibo4Ju)d{KL=@8-T}qDc*{nzR0hS;K898NL z;aYAL5>U2Hu|q@p-I)Zm tyOa5ykHGAoKDzUlhByL>17-y}X=ry7AMf_*L!|%v_?!Eb>Rb~QYA!D8}%JLi3ji?HaI)&!V_?GjxTl3 zc9gnlPUi#gp}hfk0@$KNjtq_w%~*1fIeI&LU`_TQj>L}e^p5`(n(b#TlZj?USVC+= zw6VX(uD^|ptuElj9!OV`zt?j*npAD$7=|ef!k;P6RE$$i{M1Yu@_ngUFmB@zuHA)t oB~hp@k4;4<^K;XlOU{vNme)x{Mf#CDSo9?KpYOvNpw_qX1@oOY_5c6? diff --git a/datafusion-pg-catalog/pg_catalog_arrow_exports/pg_index.feather b/datafusion-pg-catalog/pg_catalog_arrow_exports/pg_index.feather index a4f658541a2bced500ba2ec1147e9ec409520ea0..b0ce727dd2648dd33a148ec4aac2f66aa8f54b0d 100644 GIT binary patch delta 875 zcmeHGPfG$(5TDt%i(0y^vg8s{>y{`9E!IWoV&@Xept_Zyl(1CPrGp?|g8~`4^#LM+ zh|WPlhYo!JKR_R$Q&2YV*{M?pk3E=~-~5=r4DWRLx@<00tCh_HK%bvubj|rlpaZ-K zfEy~LZ#DaqOmCblw6&6ivl!4C`glnl%;Gb3Js;oc$;+clHO-~i^eC>-gEmPOEsibb z@_0pOnvXqZeGF4aBFlV}Z?#daC0NL)CG>!3f*te!X#W)S$L*l;sSvSD3ZVTE_lumMF*m pn&tjNUr!~9Tq4IJSCi#)27R~_WTl<|s}1LB8^gR>$p9GquWurYsI341 delta 533 zcmZ4G+vUyY7!>3mZpgs!9|$^FCh{3^%CImnTw!Klm^0CHJ=2;$6Mt#3-}v+YKLZ29 zWPc@z$@`Uf8CfO=GU_v$Om1XUXNvhdxsOSH@<~R1rk=l(?i=Dn|zx|kZ}Q6tN|!?0W4%<8-$Kz9P2!YBYFW&lORCnqSePwrRcAPiWQ0tBLSSK#sUSmHCU+@HOwHc>N diff --git a/datafusion-pg-catalog/pg_catalog_arrow_exports/pg_inherits.feather b/datafusion-pg-catalog/pg_catalog_arrow_exports/pg_inherits.feather index d6649cbc629733a5033876f264526ebfb5f625a0..b5f95f87fedca7b76794e8226a74c1c33bed25a3 100644 GIT binary patch literal 930 zcmeH`F;2rk5JktqI03Ctgj`Tiq@+UP2sr^L4Rm0|tHe^YF-b}eK*f1DLT&}`j~$70 zloX6L>p#1*fBw$e)7k9)@y_fE`^?P7COfxag`L_6gk?Fg5seu0eiR~~J@339e8p@J z53mr=O+UxWd7HGX#%`%u02oL(qIP9Hom5{;?UL0 zCg6__4@&S8uG}kJc80UBtu`_3z{qy}Z|qSGo#g~yH?=Eh7q`IYYSmO*rs2B4ht5fu zO&H8B;a8P|>XI2Z*YE=TsiD`ti7Sd=($MuaP`~T$@3aK6kF{_N_1*gx=w(4hAQHb$ ZrydIHoCo{A&*L8crTg6TaZLT+{08(KZ4&?h literal 654 zcmeHFIS#@=44j}44y8yzNkKtD2|We804WVE5m`Ybw44P`;0Zj2f(P&?m~nyx1wX(m zdp%xzEL%HG)7g9kJSoEfNFZq=Mua+=^e90{45B7&SXp_%oqDEDsKN{K@QTDUsA9Z~ zxA5!SowDV6=X_rHmExft;9AzzRM)k*Ueyy|-O=s+R`^op1wHzYA2lt$v1XSYoIlaO zebglA7-z#KN~(Ebef!MS43etv!EK7X#4%$HixUSu8VRX2ukpm>j+hY>XC-PHc!3kjE66951J diff --git a/datafusion-pg-catalog/pg_catalog_arrow_exports/pg_init_privs.feather b/datafusion-pg-catalog/pg_catalog_arrow_exports/pg_init_privs.feather index f17a2291bf975551d7c6c19dab0d2d2fa854d694..2768d3c25637dad6758c273733798297441a2a79 100644 GIT binary patch delta 605 zcmeyQI7x-qF(}AC+>n9cKM*{a$ZITW!N|a{fq{Xc0*Fn3m<5QJOuoyn&3IvAqyFRt z0y2{;1Oz6Y;ZYO-Y5__zDgcQ-2%AX+$c_MF4j`78Tq_`+3p5UFMgvfV0F=!Pr1LXV z7~U;wr;2FL{2 zC^Gq=fUqyfMv%!IK#~PWf@FxZnFpvA&F0OqjM{vH7C<93fEW}QAmcwwp2;sgc>}-1 S&=0OKY6cev69WSzMF9YO4_x^G delta 321 zcmbQF@=1}`F(}AC+>n9cKM({=7T_mKi{G zlOG7E2=o9MKq*EAAaMpFC?T4hlUQ7wpP2#_V>kd)FmbKCCP)>?BoJT&;{2p6urdw? z9tI8ub|3}=Mup998MXNYK^Ch3F-Qv|5GPF56p)_mAs|8<=b0%$?E+Hxod=Y!06GW~ FY5;QkPH+GK diff --git a/datafusion-pg-catalog/pg_catalog_arrow_exports/pg_language.feather b/datafusion-pg-catalog/pg_catalog_arrow_exports/pg_language.feather index b1a124b9871c941e681fa0f7d66c7bf31e357bce..42b45a2407b3a347bc427b2a0554f4cd2b97f133 100644 GIT binary patch literal 2754 zcmeHJPiqrF6o1=p(^XapS|mshs}z(9qM+cxLuwVgh@l7;FLp^|8<=j^B>p)D@!+8+ zPkxLXJ&7mnNAT!J@C)er`_0Tt*CmwPyyS&9JMYiD-7AC}EZY1s#Sl!HYvkvBplVHs(I1Lv&NU-)} z38%WJGq3|EH|^Az7tHz?>u^S__a&^mI8%hEF~LOt?cm>glXd<%mloE{Qm=m8}|j@aIrl4F)0bdX=o z<|uLwXUJ@{^H!j-Wb@v}lvd_M(q7^Dx_*xl$94TIc}G|k0gEv~L4pBWDemBYu!l)8 zGIBR7wivP)+MfPIP){*5b&KqL_F>~*8AH#6u6h<4o4P7p@rtVzgUZ*up0yyYyN7)6 zPkpGo<`rW#RAjv~M-{uuYX4cWt9;4pqf$MnQd#XcDt481zuVrfc)6E#eYxHq(%$oO zeX0Lnvf^rQhL;~TcAD=Xj@X)fRh$JsxQ&6NJ>dNyj;M~ne0_1vdGLf(@cs}--E7$D zXQ^oqUYgwGdw5LTCwIjA6MvK6hEQ7W8{u8`SiB#^5p%HbOg>9`=2VT#kQdZd^$iJp2Ooj&tM`;VEl#D5%;%!b$6AjE-fK!cpBUAzq0})XyD3!V7W8Xi ro+Gh#_;LX?@h%{h`)~eToqt#LT|WP=id6rnP5Z9C#eLea|6TtA#)d?A delta 593 zcmX>k+9b&57!>3mZpgs!9|#PXCh{3co?v8P=m6pXAXWk54-5*wRK+F!rV8EyVqBh4e|7I4l0J1cIm<5P|fx+Ow aG&zf1YH|a+#PAI$bCLoof{B3vl8OL74U(4t diff --git a/datafusion-pg-catalog/pg_catalog_arrow_exports/pg_largeobject.feather b/datafusion-pg-catalog/pg_catalog_arrow_exports/pg_largeobject.feather index 1c90d180947768579e98e10997e1a996d2e772e8..0f7b9713a051ba0f98f0b558743107cc33c464df 100644 GIT binary patch literal 674 zcmeHFK?=e^44i6hixer+g9i_Nf#A(+!Gkx!ix)u_lu{_Rpil8>{zqrh^-%B$29lkm z$z+plc{uEkYv4`U1V9GK6e%K1kPuOVkUr=ow4t}anBJ4RwJ7i+hoCr?KE{I;z{NdW zk3;h_OZ5#R>yEq&;WBR22434CZn9kiK<%*OT^o> z^+lND`ngiZ`{~qQIhsvrn!Br3glE^(?oOAPDRp=c?N8rSpR!wIS((*~QTq_rcP>KT P@xRYs``qzyO8YlIG*vTw literal 498 zcmdr}u?+$-47@)$3b}{Hli{fOV=<^ eQZpLAre-iyGF7oPw|4#M3HuLwzqv4ci4~iOCw~EV7!#L|71#8(EAGAKt7=b_FBQ1_?fPt)1DDp7dv%O}W+)Zr5K=H$puIo~ww5ewy_AtzkO5^AT+&D3X4TT!pi_*^<^0 a{XVf`n!wbVZkzq9-MIhw4sueR{=x@~8Ze9i diff --git a/datafusion-pg-catalog/pg_catalog_arrow_exports/pg_namespace.feather b/datafusion-pg-catalog/pg_catalog_arrow_exports/pg_namespace.feather index 302d58c22c2bae3a6121d81e7413a3750c2c1ba4..8e9915db67c4f65b6d6767e7093bc555f1a3ff20 100644 GIT binary patch literal 1610 zcmeHI!DZb3F(B+;!1o{SkY!Br=ic&l1d3-&X<2ziK;C&aadw7XXmNAJTM-W1_ zkMF>Bc32iw-5aLW+U}d@MqWK#+ck0#jt+5x1Ds&rR%z_s%oQ;U61?R2a1_gImr*0; zj{6U}0>wn0 A*8l(j delta 239 zcmX@bvx|$@F(}AC+>n9cKM*KP);V1W1$0JeHRcmMzZ diff --git a/datafusion-pg-catalog/pg_catalog_arrow_exports/pg_opclass.feather b/datafusion-pg-catalog/pg_catalog_arrow_exports/pg_opclass.feather index 3784878dae097678be8afb2e2029e5a529aadfbf..3d8500afd965e574770a21caade66df07760d57d 100644 GIT binary patch delta 1465 zcmeyQGs&3GF(}AC+>n9cKM)*Xp2%lpDZ|XbFolVMAq9w^FfuSy05J~`FJNF`C;(y> zAeQ?3|38po5&;qcK+FNe5|bB-h}!}cf>j6rRR}=YKm!@_GgBCNfOJ8+9*`NIn3I`U z4CFF!Kuls(0J04x&QzCF`S<_-I;_Ssii+36j9)^e@pF)j7Xz9Mv<21CKmico1mgUH zNTxnRGBpHf z3nc zaxm}#ox~1y7SJF@1t7t|AjBX67GVcRz5s&=Py`H6Yy_DP0756NQ8UvEVD5mF)&RMn4h{eS delta 621 zcmbPa{7Hw;F(}AC+>n9cKM)u&P2@AuIl;)l&;Y~%Kr8~pcNiELmH=@M5ZeGT3yA&i z|9>FGGo;O05Lld Qg8`!gkcwbpV1T4B0M1C5qyPW_ diff --git a/datafusion-pg-catalog/pg_catalog_arrow_exports/pg_operator.feather b/datafusion-pg-catalog/pg_catalog_arrow_exports/pg_operator.feather index b41a920eba6a91a40e5c141b15688ec680e29882..00886e5b9771c7910da3a69534c9d7541731cafb 100644 GIT binary patch delta 7257 zcmeI%3sh8f9>DS69q!;@gENTA2q+_+^pT`jpQ~%t=UK_4+ht~Dj1)Tu znWLL$q$CX=k(M%IJcr`0%3O03UwEs6jKaJ?k2mYQpJ)AxIloXXXUmmeZNkWmq~se- zxb)Lb8j=-ysDhcTz!AMS^XP*WE|20AMoaS`8IQ{td{F)5{$_{!CF&e zo==$O-niLkyVliEnX|3$Uln@y-s1tPB5bxnRiSt9J)YsS@l$KP9)>Hz5tCz=X#+_= z2!k;M33vo;xUel$?{>fk@{F)Om6C$pAFC8sXpYkY%C_!fV~W&91_;|E;9WcpC*)i} zSco|=FcQ_w&bjlbfI)tr6V4_qKq2O!9OrP}!iN_u#(hnLJ?DrXAm4*Hgv0orb3fn; zuHr{rgD}(@y3@@)&=Ya!g*WgfHsLU`$mc6ANg+H=nWs3noNHI$6|BS}D;-fpWHFXt zDdu1v=HdhV9%m`Mj0}$A7>?rv7Vz0V!jl+JVcD39QjYWaY&Hr|h>tmU8hz0Z@tEl2 z5t&3}GIB5lQ}Gl$n1<@f(3Gq zS|m}%@CDG~PjMFIIFEC{2(`I3gv4*@W*ArW0l$69*~a5C+ha1T-hU z8+))9`>-Dea13QQj*~cnQXIw8+!CIRQ3rM5 zLVW~d0oN?X%UFm-D8f=K!*Z;^C(Mp+JPl&e9X-$!ap+Z(@gGU6k}v{~BL`FQXS|Jf zunpU>1zWKLJMk`d;XUlZYTSqBXpgpNhcw6h`9-q+kqEJ?zpj7U{@9CdMHPVkut1GOR!`mhd996w9!QyL~g>#yi-8t#I>PXoPS?AQFwy%)>4Qt*V86iT6W1 z`eOhd#vlwvE(HxCOhp>jV*`q*=qkL5)p!kSFqTTDBLkTjhb%Z846l=27~E)ta0H+> z0#OHb5d;_NBN+7%f(8ghD$+0(>Bzu1%%}DF6gC?LC`1zH_uvBu*M9}(udYji{MVgA8uQohPs2`~~&v!K%-G+rz^bQP#c|KAc zp`tllQlGT<)UoOk=&48gG`S~Nl@uj*w<=FvO&(;>RBU`6Dta5SlRdAo9DZT$E6sg@ z#u}O&#bEmr7)#Pl!jF5sNq?#Yz`i z=?|(PiE6;?Nvdc^Q?aIpP~nDDcz7t0FsfvWQyonH_Dpqc0Hs^aA+gZ4x+hxITTip7 z{%fj==JS@+*$hI>7UHq#js%uW9Al;ludFo#IADl>T?vaT9r-{^v z3P-Am6i%e^e{>>!=AB3`imLzLok*YmvlD4_wTZOh=0x&TO(a{i=uzgvU&-^rs@4`B z5%gZwyt3t}l}MlV)2YQ0rJf@3d_hr98U1}>j$5VFeB^X6PkHB@%G@SCQ6yH=>*i)` z$&Ie9zJ91Jk-4Zge((A|H~h}8@;86mq>s&C5P80s8#i3l&)Ro>mA^(;SX94w`^aVX u(4Al9`9b^6ukzRL1+}oKe`maVG)CH@_7O-)4r delta 17571 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 VFvvwl4)H&g$IUDrZ2GSx{{!cVJ@Wtn diff --git a/datafusion-pg-catalog/pg_catalog_arrow_exports/pg_opfamily.feather b/datafusion-pg-catalog/pg_catalog_arrow_exports/pg_opfamily.feather index 1e384542b78b35fcdcb1d3aa579dada7b27b3b37..b05cd6e69574835d1c061957d6cc1f9ac8c45830 100644 GIT binary patch delta 865 zcmaDQbxMxUF(}AC+>n9cKM;5@P2@AuT*1h|pa8@l7#J7|fS3h{>;C=!52TnxfJ6Wg za{#f#7Wv=PkE2Sgfr|oCcFo*y}zyQTUkoh103kaayCSVO5K#~P$0LZ6A zIAXFtqv+-g#tB?PCO{1;Kn#iukWV6*CUfyfP1fKM8I3PU!Wt~`#Z|z>zyQfr08|5% AQvd(} delta 407 zcmX>l_ezS-F(}AC+>n9cKM+JPPUJIE{lLJ$umXrHfY=6zS%BCCC<~;R1b~DLNNjQ- zuehuZM3hkhD3XDs0>o#Tcu`s)1xdjIAbYY6qlVxaB$W`e68XfLj{Ki2$Ec`>umNZW z2rvV2er5^-2LlffvjZ_0Fe-qk&7n+_xr8i$EDazAIg}BIGZ-iT;*pvxz$-DJelaJ> LFAYGKL*fDeFH};2 diff --git a/datafusion-pg-catalog/pg_catalog_arrow_exports/pg_parameter_acl.feather b/datafusion-pg-catalog/pg_catalog_arrow_exports/pg_parameter_acl.feather index 49dff9fc6b6bbdbea9c4de6a00dd8000802a7fba..9c1856f87e202cf8b878d56b2f3f4c96cf76c9f1 100644 GIT binary patch literal 674 zcmeHFy9&ZU5S-JzkQ6~uSXlT4f}L$TJ0S?#$)O^Fs6l_mztx#d(kT9cd(7VLv9q_c zNl}*T?E-kwmJY}u8zDu65D8B-7cd5+gg)pzFl6*3HbhQj^a**fWoKP27pmrz2nbn3 zH2&@nweGZfEIoa>MtkqBI5#MOsuQ^<(xNW1NF5d)Oo9|?fX_8LAjl-lyzEl z%27YkrX1;R&T}63zOMX(Av04Vwwesxj8608W^bgNLu6T*@l{d!RjZ$Ya{u%EJe{MQJl9zyUK4 z&fTS3@1;9?Z-7$bO$jou`tXk3VN1=vyhA@bG_W1ty{7H7+n^_aDru%v%y4FQuf5h6 b(Crg5CgrBUX4%bI3n7gExc|v5P5SR|J?k(b diff --git a/datafusion-pg-catalog/pg_catalog_arrow_exports/pg_partitioned_table.feather b/datafusion-pg-catalog/pg_catalog_arrow_exports/pg_partitioned_table.feather index 71e2338f4806c620a5a9b69382818032044acc13..ee1cba1f6b420edecaa9d97dd634185f0030e45c 100644 GIT binary patch literal 1330 zcmeH{u}T9$5QgXCC7yD^5mH!K96o>`SlR?E>!O97(ubke;++x2VoHMX7yH z(B(Uv<#|?4W>f4n{t-aknR}RL3*~;r@9K+h%3htjt|Kc;S4YT+&d$AmL!5d*+)sg| zjv0*~CnIcH;bIbE#8dGHV8*HXIDfi89c1|=Q#n@E9i-?l)jhlVGo>&EU3Gi>xFr*pgTpP!OH@unLQcPcj$ vq%6?V8@f4(nVlA=F_!YHV$F=x=1^fO*-D)ABI f&53mH+EI6X(CaiBT56JK~}Jcg+oFdehNyCLcvieDRUe6 z-mbUdM{s~lG|ueqn>Wwnu?OSv$?2il2R3b)WhUFU)MD#cLWD(a*2XH~+HS5|o4rM5 z&v=5bS-;>be2BO4cX%P_h_~PD@#pv!^Xj2oO()Z0a;?2%u$lGXjjihtS)<42?|~7g ztc#O>dzV-Cq&!#0T%CQ+0!|viE$3BH6WS}dBae;0YTEJGMX{WfbzR;Utk+(UI728F&$g`zAd;e^jL`UdG8ag6r`|Wq2Uan>W;rYiHAtbHhA(ZqIao>me@-Na?|ILCXH6r`^wK&v!Ln<($QSHXFMeJG)JzyBqzex6j*( uQZZZ%Z8=zwvQUnB_&JZziyW0WMY}cY!PL9^GxmS((qEtZ2jAz!ed}L;GNjW0 diff --git a/datafusion-pg-catalog/pg_catalog_arrow_exports/pg_proc.feather b/datafusion-pg-catalog/pg_catalog_arrow_exports/pg_proc.feather index 11fed4ba686f0b0f73d614c63b2ac5c132b0a356..73bfd882b3ce0f4b6836872bdac544fe1af81897 100644 GIT binary patch delta 3610 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 literal 498 zcmZ<^3i1y(WMKFY1P>S(7zBWrfq{#Ghk=cOm4O4u0s=-BAfExq;{cK@P?CXx8OW;v zVhgY+1H%HK89*iz$P5Xn7?5IM2jYUfyyAk)6ox4fHH->Cu?u+B7nCLe)gM7pFTfxI zwwoR78Ud(VA@<1t&0_CFL=AE=iDsEz|@JIK{Qz^DKufX0E`2-eF3G>;9eN&svk Y$OMo%Aiu)Q0;wGi{{8^;ha)(y0c!O=#Q*>R diff --git a/datafusion-pg-catalog/pg_catalog_arrow_exports/pg_publication_rel.feather b/datafusion-pg-catalog/pg_catalog_arrow_exports/pg_publication_rel.feather index cb0e864395d43d43e09c39efed05684bea59fe40..87acb33b539c1243f5862dae34fbe471ae6e813d 100644 GIT binary patch literal 1070 zcmeHHL2AP=5F90rV~Q!J_>e;menFr=XzqnVD71${acBtvLsTdEL0*to^$Gb+JF}7? zkREz2U9-|^wVu)L3e6Xbho@WMi-G}AL2`u>IYuaGQC!9~xGFeiaRm2)7YCd;d+HrE zqn?BXHxkw)`Z!@s^?keB^;>*0rb11uoPMEKkvsf1rAJtjoa+0JecQ>W511JT1~u(_ zs!k?b5_tOeZv6%x&*B^73-*w{4fn+AS2LQgZMSZ>Tw)S%T|@hL#_`DYC5PWH&o~ah zP(7JjZ(}{c`E+$4DlXB mo{|;K4Y@K7RZo2pUg{0a$ohXTREu!;{?@%H`7X@uo%jaHQ-(U15qlF2Hh;kDTVBt|LEG<2Px6p5Sm{1rK zdzZ|@TV`i}^5WTSG9O7#Z0bpo%sT2SP)i|SnCEjArx5Q~Ui_CH;0!V_20pl>MN-SO z`c;gV+91o5!y(`63MWzzt$?_xM^$Z?Hy~nKW&z0ZU6G^~vqw6WHPrZABVVVRm5z?% z4dLIu^0Q(I|5D?--mK?(Z?0aww|beTmSBFCsb-KDI_d0q4beZ{60aJ9B5cR(^xJQJxaH2Cjn};3jwojHHY|j^Q2a zT;e|10#|@7hv7XL^WQis@&SAV+u#%EgEaqoy`H3K7b5fUFJ&E{$=^k4dk$Oz7eEOZ zNsQNUF5jBM^Tuu3i#EKp^;R%e!DFxl9)SD62uE4(8gqs`!p?9?JhYJ4l{su@068&d t@1a(YIz@7{|85$+Gxpz2dw*x7y_+^UXY=Np@DJ${U3CBe literal 1978 zcmeH|OKVd>6vt0AkE)U0&|0%75~Yil5`0B1;-V>~=%N_1P!PeUNm>KxO=)izx(cpb zy6^*Z(U0Jxh#$a(i!NQdbm_u{A{c*X?o1pm?NV^zDgVs;=e*{gnK`Z2>v!*878xK1 zDUm=_PD);~l93T+NGc5%*a*LA`zw-zweXn)pPBE0E~tPs`0#5mV9039NxQ~iVs3@& z+dHeR&f1#D0lB|4myh^ZZ^O;ddH4a&7E%qfYc>v(th<_xwJ3euvipueQj0&nJ*^ zQ{$Z3RbbB~{!YI(dK%<*Y4OQ}obg4KD)B?u!6(jVoViL~iuPplCb}F?o3r_fjgvep z0hQ5sT9;`(V@8dUbw-Tt9O66UDZJ@LJHOC|zjUrFd4cls9zz2oQY`hG(1xby## z&^vzBu9xihFIfKAtA{Q*?(BE1e%adVpzp!2kFNb~UeqK=`oeN?W&RnoKR+t602aX# zxDD|AMh4-!A;<<3%4Z}FMhKi@(R2LZ@^oy4~!)2wSAnEl+>(xI3(<# z{dd&w8ux7u+yGZV1sKu$r(*X3?JFGvy4N#c0?dG0U?`4QzgZMNPj$kmvegLJ+mD8Q zrCctz8c};fmQc=(Np09|;!sEA*U#1~sMom)>Ofo0P#m%OucP>p`IF!Fz;I_HklAQ^ zRA!>51-YYJDafL3r64uiCQVFz&pHV}o=?x3R~p1`S<TVxMQ>A`~sUm*B|zCh?j4}ugdQqWea|JRwY9{hp>lP1}8k`3Fm z?f$R>-UJdLKv=@VAxBA%NHWG?RMKYA0x6>-S(AZQr-fC9sDoU3YceARN6ypO-FxL+ z%vV_b{9U86YNXOWkbD?SX6KLVmhQQ`4c(Jz>Upv- mU53eqMzB5bD-F+%&MJdxNL6>yF247n%ZmTri|3LXdnX?Y_bB%O delta 151 zcmZ3-(#Oo_7!>3mZpgs!9|$%uOyo1-abaL!U;*MQK#_?tO3W+_ER$myrDT`{fPxB8 iNg&0*4#Y+InJKAxC6oD?L?`nw`jD-eYY)&ch+6>3E+Cr# diff --git a/datafusion-pg-catalog/pg_catalog_arrow_exports/pg_rewrite.feather b/datafusion-pg-catalog/pg_catalog_arrow_exports/pg_rewrite.feather index 64a38894658767cb2ba7f6386c75619097615342..bc924fc4842f5f2cb0b5cea385aa1d47c22abd88 100644 GIT binary patch delta 735 zcmZ3rl7H7~em=*bApdYf28RDY5WzH&&xmsiBLhPY5Pz7?dzo3B@xa7Hb=C-=?3?L< zmzkAW8-Pra>6Mq6)mhg7nGO>lsyKxTYmPG%xly$i%_ zMg^dp0D}nFJa({30al;@1H*KKE6i&3Y+yqf7=(ZpgRF!q0csEe@_+#BxCkHvBn#39 z0x*j~jsjWE0VG*~Buov+b1*g790yX*0kn&w`66TcMMe;2+J2Fd`Tqr`45sOqE-{Y= ZG9mye4rEbaYybhH0+486Vqk!zXaJa=lqmoJ delta 386 zcmdnBnt#4Z>xIMg5QaG`xaNSm!cANS#P?>X1UtPPW=(L!hI8GlMh^N zq&~+Ur|6j9)pz|v-7ID2u}@NhpCcX>;7e4!#8D!A(^h@o#XOGYoSw*05AoYW<<>mb zw`^ozs61vuWTG=2ROuK|eLR!tjI3n@} fL_~}&Z6MpXrDmnqJz+e7;K=ewaH+?XONB#jy_Bu!3Xd; z)N{ThG>W2&TfcH{@45H;&zE$2y|eQp;GME)0Rbdi@Zn(-9quTOOAfLQSGQWlfma8( zB=(6H@@Ha7oDi-+zx?y$Hxef#vdz=mWS)#tao2vpajD;u{+^xdcBLODL(@NeGr!I$ z?}iPVUGh4H$30_=vk5S0=s*6VAKw9shW@glA2s}|C-k39l36-VCj}{%4Z8rL)!DZ0 z1yyhHQ*C(>&&-Ek#YLrwxEaubfN}P|tYQLwA`lmi@5I4M5uG8xS zZu{{li*r)iZxe0vL+V6afF1gm=Q`_FGk!TSf6K+E_Sam> uxm0xd@Yzp~T0WU#s6x$%_VqK@>3U8-ziaBxdQPne|1zgf{BCybJNf}~W54wP literal 1074 zcmeHHF;2rk5FAIwv5*TFDJUph@Brv2NsojSA<<%)lVT~cg5!exfCo@eQ1XmCArIgY zyaAZmv&A7H=n-e_Y4>(!*0*=M>1=j!bppI|U1x;%j;;!9owW$_Pacm#3^Z1eQhqkWlC%&xahTnQz zbf%>K9Wc%TouNiTpEZ_s1H10bxz1zR7~(SEJqEmQ z_OkBE);RY8XZJIw+pOvv)!Fu(f_{#P^>b{el=o-o`*Fnl(2u_7ty_4Fl=u{5;}RAX ooG7bannp(5gxQRd_9`XqL;j$t)&G0(^=|*gdy(^PnA%(M0V$NM4*&oF diff --git a/datafusion-pg-catalog/pg_catalog_arrow_exports/pg_shdepend.feather b/datafusion-pg-catalog/pg_catalog_arrow_exports/pg_shdepend.feather index 526e971c2192792ac91c28ed833c88777db33c8f..645c722633a6d5e9072bdc0c52ac2e1e53785c8a 100644 GIT binary patch literal 1534 zcmeHHK}y3=5S_%N3G$I3S%_qj6BGmwVE2Mj3T}jwnkbb(gQ*L5;t@Q7NALh1$OE`m z-80x&JmqiOx0*meC(4RK&uvYL~)kWKq$?>cQ^3*+^ zL{iN=(u|U>uj2pi1#3fL?ft^m_S(Z3+x}@!PT@yi_J=sZ?Bh?Va-kkqD{~vg>C;IMx1ID7) A-v9sr literal 942 zcmeH`F-pWx5QZm`Y{HTvg@uJh4qzi}v29Ku1Yui^iJ$}wX1CZ|cmxX%vInrRwAh1K z8NdG}fgq%}a31q!=JEeC!wfIW^Q+CJS%(}vv&1Azi)~?nMR}7)gn89maV^fC-KCx3b z)6h*h8FtXmB84;7lP!n-BCrvYRNsh~a!E+5Il3G%c^4pJBJEF^v055FJ^k50WDswh9+24u_CbfplpEc9$k3xUma^yt-SN4W~PyJ1KG}T%}6w zGC#?`#HdMazqflUgb*Z6x{R6GeKWH&&$D|vJ3s$&@j>JXvTTS%LU|#fw526o>>!N* zSb(~)L2X5vKo8JQ&>l2`Wk$zlM|CY}v1SYnpp=);RF}!jOe<65@bgdPCpcg^V696i zYaK%=+$WhT%fh6@plZ*oaEA4Ho_rW4*XhlBY=BVvMN!`?1T%L7q3t8hK>FyphI$F% ziEMY5bB_RXSc9|h;^*7(jy>z^+V^fJ=CO}|-HChrw)QXUb+MI4F57$<`V;1CDZ$C- zy7pabX)0mX0Xydhk_-=uo1=2;b2dNR#a zrQ>lii*x-wPF1Bws?_B?pA@MX8#T&wjI8RmFTp_8M=G6|+?3T!Rc4{%q{wrf@YQe5 z+P3!ln9cKM=fNn8;@&(7?dJU;)G|Ks*O1Ix#^<@C=X!a+w5xgbYY- z;zDuV0}w$*1)zWcg9rl$kY;D#0rNl#fdH&Q0mxvPe33`mBTev-Bn1mJ!KQf{`&_R#JL5DS>9wzOR1&*E zo#%QM`}a-Nb#1*i=2*e^5_Nn3n3%VHuINU_{k^^O5iH_g+XK2oW7_}# literal 606 zcmd^-Jr06E5QQHGaAPPaEGR4}Jb)g76PVCggHT{dFkn25NAM6Hz|#BZdjlli!67?4 zKaX#JvRR%Vj(gxkOFSTkY=sCR0ysuA&u0#1j^3ZVBH+PMaqO%ET*+Y=h?7h;PGkXX zQPwTzH#PSkUCNqRGOcjwyIWJ$y>j0^;5F(O;%=<2?x;Vt#V~Y@wt?rU^HRn!*2Y`f z?&IlfFoyc`njzz^JR8AL>#(%{SoTsn8L>K-F(Pt9Dk5gO7m>6l#WPdYf4#3Q-%)1o F>I*xqP8|RM diff --git a/datafusion-pg-catalog/pg_catalog_arrow_exports/pg_statistic.feather b/datafusion-pg-catalog/pg_catalog_arrow_exports/pg_statistic.feather index 2a3aea93176f53b85b8ae0168b489f0ae988a0e2..9bc07cae9967d632c3d8dc3dcd9607d962355028 100644 GIT binary patch delta 2652 zcmeH}L1+^}6o%hycd|)oLexN_h~!YE2x*%du}Tg0=AqUakY2RShJY3d7W7a=1rfxH zhd9FY5Ya=<5-$}z=|uuYnnMpgDu~B|;328mZvWk_W{?HuIeVR*p_lT{M@M%-i@#O%KJ=n9l-@+h5r1qJo`5N)T+$L%G;>Kdi8{p4nPJ zYE_{g`{iR+WCwcGA!G#cs(U2Y>tjEv{H&JXPC)Fkg56fIGbpjMUPQLVwyR(t_+mc*d-nHX zxET;z^iV7<518zPaT=>c&n=lZSw?K=Tx(cjkY@~>WumSn@;oD7nv6%scin%+9P1?C zlvq*}c|2NH!Z~rDkFm1%u%#K|6OTk2`w3}$ZB2aTXIM)mk;- rs*ObC-D_;L-y(^nQMi7Kq<)LUK3MO!$p5@Wih3wDcp*aMy-w}{Xsuwi delta 1344 zcmeH{!Alfz6vyA2otfPc9fx*7FUklOVs5sZA&8{jIy6L5*df%-b-M%#?V&?~(8Ws! zdkepV3lVq-5usB{c#QC{kOvPUQT+iCb(7t3r|<4a4Eqmw@dw}E;lpPh!+US0_SN|G z#js~)XYbBshyt97xnXC$J0_8i92i6;?mDC)R>_v2WrzgFWh%wo2z-k_}mYx-JE30GZ zYv`~G_O#tsnLH=GhY_XRuHdoe`Cl?iv>x%R?Y?Bpq+N*^{wbO_VBc(3`E|w}d1+oz zZi;>xQJ1s>Uf^7T`c9r TQl9rxO3F%g{KTgg{xbgo`}}!o diff --git a/datafusion-pg-catalog/pg_catalog_arrow_exports/pg_statistic_ext.feather b/datafusion-pg-catalog/pg_catalog_arrow_exports/pg_statistic_ext.feather index 8109dfbc0a984c32ba7a683d922b518a3ae3805e..de74ff877b802803f65d93ed0d794dba22975a2b 100644 GIT binary patch literal 1646 zcmeHI!AiqG5S`StjZ!5@4jw$@14Iz~fr59X2=*XIuuBQnHY5Qnh^L-C`5AtOAJKyc zPkuqK8sD2uAc{)wcFJsLmYMfvUw3J@*E>Et5Gi2cnuss74e3Zrn&KgXIWBTR=3#Zq zRb(C6T|;Eyh&;oO;B)Lf!4vo)++_}IfHaA{TkhdYak6}Brb(JHKmRC-M>s;Q-9f;9 zS{shqt9U$+8ESk9(BHy7C-cj>od!8Vc-6Ow7=2kD<$072O^*EKT{#@qx;oqMeC9Tj z1^DjmT#W!dCvYmk`Dl#6F}WF=lsRNj{#@s@F{G7AJkV*A;XcBPXcR|!?vcfILe#v~ zcutWMo0`#hQt*tUYm+6>rQu%1^|~b2yvAiUq_%Yptrqp)snnjlI2S)64^}tTqmTRt zJyJ8mfon6)(4(4T?=L+(*#cf$G1(qs5!r^`WT~bNu%q^62IA8yeCor~d02UKiLl%Z w9n^lG!M+nfC`Jc&u%*bpa`2a?Zse=(A8S|dMpo|zH{!p(n>{?nuKv$_0wxFjH2?qr literal 1154 zcmeH{u}Z{15Qb;ZTrNt46c!d&q_nURuCTpc5U#NfX3@hl7m|P{_$U@WfRAydg@uI= zBgStw2?TOJfll~0Gs{2!&dx47Uo0-K&O~bLWF!)a+JS`P%UA+D%y`5?6fk=2D6&tq zH6l;o0z}}GxmS>b8Spel8)g}P$-7-t% z3r-|QwV8R;4^=<*Kn$t$a*s*>WyR>bek8b-OHtL^vo>|-e_IJ1W5^mpuG z{gBxLIXP{3CdR+*{hSyFDxS|Nabn StUcu}{JHyc&Ra8gZ_f{AvA#b5 diff --git a/datafusion-pg-catalog/pg_catalog_arrow_exports/pg_statistic_ext_data.feather b/datafusion-pg-catalog/pg_catalog_arrow_exports/pg_statistic_ext_data.feather index 386c8f6c65bb37c268227315a0905d067f25f75a..40487ccb2f23f68ef521cb11201844bc4f81213e 100644 GIT binary patch literal 1006 zcmeH`O-jT-5QQt6i9sWTA&XhKn1yRWaN%}NAk4;%phG%ngT^okl0$e57aqd{cnA;R z!W-!K@&oY*f)%Q}y7KB(byc!juP-i7&AyS3z$`V%z9kmf%wjAg2ss<4m^B<$17UVf z%oqDBdV`*!A=<)6;7oi+gO9C?t((>rZMD_efqR)?7x)w}*+YeW$e-*P%=-j)%)1e% z9KyMxDoR(Bxi4y5_69z+jGPf%xC>X~v_q`b=x z$ATQ7s>7Fe#nv}OM?;NsTl`|kY~DrKPR4$PieI)weTC=IJ35Hn_dbEEpMdh}?z^Z! zdSBh1U|w(T{ieHnj5nrY@gl*JMM6uMOF!p?j1h>08;V1$nw9LaxAOkaT^$*}oxeBt LPd=hm_n-d&&>4mu delta 196 zcmaFIeu$0NF(}AC+>n9cKM-_Gu^xfjqdqitsB2aCd`^~QyX@@?T`Muk=_PDG1inHYo;%h` zNwu%(1iY_~+xb(o=k5zx=qGtapTHabu$nD5f!{{6*HBHBFnXrICK`Y{3i!i-e;sqq zkuYYatE|c&Pi2*7vGDvR+|;7Z zu|;pe{~Xwa`SH)$)KxAf;LgDt*qWfF{CI9Em8g!ujlkPFhs*VgSaQXoXQ(&uPF)OZ zecZdp_P_w(!E^ANR1(V7=9;y#F3vm3oV3hrb(9A;F?}EkDGau)MtrprTt2#(Y<~EB zw&l?U;KSC;891)qc%R?0rrwt8+iNk8WLX%z3~l=%dgc6BJtLgJ8dw_-?<-3YZ=>b8 z_4#)#5naVuU3(smY9+YvTR*TnO|*U62XMps-@}CcbFO$axnke0hs225b&`L{X9TO| z7+k;N^ZASzYCB-XSg{XQ#R-S2)>Z%d^*b^QYK3cR)xTE#i+jfZ=wI*9 Jls4`EuAkoI)|vnS literal 2046 zcmeH|F>ljA6vzKAZfYQi2s(6N@W8;pg4BT_OQnuTNL^T1?ARqIlDpt@2;KMq42&H+ zFfjB(bYNs)V9W<#VC=vG=Kt=_!X)$qAmyUJ{m%NmyL->?IR{5aPoF&k8jf$*fB|IO zKp#D9Bca6+#hin)gx5G+fjgYNrO%K`sO1*$fvTxPYL{9@z(;CE4XHl0q~AF;ruM0r zs<}Tm+LrzAg=f6sI%Vg%sniRlX+QqiG%-cfu_+DlmvNgSJDcYdHOgvbw8fb0{uTT! z&)X9{8ky--)tsM_9blI+_ORok9)z5%pY3MwpO{)_(-L3ld)C>j8%JPAMr);y4e+aJ zK6|#e8gpQeGc_@<%L)(4{^+nN_ibYiF;sJ%S+mfjf#>8OP&D1z_dEPu+LEKp+J&i# zs(dw9RaxLYdGTv~(vDBaYoTnGPfEj0DqN6#=Xv)Yx_d}G+@oHY**LSMt+Tr1BV3Xf zKblv)XIocgHYJd<9=>~aEkB_qa;3BCgzOWtd#-+byxqJ@{qiiOmZKNI8*+!9-CE7N zR5#f+jTm|^O8H#;cys68qtWJnhcf~* goBsd%+qCKbKRvPOe}4bjQ~yK%U-IK{;Qsf21AmXM0ssI2 diff --git a/datafusion-pg-catalog/pg_catalog_arrow_exports/pg_subscription_rel.feather b/datafusion-pg-catalog/pg_catalog_arrow_exports/pg_subscription_rel.feather index d5197f83ae9a2cca13880cd9e672e2b9b7590b0a..126151b117aba860e5ae2e43017934087234bff8 100644 GIT binary patch literal 914 zcmeH`KT5<<5XQgg?k31Xf^1=7u_q8b!k$1_1RFsjF3Unt$y<9%Yfs`4EWDTgzDZK3 zU~S=qnKv_;Z~nbxxmulHo=G3jYa!J#9Vlt0sVX$6m|zR5LQV#0O-f*%IWOQjTq7&6 zWgzMyUomyw6WAD&GvzKn-n9A7_B-`^tiE9t*aa~o);$F_@0#7(em~L+IXL#*hx>62 z>!uRUUAJzxx1!~Ue~OyDzK`#ocb@ZMbBcQ1wA&_QlIIXEBOhk5KuAYA4$nC098XZx zze4?4pLvJ+{XP?Y^jr0QJj3sOB%;6e!3dr?_MDh@MnuALerNQ~t&h92_x~Qf1r-a# NU%AIOKFVeMi=R&lV9Nji literal 638 zcmeHFy9&ZU5S)`d4oQ*1!onh@t>6y??1ePeiYbI(k&EEx_#qa4f`$L1Gn)j&Z*apd zyO)`{-Q~)v+U{1so3?a74%rkL62$P#Xf9$6R-Q2$qB7u4ztT7K89it80|g9 z`v6<`2$q(1`hEAF1H*{0U?q6Mz32bu-gE9`ZF_rj=Ns@uxN86{2#SEIH2#th1 z$Thhqwu5?Ll|B!|6Rw{@3;bg&I?X87yvc|{th4daXgnE=hG)QE+O^PTycDw`L(B5N z^iAnc-~6ah1^NMdArGe7q_?-jX3fZI0 zBjxI+VoaHhkoV(LMOG&lOwg?4xmSXiBzld;f#_Y(Jp1I`Se$$gJC4Q}*psQ|g_1By#o@PDcq@|qXj9k2r l1m7uN=F&S*u6s*(ZMfdQk8hT4&cCbg=$pj{vljlFo&j;9n$7?K delta 257 zcmZ3)JBgduF(}AC+>n9cKM({=dbx$>jL#(5yo8mRZ*%dlp*9b}hg|yf$a!6kyw**0?u& z^~}cT8-D3-%}(E|3b%EDIYE`xMqHlVLW$ zx`@+xyx_`?>iS-U|MCNtdIxJ(WY-R@!Ft{R>uCjR$c!lIc#UzyMLkQ@GgxVSlPoz! z#A}}7w1Yz8TR#1|t``yWxPsBlZVjWn%co0>hd*Kjwokvl>lqj?!kG1VFJj@lzPhmK zx#u;AOEp8+Bj zCvcL#%g(;}yG%BWqWN+Rd>AtW_>kzsLk~7weld*2HMnv)TGa^d18?d^?WhT5QB!(x zvc+pu6KlZDBK+kLbOPAj1eofY+9Iau>1RNx2DLv47kDfgxeRY*v Yi_}8c;zNWXQna0Wlzigw&CNZVX6N6%uSF z-O+dkb39$HU3ULLTmY|l?lV=}@@EkjSJ@c&KurIK$9caGz&TgZ2r-uo*V=Dy#q*Zl z;Ky&?Rv=7a_^#FwRWXvBpt>wCbC;xBX;q~OkP!RqFL>q7Wrno~G9SdgvHP|9+`mp$ zb`^Jtow++K$F7R=QfUHH=Y3FYJ_Vp4L?qhsqe2+f1{U2~{b|3k)L6v{%7m4PK%SLgPmTun1h-aGkI568m zL_524Jat{yaj;&q%-8k2-H@Zl&g=2!@|zMwd;lkT2YsohOP^o7_&nU?QoFi?r0y4S zt44Z!YNFPd!+J{iMIUT_%f5J4nf0!>9C{9AKz%Jf*{@|e&n*&GtIK(QSnVz6`Es5w Q=lTDi=Wjc}y8m7N3v=8Sxc~qF literal 2174 zcmeHJv2N5r5Pc4gW6*&tks<|!ONuK%x(`Ss3JRo15mK5IIJrH`(y@2(ZA6gnGg4Ae zrbtOiks@V^6qFPx@)0zN^Jd3Lt20FO+@792w%^RW-JMz8*3QoM?rWgoco_p3WIRC+ z309HP;)r5CgHI{1aeD=x^XdE%Fely+>%{d6a7N6Dw?vP)ihvX11JNgb(eIM@N;qOb zFf~r8fyq`y!;AJEZ(f5dt@-4N{jmXF-8RjS2f35+u;uQNn_-=r6Ri1JWbGU^&qk0Z zq3z1Uqhd_G^y?GyS@d*yMP1H-@8rB!p4a^co^v&DL(W`zD~s{gd|vAVPL&f0=S=NH z?3|D_lJSgiWo0WjG$T{jX2|uwYnq>b;mh8+Qn|WzxhA-)n@Gdjsw4MYIoK_byhPxm*OAVpyLayMl=T)X$M4DJgZ$A%#1C42&Ky&qVd|0?ha^=nP(YF-3`%qlEaN;I^lHlk>Ruocox2r#tuW-*;$> z$SgA0Ceke`OC&EH(k?kPB$LG!tQ^m5@)Y7C*D@kUU>e6Tq@~0>v-e+&66kI<@t;| zN3R^UG$)ejWuO3X|{*p2JIc4R7Eryo2}f z0Y1VMe1d8C3}4_Y%*j}yCF8+7t)33hS4_8b74*XZYy|DT9R^_+?12Ith9WpngK;ch>mn__57YDDC+DvD{4ac0L=Lc4Iav6v=sNuVU2(WycSirK`~pm# BM412p delta 433 zcmdla_=uO!F(}AC+>n9cKM+JPPUJIE{lLJ$umOlmfY=6zS%BCCC<~;R1b~DLNNn;! zHgQ=Uh$y21P$UCg#l(x^vI$5E<{&8mX<(T=kzHC~29k;^K=$N6>`KfmK*?T4DLsUB zK=mNN48-}FDGVG8JV4A2#9+Xv0HQYgGI6sASpZoYKn!vn9cKM-t~$ZM?1!^ps}g@J(~2Z&jKSPUouq?km2gbxsN0I|r# zL}6Q?IkaF()&z7|3P#^ABtgqXLk9W@4i{qrt?7 z>Wmr_56ahbFz^A*We1xLlx0)^5)2GN3=&`wcCc{*3?e`gFaWzH2FL`v1tP}42BdQn z3zE~)fd&BCASZADNfsapQisQh>`*sOmSYs#Y{96&B4`5CpaR68000?wU~(p_^yCg! Pk&zxeTsMHh0ZB6ed-_-Q delta 353 zcmZ3*KZ}>wF(}AC+>n9cKM-h4#vAZi#DfMQc7ZdI4;KoU5CWPrkCRz`Wo0~7D6vx3yJOipAJ7Uf{zVc-Co z#{m=p0!9TO!LWHRqcV#i$PpSq3~~q~5L-N Ggem}nNJ1|F diff --git a/datafusion-pg-catalog/pg_catalog_arrow_exports/pg_ts_dict.feather b/datafusion-pg-catalog/pg_catalog_arrow_exports/pg_ts_dict.feather index 839c290ef80b087391a782b710a11e3365d7fb56..2759f244f7bf31adc1e6a1466953c8a4811c83eb 100644 GIT binary patch delta 908 zcmZn?c_hx~7!>3mZpgs!9|$HeP2@8Y{J_Y-umXrRfOroB1B1`RKxIai$$L5EWmyS?U#&Swq!kp>@R6&eW zT_7egDoozUDK*)dQMsNC>{SK^AqEMsW7)x86kremihu#w)(9XIKoX_~6u>Yw*n$kCo`Zp%fn)Ph#?5R@3z#NHap;Z48jb`u=weM27`;Hir~o8( KFflMdG9Un@-=p3D delta 413 zcmaDP-Xy~37!>3mZpgs!9|#sOPUJHZv|(gm_`$%yum^}+fY@VVpfaPvvMi&xYz&f$8AvKXI#?#}<&qYdf~4XC zkUjYWqZ%^{P*RXvN&;*h*fgMe5MT!4{LGZi-AsGgm^Ls@_TtnVlrA^N<#GlN1|A@0 R2VyW_Q~**ZfME}b5dh_0VvGO) diff --git a/datafusion-pg-catalog/pg_catalog_arrow_exports/pg_ts_parser.feather b/datafusion-pg-catalog/pg_catalog_arrow_exports/pg_ts_parser.feather index 46fc55d558956d73a4b7cfac8ce591c6fa43172d..c2cb87b56fed570f99dd7be7272e9585c1b05c2f 100644 GIT binary patch literal 2714 zcmeHJJ#Q015S>dd&IwM)L{St81Scvg6eNmNDCuZWtSBOMp5?}cR zDJW8+RQU=1At_R%N}YlR%zOLc+ng*M7wJ6Fe$2kvc{_VE-mGtKZfrjm89)wZMXEx% zA+c0sP9n@8K?q%-Md(A@Qy00I5jjR%LF)%1HMBFV=h{-_>7T&>)0stdTWH*~j7FjF ztkZ3(5BbMTfd+br_5^!q&-pxBN9|>u_O3odw)d#rsJ}{^jkF6$R*e53!TjhyTsMJ( z>y1k5%|=TNxeh1b`sr~k{Vn3E!8haLnJE=CaH&?kh$({oRbvW`?;wGnPaaSC{>TZQ zy!}?SFdfE}Pr#LVT<7Dtx_R2keXi39xK2E-7sxmGxs(@o=@`OXLtL%&o$6-kE;6Ht zt%iNfQRW8HRgerL^WvHDA0)7;;>+-^=Cx(j=D5t!4>{?J!d$bwSgY9e1>~#0dr=m& zwK@As%!!)1DbB=PHZ>E&kExuioIAp<2q&RWNRXhTAe_N(ICVJ|<5Z?XW6dM8p^haX zv6UDrRn2Z}R)H~I`tZzP!9S7PcHgMsj$KSjpwsW$^))-*v*V5(-QaZRujc?eI^E%i zCEV!_@0W0=JN&eSJKf=zE`ql9Vum=D_$~bV^2|8Za^1Mg(eT0Z<(;+9P<#8g963gt zFJf`1J)%r$EpB3QsJ*&+oxX4CYA$NP^Ut5mp^V`F;`5KdzmCDbjlsWw|}7 zjm60D3T`BZ#u{XFtLPuH7>4+|Bf@Gxafj>#qN;>!U8$ I_5Y;*0ISqxLjV8( literal 2074 zcmeHJJx|;~5S;^ahlqo&h@z7~U_R1O1c@I2QVJRrL_-M{b_C)u7UxKzvrltHN=ai8mF=##WcHX`ndq0kiot^i)t0F_#O-rOJv?=kW zEfX?{2-fm|1!xjaPoKmheT-Q_yGQ&3?JHV@wua`R{roc=!c9)pC zW#FZM=MJ*)EF<>{yl(|}jPDho+5G%Y&`rXVc#wt%cr%g9g4+rZ-!{zAK~Bd(i+@~; zSMD2k+}H2w+K8L8`Yz+(o*qTu`e+?D23@TH4@@`Q91|!N=1Wgk)_1Bh?zwfj!y20T z=;@*Y>hXQPAjkQrQK6M}zP5oQ{EYSmwVdI3?O#_vr+#0(Im4!xTSC2I)4S6C1@+hJ z%^5cSFHO8r->tqV`V1TYt>z7H*Z77lpK5+t^)G9D!^Z!v`6cDkanII<{c~*l+*{o0 z?XQ0Z%rB;EH4KHy%w(+#J+|Mz?G L8|%5@{wH_@OosfJ diff --git a/datafusion-pg-catalog/pg_catalog_arrow_exports/pg_ts_template.feather b/datafusion-pg-catalog/pg_catalog_arrow_exports/pg_ts_template.feather index 8b93d2cbe728013c4117d9ce3a11b5c086470fc3..3c04468bcec495f3255a1dab08bbcac39f3f3680 100644 GIT binary patch literal 1922 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 F{11Zo6kz}W literal 56026 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 Zc*WcE(dz$s|Nc$=)${(~;~DwC{RQyjbRPf! literal 642 zcmeH_Jr06E5QS%zKMe(ig@whIwsy93b|y4lKne=PfLMD7OON9LypevhKtl8i&gQ+$ zZ06_9X45R&A2uRyY;8mmQJYIFf%p>PVa6jCq6qeSR!`&!ZeRx%Ab}%lLsyaX{fw`D zEzlaZ8EDJud?~6^gYUT`@<0dSMDthf9>R2TTQ+%p&1;SCU7oS{uTjmCc$g93w`EHa zI!F1PM)}hCJ9A2XRUDZegV1T<%27z=Ir IYpMHtAIq{x#Q*>R diff --git a/datafusion-pg-catalog/pg_to_arrow.py b/datafusion-pg-catalog/pg_to_arrow.py index a364a34..2bfe469 100644 --- a/datafusion-pg-catalog/pg_to_arrow.py +++ b/datafusion-pg-catalog/pg_to_arrow.py @@ -13,7 +13,13 @@ import sys def map_postgresql_to_arrow_type(type_oid: int) -> pa.DataType: - """Map PostgreSQL data types to Arrow data types.""" + """Map PostgreSQL data types to Arrow data types. + + Every oid-alias type (oid, regproc, regtype, regclass, regnamespace, ...) + is stored as int32 (the raw object identifier) so the + `datafusion-pg-catalog` oid-coercion analyzer rule can resolve name/numeric + string comparisons uniformly. + """ # Map OIDs to Arrow types type_mapping = { # Integer types (OIDs from PostgreSQL documentation) @@ -61,6 +67,31 @@ def map_postgresql_to_arrow_type(type_oid: int) -> pa.DataType: return type_mapping.get(type_oid, pa.string()) # Fallback to string +# PostgreSQL `reg*` type names (and `oid`). Their OIDs are version-stable but +# kept here as (oid, name) pairs so we can both map them to int32 and stamp +# `pg.oid_alias=` field metadata for the catalog analyzer rule. +OID_ALIAS_TYPES_BY_NAME = { + 'oid', + 'regproc', 'regprocedure', + 'regoper', 'regoperator', + 'regclass', 'regtype', + 'regnamespace', 'regrole', + 'regconfig', 'regdictionary', 'regcollation', +} + + +def load_type_names(conn) -> dict: + """Build a {type_oid: typname} map from pg_type for oid-alias detection.""" + cur = conn.cursor() + cur.execute("SELECT oid, typname FROM pg_catalog.pg_type") + mapping = {row[0]: row[1] for row in cur.fetchall()} + cur.close() + return mapping + + +def is_oid_alias(type_name: str) -> bool: + return type_name in OID_ALIAS_TYPES_BY_NAME + def export_query_to_feather( connection_string: str, query: str, @@ -74,6 +105,9 @@ def export_query_to_feather( conn = psycopg2.connect(connection_string) cursor = conn.cursor(cursor_factory=RealDictCursor) + # type_oid -> typname, used to detect oid-alias columns for metadata. + type_names = load_type_names(conn) + # Execute query cursor.execute(query) @@ -81,16 +115,20 @@ def export_query_to_feather( columns = [] arrow_types = [] column_names = [] + column_oid_kinds = [] # pg.oid_alias value per column, or None for desc in cursor.description: col_name = desc.name col_oid = desc.type_code arrow_type = map_postgresql_to_arrow_type(col_oid) + type_name = type_names.get(col_oid, '') + oid_kind = type_name if is_oid_alias(type_name) else None columns.append(col_name) arrow_types.append(arrow_type) column_names.append(col_name) + column_oid_kinds.append(oid_kind) # Process data in batches all_data = {col: [] for col in columns} @@ -122,8 +160,12 @@ def export_query_to_feather( array = pa.array([str(x) if x is not None else None for x in all_data[col]], type=pa.string()) arrays.append(array) - # Create table and write to feather - table = pa.Table.from_arrays(arrays, names=column_names) + # Build schema with pg.oid_alias metadata on oid-alias columns. + fields = [] + for name, arrow_type, oid_kind in zip(column_names, arrow_types, column_oid_kinds): + metadata = {b'pg.oid_alias': oid_kind.encode()} if oid_kind else {} + fields.append(pa.field(name, arrow_type, metadata=metadata)) + table = pa.Table.from_arrays(arrays, schema=pa.schema(fields)) feather.write_feather(table, output_file) print(f"Successfully exported {rows_processed} rows to {output_file}") diff --git a/datafusion-pg-catalog/src/pg_catalog.rs b/datafusion-pg-catalog/src/pg_catalog.rs index f4ec2e7..2776bdb 100644 --- a/datafusion-pg-catalog/src/pg_catalog.rs +++ b/datafusion-pg-catalog/src/pg_catalog.rs @@ -26,11 +26,15 @@ use crate::pg_catalog::catalog_info::CatalogInfo; use crate::pg_catalog::context::PgCatalogContextProvider; use crate::pg_catalog::empty_table::EmptyTable; +pub mod array_bounds_udf; pub mod catalog_info; pub mod context; pub mod empty_table; pub mod format_type; pub mod has_privilege_udf; +pub mod oid_coercion_rule; +pub mod oid_field; +pub mod oid_type_planner; pub mod pg_attribute; pub mod pg_class; pub mod pg_database; @@ -224,6 +228,19 @@ impl SchemaProvider for PgCatalogSc } } +/// Backs the oid-coercion analyzer rule: build a pg_catalog table provider +/// synchronously so the rule can construct name->oid lookup subqueries at +/// plan time (data is fetched lazily at execution). +impl oid_coercion_rule::OidLookupProvider + for PgCatalogSchemaProvider +{ + fn build_table_provider(&self, name: &str) -> Result>> { + self.build_table_by_name(name)? + .map(|t| t.try_into_table_provider()) + .transpose() + } +} + impl PgCatalogSchemaProvider { pub fn try_new( catalog_list: C, @@ -1428,11 +1445,11 @@ where P: PgCatalogContextProvider, { let static_tables = Arc::new(PgCatalogStaticTables::try_new()?); - let pg_catalog = PgCatalogSchemaProvider::try_new( + let pg_catalog = Arc::new(PgCatalogSchemaProvider::try_new( session_context.state().catalog_list().clone(), static_tables.clone(), context_provider, - )?; + )?); session_context .catalog(catalog_name) .ok_or_else(|| { @@ -1440,7 +1457,7 @@ where "Catalog not found when registering pg_catalog: {catalog_name}" )) })? - .register_schema("pg_catalog", Arc::new(pg_catalog))?; + .register_schema("pg_catalog", pg_catalog.clone())?; session_context.register_udf(create_current_database_udf()); session_context.register_udf(create_current_schema_udf()); @@ -1476,6 +1493,33 @@ where session_context.register_udf(create_pg_get_partition_ancestors_udf()); session_context.register_udf(quote_ident_udf::create_quote_ident_udf()); session_context.register_udf(quote_ident_udf::create_parse_ident_udf()); + // Postgres array bounds. DataFusion ships array_length but not array_upper / + // array_lower; without these, client queries (psql/dbeaver/grafan) that use + // them were only "supported" via hardcoded blacklist token substitution. + session_context.register_udf(array_bounds_udf::create_array_upper_udf()); + session_context.register_udf(array_bounds_udf::create_array_lower_udf()); + + // Make oid / oid-alias columns (relnamespace, atttypid, ...) compare + // against string literals the way Postgres does. Requires the schema + // provider handle (kept above) to resolve names -> oids at plan time. + session_context.add_analyzer_rule(Arc::new(oid_coercion_rule::OidStringCoercion::new( + pg_catalog.clone() as Arc, + ))); + + // Teach the SQL planner to accept Postgres oid-alias type names + // (`regclass`, `regproc`, ...) -- DataFusion rejects them as unsupported + // otherwise. Each maps to int4 carrying `pg.oid_alias` metadata, which the + // analyzer rule above then reads to resolve name strings -> oids. This + // replaces the former SQL-layer cast-stripping / cast-rewriting rules. + { + use datafusion::execution::session_state::SessionStateBuilder; + let state = session_context.state_ref(); + let existing = state.read().clone(); + let new_state = SessionStateBuilder::new_from_existing(existing) + .with_type_planner(Arc::new(oid_type_planner::PgOidTypePlanner)) + .build(); + *state.write() = new_state; + } Ok(()) } diff --git a/datafusion-pg-catalog/src/pg_catalog/array_bounds_udf.rs b/datafusion-pg-catalog/src/pg_catalog/array_bounds_udf.rs new file mode 100644 index 0000000..e9a5cdb --- /dev/null +++ b/datafusion-pg-catalog/src/pg_catalog/array_bounds_udf.rs @@ -0,0 +1,345 @@ +//! PostgreSQL `array_upper` / `array_lower` scalar functions. +//! +//! DataFusion does not ship these, so any client query containing them (psql, +//! dbeaver, grafana) was rejected with "Invalid function 'array_upper'". They +//! used to only "work" because the exact query fragments were on the parser's +//! token blacklist and got swapped out before execution. +//! +//! Arrow's list types (`List`/`LargeList`/`FixedSizeList`) are always 1-based +//! and contiguous, so for any present dimension: +//! * `array_lower(arr, dim)` = 1 +//! * `array_upper(arr, dim)` = `array_length(arr, dim)` +//! +//! Following Postgres, both return NULL when the array is NULL, when `dim` is +//! out of range (< 1 or beyond the array's dimensionality), or when the array +//! is empty on the requested dimension. + +use std::sync::Arc; + +use datafusion::arrow::array::{Array, ArrayRef, AsArray, Int32Builder}; +use datafusion::arrow::datatypes::{DataType, Int32Type, Int64Type}; +use datafusion::common::DataFusionError; +use datafusion::logical_expr::{ + ArrayFunctionArgument, ArrayFunctionSignature, ColumnarValue, ScalarFunctionArgs, ScalarUDF, + ScalarUDFImpl, Signature, TypeSignature, Volatility, +}; + +/// Length of a list at a given 1-based dimension, with Postgres NULL semantics. +/// +/// Returns `Some(len)` only when `dim` is in range and that dimension is +/// non-empty; returns `None` for a null array, an out-of-range dimension, or an +/// empty dimension. This matches the behavior of Postgres `array_length` / +/// `array_upper` / `array_lower`, which all yield NULL in those cases. +fn length_at_dim(arr: Option, dim: i64) -> Option { + if dim < 1 { + return None; + } + let mut value = arr?; + let mut current = 1; + loop { + let len = value.len(); + if current == dim { + return if len == 0 { None } else { Some(len) }; + } + // Cannot descend further into an empty or non-list dimension. + if len == 0 { + return None; + } + value = match value.data_type() { + DataType::List(_) => value.as_list::().value(0), + DataType::LargeList(_) => value.as_list::().value(0), + DataType::FixedSizeList(_, _) => value.as_fixed_size_list().value(0), + _ => return None, + }; + current += 1; + } +} + +/// Read the per-row dimension argument as `Option`, accepting either +/// Postgres `integer` (Int32) or `bigint` (Int64). +fn extract_dims(arg: &ArrayRef) -> Result>, DataFusionError> { + let dims = match arg.data_type() { + DataType::Int32 => arg + .as_primitive::() + .iter() + .map(|v| v.map(|x| x as i64)) + .collect(), + DataType::Int64 => arg.as_primitive::().iter().collect(), + other => { + return Err(DataFusionError::Internal(format!( + "array dimension must be an integer, got {other}" + ))); + } + }; + Ok(dims) +} + +/// Core implementation shared by `array_upper` and `array_lower`. +/// +/// `upper` selects the upper bound (the length at the dimension); otherwise the +/// lower bound (always 1 for Arrow's 1-based lists) is produced. +fn array_bounds_impl( + args: &[ColumnarValue], + upper: bool, +) -> Result { + let args = ColumnarValue::values_to_arrays(args)?; + if args.len() != 2 { + return Err(DataFusionError::Internal(format!( + "array_upper/array_lower expect exactly 2 arguments, got {}", + args.len() + ))); + } + let list_arr = &args[0]; + let dims = extract_dims(&args[1])?; + + let rows = list_arr.len(); + let mut out = Int32Builder::with_capacity(rows); + + let build = |row: Option, dim: Option, out: &mut Int32Builder| match dim { + // Null dimension -> NULL result. + None => out.append_null(), + Some(d) => match length_at_dim(row, d) { + // Empty / out-of-range dimension -> NULL (Postgres semantics). + None => out.append_null(), + Some(len) if upper => out.append_value(len as i32), + // Lower bound of a present 1-based dimension is always 1. + Some(_) => out.append_value(1), + }, + }; + + match list_arr.data_type() { + DataType::List(_) => { + let l = list_arr.as_list::(); + for (row, dim) in l.iter().zip(dims.iter().copied()) { + build(row, dim, &mut out); + } + } + DataType::LargeList(_) => { + let l = list_arr.as_list::(); + for (row, dim) in l.iter().zip(dims.iter().copied()) { + build(row, dim, &mut out); + } + } + DataType::FixedSizeList(_, _) => { + let l = list_arr.as_fixed_size_list(); + for (row, dim) in l.iter().zip(dims.iter().copied()) { + build(row, dim, &mut out); + } + } + other => { + return Err(DataFusionError::Internal(format!( + "array_upper/array_lower expect a list argument, got {other}" + ))); + } + } + + Ok(ColumnarValue::Array(Arc::new(out.finish()))) +} + +fn two_arg_array_signature() -> Signature { + Signature::one_of( + vec![TypeSignature::ArraySignature( + ArrayFunctionSignature::Array { + arguments: vec![ArrayFunctionArgument::Array, ArrayFunctionArgument::Index], + array_coercion: None, + }, + )], + Volatility::Immutable, + ) +} + +#[derive(Debug, Hash, PartialEq, Eq)] +pub struct ArrayUpperUDF { + signature: Signature, +} + +impl Default for ArrayUpperUDF { + fn default() -> Self { + Self::new() + } +} + +impl ArrayUpperUDF { + pub fn new() -> Self { + Self { + signature: two_arg_array_signature(), + } + } + + pub fn into_scalar_udf(self) -> ScalarUDF { + ScalarUDF::new_from_impl(self) + } +} + +impl ScalarUDFImpl for ArrayUpperUDF { + fn name(&self) -> &str { + "array_upper" + } + + fn signature(&self) -> &Signature { + &self.signature + } + + fn return_type(&self, _arg_types: &[DataType]) -> Result { + Ok(DataType::Int32) + } + + fn invoke_with_args(&self, args: ScalarFunctionArgs) -> Result { + array_bounds_impl(&args.args, true) + } +} + +#[derive(Debug, Hash, PartialEq, Eq)] +pub struct ArrayLowerUDF { + signature: Signature, +} + +impl Default for ArrayLowerUDF { + fn default() -> Self { + Self::new() + } +} + +impl ArrayLowerUDF { + pub fn new() -> Self { + Self { + signature: two_arg_array_signature(), + } + } + + pub fn into_scalar_udf(self) -> ScalarUDF { + ScalarUDF::new_from_impl(self) + } +} + +impl ScalarUDFImpl for ArrayLowerUDF { + fn name(&self) -> &str { + "array_lower" + } + + fn signature(&self) -> &Signature { + &self.signature + } + + fn return_type(&self, _arg_types: &[DataType]) -> Result { + Ok(DataType::Int32) + } + + fn invoke_with_args(&self, args: ScalarFunctionArgs) -> Result { + array_bounds_impl(&args.args, false) + } +} + +/// Create the PostgreSQL `array_upper` UDF. +pub fn create_array_upper_udf() -> ScalarUDF { + ArrayUpperUDF::new().into_scalar_udf() +} + +/// Create the PostgreSQL `array_lower` UDF. +pub fn create_array_lower_udf() -> ScalarUDF { + ArrayLowerUDF::new().into_scalar_udf() +} + +#[cfg(test)] +mod tests { + use super::*; + + use datafusion::arrow::array::{Int32Builder, ListBuilder}; + + /// Build a list array where each entry is one row. `Some(vec![])` is an empty + /// (non-null) list, `Some(vec![1,2,3])` is `[1,2,3]`, and `None` is a NULL + /// list value. + fn int_list(rows: &[Option>]) -> ArrayRef { + let mut builder = ListBuilder::new(Int32Builder::new()); + for row in rows { + match row { + Some(elems) => { + for v in elems { + builder.values().append_value(*v); + } + builder.append(true); + } + None => builder.append_null(), + } + } + Arc::new(builder.finish()) + } + + fn run_bounds(list: ArrayRef, dim: i64, upper: bool) -> Vec> { + let dim_arr = Arc::new(datafusion::arrow::array::Int64Array::from(vec![ + dim; + list.len() + ])); + let args = vec![ColumnarValue::Array(list), ColumnarValue::Array(dim_arr)]; + let out = array_bounds_impl(&args, upper).unwrap(); + let arr = match out { + ColumnarValue::Array(a) => a, + _ => unreachable!(), + }; + arr.as_primitive::().iter().collect() + } + + #[test] + fn test_length_at_dim() { + let three = int_list(&[Some(vec![1, 2, 3])]); + // length_at_dim operates on a single extracted row's list value. + let row = three.as_list::().value(0); + assert_eq!(length_at_dim(Some(row.clone()), 1), Some(3)); + // dim 2 is out of range for a 1-D list + assert_eq!(length_at_dim(Some(row), 2), None); + // null array + assert_eq!(length_at_dim(None, 1), None); + // dim < 1 + let one = int_list(&[Some(vec![1])]); + assert_eq!(length_at_dim(Some(one.as_list::().value(0)), 0), None); + // empty list at dim 1 -> None (Postgres: empty array has no length) + let empty = int_list(&[Some(vec![])]); + assert_eq!( + length_at_dim(Some(empty.as_list::().value(0)), 1), + None + ); + } + + #[test] + fn test_array_upper() { + let arr = int_list(&[Some(vec![1, 2, 3])]); + assert_eq!(run_bounds(arr, 1, true), vec![Some(3)]); + + // empty (non-null) array -> NULL (Postgres semantics) + let arr = int_list(&[Some(vec![])]); + assert_eq!(run_bounds(arr, 1, true), vec![None]); + + // null array value -> NULL + let arr = int_list(&[None]); + assert_eq!(run_bounds(arr, 1, true), vec![None]); + } + + #[test] + fn test_array_lower() { + let arr = int_list(&[Some(vec![1, 2, 3])]); + assert_eq!(run_bounds(arr, 1, false), vec![Some(1)]); + + // empty (non-null) array -> NULL + let arr = int_list(&[Some(vec![])]); + assert_eq!(run_bounds(arr, 1, false), vec![None]); + + // null array value -> NULL + let arr = int_list(&[None]); + assert_eq!(run_bounds(arr, 1, false), vec![None]); + } + + #[test] + fn test_out_of_range_dim() { + let arr = int_list(&[Some(vec![1, 2, 3])]); + assert_eq!(run_bounds(arr.clone(), 2, true), vec![None]); + assert_eq!(run_bounds(arr.clone(), 2, false), vec![None]); + assert_eq!(run_bounds(arr, 0, true), vec![None]); + } + + #[test] + fn test_multiple_rows() { + // Per-row independence. + let arr = int_list(&[Some(vec![1]), Some(vec![1, 2]), Some(vec![]), None]); + assert_eq!(run_bounds(arr, 1, true), vec![Some(1), Some(2), None, None]); + } +} diff --git a/datafusion-pg-catalog/src/pg_catalog/oid_coercion_rule.rs b/datafusion-pg-catalog/src/pg_catalog/oid_coercion_rule.rs new file mode 100644 index 0000000..e81a43f --- /dev/null +++ b/datafusion-pg-catalog/src/pg_catalog/oid_coercion_rule.rs @@ -0,0 +1,652 @@ +//! Analyzer rule that makes oid / oid-alias columns compare against strings +//! the way Postgres does. +//! +//! # Background +//! Postgres catalog columns such as `pg_class.relnamespace` or +//! `pg_attribute.atttypid` are object identifiers stored as `integer` +//! (Arrow `Int32`). Clients routinely compare them against *string* literals, +//! e.g. `WHERE relnamespace = 'public'` or `WHERE atttypid = '23'`, and +//! Postgres resolves the string to an oid (name lookup for names, direct for +//! numerics). +//! +//! DataFusion has no notion of "oid". Its type coercion turns +//! `Int32_col = Utf8('public')` into `CAST(col AS Utf8) = Utf8('public')`, +//! which silently matches nothing and returns an empty result. +//! +//! # Fix +//! Columns marked with the [`OID_ALIAS_KEY`](crate::pg_catalog::oid_field) +//! Field metadata are recognized by this rule. When such a column is compared +//! against a string literal, the string is resolved to an oid using Postgres +//! semantics: +//! +//! * a **numeric** string (`'16417'`) becomes a literal `Int32` oid; +//! * a **name** string (`'public'`) becomes a scalar subquery that looks the +//! name up in the backing catalog table (`pg_namespace`, `pg_class`, +//! `pg_proc`). +//! +//! The rule is order-independent: it handles both the pre-coercion form +//! `col = 'x'` and the post-coercion form `CAST(col AS Utf8) = 'x'`. + +use std::fmt::Debug; +use std::sync::Arc; + +use datafusion::common::Column; +use datafusion::common::config::ConfigOptions; +use datafusion::common::tree_node::{Transformed, TreeNode, TreeNodeRewriter}; +use datafusion::common::{DFSchemaRef, ExprSchema, Result, ScalarValue, Spans}; +use datafusion::datasource::{TableProvider, provider_as_source}; +use datafusion::logical_expr::expr::InList; +use datafusion::logical_expr::{ + BinaryExpr, Cast, Expr, LogicalPlan, LogicalPlanBuilder, Operator, Subquery, TryCast, +}; +use datafusion::optimizer::analyzer::AnalyzerRule; + +use crate::pg_catalog::oid_field::{self, OID_ALIAS_KEY}; + +/// Synchronous accessor for the pg_catalog tables backing name->oid lookups. +/// +/// Implemented by `PgCatalogSchemaProvider`, which can build a table provider +/// without async I/O (dynamic tables defer data fetch to execution time via a +/// streaming source). +pub trait OidLookupProvider: Send + Sync + Debug { + /// Build the named pg_catalog table as a [`TableProvider`], or `None` if it + /// does not exist. + fn build_table_provider(&self, name: &str) -> Result>>; +} + +/// Rewrite oid / oid-alias column comparisons against string literals to use +/// Postgres name/numeric oid resolution. +#[derive(Debug)] +pub struct OidStringCoercion { + provider: Arc, +} + +impl OidStringCoercion { + pub fn new(provider: Arc) -> Self { + Self { provider } + } +} + +impl AnalyzerRule for OidStringCoercion { + fn analyze(&self, plan: LogicalPlan, _config: &ConfigOptions) -> Result { + let mut rewriter = PlanRewriter { + provider: &self.provider, + }; + Ok(plan.rewrite(&mut rewriter)?.data) + } + + fn name(&self) -> &str { + "oid_string_coercion" + } +} + +/// Plan-level rewriter: visits every node top-down and rewrites `Filter` +/// predicates. +struct PlanRewriter<'a> { + provider: &'a Arc, +} + +impl<'a> TreeNodeRewriter for PlanRewriter<'a> { + type Node = LogicalPlan; + + fn f_down(&mut self, plan: LogicalPlan) -> Result> { + // Rewrite every expression in every plan node (filters, join ON + // filters, projections, ...) using that node's schema. The + // schema-free cast arm (which carries its own kind via the + // PgOidTypePlanner metadata) is what makes projections and + // oid-column casts like `classoid = 'pg_namespace'::regclass` work; + // the schema is only consulted by the bare `col = 'str'` path. + let schema = plan.schema().clone(); + plan.map_expressions(|expr| { + let mut rewriter = ExprOidRewriter { + schema: schema.clone(), + provider: self.provider, + }; + expr.rewrite(&mut rewriter) + }) + } +} + +/// Expression-level rewriter: rewrites oid-alias comparisons inside one +/// predicate. +struct ExprOidRewriter<'a> { + schema: DFSchemaRef, + provider: &'a Arc, +} + +impl<'a> TreeNodeRewriter for ExprOidRewriter<'a> { + type Node = Expr; + + fn f_down(&mut self, e: Expr) -> Result> { + match rewrite_expr_shallow(&e, &self.schema, self.provider)? { + Some(new_e) => Ok(Transformed::yes(new_e)), + None => Ok(Transformed::no(e)), + } + } +} + +/// Examine a single predicate expression and, if it is an oid-alias comparison +/// against a string, return the rewritten expression. +fn rewrite_expr_shallow( + e: &Expr, + schema: &DFSchemaRef, + provider: &Arc, +) -> Result> { + match e { + Expr::BinaryExpr(b) if matches!(b.op, Operator::Eq | Operator::NotEq) => { + // Try both operand orders: `col = 'x'` and `'x' = col`. + for (col_side, lit_side) in [(&b.left, &b.right), (&b.right, &b.left)] { + let Some(col) = unwrap_column(col_side) else { + continue; + }; + let Some(kind) = oid_kind(&col, schema) else { + continue; + }; + let Some(s) = as_str_literal(lit_side) else { + continue; + }; + if let Some(resolved) = resolve_operand(&kind, s, provider)? { + return Ok(Some(Expr::BinaryExpr(BinaryExpr { + left: Box::new(Expr::Column(col)), + op: b.op, + right: Box::new(resolved), + }))); + } + } + Ok(None) + } + Expr::InList(InList { + expr, + list, + negated, + }) => { + let Some(col) = unwrap_column(expr) else { + return Ok(None); + }; + let Some(kind) = oid_kind(&col, schema) else { + return Ok(None); + }; + + // Resolve every string-literal entry; if any is a name we cannot + // resolve (no backing table), leave the whole IN alone rather than + // producing a half-coerced list. + let mut new_list = Vec::with_capacity(list.len()); + let mut any_changed = false; + for item in list { + let Some(s) = as_str_literal(item) else { + new_list.push(item.clone()); + continue; + }; + match resolve_operand(&kind, s, provider)? { + Some(resolved) => { + any_changed = true; + new_list.push(resolved); + } + None => return Ok(None), + } + } + if any_changed { + Ok(Some(Expr::InList(InList { + expr: Box::new(Expr::Column(col)), + list: new_list, + negated: *negated, + }))) + } else { + Ok(None) + } + } + // An explicit oid-alias cast whose kind is stamped on its target Field + // by `PgOidTypePlanner` -- e.g. `'public'::regnamespace`, + // `typinput = 'array_in'::regproc`, or `classoid = 'pg_namespace'::regclass` + // (where `classoid` is a plain `oid`, so only the CAST declares the kind). + // Resolve the cast operand to an oid (literal for numeric strings, + // name-lookup subquery otherwise), in ANY plan position (this arm is + // reached via `map_expressions`, so projections / filters / joins all + // benefit). Returning `None` here for a non-string operand lets the + // rewriter descend into nested casts (e.g. `'x'::regclass::oid`). + Expr::Cast(Cast { + expr: operand, + field, + }) + | Expr::TryCast(TryCast { + expr: operand, + field, + }) if kind_from_field(field).is_some() => { + let kind = kind_from_field(field).unwrap(); + if let Some(s) = immediate_str_literal(operand) { + resolve_operand(&kind, s, provider) + } else { + Ok(None) + } + } + _ => Ok(None), + } +} + +/// If `e` is a `Column`, or a single-level `CAST`/`TRY_CAST` around a `Column` +/// (the post-coercion shape produced by DataFusion's type coercion), return +/// the inner [`Column`]. +fn unwrap_column(e: &Expr) -> Option { + match e { + Expr::Column(c) => Some(c.clone()), + Expr::Cast(Cast { expr, .. }) | Expr::TryCast(TryCast { expr, .. }) => { + match expr.as_ref() { + Expr::Column(c) => Some(c.clone()), + _ => None, + } + } + _ => None, + } +} + +/// The oid-alias kind of `col` if it is annotated in the schema, else `None`. +fn oid_kind(col: &Column, schema: &DFSchemaRef) -> Option { + schema + .field_from_column(col) + .ok()? + .metadata() + .get(OID_ALIAS_KEY) + .cloned() +} + +/// The oid-alias kind stamped on a cast's target [`Field`] by the +/// `PgOidTypePlanner`, if any (e.g. `'x'::regclass` -> `"regclass"`). +fn kind_from_field(field: &datafusion::arrow::datatypes::Field) -> Option { + field.metadata().get(OID_ALIAS_KEY).cloned() +} + +/// The string value of `e` if it is an *immediate* string literal (NOT peeking +/// through a cast), else `None`. Used to recognize the operand of an oid-alias +/// cast (`'name'::regclass`) without conflating it with a nested inner cast. +fn immediate_str_literal(e: &Expr) -> Option<&str> { + if let Expr::Literal(s, _) = e { + match s { + ScalarValue::Utf8(Some(s)) | ScalarValue::LargeUtf8(Some(s)) => Some(s.as_str()), + ScalarValue::Utf8View(Some(s)) => Some(s.as_str()), + _ => None, + } + } else { + None + } +} + +/// If `e` is a string literal -- possibly wrapped in a `CAST`/`TRY_CAST` to an +/// integer type that DataFusion's type-coercion analyzer produces when it sees +/// an `Int32` oid column compared against a string -- return its value; +/// otherwise `None`. +/// +/// Peeking through the cast keeps this rule order-independent: whether our +/// rule runs before type coercion (bare `'str'`) or after it +/// (`CAST('str' AS Int32)`), the same string is recovered. +fn as_str_literal(e: &Expr) -> Option<&str> { + let inner = match e { + Expr::Cast(Cast { expr, .. }) | Expr::TryCast(TryCast { expr, .. }) => expr.as_ref(), + other => other, + }; + if let Expr::Literal(s, _) = inner { + match s { + ScalarValue::Utf8(Some(s)) | ScalarValue::LargeUtf8(Some(s)) => Some(s.as_str()), + ScalarValue::Utf8View(Some(s)) => Some(s.as_str()), + _ => None, + } + } else { + None + } +} + +/// The `(table, name_column)` used to resolve a name to an oid for a given +/// oid-alias kind. Returns `None` for kinds without a backing catalog table +/// (e.g. bare `oid`, or `regtype` where `pg_type` is unavailable) -- those only +/// support numeric resolution. +fn lookup_target(kind: &str) -> Option<(&'static str, &'static str)> { + match kind { + oid_field::kind::REGNAMESPACE => Some(("pg_namespace", "nspname")), + oid_field::kind::REGCLASS => Some(("pg_class", "relname")), + oid_field::kind::REGTYPE => Some(("pg_type", "typname")), + oid_field::kind::REGPROC => Some(("pg_proc", "proname")), + _ => None, + } +} + +/// Resolve a string operand to an oid-valued expression. +/// +/// * numeric strings -> literal `Int32` (Postgres behavior for every +/// oid-alias type); +/// * names -> a scalar subquery `SELECT oid FROM
WHERE = $s` +/// for kinds that have a backing table. +fn resolve_operand( + kind: &str, + s: &str, + provider: &Arc, +) -> Result> { + // Numeric string -> literal oid (valid for every oid-alias kind). + if !s.is_empty() && s.bytes().all(|b| b.is_ascii_digit()) { + return Ok(s + .parse::() + .ok() + .map(|n| Expr::Literal(ScalarValue::Int32(Some(n)), None))); + } + + // Name -> oid lookup subquery (only for kinds with a backing table). + let Some((table, name_col)) = lookup_target(kind) else { + return Ok(None); + }; + let Some(provider) = provider.build_table_provider(table)? else { + return Ok(None); + }; + + let source = provider_as_source(provider); + let plan = LogicalPlanBuilder::scan(table.to_string(), source, None)? + .filter(eq_str(name_col, s))? + .project(vec![Expr::Column(Column::new_unqualified("oid"))])? + .build()?; + Ok(Some(Expr::ScalarSubquery(Subquery { + subquery: Arc::new(plan), + outer_ref_columns: vec![], + spans: Spans::default(), + }))) +} + +/// Build ` = ''` against a freshly-scanned table. +fn eq_str(name_col: &str, s: &str) -> Expr { + Expr::BinaryExpr(BinaryExpr { + left: Box::new(Expr::Column(Column::new_unqualified(name_col))), + op: Operator::Eq, + right: Box::new(Expr::Literal(ScalarValue::Utf8(Some(s.to_string())), None)), + }) +} + +#[cfg(test)] +mod tests { + use super::*; + use datafusion::arrow::datatypes::DataType; + + #[test] + fn lookup_target_only_for_backed_kinds() { + assert_eq!( + lookup_target(oid_field::kind::REGNAMESPACE), + Some(("pg_namespace", "nspname")) + ); + assert_eq!( + lookup_target(oid_field::kind::REGCLASS), + Some(("pg_class", "relname")) + ); + assert_eq!( + lookup_target(oid_field::kind::REGPROC), + Some(("pg_proc", "proname")) + ); + // bare oid has no backing table -> name resolution unsupported + assert_eq!(lookup_target(oid_field::kind::OID), None); + } + + #[test] + fn unwrap_column_handles_bare_and_cast_forms() { + let bare = Expr::Column(Column::new_unqualified("relnamespace")); + assert_eq!( + unwrap_column(&bare).map(|c| c.name().to_string()), + Some("relnamespace".to_string()) + ); + + let cast = Expr::Cast(Cast { + expr: Box::new(Expr::Column(Column::new_unqualified("relnamespace"))), + field: std::sync::Arc::new(datafusion::arrow::datatypes::Field::new( + "", + DataType::Utf8, + true, + )), + }); + assert_eq!( + unwrap_column(&cast).map(|c| c.name().to_string()), + Some("relnamespace".to_string()) + ); + + let trycast = Expr::TryCast(TryCast { + expr: Box::new(Expr::Column(Column::new_unqualified("oid"))), + field: std::sync::Arc::new(datafusion::arrow::datatypes::Field::new( + "", + DataType::Utf8, + true, + )), + }); + assert_eq!( + unwrap_column(&trycast).map(|c| c.name().to_string()), + Some("oid".to_string()) + ); + + // a cast around something that isn't a column is not unwrapped + let nested = Expr::Cast(Cast { + expr: Box::new(Expr::Literal(ScalarValue::Int32(Some(1)), None)), + field: std::sync::Arc::new(datafusion::arrow::datatypes::Field::new( + "", + DataType::Utf8, + true, + )), + }); + assert_eq!(unwrap_column(&nested), None); + } + + #[test] + fn as_str_literal_recognizes_string_variants() { + let u = Expr::Literal(ScalarValue::Utf8(Some("public".to_string())), None); + let lu = Expr::Literal(ScalarValue::LargeUtf8(Some("public".to_string())), None); + let uv = Expr::Literal(ScalarValue::Utf8View(Some("public".to_string())), None); + let n = Expr::Literal(ScalarValue::Int32(Some(3)), None); + assert_eq!(as_str_literal(&u), Some("public")); + assert_eq!(as_str_literal(&lu), Some("public")); + assert_eq!(as_str_literal(&uv), Some("public")); + assert_eq!(as_str_literal(&n), None); + + // DataFusion's type-coercion analyzer wraps the literal in a cast to the + // column's Int32 type (`col = CAST('public' AS Int32)`) when it runs + // before this rule. The string must still be recoverable so the rule + // stays order-independent. + let cast = Expr::Cast(Cast { + expr: Box::new(Expr::Literal( + ScalarValue::Utf8(Some("public".to_string())), + None, + )), + field: std::sync::Arc::new(datafusion::arrow::datatypes::Field::new( + "", + DataType::Int32, + true, + )), + }); + assert_eq!(as_str_literal(&cast), Some("public")); + } + + // --- end-to-end: a real pg_catalog with the analyzer rule installed --- + + use crate::pg_catalog::context::EmptyContextProvider; + use crate::pg_catalog::setup_pg_catalog; + use datafusion::arrow::array::{StringArray, StringViewArray}; + use datafusion::prelude::SessionContext; + + /// Collect the single-column string values of a query into a sorted Vec. + async fn utf8_column(ctx: &SessionContext, query: &str) -> Vec { + let batches = ctx.sql(query).await.unwrap().collect().await.unwrap(); + let mut out = Vec::new(); + for b in &batches { + let col = b.column(0); + let strs: Vec> = match col.data_type() { + DataType::Utf8 => col + .as_any() + .downcast_ref::() + .unwrap() + .iter() + .collect(), + DataType::LargeUtf8 => col + .as_any() + .downcast_ref::>() + .unwrap() + .iter() + .collect(), + DataType::Utf8View => col + .as_any() + .downcast_ref::() + .unwrap() + .iter() + .collect(), + other => panic!("expected string column, got {other:?}"), + }; + for v in strs { + out.push(v.unwrap().to_string()); + } + } + out.sort(); + out + } + + async fn make_ctx() -> SessionContext { + let ctx = SessionContext::new(); + setup_pg_catalog(&ctx, "datafusion", EmptyContextProvider).unwrap(); + ctx + } + + /// Find a schema that actually has relations in `pg_class` and return + /// `(oid_as_string, nspname)`. Data-driven so the test does not depend on + /// any particular schema being present. + async fn schema_with_relations(ctx: &SessionContext) -> (String, String) { + let oids = utf8_column( + ctx, + "SELECT DISTINCT relnamespace::text FROM pg_catalog.pg_class ORDER BY 1 LIMIT 1", + ) + .await; + assert!( + !oids.is_empty(), + "pg_class should contain at least one relation" + ); + let oid = oids[0].clone(); + let names = utf8_column( + ctx, + &format!("SELECT nspname FROM pg_catalog.pg_namespace WHERE oid = {oid}"), + ) + .await; + assert_eq!( + names.len(), + 1, + "relnamespace oid should map to exactly one schema" + ); + (oid, names[0].clone()) + } + + #[tokio::test] + async fn name_string_resolves_like_postgres() { + let ctx = make_ctx().await; + let (oid, name) = schema_with_relations(&ctx).await; + + // Baseline: compare relnamespace against the schema oid as an int. + let baseline = utf8_column( + &ctx, + &format!("SELECT relname FROM pg_catalog.pg_class WHERE relnamespace = {oid}"), + ) + .await; + assert!( + !baseline.is_empty(), + "baseline (int oid) should match relations" + ); + + // The headline case: compare against a NAME string. Without the rule + // DataFusion silently returns 0 rows; with it, Postgres name->oid + // resolution applies and the same relations match. + let by_name = utf8_column( + &ctx, + &format!("SELECT relname FROM pg_catalog.pg_class WHERE relnamespace = '{name}'"), + ) + .await; + assert_eq!( + by_name, baseline, + "name-string resolution must match int-oid resolution (name={name}, oid={oid})" + ); + } + + #[tokio::test] + async fn numeric_string_resolves_to_literal_oid() { + let ctx = make_ctx().await; + let (oid, _name) = schema_with_relations(&ctx).await; + let baseline = utf8_column( + &ctx, + &format!("SELECT relname FROM pg_catalog.pg_class WHERE relnamespace = {oid}"), + ) + .await; + let by_numeric_str = utf8_column( + &ctx, + &format!("SELECT relname FROM pg_catalog.pg_class WHERE relnamespace = '{oid}'"), + ) + .await; + assert_eq!( + by_numeric_str, baseline, + "numeric-string resolution must match int-oid resolution" + ); + } + + #[tokio::test] + async fn in_list_with_name_resolves() { + let ctx = make_ctx().await; + let (oid, name) = schema_with_relations(&ctx).await; + let baseline = utf8_column( + &ctx, + &format!("SELECT relname FROM pg_catalog.pg_class WHERE relnamespace = {oid}"), + ) + .await; + let via_in = utf8_column( + &ctx, + &format!("SELECT relname FROM pg_catalog.pg_class WHERE relnamespace IN ('{name}')"), + ) + .await; + assert_eq!( + via_in, baseline, + "IN ('{name}') must resolve the name the same as = {oid}" + ); + } + + /// End-to-end proof that oid metadata embedded in the FEATHER files (not + /// hand-annotated in the dynamic builder) reaches the analyzer rule. + /// `pg_type` and `pg_proc` are both static tables loaded from feather; + /// `pg_type.typinput` is annotated `regproc` purely via the export script. + #[tokio::test] + async fn feather_metadata_reaches_rule_for_static_tables() { + let ctx = make_ctx().await; + + // Find a pg_type row whose typinput maps to a real pg_proc row, so we + // have a concrete (name, oid) pair to test name resolution. + let pairs = utf8_column( + &ctx, + "SELECT p.proname FROM pg_catalog.pg_proc p \ + JOIN pg_catalog.pg_type t ON t.typinput = p.oid \ + WHERE p.proname IS NOT NULL LIMIT 1", + ) + .await; + assert!(!pairs.is_empty(), "should find a pg_type/pg_proc join"); + let proc_name = &pairs[0]; + + // Baseline: the int oid of that proc. + let oid_rows = utf8_column( + &ctx, + &format!( + "SELECT oid::text FROM pg_catalog.pg_proc WHERE proname = '{proc_name}' LIMIT 1" + ), + ) + .await; + let oid = &oid_rows[0]; + + // Baseline: pg_type rows whose typinput equals that oid (as int). + let baseline = utf8_column( + &ctx, + &format!("SELECT typname FROM pg_catalog.pg_type WHERE typinput = {oid}"), + ) + .await; + + // The headline: compare typinput (regproc, from feather metadata) + // against the proc NAME string. Without the rule this returns 0 rows; + // with it, the name resolves via pg_proc and matches the baseline. + let by_name = utf8_column( + &ctx, + &format!("SELECT typname FROM pg_catalog.pg_type WHERE typinput = '{proc_name}'"), + ) + .await; + assert_eq!( + by_name, baseline, + "feather-annotated regproc column must resolve name strings via the rule" + ); + } +} diff --git a/datafusion-pg-catalog/src/pg_catalog/oid_field.rs b/datafusion-pg-catalog/src/pg_catalog/oid_field.rs new file mode 100644 index 0000000..ab1c102 --- /dev/null +++ b/datafusion-pg-catalog/src/pg_catalog/oid_field.rs @@ -0,0 +1,105 @@ +//! Arrow `Field` metadata helpers for marking Postgres oid / oid-alias columns. +//! +//! Postgres catalog columns like `pg_class.relnamespace` or `pg_attribute.atttypid` +//! are stored as `integer` (Arrow `Int32`) but are semantically *object +//! identifiers* that clients frequently compare against *string* literals +//! (`WHERE relnamespace = 'public'`, `WHERE atttypid = 'int4'`). DataFusion has +//! no notion of "oid"; it silently coerces such comparisons the wrong way and +//! returns empty results (see the `oid_string_coercion` analyzer rule). +//! +//! To fix that, oid / oid-alias columns are annotated here with Field metadata, +//! which survives into the logical plan schema and is readable via +//! [`datafusion::common::ExprSchema::metadata`]. + +use std::collections::HashMap; + +use datafusion::arrow::datatypes::{DataType, Field}; + +/// Field metadata key whose value names the oid-alias kind of a column. +/// +/// Example: a `relnamespace Int32` column carries +/// `{ "pg.oid_alias": "regnamespace" }`. +pub const OID_ALIAS_KEY: &str = "pg.oid_alias"; + +/// The supported oid-alias "kinds", stored as the value under [`OID_ALIAS_KEY`]. +pub mod kind { + /// A bare `oid` column. Name strings are *not* resolvable (only numeric). + pub const OID: &str = "oid"; + /// A `regclass` column (relation oid). Name strings resolve via `pg_class`. + pub const REGCLASS: &str = "regclass"; + /// A `regnamespace` column (namespace oid). Resolves via `pg_namespace`. + pub const REGNAMESPACE: &str = "regnamespace"; + /// A `regtype` column (type oid). Numeric-only here (no `pg_type` table). + pub const REGTYPE: &str = "regtype"; + /// A `regproc` column (function oid). Resolves via `pg_proc`. + pub const REGPROC: &str = "regproc"; +} + +/// Every Postgres oid-alias type name this crate recognizes. +/// +/// This is the **single source of truth** for: +/// * the `pg.oid_alias` metadata value stamped on Int32 catalog columns (see +/// [`oid_field`]) and embedded in the pg_catalog feather exports, and +/// * the set of oid-alias cast type names accepted by the `PgOidTypePlanner` +/// SQL type planner (so DataFusion's `sql_to_plan` maps them to int4 oids +/// carrying this metadata instead of rejecting them as unsupported types). +/// +/// The oid-coercion analyzer rule then reads the metadata (on the column or +/// on the cast's target field) to resolve string comparisons the way Postgres +/// does. The +/// [`kind`] named constants anchor the subset that the dynamic catalog tables +/// use and that have name-lookup support (`regclass`/`regnamespace`/`regproc`); +/// the remainder are numeric-resolution-only. +pub const OID_ALIAS_TYPE_NAMES: &[&str] = &[ + kind::OID, + kind::REGPROC, + "regprocedure", + "regoper", + "regoperator", + kind::REGCLASS, + kind::REGTYPE, + kind::REGNAMESPACE, + "regrole", + "regconfig", + "regdictionary", + "regcollation", +]; + +/// Build an `Int32` [`Field`] for an oid / oid-alias column, annotated with +/// metadata so the oid-coercion analyzer rule can recognize it. +/// +/// `kind` should be one of the names in [`OID_ALIAS_TYPE_NAMES`] (e.g. +/// [`kind::REGNAMESPACE`]). +pub fn oid_field(name: impl Into, kind: &str, nullable: bool) -> Field { + debug_assert!( + OID_ALIAS_TYPE_NAMES.contains(&kind), + "unknown oid-alias kind: {kind}" + ); + Field::new(name, DataType::Int32, nullable).with_metadata(HashMap::from([( + OID_ALIAS_KEY.to_string(), + kind.to_string(), + )])) +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn oid_field_carries_kind_metadata() { + let f = oid_field("relnamespace", kind::REGNAMESPACE, false); + assert_eq!(f.data_type(), &DataType::Int32); + assert_eq!( + f.metadata().get(OID_ALIAS_KEY).map(String::as_str), + Some("regnamespace") + ); + assert!(!f.is_nullable()); + + let nullable = oid_field("reloftype", kind::REGTYPE, true); + assert!(nullable.is_nullable()); + assert_eq!( + nullable.metadata().get(OID_ALIAS_KEY).map(String::as_str), + Some("regtype") + ); + } +} diff --git a/datafusion-pg-catalog/src/pg_catalog/oid_type_planner.rs b/datafusion-pg-catalog/src/pg_catalog/oid_type_planner.rs new file mode 100644 index 0000000..86f5edd --- /dev/null +++ b/datafusion-pg-catalog/src/pg_catalog/oid_type_planner.rs @@ -0,0 +1,154 @@ +//! A DataFusion [`TypePlanner`] that teaches the SQL planner to accept the +//! Postgres oid-alias type names (`regclass`, `regproc`, `regtype`, +//! `regnamespace`, `oid`, ...) that DataFusion otherwise rejects as +//! "Unsupported SQL type". +//! +//! Each such type is mapped to an `Int32` [`Field`] (oids are stored as int4) +//! carrying the same `pg.oid_alias` metadata the catalog columns use, so the +//! kind survives into the logical plan inside the resulting [`Expr::Cast`]'s +//! `field`. The oid-coercion analyzer rule then reads that metadata to resolve +//! name strings -> oids the way Postgres does -- no SQL/AST rewriting needed. +//! +//! This is the metadata-aware replacement for the former `RemoveOidTypeCast` +//! (SQL rewrite) + `RewriteRegCastToSubquery` (SQL rewrite) pair: instead of +//! stripping the cast at the AST layer (losing the type) and reconstructing it +//! later, the type is accepted up front and resolved at the analyzer layer. + +use std::sync::Arc; + +use datafusion::arrow::datatypes::{DataType, Field}; +use datafusion::common::Result; +use datafusion::logical_expr::planner::TypePlanner; +use datafusion::sql::sqlparser::ast::{DataType as SQLDataType, ObjectNamePart}; + +use crate::pg_catalog::oid_field::{self, OID_ALIAS_KEY, OID_ALIAS_TYPE_NAMES}; + +/// Recognize every Postgres oid-alias type name and map it to an int4 oid +/// [`Field`] annotated with its `pg.oid_alias` kind. +#[derive(Debug, Default)] +pub struct PgOidTypePlanner; + +impl PgOidTypePlanner { + /// Build the int4 oid field for a given kind (`regclass`, `oid`, ...). + fn oid_field(kind: &str) -> Arc { + Arc::new(Field::new("", DataType::Int32, true).with_metadata( + std::collections::HashMap::from([(OID_ALIAS_KEY.to_string(), kind.to_string())]), + )) + } + + /// Lowercase last identifier of a `Custom(...)` type name, if any. + /// + /// `regproc` -> `regproc`, `pg_catalog.regclass` -> `regclass`. + fn custom_type_name(sql_type: &SQLDataType) -> Option { + let SQLDataType::Custom(name, args) = sql_type else { + return None; + }; + if !args.is_empty() { + return None; + } + let last = name.0.last()?; + let ObjectNamePart::Identifier(ident) = last else { + return None; + }; + Some(ident.value.to_lowercase()) + } + + /// The oid-alias kind for a SQL type, if it is one we handle. + fn kind_for(sql_type: &SQLDataType) -> Option { + match sql_type { + SQLDataType::Regclass => Some(oid_field::kind::REGCLASS.to_string()), + SQLDataType::Custom(_, _) => Self::custom_type_name(sql_type) + .filter(|n| OID_ALIAS_TYPE_NAMES.contains(&n.as_str())), + _ => None, + } + } +} + +impl TypePlanner for PgOidTypePlanner { + fn plan_type_field(&self, sql_type: &SQLDataType) -> Result>> { + // Scalar oid-alias types -> int4 with kind metadata. + if let Some(kind) = Self::kind_for(sql_type) { + return Ok(Some(Self::oid_field(&kind))); + } + // Array of an oid-alias type (e.g. `regtype[]`): a list whose *element* + // field carries the kind metadata. The recursion below consults this + // planner again for the inner type; DataFusion wraps the result with + // `into_list()` before reaching us, so we only see the scalar here in + // practice -- but handle the bracketed form defensively. + Ok(None) + } +} + +#[cfg(test)] +mod tests { + use super::*; + use datafusion::sql::sqlparser::dialect::PostgreSqlDialect; + use datafusion::sql::sqlparser::parser::Parser; + + fn cast_target_type(sql: &str) -> SQLDataType { + // SELECT 'x':: AS c -> the cast's target DataType + let mut stmts = Parser::parse_sql(&PostgreSqlDialect {}, sql).unwrap(); + let stmt = stmts.remove(0); + use datafusion::sql::sqlparser::ast::{SetExpr, Statement}; + let Statement::Query(q) = stmt else { + panic!("not a query"); + }; + let SetExpr::Select(sel) = *q.body else { + panic!("not a select"); + }; + let cast = match &sel.projection[0] { + datafusion::sql::sqlparser::ast::SelectItem::UnnamedExpr(e) => e, + datafusion::sql::sqlparser::ast::SelectItem::ExprWithAlias { expr, .. } => expr, + other => panic!("unexpected projection {other:?}"), + }; + let datafusion::sql::sqlparser::ast::Expr::Cast { data_type, .. } = cast else { + panic!("not a cast: {cast:?}"); + }; + data_type.clone() + } + + #[test] + fn recognizes_all_oid_alias_type_names() { + let planner = PgOidTypePlanner; + for t in [ + "regclass", + "regproc", + "regtype", + "regnamespace", + "oid", + "pg_catalog.regclass", + "pg_catalog.regtype", + "regrole", + ] { + let dt = cast_target_type(&format!("SELECT 'x'::{t} AS c")); + let field = planner.plan_type_field(&dt).unwrap().unwrap(); + assert_eq!(field.data_type(), &DataType::Int32, "{t}"); + let kind = field.metadata().get(OID_ALIAS_KEY).cloned(); + assert!(kind.is_some(), "{t} should carry oid-alias metadata"); + assert!( + OID_ALIAS_TYPE_NAMES.contains(&kind.unwrap().as_str()), + "{t} kind must be canonical" + ); + } + } + + #[test] + fn leaves_non_oid_types_alone() { + let planner = PgOidTypePlanner; + for t in ["int4", "text", "varchar", "timestamp"] { + let dt = cast_target_type(&format!("SELECT 'x'::{t} AS c")); + assert_eq!(planner.plan_type_field(&dt).unwrap(), None, "{t}"); + } + } + + #[test] + fn pg_catalog_prefix_normalizes_to_kind() { + let planner = PgOidTypePlanner; + let dt = cast_target_type("SELECT 'x'::pg_catalog.regproc AS c"); + let field = planner.plan_type_field(&dt).unwrap().unwrap(); + assert_eq!( + field.metadata().get(OID_ALIAS_KEY).map(String::as_str), + Some(oid_field::kind::REGPROC) + ); + } +} diff --git a/datafusion-pg-catalog/src/pg_catalog/pg_attribute.rs b/datafusion-pg-catalog/src/pg_catalog/pg_attribute.rs index 2561329..9246855 100644 --- a/datafusion-pg-catalog/src/pg_catalog/pg_attribute.rs +++ b/datafusion-pg-catalog/src/pg_catalog/pg_attribute.rs @@ -16,6 +16,7 @@ use tokio::sync::RwLock; use crate::pg_catalog::catalog_info::CatalogInfo; use super::OidCacheKey; +use super::oid_field; #[derive(Debug, Clone)] pub(crate) struct PgAttributeTable { @@ -34,11 +35,11 @@ impl PgAttributeTable { // Define the schema for pg_attribute // This matches PostgreSQL's pg_attribute table columns let schema = Arc::new(Schema::new(vec![ - Field::new("attrelid", DataType::Int32, false), // OID of the relation this column belongs to - Field::new("attname", DataType::Utf8, false), // Column name - Field::new("atttypid", DataType::Int32, false), // OID of the column data type - Field::new("attstattarget", DataType::Int32, false), // Statistics target - Field::new("attlen", DataType::Int16, false), // Length of the type + oid_field::oid_field("attrelid", oid_field::kind::REGCLASS, false), // OID of the relation this column belongs to + Field::new("attname", DataType::Utf8, false), // Column name + oid_field::oid_field("atttypid", oid_field::kind::REGTYPE, false), // OID of the column data type + Field::new("attstattarget", DataType::Int32, false), // Statistics target + Field::new("attlen", DataType::Int16, false), // Length of the type Field::new("attnum", DataType::Int16, false), // Column number (positive for regular columns) Field::new("attndims", DataType::Int32, false), // Number of dimensions for array types Field::new("attcacheoff", DataType::Int32, false), // Cache offset diff --git a/datafusion-pg-catalog/src/pg_catalog/pg_class.rs b/datafusion-pg-catalog/src/pg_catalog/pg_class.rs index 58978e5..2b0b3ba 100644 --- a/datafusion-pg-catalog/src/pg_catalog/pg_class.rs +++ b/datafusion-pg-catalog/src/pg_catalog/pg_class.rs @@ -12,6 +12,8 @@ use datafusion::execution::{SendableRecordBatchStream, TaskContext}; use datafusion::physical_plan::stream::RecordBatchStreamAdapter; use datafusion::physical_plan::streaming::PartitionStream; use postgres_types::Oid; + +use super::oid_field; use tokio::sync::RwLock; use crate::pg_catalog::catalog_info::{CatalogInfo, table_type_to_string}; @@ -35,11 +37,11 @@ impl PgClassTable { // Define the schema for pg_class // This matches key columns from PostgreSQL's pg_class let schema = Arc::new(Schema::new(vec![ - Field::new("oid", DataType::Int32, false), // Object identifier + oid_field::oid_field("oid", oid_field::kind::OID, false), // Object identifier Field::new("relname", DataType::Utf8, false), // Name of the table, index, view, etc. - Field::new("relnamespace", DataType::Int32, false), // OID of the namespace that contains this relation - Field::new("reltype", DataType::Int32, false), // OID of the data type (composite type) this table describes - Field::new("reloftype", DataType::Int32, true), // OID of the composite type for typed table, 0 otherwise + oid_field::oid_field("relnamespace", oid_field::kind::REGNAMESPACE, false), // OID of the namespace that contains this relation + oid_field::oid_field("reltype", oid_field::kind::REGTYPE, false), // OID of the data type (composite type) this table describes + oid_field::oid_field("reloftype", oid_field::kind::REGTYPE, true), // OID of the composite type for typed table, 0 otherwise Field::new("relowner", DataType::Int32, false), // Owner of the relation Field::new("relam", DataType::Int32, false), // If this is an index, the access method used Field::new("relfilenode", DataType::Int32, false), // Name of the on-disk file of this relation @@ -47,7 +49,7 @@ impl PgClassTable { Field::new("relpages", DataType::Int32, false), // Size of the on-disk representation in pages Field::new("reltuples", DataType::Float64, false), // Number of tuples Field::new("relallvisible", DataType::Int32, false), // Number of all-visible pages - Field::new("reltoastrelid", DataType::Int32, false), // OID of the TOAST table + oid_field::oid_field("reltoastrelid", oid_field::kind::REGCLASS, false), // OID of the TOAST table Field::new("relhasindex", DataType::Boolean, false), // True if this is a table and it has (or recently had) any indexes Field::new("relisshared", DataType::Boolean, false), // True if this table is shared across all databases Field::new("relpersistence", DataType::Utf8, false), // p=permanent table, u=unlogged table, t=temporary table @@ -62,7 +64,7 @@ impl PgClassTable { Field::new("relispopulated", DataType::Boolean, false), // True if relation is populated (not true for some materialized views) Field::new("relreplident", DataType::Utf8, false), // Columns used to form "replica identity" for rows Field::new("relispartition", DataType::Boolean, false), // True if table is a partition - Field::new("relrewrite", DataType::Int32, true), // OID of a rule that rewrites this relation + oid_field::oid_field("relrewrite", oid_field::kind::REGCLASS, true), // OID of a rule that rewrites this relation Field::new("relfrozenxid", DataType::Int32, false), // All transaction IDs before this have been replaced with a permanent ("frozen") transaction ID Field::new("relminmxid", DataType::Int32, false), // All Multixact IDs before this have been replaced with a transaction ID Field::new("relpartbound", DataType::Utf8, true), diff --git a/datafusion-pg-catalog/src/pg_catalog/pg_namespace.rs b/datafusion-pg-catalog/src/pg_catalog/pg_namespace.rs index 923ca9b..663b68e 100644 --- a/datafusion-pg-catalog/src/pg_catalog/pg_namespace.rs +++ b/datafusion-pg-catalog/src/pg_catalog/pg_namespace.rs @@ -8,6 +8,8 @@ use datafusion::error::Result; use datafusion::execution::{SendableRecordBatchStream, TaskContext}; use datafusion::physical_plan::stream::RecordBatchStreamAdapter; use datafusion::physical_plan::streaming::PartitionStream; + +use super::oid_field; use postgres_types::Oid; use tokio::sync::RwLock; @@ -32,11 +34,11 @@ impl PgNamespaceTable { // Define the schema for pg_namespace // This matches the columns from PostgreSQL's pg_namespace let schema = Arc::new(Schema::new(vec![ - Field::new("oid", DataType::Int32, false), // Object identifier + oid_field::oid_field("oid", oid_field::kind::OID, false), // Object identifier Field::new("nspname", DataType::Utf8, false), // Name of the namespace (schema) Field::new("nspowner", DataType::Int32, false), // Owner of the namespace - Field::new("nspacl", DataType::Utf8, true), // Access privileges - Field::new("options", DataType::Utf8, true), // Schema-level options + Field::new("nspacl", DataType::Utf8, true), // Access privileges + Field::new("options", DataType::Utf8, true), // Schema-level options ])); Self { diff --git a/datafusion-pg-catalog/src/sql/parser.rs b/datafusion-pg-catalog/src/sql/parser.rs index a918b5b..df40bb6 100644 --- a/datafusion-pg-catalog/src/sql/parser.rs +++ b/datafusion-pg-catalog/src/sql/parser.rs @@ -9,6 +9,7 @@ use datafusion::sql::sqlparser::tokenizer::Token; use datafusion::sql::sqlparser::tokenizer::TokenWithSpan; use super::rules::AliasDuplicatedProjectionRewrite; +use super::rules::CastArrayBoundsForGenerateSeries; use super::rules::CurrentUserVariableToSessionUserFunctionCall; use super::rules::FixArrayLiteral; use super::rules::FixCollate; @@ -16,10 +17,8 @@ use super::rules::FixVersionColumnName; use super::rules::PrependUnqualifiedPgTableName; use super::rules::RemoveQualifier; use super::rules::RemoveSubqueryFromProjection; -use super::rules::RemoveUnsupportedTypes; use super::rules::ResolveUnqualifiedIdentifer; use super::rules::RewriteArrayAnyAllOperation; -use super::rules::RewriteRegclassCastToSubquery; use super::rules::SqlStatementRewriteRule; const BLACKLIST_SQL_MAPPING: &[(&str, &str)] = &[ @@ -230,8 +229,7 @@ impl PostgresCompatibilityParser { Arc::new(RewriteArrayAnyAllOperation), Arc::new(PrependUnqualifiedPgTableName), Arc::new(RemoveQualifier), - Arc::new(RewriteRegclassCastToSubquery::new()), - Arc::new(RemoveUnsupportedTypes::new()), + Arc::new(CastArrayBoundsForGenerateSeries), Arc::new(FixArrayLiteral), Arc::new(CurrentUserVariableToSessionUserFunctionCall), Arc::new(FixCollate), diff --git a/datafusion-pg-catalog/src/sql/rules.rs b/datafusion-pg-catalog/src/sql/rules.rs index dd2f8fe..9975da8 100644 --- a/datafusion-pg-catalog/src/sql/rules.rs +++ b/datafusion-pg-catalog/src/sql/rules.rs @@ -25,16 +25,14 @@ use datafusion::sql::sqlparser::ast::SelectItemQualifiedWildcardKind; use datafusion::sql::sqlparser::ast::SetExpr; use datafusion::sql::sqlparser::ast::Statement; use datafusion::sql::sqlparser::ast::TableFactor; +use datafusion::sql::sqlparser::ast::TableFunctionArgs; use datafusion::sql::sqlparser::ast::TableWithJoins; -use datafusion::sql::sqlparser::ast::TypedString; use datafusion::sql::sqlparser::ast::UnaryOperator; use datafusion::sql::sqlparser::ast::Value; use datafusion::sql::sqlparser::ast::ValueWithSpan; use datafusion::sql::sqlparser::ast::VisitMut; use datafusion::sql::sqlparser::ast::Visitor; use datafusion::sql::sqlparser::ast::VisitorMut; -use datafusion::sql::sqlparser::dialect::PostgreSqlDialect; -use datafusion::sql::sqlparser::parser::Parser; pub trait SqlStatementRewriteRule: Send + Sync + Debug { fn rewrite(&self, s: Statement) -> Statement; @@ -299,239 +297,74 @@ impl SqlStatementRewriteRule for ResolveUnqualifiedIdentifer { } } -/// Remove datafusion unsupported type annotations -/// it also removes pg_catalog as qualifier -#[derive(Debug)] -pub struct RemoveUnsupportedTypes { - unsupported_types: HashSet, -} - -impl Default for RemoveUnsupportedTypes { - fn default() -> Self { - Self::new() - } -} - -impl RemoveUnsupportedTypes { - pub fn new() -> Self { - let mut unsupported_types = HashSet::new(); - - for item in [ - "regclass", - "regproc", - "regtype", - "regtype[]", - "regnamespace", - "oid", - ] { - unsupported_types.insert(item.to_owned()); - unsupported_types.insert(format!("pg_catalog.{item}")); - } - - Self { unsupported_types } - } -} - -struct RemoveUnsupportedTypesVisitor<'a> { - unsupported_types: &'a HashSet, -} - -impl VisitorMut for RemoveUnsupportedTypesVisitor<'_> { - type Break = (); - - fn pre_visit_expr(&mut self, expr: &mut Expr) -> ControlFlow { - match expr { - // This is the key part: identify constants with type annotations. - Expr::TypedString(TypedString { - data_type, - value, - uses_odbc_syntax: _, - }) if self - .unsupported_types - .contains(data_type.to_string().to_lowercase().as_str()) => - { - *expr = Expr::Value(Value::SingleQuotedString(value.to_string()).with_empty_span()); - } - Expr::Cast { - data_type, - expr: value, - .. - } if self - .unsupported_types - .contains(data_type.to_string().to_lowercase().as_str()) => - { - *expr = *value.clone(); - } - - // Add more match arms for other expression types (e.g., `Function`, `InList`) as needed. - _ => {} - } - - ControlFlow::Continue(()) - } -} - -impl SqlStatementRewriteRule for RemoveUnsupportedTypes { - fn rewrite(&self, mut statement: Statement) -> Statement { - let mut visitor = RemoveUnsupportedTypesVisitor { - unsupported_types: &self.unsupported_types, - }; - let _ = statement.visit(&mut visitor); - statement - } -} - -/// Rewrite regclass::oid cast to subquery +/// Cast `array_upper`/`array_lower` results to `bigint` when used as +/// `generate_series` arguments. /// -/// This rewrites patterns like `$1::regclass::oid` to -/// `(SELECT oid FROM pg_catalog.pg_class WHERE relname = $1)` +/// DataFusion's `generate_series` requires Int64 bounds, but our +/// `array_upper`/`array_lower` UDFs return Int32 (correct Postgres semantics -- +/// Postgres `array_upper` returns `int4`). Postgres implicitly coerces int4 to +/// int8 for `generate_series`; DataFusion does not, so without this rule +/// `generate_series(1, array_upper(current_schemas(false), 1))` fails with +/// "Argument #2 must be an INTEGER". This rule performs the coercion the way +/// Postgres would, removing the need to blacklist such client queries. #[derive(Debug)] -pub struct RewriteRegclassCastToSubquery(Box); - -impl Default for RewriteRegclassCastToSubquery { - fn default() -> Self { - Self::new() - } -} - -impl RewriteRegclassCastToSubquery { - pub fn new() -> Self { - let sql = "SELECT c.oid -FROM pg_catalog.pg_class c -JOIN pg_catalog.pg_namespace n ON n.oid = c.relnamespace -CROSS JOIN (SELECT parse_ident($1::TEXT) AS parts) p -WHERE n.nspname = COALESCE( - CASE WHEN array_length(p.parts, 1) > 1 THEN p.parts[1] END, - current_schema() -) -AND c.relname = p.parts[-1]"; - let dialect = PostgreSqlDialect {}; - let query = Parser::parse_sql(&dialect, sql) - .map(|mut stmts| { - let stmt = stmts.remove(0); - if let Statement::Query(query) = stmt { - query - } else { - unreachable!() - } - }) - .expect("Failed to parse prepared query"); - Self(query) - } -} - -struct RewriteRegclassCastToSubqueryVisitor(Box); - -impl RewriteRegclassCastToSubqueryVisitor { - pub fn new(query: Box) -> Self { - Self(query) - } - - fn create_subquery(&self, expr: &Expr) -> Expr { - struct PlaceholderReplacer(Expr); - - impl VisitorMut for PlaceholderReplacer { - type Break = (); - - fn pre_visit_expr(&mut self, e: &mut Expr) -> ControlFlow { - if let Expr::Value(ValueWithSpan { - value: Value::Placeholder(_placeholder), - .. - }) = e - { - *e = self.0.clone(); - } - ControlFlow::Continue(()) - } - } +pub struct CastArrayBoundsForGenerateSeries; - let mut query = self.0.clone(); - let mut replacer = PlaceholderReplacer(expr.clone()); - let _ = query.visit(&mut replacer); - Expr::Subquery(query) - } - - fn is_regclass_to_oid_cast(&self, expr: &Expr) -> bool { - if let Expr::Cast { - kind, - data_type, - expr: inner_expr, - format: _, - .. - } = expr - && *kind == CastKind::DoubleColon - { - let dt_lower = data_type.to_string().to_lowercase(); - if dt_lower == "oid" || dt_lower == "pg_catalog.oid" { - return self.is_regclass_cast(inner_expr); - } - } - false - } +struct CastArrayBoundsForGenerateSeriesVisitor; - fn is_regclass_cast(&self, expr: &Expr) -> bool { - if let Expr::Cast { - kind, - data_type, - expr: _, - format: _, - .. - } = expr - && *kind == CastKind::DoubleColon +impl CastArrayBoundsForGenerateSeriesVisitor { + /// True when `expr` is a call to `array_upper`/`array_lower` (optionally + /// `pg_catalog.`-qualified) -- the Int32-returning UDFs that collide with + /// `generate_series`'s Int64 requirement. + fn is_array_bounds_call(expr: &Expr) -> bool { + if let Expr::Function(f) = expr + && let Some(ObjectNamePart::Identifier(ident)) = f.name.0.last() { - let dt_lower = data_type.to_string().to_lowercase(); - return dt_lower == "regclass" || dt_lower == "pg_catalog.regclass"; + let v = ident.value.to_lowercase(); + return v == "array_upper" || v == "array_lower"; } false } - fn extract_inner_expr(&self, expr: &Expr) -> Option { - if let Expr::Cast { - kind, - data_type, - expr: inner_expr, - format: _, - .. - } = expr - && *kind == CastKind::DoubleColon - { - let dt_lower = data_type.to_string().to_lowercase(); - if (dt_lower == "oid" || dt_lower == "pg_catalog.oid") - && let Expr::Cast { - kind: inner_kind, - data_type: inner_data_type, - expr: inner_inner_expr, - format: _, - .. - } = inner_expr.as_ref() - && *inner_kind == CastKind::DoubleColon - { - let inner_dt_lower = inner_data_type.to_string().to_lowercase(); - if inner_dt_lower == "regclass" || inner_dt_lower == "pg_catalog.regclass" { - return Some((**inner_inner_expr).clone()); - } - } + /// Wrap `expr` in `::bigint` if it's an array_bounds call. + fn maybe_cast(expr: &mut Expr) { + if Self::is_array_bounds_call(expr) { + let inner = std::mem::replace(expr, Expr::Value(Value::Null.with_empty_span())); + *expr = Expr::Cast { + expr: Box::new(inner), + kind: CastKind::DoubleColon, + data_type: DataType::BigInt(None), + array: false, + format: None, + }; } - None } } -impl VisitorMut for RewriteRegclassCastToSubqueryVisitor { +impl VisitorMut for CastArrayBoundsForGenerateSeriesVisitor { type Break = (); - fn pre_visit_expr(&mut self, expr: &mut Expr) -> ControlFlow { - if self.is_regclass_to_oid_cast(expr) - && let Some(inner_expr) = self.extract_inner_expr(expr) + fn pre_visit_table_factor(&mut self, tf: &mut TableFactor) -> ControlFlow { + if let TableFactor::Table { name, args, .. } = tf + && let Some(ObjectNamePart::Identifier(ident)) = name.0.last() + && ident.value.to_lowercase() == "generate_series" + && let Some(TableFunctionArgs { + args: func_args, .. + }) = args { - *expr = self.create_subquery(&inner_expr); + for fa in func_args { + if let FunctionArg::Unnamed(FunctionArgExpr::Expr(e)) = fa { + Self::maybe_cast(e); + } + } } ControlFlow::Continue(()) } } -impl SqlStatementRewriteRule for RewriteRegclassCastToSubquery { +impl SqlStatementRewriteRule for CastArrayBoundsForGenerateSeries { fn rewrite(&self, mut s: Statement) -> Statement { - let mut visitor = RewriteRegclassCastToSubqueryVisitor::new(self.0.clone()); + let mut visitor = CastArrayBoundsForGenerateSeriesVisitor; let _ = s.visit(&mut visitor); s } @@ -1098,8 +931,7 @@ impl SqlStatementRewriteRule for FixVersionColumnName { mod tests { use super::*; use datafusion::sql::sqlparser::dialect::PostgreSqlDialect; - use datafusion::sql::sqlparser::parser::Parser; - use datafusion::sql::sqlparser::parser::ParserError; + use datafusion::sql::sqlparser::parser::{Parser, ParserError}; use std::sync::Arc; fn parse(sql: &str) -> Result, ParserError> { @@ -1190,74 +1022,34 @@ mod tests { } #[test] - fn test_remove_unsupported_types() { - let rules: Vec> = vec![ - Arc::new(RemoveQualifier), - Arc::new(RemoveUnsupportedTypes::new()), - ]; - - assert_rewrite!( - &rules, - "SELECT n.* FROM pg_catalog.pg_namespace n WHERE n.nspname = 'pg_catalog'::regclass ORDER BY n.nspname", - "SELECT n.* FROM pg_catalog.pg_namespace n WHERE n.nspname = 'pg_catalog' ORDER BY n.nspname" - ); - - assert_rewrite!( - &rules, - "SELECT n.* FROM pg_catalog.pg_namespace n WHERE n.oid = 1 AND n.nspname = 'pg_catalog'::regclass ORDER BY n.nspname", - "SELECT n.* FROM pg_catalog.pg_namespace n WHERE n.oid = 1 AND n.nspname = 'pg_catalog' ORDER BY n.nspname" - ); - - assert_rewrite!( - &rules, - "SELECT n.oid, n.*, d.description FROM pg_catalog.pg_namespace n LEFT OUTER JOIN pg_catalog.pg_description d ON d.objoid = n.oid AND d.objsubid = 0 AND d.classoid = 'pg_namespace'::regclass ORDER BY nspname", - "SELECT n.oid, n.*, d.description FROM pg_catalog.pg_namespace n LEFT OUTER JOIN pg_catalog.pg_description d ON d.objoid = n.oid AND d.objsubid = 0 AND d.classoid = 'pg_namespace' ORDER BY nspname" - ); - - assert_rewrite!( - &rules, - "SELECT n.* FROM pg_catalog.pg_namespace n WHERE n.nspname = 'pg_catalog' ORDER BY n.nspname", - "SELECT n.* FROM pg_catalog.pg_namespace n WHERE n.nspname = 'pg_catalog' ORDER BY n.nspname" - ); - - assert_rewrite!( - &rules, - "SELECT c.relchecks, c.relkind, c.relhasindex, c.relhasrules, c.relhastriggers, c.relrowsecurity, c.relforcerowsecurity, false AS relhasoids, c.relispartition, '', c.reltablespace, CASE WHEN c.reloftype = 0 THEN '' ELSE c.reloftype::pg_catalog.regtype::pg_catalog.text END, c.relpersistence, c.relreplident, am.amname - FROM pg_catalog.pg_class c - LEFT JOIN pg_catalog.pg_class tc ON (c.reltoastrelid = tc.oid) - LEFT JOIN pg_catalog.pg_am am ON (c.relam = am.oid) - WHERE c.oid = '16386'", - "SELECT c.relchecks, c.relkind, c.relhasindex, c.relhasrules, c.relhastriggers, c.relrowsecurity, c.relforcerowsecurity, false AS relhasoids, c.relispartition, '', c.reltablespace, CASE WHEN c.reloftype = 0 THEN '' ELSE c.reloftype::TEXT END, c.relpersistence, c.relreplident, am.amname FROM pg_catalog.pg_class c LEFT JOIN pg_catalog.pg_class tc ON (c.reltoastrelid = tc.oid) LEFT JOIN pg_catalog.pg_am am ON (c.relam = am.oid) WHERE c.oid = '16386'" - ); - } - - #[test] - fn test_rewrite_regclass_cast_to_subquery() { + fn test_cast_array_bounds_for_generate_series() { + // array_upper/array_lower return Int32; generate_series wants Int64. + // The rule wraps those calls in ::bigint when used as generate_series args. let rules: Vec> = - vec![Arc::new(RewriteRegclassCastToSubquery::new())]; + vec![Arc::new(CastArrayBoundsForGenerateSeries)]; assert_rewrite!( &rules, - "SELECT $1::regclass::oid", - "SELECT (SELECT c.oid FROM pg_catalog.pg_class c JOIN pg_catalog.pg_namespace n ON n.oid = c.relnamespace CROSS JOIN (SELECT parse_ident($1::TEXT) AS parts) p WHERE n.nspname = COALESCE(CASE WHEN array_length(p.parts, 1) > 1 THEN p.parts[1] END, current_schema()) AND c.relname = p.parts[-1])" + "SELECT s.r FROM generate_series(1, array_upper(current_schemas(false), 1)) as s(r)", + "SELECT s.r FROM generate_series(1, array_upper(current_schemas(false), 1)::BIGINT) AS s (r)" ); - assert_rewrite!( &rules, - "SELECT $1::pg_catalog.regclass::oid", - "SELECT (SELECT c.oid FROM pg_catalog.pg_class c JOIN pg_catalog.pg_namespace n ON n.oid = c.relnamespace CROSS JOIN (SELECT parse_ident($1::TEXT) AS parts) p WHERE n.nspname = COALESCE(CASE WHEN array_length(p.parts, 1) > 1 THEN p.parts[1] END, current_schema()) AND c.relname = p.parts[-1])" + "SELECT s.r FROM generate_series(array_lower(x, 1), array_upper(x, 1)) as s(r)", + "SELECT s.r FROM generate_series(array_lower(x, 1)::BIGINT, array_upper(x, 1)::BIGINT) AS s (r)" ); + // Non-array-bounds args are left alone (literal ints already work). assert_rewrite!( &rules, - "SELECT $1::pg_catalog.regclass::pg_catalog.oid", - "SELECT (SELECT c.oid FROM pg_catalog.pg_class c JOIN pg_catalog.pg_namespace n ON n.oid = c.relnamespace CROSS JOIN (SELECT parse_ident($1::TEXT) AS parts) p WHERE n.nspname = COALESCE(CASE WHEN array_length(p.parts, 1) > 1 THEN p.parts[1] END, current_schema()) AND c.relname = p.parts[-1])" + "SELECT s.r FROM generate_series(1, 10) as s(r)", + "SELECT s.r FROM generate_series(1, 10) AS s (r)" ); - + // array_upper used outside generate_series is NOT touched. assert_rewrite!( &rules, - "SELECT * FROM pg_catalog.pg_class WHERE oid = 't'::pg_catalog.regclass::pg_catalog.oid", - "SELECT * FROM pg_catalog.pg_class WHERE oid = (SELECT c.oid FROM pg_catalog.pg_class c JOIN pg_catalog.pg_namespace n ON n.oid = c.relnamespace CROSS JOIN (SELECT parse_ident('t'::TEXT) AS parts) p WHERE n.nspname = COALESCE(CASE WHEN array_length(p.parts, 1) > 1 THEN p.parts[1] END, current_schema()) AND c.relname = p.parts[-1])" + "SELECT array_upper(x, 1)", + "SELECT array_upper(x, 1)" ); } diff --git a/datafusion-postgres/src/handlers.rs b/datafusion-postgres/src/handlers.rs index c7d5320..0a6cec3 100644 --- a/datafusion-postgres/src/handlers.rs +++ b/datafusion-postgres/src/handlers.rs @@ -474,7 +474,11 @@ fn ordered_param_types(types: &HashMap>) -> Vec>(); - types.sort_by(|a, b| a.0.cmp(b.0)); + types.sort_by_key(|(key, _)| { + key.trim_start_matches('$') + .parse::() + .unwrap_or(u32::MAX) + }); types.into_iter().map(|pt| pt.1.as_ref()).collect() } @@ -525,6 +529,29 @@ mod tests { } } + #[test] + fn test_ordered_param_types_sorts_placeholders_numerically() { + let params = HashMap::from([ + ("$1".to_string(), Some(DataType::Boolean)), + ("$2".to_string(), Some(DataType::Int64)), + ("$10".to_string(), Some(DataType::Utf8)), + ]); + + let ordered = ordered_param_types(¶ms) + .into_iter() + .map(|ty| ty.cloned()) + .collect::>(); + + assert_eq!( + ordered, + vec![ + Some(DataType::Boolean), + Some(DataType::Int64), + Some(DataType::Utf8) + ] + ); + } + #[tokio::test] async fn test_query_hooks() { let hook = TestHook; diff --git a/datafusion-postgres/tests/array_bounds.rs b/datafusion-postgres/tests/array_bounds.rs new file mode 100644 index 0000000..73155d6 --- /dev/null +++ b/datafusion-postgres/tests/array_bounds.rs @@ -0,0 +1,38 @@ +//! End-to-end tests for the `array_upper` / `array_lower` UDFs. +//! +//! These queries intentionally do NOT match any blacklist fragment, so they +//! exercise the real parse -> rewrite -> plan -> execute path and prove the +//! UDFs are registered and resolvable. Before these UDFs existed, such queries +//! failed at planning with "Invalid function 'array_upper'". + +use pgwire::api::query::SimpleQueryHandler; + +use datafusion_postgres::testing::*; + +const QUERIES: &[&str] = &[ + // Bare UDFs over an array literal. + "SELECT array_upper(ARRAY[1, 2, 3], 1), array_lower(ARRAY[1, 2, 3], 1)", + // pg_catalog-qualified form (qualifier stripped by RemoveQualifier rule). + "SELECT pg_catalog.array_upper(ARRAY['a', 'b'], 1)", + "SELECT pg_catalog.array_lower(ARRAY['a', 'b'], 1)", + // Typical usage pattern: generate_series over array bounds, mirroring the + // shape grafana/psql clients send (but without matching the blacklisted + // fragment verbatim). + "SELECT array_upper(string_to_array('public,utils', ','), 1)", + "SELECT array_lower(string_to_array('public,utils', ','), 1)", +]; + +#[tokio::test] +pub async fn test_array_bounds_udfs() { + env_logger::init(); + let service = setup_handlers(); + let mut client = MockClient::new(); + + for query in QUERIES { + SimpleQueryHandler::do_query(&service, &mut client, query) + .await + .unwrap_or_else(|e| { + panic!("failed to run sql:\n--------------\n {query}\n--------------\n{e}") + }); + } +} diff --git a/tests/probe_blacklist_removal.rs b/tests/probe_blacklist_removal.rs new file mode 100644 index 0000000..abb2011 --- /dev/null +++ b/tests/probe_blacklist_removal.rs @@ -0,0 +1,58 @@ +//! Probe each BLACKLIST entry's EXACT original sql through the full rewrite + +//! planning + execution pipeline (blacklist bypassed) to find removable entries. +use std::sync::Arc; + +use datafusion::prelude::{SessionConfig, SessionContext}; +use datafusion::sql::sqlparser::dialect::PostgreSqlDialect; +use datafusion::sql::sqlparser::parser::Parser as SqlParser; +use datafusion_pg_catalog::pg_catalog::setup_pg_catalog; +use datafusion_pg_catalog::sql::PostgresCompatibilityParser; +use datafusion_postgres::auth::AuthManager; + +fn rewrite_only(sql: &str) -> String { + let dialect = PostgreSqlDialect {}; + let parser = PostgresCompatibilityParser::new(); + let mut stmts = SqlParser::parse_sql(&dialect, sql).unwrap(); + parser.rewrite(stmts.remove(0)).to_string() +} + +async fn try_query(ctx: &SessionContext, label: &str, sql: &str) { + let rewritten = rewrite_only(sql); + match ctx.sql(&rewritten).await { + Ok(df) => match df.collect().await { + Ok(_) => println!("ZZZ OK [{label}]"), + Err(e) => println!( + "ZZZ EXEC [{label}] -> {}", + e.to_string().lines().next().unwrap_or("") + ), + }, + Err(e) => println!( + "ZZZ PLAN [{label}] -> {}", + e.to_string().lines().next().unwrap_or("") + ), + } +} + +#[tokio::test] +async fn probe_blacklist_removal() { + let ctx = + SessionContext::new_with_config(SessionConfig::new().with_information_schema(true)); + setup_pg_catalog(&ctx, "datafusion", Arc::new(AuthManager::default())).unwrap(); + + let labels = [ + "1-pgcli-fk", + "2-pgcli-types", + "3-psql-policies", + "4-statistics", + "5-publications", + "6-dbeaver-relsize", + "7-grafana-arrayidx", + ]; + for (i, label) in labels.iter().enumerate() { + let sql = std::fs::read_to_string(format!("/tmp/blist_{}.sql", i + 1)).unwrap(); + // Substitute any $1 placeholders with a literal oid that exists. + let sql = sql.replace("$1", "1"); + try_query(&ctx, label, &sql).await; + } + panic!("probe complete"); +} From 36e5ac7b8aee4b6d862b0cf3f985a02a399f95f7 Mon Sep 17 00:00:00 2001 From: Ning Sun Date: Sun, 28 Jun 2026 16:47:16 +0800 Subject: [PATCH 4/5] chore: remove probe test script --- tests/probe_blacklist_removal.rs | 58 -------------------------------- 1 file changed, 58 deletions(-) delete mode 100644 tests/probe_blacklist_removal.rs diff --git a/tests/probe_blacklist_removal.rs b/tests/probe_blacklist_removal.rs deleted file mode 100644 index abb2011..0000000 --- a/tests/probe_blacklist_removal.rs +++ /dev/null @@ -1,58 +0,0 @@ -//! Probe each BLACKLIST entry's EXACT original sql through the full rewrite + -//! planning + execution pipeline (blacklist bypassed) to find removable entries. -use std::sync::Arc; - -use datafusion::prelude::{SessionConfig, SessionContext}; -use datafusion::sql::sqlparser::dialect::PostgreSqlDialect; -use datafusion::sql::sqlparser::parser::Parser as SqlParser; -use datafusion_pg_catalog::pg_catalog::setup_pg_catalog; -use datafusion_pg_catalog::sql::PostgresCompatibilityParser; -use datafusion_postgres::auth::AuthManager; - -fn rewrite_only(sql: &str) -> String { - let dialect = PostgreSqlDialect {}; - let parser = PostgresCompatibilityParser::new(); - let mut stmts = SqlParser::parse_sql(&dialect, sql).unwrap(); - parser.rewrite(stmts.remove(0)).to_string() -} - -async fn try_query(ctx: &SessionContext, label: &str, sql: &str) { - let rewritten = rewrite_only(sql); - match ctx.sql(&rewritten).await { - Ok(df) => match df.collect().await { - Ok(_) => println!("ZZZ OK [{label}]"), - Err(e) => println!( - "ZZZ EXEC [{label}] -> {}", - e.to_string().lines().next().unwrap_or("") - ), - }, - Err(e) => println!( - "ZZZ PLAN [{label}] -> {}", - e.to_string().lines().next().unwrap_or("") - ), - } -} - -#[tokio::test] -async fn probe_blacklist_removal() { - let ctx = - SessionContext::new_with_config(SessionConfig::new().with_information_schema(true)); - setup_pg_catalog(&ctx, "datafusion", Arc::new(AuthManager::default())).unwrap(); - - let labels = [ - "1-pgcli-fk", - "2-pgcli-types", - "3-psql-policies", - "4-statistics", - "5-publications", - "6-dbeaver-relsize", - "7-grafana-arrayidx", - ]; - for (i, label) in labels.iter().enumerate() { - let sql = std::fs::read_to_string(format!("/tmp/blist_{}.sql", i + 1)).unwrap(); - // Substitute any $1 placeholders with a literal oid that exists. - let sql = sql.replace("$1", "1"); - try_query(&ctx, label, &sql).await; - } - panic!("probe complete"); -} From f0360d0e8dbbe97c13f0f856de3b9c3c5e6b4246 Mon Sep 17 00:00:00 2001 From: Ning Sun Date: Sun, 28 Jun 2026 16:48:45 +0800 Subject: [PATCH 5/5] refactor: use type planner for pg-catalog qualified data type --- .../src/pg_catalog/oid_type_planner.rs | 181 ++++++++++++++++-- datafusion-pg-catalog/src/sql/rules.rs | 50 ++--- 2 files changed, 183 insertions(+), 48 deletions(-) diff --git a/datafusion-pg-catalog/src/pg_catalog/oid_type_planner.rs b/datafusion-pg-catalog/src/pg_catalog/oid_type_planner.rs index 86f5edd..07a1c48 100644 --- a/datafusion-pg-catalog/src/pg_catalog/oid_type_planner.rs +++ b/datafusion-pg-catalog/src/pg_catalog/oid_type_planner.rs @@ -1,18 +1,30 @@ //! A DataFusion [`TypePlanner`] that teaches the SQL planner to accept the -//! Postgres oid-alias type names (`regclass`, `regproc`, `regtype`, -//! `regnamespace`, `oid`, ...) that DataFusion otherwise rejects as -//! "Unsupported SQL type". +//! Postgres type names DataFusion otherwise rejects as "Unsupported SQL type": //! -//! Each such type is mapped to an `Int32` [`Field`] (oids are stored as int4) -//! carrying the same `pg.oid_alias` metadata the catalog columns use, so the -//! kind survives into the logical plan inside the resulting [`Expr::Cast`]'s -//! `field`. The oid-coercion analyzer rule then reads that metadata to resolve -//! name strings -> oids the way Postgres does -- no SQL/AST rewriting needed. +//! # oid-alias types +//! +//! `regclass`, `regproc`, `regtype`, `regnamespace`, `oid`, ... Each is mapped +//! to an `Int32` [`Field`] (oids are stored as int4) carrying the same +//! `pg.oid_alias` metadata the catalog columns use, so the kind survives into +//! the logical plan inside the resulting [`Expr::Cast`]'s `field`. The +//! oid-coercion analyzer rule then reads that metadata to resolve name strings +//! -> oids the way Postgres does -- no SQL/AST rewriting needed. //! //! This is the metadata-aware replacement for the former `RemoveOidTypeCast` //! (SQL rewrite) + `RewriteRegCastToSubquery` (SQL rewrite) pair: instead of //! stripping the cast at the AST layer (losing the type) and reconstructing it //! later, the type is accepted up front and resolved at the analyzer layer. +//! +//! # `pg_catalog`-qualified builtins +//! +//! `pg_catalog.text`, `pg_catalog.int2`, `pg_catalog.int4`, ... sqlparser can +//! only represent a schema-qualified builtin as the catch-all `Custom` type, +//! which DataFusion rejects. This planner maps the canonical pg name to the +//! same Arrow type its unqualified builtin would produce, so casts like +//! `reloftype::pg_catalog.regtype::pg_catalog.text` plan cleanly. Arrays +//! (`pg_catalog.int2[]`) need no special handling: DataFusion recurses into +//! this planner for the array element type. This replaces the cast branch of +//! the former `RemoveQualifier` SQL rewrite. use std::sync::Arc; @@ -23,8 +35,8 @@ use datafusion::sql::sqlparser::ast::{DataType as SQLDataType, ObjectNamePart}; use crate::pg_catalog::oid_field::{self, OID_ALIAS_KEY, OID_ALIAS_TYPE_NAMES}; -/// Recognize every Postgres oid-alias type name and map it to an int4 oid -/// [`Field`] annotated with its `pg.oid_alias` kind. +/// Recognize Postgres type names DataFusion rejects and map them to Arrow +/// types/metadata at planning time. #[derive(Debug, Default)] pub struct PgOidTypePlanner; @@ -62,19 +74,84 @@ impl PgOidTypePlanner { _ => None, } } + + /// Map a `pg_catalog.` custom type to the Arrow [`DataType`] of its + /// unqualified builtin. + /// + /// Returns `None` unless the type is exactly a two-part + /// `pg_catalog.` with no type arguments, or `` is not a + /// builtin we know about (in which case it is left for DataFusion to error + /// on, or for another planner/rule to handle). The oid-alias arm in + /// [`TypePlanner::plan_type_field`] runs first, so oid-alias names + /// (`pg_catalog.regclass`, ...) never reach here. + fn pg_catalog_builtin(sql_type: &SQLDataType) -> Option { + let SQLDataType::Custom(name, args) = sql_type else { + return None; + }; + if !args.is_empty() || name.0.len() != 2 { + return None; + } + let mut parts = name.0.iter().filter_map(|p| match p { + ObjectNamePart::Identifier(i) => Some(i.value.as_str()), + _ => None, + }); + let (schema, type_name) = match (parts.next(), parts.next()) { + (Some(s), Some(t)) => (s, t), + _ => return None, + }; + if !schema.eq_ignore_ascii_case("pg_catalog") { + return None; + } + builtin_arrow_type(type_name) + } +} + +/// Arrow [`DataType`] for a Postgres pg_catalog builtin type name, or `None` +/// if it is not one we map (a user-defined type, or a builtin whose parameters +/// we don't model). +/// +/// String types map to `Utf8`, matching DataFusion's default conversion of the +/// unqualified `text`/`varchar`/`char` variants. The +/// `map_string_types_to_utf8view` session option is not consulted because the +/// [`TypePlanner`] trait does not expose session config; if a deployment needs +/// `Utf8View` it can register an additional planner. +fn builtin_arrow_type(name: &str) -> Option { + use DataType::*; + let dt = match name.to_ascii_lowercase().as_str() { + // booleans + "bool" | "boolean" => Boolean, + // integers + "int2" | "smallint" => Int16, + "int4" | "integer" | "int" => Int32, + "int8" | "bigint" => Int64, + // floats + "float4" | "real" => Float32, + "float8" => Float64, + // strings -> Utf8 (DataFusion's default for unqualified Text/Varchar) + "text" | "varchar" | "bpchar" | "char" | "name" => Utf8, + // bytes + "bytea" => Binary, + _ => return None, + }; + Some(dt) } impl TypePlanner for PgOidTypePlanner { fn plan_type_field(&self, sql_type: &SQLDataType) -> Result>> { - // Scalar oid-alias types -> int4 with kind metadata. + // 1. Scalar oid-alias types (regclass, oid, ...) -> int4 with kind + // metadata. Arrays of these (`regtype[]`) are handled by DataFusion + // recursing into this planner for the element type, so no Array arm + // is needed here. if let Some(kind) = Self::kind_for(sql_type) { return Ok(Some(Self::oid_field(&kind))); } - // Array of an oid-alias type (e.g. `regtype[]`): a list whose *element* - // field carries the kind metadata. The recursion below consults this - // planner again for the inner type; DataFusion wraps the result with - // `into_list()` before reaching us, so we only see the scalar here in - // practice -- but handle the bracketed form defensively. + // 2. pg_catalog-qualified builtins (pg_catalog.text, pg_catalog.int2, + // ...). sqlparser represents these as `Custom`, which DataFusion + // otherwise rejects; map them to their builtin Arrow type. As above, + // `pg_catalog.int2[]` works via element-type recursion. + if let Some(dt) = Self::pg_catalog_builtin(sql_type) { + return Ok(Some(Arc::new(Field::new("", dt, true)))); + } Ok(None) } } @@ -151,4 +228,76 @@ mod tests { Some(oid_field::kind::REGPROC) ); } + + #[test] + fn pg_catalog_builtins_map_to_arrow_types() { + let planner = PgOidTypePlanner; + for (sql, expected) in [ + ("pg_catalog.text", DataType::Utf8), + ("pg_catalog.varchar", DataType::Utf8), + ("pg_catalog.bpchar", DataType::Utf8), + ("pg_catalog.name", DataType::Utf8), + ("pg_catalog.bool", DataType::Boolean), + ("pg_catalog.boolean", DataType::Boolean), + ("pg_catalog.int2", DataType::Int16), + ("pg_catalog.smallint", DataType::Int16), + ("pg_catalog.int4", DataType::Int32), + ("pg_catalog.int8", DataType::Int64), + ("pg_catalog.bigint", DataType::Int64), + ("pg_catalog.float4", DataType::Float32), + ("pg_catalog.real", DataType::Float32), + ("pg_catalog.float8", DataType::Float64), + ("pg_catalog.bytea", DataType::Binary), + ] { + let dt = cast_target_type(&format!("SELECT 'x'::{sql} AS c")); + let field = planner + .plan_type_field(&dt) + .unwrap() + .unwrap_or_else(|| panic!("{sql} should be handled by the planner")); + assert_eq!(field.data_type(), &expected, "{sql}"); + // No oid-alias metadata for plain builtins. + assert!( + field.metadata().get(OID_ALIAS_KEY).is_none(), + "{sql} must not carry oid-alias metadata" + ); + } + } + + #[test] + fn pg_catalog_builtin_rejects_non_builtins_and_unknown_schemas() { + let planner = PgOidTypePlanner; + + // User-defined-looking custom type under pg_catalog is not mapped (left + // for DataFusion to error on / another rule to handle). + let dt = cast_target_type("SELECT 'x'::pg_catalog.some_udt AS c"); + assert_eq!(planner.plan_type_field(&dt).unwrap(), None); + + // A builtin name qualified by a different schema is not mapped either. + let dt = cast_target_type("SELECT 'x'::public.text AS c"); + assert_eq!(planner.plan_type_field(&dt).unwrap(), None); + + // `pg_catalog.regclass` is an oid-alias: handled by the oid arm (Int32 + // + metadata), NOT by the builtin arm. + let dt = cast_target_type("SELECT 'x'::pg_catalog.regclass AS c"); + let field = planner.plan_type_field(&dt).unwrap().unwrap(); + assert_eq!(field.data_type(), &DataType::Int32); + assert!(field.metadata().get(OID_ALIAS_KEY).is_some()); + } + + #[test] + fn pg_catalog_builtin_does_not_need_array_arm() { + // `pg_catalog.int2[]` parses as Array(Custom(pg_catalog.int2)). The + // planner only handles the scalar Custom element; DataFusion is the one + // that recurses into the planner for the element and wraps it into a + // list. So at the planner level, the Array itself returns None and only + // its element resolves -- proving no Array arm is required here. + let planner = PgOidTypePlanner; + let dt = cast_target_type("SELECT 'x'::pg_catalog.int2[] AS c"); + assert_eq!(planner.plan_type_field(&dt).unwrap(), None); + + // ...but the element type alone resolves to Int16. + let dt = cast_target_type("SELECT 'x'::pg_catalog.int2 AS c"); + let field = planner.plan_type_field(&dt).unwrap().unwrap(); + assert_eq!(field.data_type(), &DataType::Int16); + } } diff --git a/datafusion-pg-catalog/src/sql/rules.rs b/datafusion-pg-catalog/src/sql/rules.rs index 667a25b..f7c1295 100644 --- a/datafusion-pg-catalog/src/sql/rules.rs +++ b/datafusion-pg-catalog/src/sql/rules.rs @@ -2,7 +2,7 @@ use std::collections::HashSet; use std::fmt::Debug; use std::ops::ControlFlow; -use crate::pg_catalog::{PG_CATALOG_TABLES, oid_field}; +use crate::pg_catalog::PG_CATALOG_TABLES; use datafusion::sql::sqlparser::ast::Array; use datafusion::sql::sqlparser::ast::ArrayElemTypeDef; @@ -605,10 +605,16 @@ impl SqlStatementRewriteRule for FixArrayLiteral { /// Remove qualifier from unsupported items /// -/// This rewriter removes qualifier from following items: -/// 1. type cast: for example: `pg_catalog.text` -/// 2. function name: for example: `pg_catalog.array_to_string`, -/// 3. table function name +/// This rewriter removes the `pg_catalog.` qualifier from: +/// 1. function names, for example `pg_catalog.array_to_string` +/// 2. table function names +/// +/// Type-cast qualifiers such as `pg_catalog.text` / `pg_catalog.int2[]` used +/// to be handled here too, but are now resolved by the [`PgOidTypePlanner`] +/// type planner (which sees the cast target type at planning time and maps the +/// pg name to its Arrow type). +/// +/// [`PgOidTypePlanner`]: crate::pg_catalog::oid_type_planner::PgOidTypePlanner #[derive(Debug)] pub struct RemoveQualifier; @@ -636,34 +642,14 @@ impl VisitorMut for RemoveQualifierVisitor { } fn pre_visit_expr(&mut self, expr: &mut Expr) -> ControlFlow { - match expr { - Expr::Cast { data_type, .. } => { - // rewrite custom pg_catalog. qualified types - let data_type_str = data_type.to_string(); - match data_type_str.as_str() { - "pg_catalog.text" => { - *data_type = DataType::Text; - } - "pg_catalog.int2[]" => { - *data_type = DataType::Array(ArrayElemTypeDef::SquareBracket( - Box::new(DataType::Int16), - None, - )); - } - _ => {} - } - } - Expr::Function(function) => { - // remove qualifier from pg_catalog.function - let name = &mut function.name; - if name.0.len() > 1 - && let Some(last_ident) = name.0.pop() - { - *name = ObjectName(vec![last_ident]); - } + // remove qualifier from pg_catalog.function + if let Expr::Function(function) = expr { + let name = &mut function.name; + if name.0.len() > 1 + && let Some(last_ident) = name.0.pop() + { + *name = ObjectName(vec![last_ident]); } - - _ => {} } ControlFlow::Continue(()) }