From f7e188eee722a733b6080197b55420e69b425fbf Mon Sep 17 00:00:00 2001 From: houseme Date: Thu, 18 Sep 2025 23:30:25 +0800 Subject: [PATCH] =?UTF-8?q?feat:=20upgrade=20datafusion=20to=20v50.0.0=20a?= =?UTF-8?q?nd=20update=20related=20dependencies=20f=E2=80=A6=20(#563)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * feat: upgrade datafusion to v50.0.0 and update related dependencies for compatibility * fix * fmt --- Cargo.lock | 439 ++++++++++++------ Cargo.toml | 4 +- crates/policy/src/policy/function.rs | 1 + crates/s3select-api/src/object_store.rs | 29 +- crates/s3select-query/src/metadata/mod.rs | 2 +- .../src/sql/logical/optimizer.rs | 3 - rustfs/src/main.rs | 123 +++-- 7 files changed, 392 insertions(+), 209 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index a15dc3b56..45aeb0bc9 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -217,9 +217,9 @@ checksum = "7c02d123df017efcdfbd739ef81735b36c5ba83ec3c59c80a9d7ecc718f92e50" [[package]] name = "arrow" -version = "54.3.1" +version = "56.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b5ec52ba94edeed950e4a41f75d35376df196e8cb04437f7280a5aa49f20f796" +checksum = "c26b57282a08ae92f727497805122fec964c6245cfa0e13f0e75452eaf3bc41f" dependencies = [ "arrow-arith", "arrow-array", @@ -238,9 +238,9 @@ dependencies = [ [[package]] name = "arrow-arith" -version = "54.3.1" +version = "56.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8fc766fdacaf804cb10c7c70580254fcdb5d55cdfda2bc57b02baf5223a3af9e" +checksum = "cebf38ca279120ff522f4954b81a39527425b6e9f615e6b72842f4de1ffe02b8" dependencies = [ "arrow-array", "arrow-buffer", @@ -252,9 +252,9 @@ dependencies = [ [[package]] name = "arrow-array" -version = "54.3.1" +version = "56.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a12fcdb3f1d03f69d3ec26ac67645a8fe3f878d77b5ebb0b15d64a116c212985" +checksum = "744109142cdf8e7b02795e240e20756c2a782ac9180d4992802954a8f871c0de" dependencies = [ "ahash", "arrow-buffer", @@ -269,9 +269,9 @@ dependencies = [ [[package]] name = "arrow-buffer" -version = "54.3.1" +version = "56.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "263f4801ff1839ef53ebd06f99a56cecd1dbaf314ec893d93168e2e860e0291c" +checksum = "601bb103c4c374bcd1f62c66bcea67b42a2ee91a690486c37d4c180236f11ccc" dependencies = [ "bytes", "half", @@ -280,9 +280,9 @@ dependencies = [ [[package]] name = "arrow-cast" -version = "54.3.1" +version = "56.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ede6175fbc039dfc946a61c1b6d42fd682fcecf5ab5d148fbe7667705798cac9" +checksum = "eed61d9d73eda8df9e3014843def37af3050b5080a9acbe108f045a316d5a0be" dependencies = [ "arrow-array", "arrow-buffer", @@ -301,9 +301,9 @@ dependencies = [ [[package]] name = "arrow-csv" -version = "54.3.1" +version = "56.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1644877d8bc9a0ef022d9153dc29375c2bda244c39aec05a91d0e87ccf77995f" +checksum = "fa95b96ce0c06b4d33ac958370db8c0d31e88e54f9d6e08b0353d18374d9f991" dependencies = [ "arrow-array", "arrow-cast", @@ -311,15 +311,14 @@ dependencies = [ "chrono", "csv", "csv-core", - "lazy_static", "regex", ] [[package]] name = "arrow-data" -version = "54.3.1" +version = "56.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "61cfdd7d99b4ff618f167e548b2411e5dd2c98c0ddebedd7df433d34c20a4429" +checksum = "43407f2c6ba2367f64d85d4603d6fb9c4b92ed79d2ffd21021b37efa96523e12" dependencies = [ "arrow-buffer", "arrow-schema", @@ -329,23 +328,25 @@ dependencies = [ [[package]] name = "arrow-ipc" -version = "54.3.1" +version = "56.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "62ff528658b521e33905334723b795ee56b393dbe9cf76c8b1f64b648c65a60c" +checksum = "e4b0487c4d2ad121cbc42c4db204f1509f8618e589bc77e635e9c40b502e3b90" dependencies = [ "arrow-array", "arrow-buffer", "arrow-data", "arrow-schema", - "flatbuffers 24.12.23", + "arrow-select", + "flatbuffers", "lz4_flex", + "zstd", ] [[package]] name = "arrow-json" -version = "54.3.1" +version = "56.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0ee5b4ca98a7fb2efb9ab3309a5d1c88b5116997ff93f3147efdc1062a6158e9" +checksum = "26d747573390905905a2dc4c5a61a96163fe2750457f90a04ee2a88680758c79" dependencies = [ "arrow-array", "arrow-buffer", @@ -365,9 +366,9 @@ dependencies = [ [[package]] name = "arrow-ord" -version = "54.3.1" +version = "56.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f0a3334a743bd2a1479dbc635540617a3923b4b2f6870f37357339e6b5363c21" +checksum = "c142a147dceb59d057bad82400f1693847c80dca870d008bf7b91caf902810ae" dependencies = [ "arrow-array", "arrow-buffer", @@ -378,9 +379,9 @@ dependencies = [ [[package]] name = "arrow-row" -version = "54.3.1" +version = "56.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8d1d7a7291d2c5107e92140f75257a99343956871f3d3ab33a7b41532f79cb68" +checksum = "dac6620667fccdab4204689ca173bd84a15de6bb6b756c3a8764d4d7d0c2fc04" dependencies = [ "arrow-array", "arrow-buffer", @@ -391,15 +392,19 @@ dependencies = [ [[package]] name = "arrow-schema" -version = "54.3.1" +version = "56.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "39cfaf5e440be44db5413b75b72c2a87c1f8f0627117d110264048f2969b99e9" +checksum = "dfa93af9ff2bb80de539e6eb2c1c8764abd0f4b73ffb0d7c82bf1f9868785e66" +dependencies = [ + "serde", + "serde_json", +] [[package]] name = "arrow-select" -version = "54.3.1" +version = "56.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "69efcd706420e52cd44f5c4358d279801993846d1c2a8e52111853d61d55a619" +checksum = "be8b2e0052cd20d36d64f32640b68a5ab54d805d24a473baee5d52017c85536c" dependencies = [ "ahash", "arrow-array", @@ -411,9 +416,9 @@ dependencies = [ [[package]] name = "arrow-string" -version = "54.3.1" +version = "56.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a21546b337ab304a32cfc0770f671db7411787586b45b78b4593ae78e64e2b03" +checksum = "c2155e26e17f053c8975c546fc70cf19c00542f9abf43c23a88a46ef7204204f" dependencies = [ "arrow-array", "arrow-buffer", @@ -1204,17 +1209,6 @@ dependencies = [ "hybrid-array", ] -[[package]] -name = "brotli" -version = "7.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cc97b8f16f944bba54f0433f07e30be199b6dc2bd25937444bbad560bcea29bd" -dependencies = [ - "alloc-no-stdlib", - "alloc-stdlib", - "brotli-decompressor 4.0.3", -] - [[package]] name = "brotli" version = "8.0.2" @@ -1223,17 +1217,7 @@ checksum = "4bd8b9603c7aa97359dbd97ecf258968c95f3adddd6db2f7e7a5bef101c84560" dependencies = [ "alloc-no-stdlib", "alloc-stdlib", - "brotli-decompressor 5.0.0", -] - -[[package]] -name = "brotli-decompressor" -version = "4.0.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a334ef7c9e23abf0ce748e8cd309037da93e606ad52eb372e4ce327a0dcfbdfd" -dependencies = [ - "alloc-no-stdlib", - "alloc-stdlib", + "brotli-decompressor", ] [[package]] @@ -2020,22 +2004,25 @@ checksum = "2a2330da5de22e8a3cb63252ce2abb30116bf5265e89c0e01bc17015ce30a476" [[package]] name = "datafusion" -version = "46.0.1" +version = "50.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "914e6f9525599579abbd90b0f7a55afcaaaa40350b9e9ed52563f126dfe45fd3" +checksum = "481d0c1cad7606cee11233abcdff8eec46e43dd25abda007db6d5d26ae8483c4" dependencies = [ "arrow", "arrow-ipc", "arrow-schema", "async-trait", "bytes", - "bzip2 0.5.2", + "bzip2 0.6.0", "chrono", "datafusion-catalog", "datafusion-catalog-listing", "datafusion-common", "datafusion-common-runtime", "datafusion-datasource", + "datafusion-datasource-csv", + "datafusion-datasource-json", + "datafusion-datasource-parquet", "datafusion-execution", "datafusion-expr", "datafusion-expr-common", @@ -2044,12 +2031,13 @@ dependencies = [ "datafusion-functions-nested", "datafusion-functions-table", "datafusion-functions-window", - "datafusion-macros", "datafusion-optimizer", "datafusion-physical-expr", + "datafusion-physical-expr-adapter", "datafusion-physical-expr-common", "datafusion-physical-optimizer", "datafusion-physical-plan", + "datafusion-session", "datafusion-sql", "flate2", "futures", @@ -2058,7 +2046,7 @@ dependencies = [ "object_store", "parking_lot", "parquet", - "rand 0.8.5", + "rand 0.9.2", "regex", "sqlparser", "tempfile", @@ -2071,29 +2059,35 @@ dependencies = [ [[package]] name = "datafusion-catalog" -version = "46.0.1" +version = "50.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "998a6549e6ee4ee3980e05590b2960446a56b343ea30199ef38acd0e0b9036e2" +checksum = "d70327e81ab3a1f5832d8b372d55fa607851d7cea6d1f8e65ff0c98fcc32d222" 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-sql", "futures", "itertools 0.14.0", "log", + "object_store", "parking_lot", + "tokio", ] [[package]] name = "datafusion-catalog-listing" -version = "46.0.1" +version = "50.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a5ac10096a5b3c0d8a227176c0e543606860842e943594ccddb45cf42a526e43" +checksum = "268819e6bb20ba70a664abddc20deac604f30d3267f8c91847064542a8c0720c" dependencies = [ "arrow", "async-trait", @@ -2105,6 +2099,7 @@ dependencies = [ "datafusion-physical-expr", "datafusion-physical-expr-common", "datafusion-physical-plan", + "datafusion-session", "futures", "log", "object_store", @@ -2113,14 +2108,15 @@ dependencies = [ [[package]] name = "datafusion-common" -version = "46.0.1" +version = "50.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1f53d7ec508e1b3f68bd301cee3f649834fad51eff9240d898a4b2614cfd0a7a" +checksum = "054873d5563f115f83ef4270b560ac2ce4de713905e825a40cac49d6ff348254" dependencies = [ "ahash", "arrow", "arrow-ipc", "base64 0.22.1", + "chrono", "half", "hashbrown 0.14.5", "indexmap", @@ -2137,41 +2133,45 @@ dependencies = [ [[package]] name = "datafusion-common-runtime" -version = "46.0.1" +version = "50.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e0fcf41523b22e14cc349b01526e8b9f59206653037f2949a4adbfde5f8cb668" +checksum = "b8a1d1bc69aaaadb8008b65329ed890b33e845dc063225c190f77b20328fbe1d" dependencies = [ + "futures", "log", "tokio", ] [[package]] name = "datafusion-datasource" -version = "46.0.1" +version = "50.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cf7f37ad8b6e88b46c7eeab3236147d32ea64b823544f498455a8d9042839c92" +checksum = "d855160469020982880fd9bd0962e033d2f4728f56f85a83d8c90785638b6519" dependencies = [ "arrow", "async-compression", "async-trait", "bytes", - "bzip2 0.5.2", + "bzip2 0.6.0", "chrono", - "datafusion-catalog", "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", "flate2", "futures", "glob", "itertools 0.14.0", "log", "object_store", - "rand 0.8.5", + "parquet", + "rand 0.9.2", + "tempfile", "tokio", "tokio-util", "url", @@ -2180,18 +2180,102 @@ dependencies = [ ] [[package]] -name = "datafusion-doc" -version = "46.0.1" +name = "datafusion-datasource-csv" +version = "50.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7db7a0239fd060f359dc56c6e7db726abaa92babaed2fb2e91c3a8b2fff8b256" +checksum = "9ec3aa7575378d23aae96b955b5233bea6f9d461648174f6ccc8f3c160f2b7a7" +dependencies = [ + "arrow", + "async-trait", + "bytes", + "datafusion-catalog", + "datafusion-common", + "datafusion-common-runtime", + "datafusion-datasource", + "datafusion-execution", + "datafusion-expr", + "datafusion-physical-expr", + "datafusion-physical-expr-common", + "datafusion-physical-plan", + "datafusion-session", + "futures", + "object_store", + "regex", + "tokio", +] + +[[package]] +name = "datafusion-datasource-json" +version = "50.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "00cfb8f33e2864eeb3188b6818acf5546d56a5a487d423cce9b684a554caabfa" +dependencies = [ + "arrow", + "async-trait", + "bytes", + "datafusion-catalog", + "datafusion-common", + "datafusion-common-runtime", + "datafusion-datasource", + "datafusion-execution", + "datafusion-expr", + "datafusion-physical-expr", + "datafusion-physical-expr-common", + "datafusion-physical-plan", + "datafusion-session", + "futures", + "object_store", + "serde_json", + "tokio", +] + +[[package]] +name = "datafusion-datasource-parquet" +version = "50.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ab3bfb48fb4ff42ac1485a12ea56434eaab53f7da8f00b2443b1a3d35a0b6d10" +dependencies = [ + "arrow", + "async-trait", + "bytes", + "datafusion-catalog", + "datafusion-common", + "datafusion-common-runtime", + "datafusion-datasource", + "datafusion-execution", + "datafusion-expr", + "datafusion-functions-aggregate", + "datafusion-physical-expr", + "datafusion-physical-expr-adapter", + "datafusion-physical-expr-common", + "datafusion-physical-optimizer", + "datafusion-physical-plan", + "datafusion-pruning", + "datafusion-session", + "futures", + "itertools 0.14.0", + "log", + "object_store", + "parking_lot", + "parquet", + "rand 0.9.2", + "tokio", +] + +[[package]] +name = "datafusion-doc" +version = "50.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2fbf41013cf55c2369b5229594898e8108c8a1beeb49d97feb5e0cce9933eb8f" [[package]] name = "datafusion-execution" -version = "46.0.1" +version = "50.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0938f9e5b6bc5782be4111cdfb70c02b7b5451bf34fd57e4de062a7f7c4e31f1" +checksum = "26fd0c1ffe3885687758f985ed548184bf63b17b2a7a5ae695de422ad6432118" dependencies = [ "arrow", + "async-trait", "dashmap", "datafusion-common", "datafusion-expr", @@ -2199,18 +2283,19 @@ dependencies = [ "log", "object_store", "parking_lot", - "rand 0.8.5", + "rand 0.9.2", "tempfile", "url", ] [[package]] name = "datafusion-expr" -version = "46.0.1" +version = "50.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b36c28b00b00019a8695ad7f1a53ee1673487b90322ecbd604e2cf32894eb14f" +checksum = "5c4fe6411218a9dab656437b1e69b00a470a7a2d7db087867a366c145eb164a7" dependencies = [ "arrow", + "async-trait", "chrono", "datafusion-common", "datafusion-doc", @@ -2227,9 +2312,9 @@ dependencies = [ [[package]] name = "datafusion-expr-common" -version = "46.0.1" +version = "50.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "18f0a851a436c5a2139189eb4617a54e6a9ccb9edc96c4b3c83b3bb7c58b950e" +checksum = "4a45bee7d2606bfb41ceb1d904ba7cecf69bd5a6f8f3e6c57c3f5a83d84bdd97" dependencies = [ "arrow", "datafusion-common", @@ -2240,9 +2325,9 @@ dependencies = [ [[package]] name = "datafusion-functions" -version = "46.0.1" +version = "50.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e3196e37d7b65469fb79fee4f05e5bb58a456831035f9a38aa5919aeb3298d40" +checksum = "9c7e1c532ff9d14f291160bca23e55ffd4899800301dd2389786c2f02d76904a" dependencies = [ "arrow", "arrow-buffer", @@ -2260,7 +2345,7 @@ dependencies = [ "itertools 0.14.0", "log", "md-5", - "rand 0.8.5", + "rand 0.9.2", "regex", "sha2 0.10.9", "unicode-segmentation", @@ -2269,9 +2354,9 @@ dependencies = [ [[package]] name = "datafusion-functions-aggregate" -version = "46.0.1" +version = "50.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "adfc2d074d5ee4d9354fdcc9283d5b2b9037849237ddecb8942a29144b77ca05" +checksum = "b05d47426645aef1e73b1a034c75ab2401bc504175feb191accbe211ec24a342" dependencies = [ "ahash", "arrow", @@ -2290,9 +2375,9 @@ dependencies = [ [[package]] name = "datafusion-functions-aggregate-common" -version = "46.0.1" +version = "50.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1cbceba0f98d921309a9121b702bcd49289d383684cccabf9a92cda1602f3bbb" +checksum = "05c99f648b2b1743de0c1c19eef07e8cc5a085237f172b2e20bf6934e0a804e4" dependencies = [ "ahash", "arrow", @@ -2303,9 +2388,9 @@ dependencies = [ [[package]] name = "datafusion-functions-nested" -version = "46.0.1" +version = "50.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "170e27ce4baa27113ddf5f77f1a7ec484b0dbeda0c7abbd4bad3fc609c8ab71a" +checksum = "4227782023f4fb68d3d5c5eb190665212f43c9a0b437553e4b938b379aff6cf6" dependencies = [ "arrow", "arrow-ord", @@ -2315,6 +2400,7 @@ dependencies = [ "datafusion-expr", "datafusion-functions", "datafusion-functions-aggregate", + "datafusion-functions-aggregate-common", "datafusion-macros", "datafusion-physical-expr-common", "itertools 0.14.0", @@ -2324,9 +2410,9 @@ dependencies = [ [[package]] name = "datafusion-functions-table" -version = "46.0.1" +version = "50.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7d3a06a7f0817ded87b026a437e7e51de7f59d48173b0a4e803aa896a7bd6bb5" +checksum = "3d902b1769f69058236e89f04f3bff2cf62f24311adb7bf3c6c3e945c9451076" dependencies = [ "arrow", "async-trait", @@ -2340,10 +2426,11 @@ dependencies = [ [[package]] name = "datafusion-functions-window" -version = "46.0.1" +version = "50.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d6c608b66496a1e05e3d196131eb9bebea579eed1f59e88d962baf3dda853bc6" +checksum = "4b8ee43974c92eb9920fe8e97e0fab48675e93b062abcb48bef4c1d4305b6ee4" dependencies = [ + "arrow", "datafusion-common", "datafusion-doc", "datafusion-expr", @@ -2357,9 +2444,9 @@ dependencies = [ [[package]] name = "datafusion-functions-window-common" -version = "46.0.1" +version = "50.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "da2f9d83348957b4ad0cd87b5cb9445f2651863a36592fe5484d43b49a5f8d82" +checksum = "a1e149d36cdd44fb425dc815c5fac55025aa9a592dd65cb3c421881096292c02" dependencies = [ "datafusion-common", "datafusion-physical-expr-common", @@ -2367,9 +2454,9 @@ dependencies = [ [[package]] name = "datafusion-macros" -version = "46.0.1" +version = "50.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4800e1ff7ecf8f310887e9b54c9c444b8e215ccbc7b21c2f244cfae373b1ece7" +checksum = "07c9faa0cdefb6e6e756482b846397b5c2d84d369e30b009472b9ab9b1430fbd" dependencies = [ "datafusion-expr", "quote", @@ -2378,14 +2465,15 @@ dependencies = [ [[package]] name = "datafusion-optimizer" -version = "46.0.1" +version = "50.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "971c51c54cd309001376fae752fb15a6b41750b6d1552345c46afbfb6458801b" +checksum = "f16a4f7059302ad1de6e97ab0eebb5c34405917b1f80806a30a66e38ad118251" dependencies = [ "arrow", "chrono", "datafusion-common", "datafusion-expr", + "datafusion-expr-common", "datafusion-physical-expr", "indexmap", "itertools 0.14.0", @@ -2397,9 +2485,9 @@ dependencies = [ [[package]] name = "datafusion-physical-expr" -version = "46.0.1" +version = "50.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e1447c2c6bc8674a16be4786b4abf528c302803fafa186aa6275692570e64d85" +checksum = "10bb87a605d8ce9672d5347c0293c12211b0c03923fc12fbdc665fe76e6f9e01" dependencies = [ "ahash", "arrow", @@ -2413,15 +2501,31 @@ dependencies = [ "indexmap", "itertools 0.14.0", "log", + "parking_lot", "paste", - "petgraph", + "petgraph 0.8.2", +] + +[[package]] +name = "datafusion-physical-expr-adapter" +version = "50.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2da3a7429a555dd5ff0bec4d24bd5532ec43876764088da635cad55b2f178dc2" +dependencies = [ + "arrow", + "datafusion-common", + "datafusion-expr", + "datafusion-functions", + "datafusion-physical-expr", + "datafusion-physical-expr-common", + "itertools 0.14.0", ] [[package]] name = "datafusion-physical-expr-common" -version = "46.0.1" +version = "50.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "69f8c25dcd069073a75b3d2840a79d0f81e64bdd2c05f2d3d18939afb36a7dcb" +checksum = "845eb44ef1e04d2a15c6d955cb146b40a41814a7be4377f0a541857d3e257d6f" dependencies = [ "ahash", "arrow", @@ -2433,9 +2537,9 @@ dependencies = [ [[package]] name = "datafusion-physical-optimizer" -version = "46.0.1" +version = "50.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "68da5266b5b9847c11d1b3404ee96b1d423814e1973e1ad3789131e5ec912763" +checksum = "32b9b648ee2785722c79eae366528e52e93ece6808aef9297cf8e5521de381da" dependencies = [ "arrow", "datafusion-common", @@ -2445,6 +2549,7 @@ dependencies = [ "datafusion-physical-expr", "datafusion-physical-expr-common", "datafusion-physical-plan", + "datafusion-pruning", "itertools 0.14.0", "log", "recursive", @@ -2452,9 +2557,9 @@ dependencies = [ [[package]] name = "datafusion-physical-plan" -version = "46.0.1" +version = "50.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "88cc160df00e413e370b3b259c8ea7bfbebc134d32de16325950e9e923846b7f" +checksum = "7e6688d17b78104e169d7069749832c20ff50f112be853d2c058afe46c889064" dependencies = [ "ahash", "arrow", @@ -2466,6 +2571,7 @@ dependencies = [ "datafusion-common-runtime", "datafusion-execution", "datafusion-expr", + "datafusion-functions-aggregate-common", "datafusion-functions-window-common", "datafusion-physical-expr", "datafusion-physical-expr-common", @@ -2481,10 +2587,52 @@ dependencies = [ ] [[package]] -name = "datafusion-sql" -version = "46.0.1" +name = "datafusion-pruning" +version = "50.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "325a212b67b677c0eb91447bf9a11b630f9fc4f62d8e5d145bf859f5a6b29e64" +checksum = "8a893a46c56f5f190085e13949eb8ec163672c7ec2ac33bdb82c84572e71ca73" +dependencies = [ + "arrow", + "arrow-schema", + "datafusion-common", + "datafusion-datasource", + "datafusion-expr-common", + "datafusion-physical-expr", + "datafusion-physical-expr-common", + "datafusion-physical-plan", + "itertools 0.14.0", + "log", +] + +[[package]] +name = "datafusion-session" +version = "50.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f8b62684c7a1db6121a8c83100209cffa1e664a8d9ced87e1a32f8cdc2fff3c2" +dependencies = [ + "arrow", + "async-trait", + "dashmap", + "datafusion-common", + "datafusion-common-runtime", + "datafusion-execution", + "datafusion-expr", + "datafusion-physical-expr", + "datafusion-physical-plan", + "datafusion-sql", + "futures", + "itertools 0.14.0", + "log", + "object_store", + "parking_lot", + "tokio", +] + +[[package]] +name = "datafusion-sql" +version = "50.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f09cff94b8242843e1da5d069e9d2cfc53807f1f00b1c0da78c297f47c21456e" dependencies = [ "arrow", "bigdecimal", @@ -2667,7 +2815,7 @@ dependencies = [ "aws-config", "aws-sdk-s3", "bytes", - "flatbuffers 25.2.10", + "flatbuffers", "futures", "rmp-serde", "rustfs-ecstore", @@ -2889,16 +3037,6 @@ version = "0.5.7" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1d674e81391d1e1ab681a28d99df07927c6d4aa5b027d7da16ba32d1d21ecd99" -[[package]] -name = "flatbuffers" -version = "24.12.23" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4f1baf0dbf96932ec9a3038d57900329c015b0bfb7b63d904f3bc27e2b02a096" -dependencies = [ - "bitflags 1.3.2", - "rustc_version", -] - [[package]] name = "flatbuffers" version = "25.2.10" @@ -4172,7 +4310,7 @@ version = "0.11.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "08ab2867e3eeeca90e844d1940eab391c9dc5228783db2ed999acbc0a9ed375a" dependencies = [ - "twox-hash 2.1.2", + "twox-hash", ] [[package]] @@ -4691,23 +4829,26 @@ dependencies = [ [[package]] name = "object_store" -version = "0.11.2" +version = "0.12.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3cfccb68961a56facde1163f9319e0d15743352344e7808a11795fb99698dcaf" +checksum = "efc4f07659e11cd45a341cd24d71e683e3be65d9ff1f8150061678fe60437496" dependencies = [ "async-trait", "bytes", "chrono", "futures", + "http 1.3.1", "humantime", - "itertools 0.13.0", + "itertools 0.14.0", "parking_lot", "percent-encoding", - "snafu", + "thiserror 2.0.16", "tokio", "tracing", "url", "walkdir", + "wasm-bindgen-futures", + "web-time", ] [[package]] @@ -4899,9 +5040,9 @@ dependencies = [ [[package]] name = "parquet" -version = "54.3.1" +version = "56.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bfb15796ac6f56b429fd99e33ba133783ad75b27c36b4b5ce06f1f82cc97754e" +checksum = "89b56b41d1bd36aae415e42f91cae70ee75cf6cba74416b14dce3e958d5990ec" dependencies = [ "ahash", "arrow-array", @@ -4912,7 +5053,7 @@ dependencies = [ "arrow-schema", "arrow-select", "base64 0.22.1", - "brotli 7.0.0", + "brotli", "bytes", "chrono", "flate2", @@ -4924,12 +5065,13 @@ dependencies = [ "num-bigint", "object_store", "paste", + "ring", "seq-macro", "simdutf8", "snap", "thrift", "tokio", - "twox-hash 1.6.3", + "twox-hash", "zstd", ] @@ -5019,6 +5161,18 @@ dependencies = [ "indexmap", ] +[[package]] +name = "petgraph" +version = "0.8.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "54acf3a685220b533e437e264e4d932cfbdc4cc7ec0cd232ed73c08d03b8a7ca" +dependencies = [ + "fixedbitset 0.5.7", + "hashbrown 0.15.5", + "indexmap", + "serde", +] + [[package]] name = "phf" version = "0.12.1" @@ -5286,7 +5440,7 @@ dependencies = [ "log", "multimap", "once_cell", - "petgraph", + "petgraph 0.7.1", "prettyplease", "prost 0.14.1", "prost-types", @@ -5518,7 +5672,6 @@ version = "0.8.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "34af8d1a0e25924bc5b7c43c079c942339d8f0a8b57c39049bef581b46327404" dependencies = [ - "libc", "rand_chacha 0.3.1", "rand_core 0.6.4", ] @@ -6164,7 +6317,7 @@ dependencies = [ "chrono", "criterion", "enumset", - "flatbuffers 25.2.10", + "flatbuffers", "futures", "futures-util", "glob", @@ -6406,7 +6559,7 @@ dependencies = [ name = "rustfs-protos" version = "0.0.5" dependencies = [ - "flatbuffers 25.2.10", + "flatbuffers", "prost 0.14.1", "rustfs-common", "tonic 0.14.2", @@ -6543,7 +6696,7 @@ version = "0.0.5" dependencies = [ "base64-simd", "blake3", - "brotli 8.0.2", + "brotli", "bytes", "crc32fast", "flate2", @@ -7358,9 +7511,9 @@ dependencies = [ [[package]] name = "sqlparser" -version = "0.54.0" +version = "0.58.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c66e3b7374ad4a6af849b08b3e7a6eda0edbd82f0fd59b57e22671bf16979899" +checksum = "ec4b661c54b1e4b603b37873a18c59920e4c51ea8ea2cf527d925424dbd4437c" dependencies = [ "log", "recursive", @@ -8306,16 +8459,6 @@ version = "0.2.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e421abadd41a4225275504ea4d6566923418b7f05506fbc9c0fe86ba7396114b" -[[package]] -name = "twox-hash" -version = "1.6.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "97fee6b57c6a41524a810daee9286c02d7752c4253064d0b05472833a438f675" -dependencies = [ - "cfg-if", - "static_assertions", -] - [[package]] name = "twox-hash" version = "2.1.2" diff --git a/Cargo.toml b/Cargo.toml index 8cf7602e0..e7df523de 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -116,7 +116,7 @@ crc32fast = "1.5.0" criterion = { version = "0.7", features = ["html_reports"] } crossbeam-queue = "0.3.12" dashmap = "6.1.0" -datafusion = "46.0.1" +datafusion = "50.0.0" derive_builder = "0.20.2" enumset = "1.1.10" flatbuffers = "25.2.10" @@ -156,7 +156,7 @@ nix = { version = "0.30.1", features = ["fs"] } nu-ansi-term = "0.50.1" num_cpus = { version = "1.17.0" } nvml-wrapper = "0.11.0" -object_store = "0.11.2" +object_store = "0.12.3" once_cell = "1.21.3" opentelemetry = { version = "0.30.0" } opentelemetry-appender-tracing = { version = "0.30.1", features = [ diff --git a/crates/policy/src/policy/function.rs b/crates/policy/src/policy/function.rs index c092906df..9a847608b 100644 --- a/crates/policy/src/policy/function.rs +++ b/crates/policy/src/policy/function.rs @@ -173,6 +173,7 @@ impl PartialEq for Functions { } #[derive(Clone, Serialize, Deserialize)] +#[allow(dead_code)] pub struct Value; #[cfg(test)] diff --git a/crates/s3select-api/src/object_store.rs b/crates/s3select-api/src/object_store.rs index 79594a4c3..87e5f01b6 100644 --- a/crates/s3select-api/src/object_store.rs +++ b/crates/s3select-api/src/object_store.rs @@ -19,19 +19,10 @@ use futures::pin_mut; use futures::{Stream, StreamExt}; use futures_core::stream::BoxStream; use http::HeaderMap; -use object_store::Attributes; -use object_store::GetOptions; -use object_store::GetResult; -use object_store::ListResult; -use object_store::MultipartUpload; -use object_store::ObjectMeta; -use object_store::ObjectStore; -use object_store::PutMultipartOpts; -use object_store::PutOptions; -use object_store::PutPayload; -use object_store::PutResult; -use object_store::path::Path; -use object_store::{Error as o_Error, Result}; +use object_store::{ + Attributes, Error as o_Error, GetOptions, GetResult, ListResult, MultipartUpload, ObjectMeta, ObjectStore, + PutMultipartOptions, PutOptions, PutPayload, PutResult, Result, path::Path, +}; use pin_project_lite::pin_project; use rustfs_common::DEFAULT_DELIMITER; use rustfs_ecstore::StorageAPI; @@ -102,7 +93,7 @@ impl ObjectStore for EcObjectStore { unimplemented!() } - async fn put_multipart_opts(&self, _location: &Path, _opts: PutMultipartOpts) -> Result> { + async fn put_multipart_opts(&self, _location: &Path, _opts: PutMultipartOptions) -> Result> { unimplemented!() } @@ -122,7 +113,7 @@ impl ObjectStore for EcObjectStore { let meta = ObjectMeta { location: location.clone(), last_modified: Utc::now(), - size: reader.object_info.size as usize, + size: reader.object_info.size as u64, e_tag: reader.object_info.etag, version: None, }; @@ -151,12 +142,12 @@ impl ObjectStore for EcObjectStore { Ok(GetResult { payload, meta, - range: 0..reader.object_info.size as usize, + range: 0..reader.object_info.size as u64, attributes, }) } - async fn get_ranges(&self, _location: &Path, _ranges: &[Range]) -> Result> { + async fn get_ranges(&self, _location: &Path, _ranges: &[Range]) -> Result> { unimplemented!() } @@ -175,7 +166,7 @@ impl ObjectStore for EcObjectStore { Ok(ObjectMeta { location: location.clone(), last_modified: Utc::now(), - size: info.size as usize, + size: info.size as u64, e_tag: info.etag, version: None, }) @@ -185,7 +176,7 @@ impl ObjectStore for EcObjectStore { unimplemented!() } - fn list(&self, _prefix: Option<&Path>) -> BoxStream<'_, Result> { + fn list(&self, _prefix: Option<&Path>) -> BoxStream<'static, Result> { unimplemented!() } diff --git a/crates/s3select-query/src/metadata/mod.rs b/crates/s3select-query/src/metadata/mod.rs index 707e44407..f13b862b3 100644 --- a/crates/s3select-query/src/metadata/mod.rs +++ b/crates/s3select-query/src/metadata/mod.rs @@ -61,7 +61,7 @@ impl MetadataProvider { Self { provider, current_session_table_provider, - config_options: session.inner().config_options().clone(), + config_options: session.inner().config_options().as_ref().clone(), session, func_manager, } diff --git a/crates/s3select-query/src/sql/logical/optimizer.rs b/crates/s3select-query/src/sql/logical/optimizer.rs index 603c738a2..b1c669321 100644 --- a/crates/s3select-query/src/sql/logical/optimizer.rs +++ b/crates/s3select-query/src/sql/logical/optimizer.rs @@ -26,7 +26,6 @@ use datafusion::{ propagate_empty_relation::PropagateEmptyRelation, push_down_filter::PushDownFilter, push_down_limit::PushDownLimit, replace_distinct_aggregate::ReplaceDistinctWithAggregate, scalar_subquery_to_join::ScalarSubqueryToJoin, simplify_expressions::SimplifyExpressions, single_distinct_to_groupby::SingleDistinctToGroupBy, - unwrap_cast_in_comparison::UnwrapCastInComparison, }, }; use rustfs_s3select_api::{ @@ -66,7 +65,6 @@ impl Default for DefaultLogicalOptimizer { let rules: Vec> = vec![ // df default rules start Arc::new(SimplifyExpressions::new()), - Arc::new(UnwrapCastInComparison::new()), Arc::new(ReplaceDistinctWithAggregate::new()), Arc::new(EliminateJoin::new()), Arc::new(DecorrelatePredicateSubquery::new()), @@ -91,7 +89,6 @@ impl Default for DefaultLogicalOptimizer { // The previous optimizations added expressions and projections, // that might benefit from the following rules Arc::new(SimplifyExpressions::new()), - Arc::new(UnwrapCastInComparison::new()), Arc::new(CommonSubexprEliminate::new()), // PushDownProjection can pushdown Projections through Limits, do PushDownLimit again. Arc::new(PushDownLimit::new()), diff --git a/rustfs/src/main.rs b/rustfs/src/main.rs index 2c3135f32..cfcd7012e 100644 --- a/rustfs/src/main.rs +++ b/rustfs/src/main.rs @@ -143,7 +143,15 @@ async fn run(opt: config::Opt) -> Result<()> { let server_port = server_addr.port(); let server_address = server_addr.to_string(); - info!("server_address {}, ip:{}", &server_address, server_addr.ip()); + info!( + target: "rustfs::main::run", + server_address = %server_address, + ip = %server_addr.ip(), + port = %server_port, + version = %version::get_version(), + "Starting RustFS server at {}", + &server_address + ); // Set up AK and SK rustfs_ecstore::global::init_global_action_cred(Some(opt.access_key.clone()), Some(opt.secret_key.clone())); @@ -162,6 +170,7 @@ async fn run(opt: config::Opt) -> Result<()> { for (i, eps) in endpoint_pools.as_ref().iter().enumerate() { info!( + target: "rustfs::main::run", "Formatting {}st pool, {} set(s), {} drives per set.", i + 1, eps.set_count, @@ -175,12 +184,20 @@ async fn run(opt: config::Opt) -> Result<()> { for (i, eps) in endpoint_pools.as_ref().iter().enumerate() { info!( + target: "rustfs::main::run", + id = i, + set_count = eps.set_count, + drives_per_set = eps.drives_per_set, + cmd = ?eps.cmd_line, "created endpoints {}, set_count:{}, drives_per_set: {}, cmd: {:?}", i, eps.set_count, eps.drives_per_set, eps.cmd_line ); for ep in eps.endpoints.as_ref().iter() { - info!(" - {}", ep); + info!( + target: "rustfs::main::run", + " - endpoint: {}", ep + ); } } @@ -202,7 +219,12 @@ async fn run(opt: config::Opt) -> Result<()> { external_port, server_port ); } - info!("Using external address {} for endpoint access", external_addr); + info!( + target: "rustfs::main::run", + external_address = %external_addr, + external_port = %external_port, + "Using external address {} for endpoint access", external_addr + ); rustfs_ecstore::global::set_global_rustfs_external_port(external_port); set_global_addr(&opt.external_address).await; (external_addr.ip(), external_port) @@ -279,7 +301,12 @@ async fn run(opt: config::Opt) -> Result<()> { let enable_scanner = parse_bool_env_var("RUSTFS_ENABLE_SCANNER", true); let enable_heal = parse_bool_env_var("RUSTFS_ENABLE_HEAL", true); - info!("Background services configuration: scanner={}, heal={}", enable_scanner, enable_heal); + info!( + target: "rustfs::main::run", + enable_scanner = enable_scanner, + enable_heal = enable_heal, + "Background services configuration: scanner={}, heal={}", enable_scanner, enable_heal + ); // Initialize heal manager and scanner based on environment variables if enable_heal || enable_scanner { @@ -289,11 +316,11 @@ async fn run(opt: config::Opt) -> Result<()> { let heal_manager = init_heal_manager(heal_storage, None).await?; if enable_scanner { - info!("Starting scanner with heal manager..."); + info!(target: "rustfs::main::run","Starting scanner with heal manager..."); let scanner = Scanner::new(Some(ScannerConfig::default()), Some(heal_manager)); scanner.start().await?; } else { - info!("Scanner disabled, but heal manager is initialized and available"); + info!(target: "rustfs::main::run","Scanner disabled, but heal manager is initialized and available"); } } else if enable_scanner { info!("Starting scanner without heal manager..."); @@ -301,7 +328,7 @@ async fn run(opt: config::Opt) -> Result<()> { scanner.start().await?; } } else { - info!("Both scanner and heal are disabled, skipping AHM service initialization"); + info!(target: "rustfs::main::run","Both scanner and heal are disabled, skipping AHM service initialization"); } // print server info @@ -311,21 +338,6 @@ async fn run(opt: config::Opt) -> Result<()> { init_update_check(); - // if opt.console_enable { - // debug!("console is enabled"); - // let console_address = opt.console_address.clone(); - // let tls_path = opt.tls_path.clone(); - // - // if console_address.is_empty() { - // error!("console_address is empty"); - // return Err(Error::other("console_address is empty".to_string())); - // } - // - // tokio::spawn(async move { - // console::start_static_file_server(&console_address, tls_path).await; - // }); - // } - // Perform hibernation for 1 second tokio::time::sleep(SHUTDOWN_TIMEOUT).await; // listen to the shutdown signal @@ -340,7 +352,7 @@ async fn run(opt: config::Opt) -> Result<()> { } } - info!("server is stopped state: {:?}", state_manager.current_state()); + info!(target: "rustfs::main::run","server is stopped state: {:?}", state_manager.current_state()); Ok(()) } @@ -357,7 +369,10 @@ fn parse_bool_env_var(var_name: &str, default: bool) -> bool { /// Handles the shutdown process of the server async fn handle_shutdown(state_manager: &ServiceStateManager, shutdown_tx: &tokio::sync::broadcast::Sender<()>) { - info!("Shutdown signal received in main thread"); + info!( + target: "rustfs::main::handle_shutdown", + "Shutdown signal received in main thread" + ); // update the status to stopping first state_manager.update(ServiceState::Stopping); @@ -367,19 +382,31 @@ async fn handle_shutdown(state_manager: &ServiceStateManager, shutdown_tx: &toki // Stop background services based on what was enabled if enable_scanner || enable_heal { - info!("Stopping background services (data scanner and auto heal)..."); + info!( + target: "rustfs::main::handle_shutdown", + "Stopping background services (data scanner and auto heal)..." + ); shutdown_background_services(); - info!("Stopping AHM services..."); + info!( + target: "rustfs::main::handle_shutdown", + "Stopping AHM services..." + ); shutdown_ahm_services(); } else { - info!("Background services were disabled, skipping AHM shutdown"); + info!( + target: "rustfs::main::handle_shutdown", + "Background services were disabled, skipping AHM shutdown" + ); } // Stop the notification system shutdown_event_notifier().await; - info!("Server is stopping..."); + info!( + target: "rustfs::main::handle_shutdown", + "Server is stopping..." + ); let _ = shutdown_tx.send(()); // Wait for the worker thread to complete the cleaning work @@ -387,12 +414,18 @@ async fn handle_shutdown(state_manager: &ServiceStateManager, shutdown_tx: &toki // the last updated status is stopped state_manager.update(ServiceState::Stopped); - info!("Server stopped current "); + info!( + target: "rustfs::main::handle_shutdown", + "Server stopped current " + ); } #[instrument] async fn init_event_notifier() { - info!("Initializing event notifier..."); + info!( + target: "rustfs::main::init_event_notifier", + "Initializing event notifier..." + ); // 1. Get the global configuration loaded by ecstore let server_config = match GLOBAL_SERVER_CONFIG.get() { @@ -403,7 +436,10 @@ async fn init_event_notifier() { } }; - info!("Global server configuration loaded successfully"); + info!( + target: "rustfs::main::init_event_notifier", + "Global server configuration loaded successfully" + ); // 2. Check if the notify subsystem exists in the configuration, and skip initialization if it doesn't if server_config .get_value(rustfs_config::notify::NOTIFY_MQTT_SUB_SYS, DEFAULT_DELIMITER) @@ -412,18 +448,27 @@ async fn init_event_notifier() { .get_value(rustfs_config::notify::NOTIFY_WEBHOOK_SUB_SYS, DEFAULT_DELIMITER) .is_none() { - info!("'notify' subsystem not configured, skipping event notifier initialization."); + info!( + target: "rustfs::main::init_event_notifier", + "'notify' subsystem not configured, skipping event notifier initialization." + ); return; } - info!("Event notifier configuration found, proceeding with initialization."); + info!( + target: "rustfs::main::init_event_notifier", + "Event notifier configuration found, proceeding with initialization." + ); // 3. Initialize the notification system asynchronously with a global configuration // Use direct await for better error handling and faster initialization if let Err(e) = rustfs_notify::initialize(server_config).await { error!("Failed to initialize event notifier system: {}", e); } else { - info!("Event notifier system initialized successfully."); + info!( + target: "rustfs::main::init_event_notifier", + "Event notifier system initialized successfully." + ); } } @@ -492,7 +537,10 @@ async fn add_bucket_notification_configuration(buckets: Vec) { match has_notification_config { Some(cfg) => { - info!("Bucket '{}' has existing notification configuration: {:?}", bucket, cfg); + info!( + target: "rustfs::main::add_bucket_notification_configuration", + bucket = %bucket, + "Bucket '{}' has existing notification configuration: {:?}", bucket, cfg); let mut event_rules = Vec::new(); process_queue_configurations(&mut event_rules, cfg.queue_configurations.clone(), TargetID::from_str); @@ -508,7 +556,10 @@ async fn add_bucket_notification_configuration(buckets: Vec) { } } None => { - info!("Bucket '{}' has no existing notification configuration.", bucket); + info!( + target: "rustfs::main::add_bucket_notification_configuration", + bucket = %bucket, + "Bucket '{}' has no existing notification configuration.", bucket); } } }