fix(table): list the supported formats when a format table is rejected (#702)
diff --git a/crates/paimon/src/spec/core_options.rs b/crates/paimon/src/spec/core_options.rs
index f09a1e4..0e447a1 100644
--- a/crates/paimon/src/spec/core_options.rs
+++ b/crates/paimon/src/spec/core_options.rs
@@ -700,8 +700,8 @@
/// default 32). Used as the per-operation fan-out limit for sorted BTree and
/// bitmap shard reads, global-index vector search, and primary-key vector
/// search. A value of `1` reproduces strict sequential execution. A
- /// non-positive value is a misconfiguration and fails loud rather than being
- /// silently clamped.
+ /// non-positive value, or one above [`MAX_GLOBAL_INDEX_THREAD_NUM`], is a
+ /// misconfiguration and fails loud rather than being silently clamped.
pub fn global_index_thread_num(&self) -> crate::Result<usize> {
let value = self
.parse_i64_option(GLOBAL_INDEX_THREAD_NUM_OPTION)?
diff --git a/crates/paimon/src/table/format_table_scan.rs b/crates/paimon/src/table/format_table_scan.rs
index 4c83180..224ef50 100644
--- a/crates/paimon/src/table/format_table_scan.rs
+++ b/crates/paimon/src/table/format_table_scan.rs
@@ -615,6 +615,18 @@
.ok()
}
+fn supported_format_table_formats() -> Vec<&'static str> {
+ vec![
+ "parquet",
+ "orc",
+ "avro",
+ "row",
+ "mosaic",
+ #[cfg(feature = "vortex")]
+ "vortex",
+ ]
+}
+
fn supported_format_table_extension(format: &str) -> crate::Result<&'static str> {
match format.to_ascii_lowercase().as_str() {
"parquet" => Ok(".parquet"),
@@ -626,7 +638,9 @@
"vortex" => Ok(".vortex"),
other => Err(crate::Error::Unsupported {
message: format!(
- "Format table file.format '{other}' is not supported by the Rust reader yet"
+ "Format table file.format '{other}' is not supported by the Rust reader yet, \
+ expected one of: {}",
+ supported_format_table_formats().join(", ")
),
}),
}
@@ -656,3 +670,32 @@
write_cols: None,
}
}
+
+#[cfg(test)]
+mod tests {
+ use super::*;
+
+ #[test]
+ fn test_unsupported_format_lists_the_supported_ones() {
+ let error = supported_format_table_extension("csv").unwrap_err();
+ let crate::Error::Unsupported { message } = error else {
+ panic!("expected Unsupported, got {error:?}");
+ };
+ assert!(message.contains("'csv'"), "{message}");
+ for format in supported_format_table_formats() {
+ assert!(message.contains(format), "{format} missing from {message}");
+ }
+ }
+
+ #[test]
+ fn test_supported_formats_are_accepted_case_insensitively() {
+ for format in supported_format_table_formats() {
+ let expected = format!(".{format}");
+ assert_eq!(supported_format_table_extension(format).unwrap(), expected);
+ assert_eq!(
+ supported_format_table_extension(&format.to_ascii_uppercase()).unwrap(),
+ expected
+ );
+ }
+ }
+}
diff --git a/docs/src/sql.md b/docs/src/sql.md
index fc06266..34aa36a 100644
--- a/docs/src/sql.md
+++ b/docs/src/sql.md
@@ -2053,7 +2053,7 @@
| `btree-index.fallback-scan-max-size` | `256mb` | Maximum total size of selected BTree global-index files for fallback scans used by range/between and suffix/contains/complex LIKE predicates; `0` disables BTree fallback index scans. |
| `bitmap-index.fallback-scan-max-size` | `256mb` | Maximum total size of selected bitmap global-index files for fallback scans used by range/between and suffix/contains/complex LIKE predicates; `0` disables bitmap fallback index scans. |
| `global-index.search-mode` | `fast` | Global index coverage mode for reads: `fast`, `full`, or `detail`. |
-| `global-index.thread-num` | `32` | Number of threads used to search global index fields concurrently; must be greater than 0. |
+| `global-index.thread-num` | `32` | Number of threads used to search global index fields concurrently; must be greater than 0 and must not exceed the runtime's task limit. |
| `global-index.column-update-action` | `THROW_ERROR` | What a commit does when it updates an indexed column: `THROW_ERROR` rejects the commit, `DROP_PARTITION_INDEX` drops the affected partition index instead. |
### Variant Shredding Options